def __init__(self, deviceNode="/dev/vfd"): self._device_node = deviceNode if not os.path.exists(deviceNode): logger.warning( "Device node %s does not exist. Subsequent ops WILL fail!", deviceNode) size = ctypes.c_int(0) self._TM1628_IOC_MAGIC = ord('S') self._TM1628_IOC_POWER = IOW(self._TM1628_IOC_MAGIC, 0, size) self._TM1628_IOC_SBRIGHT = IOW(self._TM1628_IOC_MAGIC, 1, size) self._TM1628_IOC_MAXNR = 4
class KVM(IOCTL): """Class for connecting to the KVM and attaching to virtual machines.""" __slots__ = ( 'kvm_file' ) KVM_NODE = '/dev/kvm' KVM_NITRO_ATTACH_VM = IOW(KVMIO, 0xE1, c_int) def __init__(self): super().__init__() self.kvm_file = open(self.KVM_NODE, 'r+') self.fd = self.kvm_file.fileno() def attach_vm(self, pid): """ Attach to KVM virtual machine :param int pid: pid of the Qemu process to attach to. :raises: RuntimeError """ logging.debug('attach_vm PID = %s', pid) c_pid = c_int(pid) r = self.make_ioctl(self.KVM_NITRO_ATTACH_VM, byref(c_pid)) if r < 0: # invalid vm fd raise RuntimeError('Error: fail to attach to the VM') return r
class VM(IOCTL): __slots__ = ('vcpus_struct') KVM_NITRO_ATTACH_VCPUS = IOR(KVMIO, 0xE2, NitroVCPUs) KVM_NITRO_SET_SYSCALL_TRAP = IOW(KVMIO, 0xE3, c_bool) def __init__(self, vm_fd): super().__init__() self.fd = vm_fd self.vcpus_struct = NitroVCPUs() def attach_vcpus(self): logging.debug('attach_vcpus') r = self.make_ioctl(self.KVM_NITRO_ATTACH_VCPUS, byref(self.vcpus_struct)) if r != 0: raise RuntimeError('Error: fail to attach to vcpus') vcpus = [ VCPU(i, self.vcpus_struct.fds[i]) for i in range(self.vcpus_struct.num_vcpus) ] return vcpus def set_syscall_trap(self, enabled): logging.debug('set_syscall_trap {}'.format(enabled)) c_enabled = c_bool(enabled) r = self.make_ioctl(self.KVM_NITRO_SET_SYSCALL_TRAP, byref(c_enabled)) return r
class VCPU(IOCTL): __slots__ = ('vcpu_nb', ) KVM_NITRO_GET_EVENT = IOR(KVMIO, 0xE5, NitroEventStr) KVM_NITRO_CONTINUE = IO(KVMIO, 0xE6) KVM_NITRO_GET_REGS = IOR(KVMIO, 0xE7, Regs) KVM_NITRO_SET_REGS = IOW(KVMIO, 0xE8, Regs) KVM_NITRO_GET_SREGS = IOR(KVMIO, 0xE9, SRegs) KVM_NITRO_SET_SREGS = IOW(KVMIO, 0xEA, SRegs) def __init__(self, vcpu_nb, vcpu_fd): super().__init__() self.vcpu_nb = vcpu_nb self.fd = vcpu_fd def get_event(self): # logging.debug('get_event %s, self.vcpu_nb) nitro_ev = NitroEventStr() ret = self.make_ioctl(self.KVM_NITRO_GET_EVENT, byref(nitro_ev)) if ret != 0: logging.error("get_event failed (vcpu: %d; returned: %d)", self.vcpu_nb, ret) raise ValueError("get_event failed") return nitro_ev def continue_vm(self): # logging.debug('continue_vm %s', self.vcpu_nb) return self.make_ioctl(self.KVM_NITRO_CONTINUE, 0) def get_regs(self): regs = Regs() self.make_ioctl(self.KVM_NITRO_GET_REGS, byref(regs)) return regs def get_sregs(self): sregs = SRegs() self.make_ioctl(self.KVM_NITRO_GET_SREGS, byref(sregs)) return sregs def set_regs(self, regs): ret = self.make_ioctl(self.KVM_NITRO_SET_REGS, byref(regs)) return ret def set_sregs(self, sregs): ret = self.make_ioctl(self.KVM_NITRO_SET_SREGS, byref(sregs)) return ret
class KVM(IOCTL): KVM_NODE = '/dev/kvm' KVM_NITRO_ATTACH_VM = IOW(KVMIO, 0xE1, c_int) def __init__(self): super().__init__() self.kvm_file = open(self.KVM_NODE, 'r+') self.fd = self.kvm_file.fileno() def attach_vm(self, pid): logging.debug('attach_vm PID = {}'.format(pid)) c_pid = c_int(pid) r = self.make_ioctl(self.KVM_NITRO_ATTACH_VM, byref(c_pid)) return r
class VM(IOCTL): __slots__ = ('vcpus_struct') KVM_NITRO_ATTACH_VCPUS = IOR(KVMIO, 0xE2, NitroVCPUs) KVM_NITRO_SET_SYSCALL_TRAP = IOW(KVMIO, 0xE3, c_bool) KVM_NITRO_ADD_SYSCALL_FILTER = IOR(KVMIO, 0xEB, c_ulonglong) KVM_NITRO_REMOVE_SYSCALL_FILTER = IOR(KVMIO, 0xEC, c_ulonglong) def __init__(self, vm_fd): super().__init__() self.fd = vm_fd self.vcpus_struct = NitroVCPUs() def attach_vcpus(self): logging.debug('attach_vcpus') r = self.make_ioctl(self.KVM_NITRO_ATTACH_VCPUS, byref(self.vcpus_struct)) if r != 0: raise RuntimeError('Error: fail to attach to vcpus') vcpus = [ VCPU(i, self.vcpus_struct.fds[i]) for i in range(self.vcpus_struct.num_vcpus) ] return vcpus def set_syscall_trap(self, enabled): logging.debug('set_syscall_trap %s', enabled) c_enabled = c_bool(enabled) r = self.make_ioctl(self.KVM_NITRO_SET_SYSCALL_TRAP, byref(c_enabled)) return r def add_syscall_filter(self, syscall_nb): logging.debug('adding syscall filter on %s' % (syscall_nb)) c_syscall_nb = c_ulonglong(syscall_nb) r = self.make_ioctl(self.KVM_NITRO_ADD_SYSCALL_FILTER, byref(c_syscall_nb)) if r != 0: raise RuntimeError('Error: fail to add syscall filter') return r def remove_syscall_filter(self, syscall_nb): logging.debug('removing syscall filter on %s' % (syscall_nb)) c_syscall_nb = c_ulonglong(syscall_nb) r = self.make_ioctl(self.KVM_NITRO_REMOVE_SYSCALL_FILTER, byref(c_syscall_nb)) if r != 0: raise RuntimeError('Error: fail to remove syscall filter') return r
class KVM(IOCTL): __slots__ = ('kvm_file') KVM_NODE = '/dev/kvm' KVM_NITRO_ATTACH_VM = IOW(KVMIO, 0xE1, c_int) def __init__(self): super().__init__() self.kvm_file = open(self.KVM_NODE, 'r+') self.fd = self.kvm_file.fileno() def attach_vm(self, pid): logging.debug('attach_vm PID = %s', pid) c_pid = c_int(pid) r = self.make_ioctl(self.KVM_NITRO_ATTACH_VM, byref(c_pid)) if r < 0: # invalid vm fd raise RuntimeError('Error: fail to attach to the VM') return r
class dma_buf: ''' Methods and constants for the dma-buf subsystem. Copyright (c) 2015 Intel Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. References: - https://github.com/raspberrypi/linux/blob/rpi-5.10.y/include/uapi/linux/dma-buf.h ''' __MAGIC = ord('b') __CMD_SYNC = 0 SYNC_READ = 1 << 0 SYNC_WRITE = 2 << 0 SYNC_RW = SYNC_READ | SYNC_WRITE SYNC_START = 0 << 2 SYNC_END = 1 << 2 class __st_sync(Structure): _fields_ = [ ('flags', c_uint64), ] __IOCTL_SYNC = IOW(__MAGIC, __CMD_SYNC, __st_sync) @staticmethod def ioctl_sync(*, fd, flags): s = dma_buf.__st_sync(flags=flags) ioctl(fd, dma_buf.__IOCTL_SYNC, s)
class DRM_V3D(object): def __init__(self, path='/dev/dri/by-path/platform-fec00000.v3d-card'): self.fd = os.open(path, os.O_RDWR) def close(self): if self.fd is not None: os.close(self.fd) self.fd = None def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() return exc_value is None # Derived from linux/include/uapi/drm/drm.h DRM_IOCTL_BASE = ord('d') DRM_COMMAND_BASE = 0x40 DRM_GEM_CLOSE = 0x09 # Derived from linux/include/uapi/drm/v3d_drm.h DRM_V3D_WAIT_BO = DRM_COMMAND_BASE + 0x01 DRM_V3D_CREATE_BO = DRM_COMMAND_BASE + 0x02 DRM_V3D_MMAP_BO = DRM_COMMAND_BASE + 0x03 DRM_V3D_GET_PARAM = DRM_COMMAND_BASE + 0x04 DRM_V3D_SUBMIT_CSD = DRM_COMMAND_BASE + 0x07 V3D_PARAM_V3D_UIFCFG = 0 V3D_PARAM_V3D_HUB_IDENT1 = 1 V3D_PARAM_V3D_HUB_IDENT2 = 2 V3D_PARAM_V3D_HUB_IDENT3 = 3 V3D_PARAM_V3D_CORE0_IDENT0 = 4 V3D_PARAM_V3D_CORE0_IDENT1 = 5 V3D_PARAM_V3D_CORE0_IDENT2 = 6 V3D_PARAM_SUPPORTS_TFU = 7 V3D_PARAM_SUPPORTS_CSD = 8 class st_gem_close(Structure): _fields_ = [ ('handle', c_uint32), ('pad', c_uint32), ] class st_v3d_wait_bo(Structure): _fields_ = [ ('handle', c_uint32), ('pad', c_uint32), ('timeout_ns', c_uint64), ] class st_v3d_create_bo(Structure): _fields_ = [ ('size', c_uint32), ('flags', c_uint32), ('handle', c_uint32), ('offset', c_uint32), ] class st_v3d_mmap_bo(Structure): _fields_ = [ ('handle', c_uint32), ('flags', c_uint32), ('offset', c_uint64), ] class st_v3d_get_param(Structure): _fields_ = [ ('param', c_uint32), ('pad', c_uint32), ('value', c_uint64), ] class st_v3d_submit_csd(Structure): _fields_ = [ ('cfg', c_uint32 * 7), ('coef', c_uint32 * 4), ('bo_handles', c_uint64), ('bo_handle_count', c_uint32), ('in_sync', c_uint32), ('out_sync', c_uint32), ] IOCTL_GEM_CLOSE = IOW(DRM_IOCTL_BASE, DRM_GEM_CLOSE, st_gem_close) IOCTL_V3D_WAIT_BO = IOWR(DRM_IOCTL_BASE, DRM_V3D_WAIT_BO, st_v3d_wait_bo) IOCTL_V3D_CREATE_BO = IOWR(DRM_IOCTL_BASE, DRM_V3D_CREATE_BO, st_v3d_create_bo) IOCTL_V3D_MMAP_BO = IOWR(DRM_IOCTL_BASE, DRM_V3D_MMAP_BO, st_v3d_mmap_bo) IOCTL_V3D_GET_PARAM = IOWR(DRM_IOCTL_BASE, DRM_V3D_GET_PARAM, st_v3d_get_param) IOCTL_V3D_SUBMIT_CSD = IOW(DRM_IOCTL_BASE, DRM_V3D_SUBMIT_CSD, st_v3d_submit_csd) def gem_close(self, handle): st = self.st_gem_close( handle=handle, pad=0, ) ioctl(self.fd, self.IOCTL_GEM_CLOSE, st) def v3d_wait_bo(self, handle, timeout_ns): st = self.st_v3d_wait_bo( handle=handle, pad=0, timeout_ns=timeout_ns, ) ioctl(self.fd, self.IOCTL_V3D_WAIT_BO, st) def v3d_create_bo(self, size, flags=0): st = self.st_v3d_create_bo( size=size, flags=flags, handle=0, offset=0, ) ioctl(self.fd, self.IOCTL_V3D_CREATE_BO, st) return st.handle, st.offset def v3d_mmap_bo(self, handle, flags=0): st = self.st_v3d_mmap_bo( handle=handle, flags=flags, offset=0, ) ioctl(self.fd, self.IOCTL_V3D_MMAP_BO, st) return st.offset def v3d_get_param(self, param): st = self.st_v3d_get_param( param=param, pad=0, value=0, ) ioctl(self.fd, self.IOCTL_V3D_GET_PARAM, st) return st.value def v3d_submit_csd(self, cfg, coef, bo_handles, bo_handle_count, in_sync, out_sync): st = self.st_v3d_submit_csd( # XXX: Dirty hack! cfg=(c_uint32 * 7)(*cfg), coef=(c_uint32 * 4)(*coef), bo_handles=bo_handles, bo_handle_count=bo_handle_count, in_sync=in_sync, out_sync=out_sync, ) ioctl(self.fd, self.IOCTL_V3D_SUBMIT_CSD, st)
def __init__(self, device_name="/dev/skunk"): self.device_name = device_name self.func_call_ioctl_num = IOWR(0xEE, 0, ctypes.c_char_p) self.mock_create_ioctl_num = IOW(0xEE, 1, ctypes.c_char_p) self.mock_destroy_ioctl_num = IO(0xEE, 2) self.mock_return_values = skunk_pb2.ReturnValueMock()
class VCPU(IOCTL): """Class that allows controlling and inspecting the state of an individual virtual CPU.""" __slots__ = ( 'vcpu_nb', ) #: Request for retrieving event KVM_NITRO_GET_EVENT = IOR(KVMIO, 0xE5, NitroEventStr) #: Request to continue KVM_NITRO_CONTINUE = IO(KVMIO, 0xE6) #: Request to get register state KVM_NITRO_GET_REGS = IOR(KVMIO, 0xE7, Regs) #: Request to set register state KVM_NITRO_SET_REGS = IOW(KVMIO, 0xE8, Regs) #: Request to get special registers KVM_NITRO_GET_SREGS = IOR(KVMIO, 0xE9, SRegs) #: Request to set special registers KVM_NITRO_SET_SREGS = IOW(KVMIO, 0xEA, SRegs) def __init__(self, vcpu_nb, vcpu_fd): super().__init__() self.vcpu_nb = vcpu_nb self.fd = vcpu_fd def get_event(self): """ Retrieve event from the virtual machine :rtype: NitroEventStr """ # logging.debug('get_event %s, self.vcpu_nb) nitro_ev = NitroEventStr() ret = self.make_ioctl(self.KVM_NITRO_GET_EVENT, byref(nitro_ev)) if ret != 0: raise ValueError("get_event failed on vcpu %d (%d)".format(self.vcpu_nb, ret)) return nitro_ev def continue_vm(self): """Continue virtual machine execution""" # logging.debug('continue_vm %s', self.vcpu_nb) return self.make_ioctl(self.KVM_NITRO_CONTINUE, 0) def get_regs(self): """ Get registers from the virtual machine. :rtype: Regs """ regs = Regs() self.make_ioctl(self.KVM_NITRO_GET_REGS, byref(regs)) return regs def get_sregs(self): """ Get special registers from the virtual machine. :rtype: SRegs """ sregs = SRegs() self.make_ioctl(self.KVM_NITRO_GET_SREGS, byref(sregs)) return sregs def set_regs(self, regs): """ Set registers for the virtual machine. :param Regs regs: Values for registers """ ret = self.make_ioctl(self.KVM_NITRO_SET_REGS, byref(regs)) return ret def set_sregs(self, sregs): """ Set special registers for the virtual machine. :param SRegs sregs: Values for special registers """ ret = self.make_ioctl(self.KVM_NITRO_SET_SREGS, byref(sregs)) return ret
class VM(IOCTL): """Class that allows low-level control of KVM virtual machines. VM makes it possible to attach to machine's virtual CPUs and add system call filters. """ __slots__ = ( 'vcpus_struct', 'syscall_filters' ) #: Reguest for attaching to a virtual CPU KVM_NITRO_ATTACH_VCPUS = IOR(KVMIO, 0xE2, NitroVCPUs) #: Request for setting system call trap KVM_NITRO_SET_SYSCALL_TRAP = IOW(KVMIO, 0xE3, c_bool) #: Request for adding system call filter KVM_NITRO_ADD_SYSCALL_FILTER = IOR(KVMIO, 0xEB, c_ulonglong) #: Request for removing system call filter KVM_NITRO_REMOVE_SYSCALL_FILTER = IOR(KVMIO, 0xEC, c_ulonglong) def __init__(self, vm_fd): super().__init__() self.fd = vm_fd self.vcpus_struct = NitroVCPUs() self.syscall_filters = set() def attach_vcpus(self): """ Attach to virtual CPUs :rtype: List of VCPUs """ logging.debug('attach_vcpus') r = self.make_ioctl(self.KVM_NITRO_ATTACH_VCPUS, byref(self.vcpus_struct)) if r != 0: raise RuntimeError('Error: fail to attach to vcpus') vcpus = [VCPU(i, self.vcpus_struct.fds[i]) for i in range(self.vcpus_struct.num_vcpus)] return vcpus def set_syscall_trap(self, enabled): logging.debug('set_syscall_trap %s', enabled) c_enabled = c_bool(enabled) r = self.make_ioctl(self.KVM_NITRO_SET_SYSCALL_TRAP, byref(c_enabled)) return r def add_syscall_filter(self, syscall_nb): logging.debug('adding syscall filter on %s' % (hex(syscall_nb))) c_syscall_nb = c_ulonglong(syscall_nb) r = self.make_ioctl(self.KVM_NITRO_ADD_SYSCALL_FILTER, byref(c_syscall_nb)) if r != 0: raise RuntimeError('Error: fail to add syscall filter') self.syscall_filters.add(syscall_nb) return r def remove_syscall_filter(self, syscall_nb): logging.debug('removing syscall filter on %s' % (hex(syscall_nb))) c_syscall_nb = c_ulonglong(syscall_nb) r = self.make_ioctl(self.KVM_NITRO_REMOVE_SYSCALL_FILTER, byref(c_syscall_nb)) if r != 0: raise RuntimeError('Error: fail to remove syscall filter') self.syscall_filters.remove(syscall_nb) return r
('exit_reasons', KVMRunExitReasons) ] KVMIO = 0xae # KVM IOCTLs KVM_GET_API_VERSION = IO(KVMIO, 0x00) KVM_CREATE_VM = IO(KVMIO, 0x01) KVM_CHECK_EXTENSION = IO(KVMIO, 0x03) KVM_GET_VCPU_MMAP_SIZE = IO(KVMIO, 0x04) # KVM VM IOCTLs KVM_CREATE_VCPU = IO(KVMIO, 0x41) KVM_SET_TSS_ADDR = IO(KVMIO, 0x47) KVM_SET_USER_MEMORY_REGION = IOW(KVMIO, 0x46, KVMUserSpaceMemoryRegion) # KVM CPU IOCTLs KVM_RUN = IO(KVMIO, 0x80) KVM_GET_REGS = IOR(KVMIO, 0x81, KVMRegs) KVM_SET_REGS = IOW(KVMIO, 0x82, KVMRegs) KVM_GET_SREGS = IOR(KVMIO, 0x83, KVMSRegs) KVM_SET_SREGS = IOW(KVMIO, 0x84, KVMSRegs) ######################################################################################### # The KVM structures and APIs below are not part of the standard KVM interface. # They are part of the KVM extensions for symbolic execution by S2E (http://s2e.systems). # Available with KVM_CAP_MEM_FIXED_REGION