Example #1
0
File: kvm.py Project: Soft/nitro
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
Example #2
0
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
Example #3
0
File: kvm.py Project: Soft/nitro
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
Example #4
0
class VCPU(IOCTL):

    KVM_NITRO_GET_EVENT = IOR(KVMIO, 0xE5, NitroEventStr)
    KVM_NITRO_CONTINUE = IO(KVMIO, 0xE6)

    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 {}'.format(self.vcpu_nb))
        nitro_ev = NitroEventStr()
        self.make_ioctl(self.KVM_NITRO_GET_EVENT, byref(nitro_ev))
        return nitro_ev

    def continue_vm(self):
        # logging.debug('continue_vm {}'.format(self.vcpu_nb))
        return self.make_ioctl(self.KVM_NITRO_CONTINUE, None)
Example #5
0
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
Example #6
0
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
Example #7
0
import ctypes, fcntl
from ioctl_opt import IOR, IOC, IOC_READ, IOC_WRITE


class hidraw_devinfo(ctypes.Structure):
    _fields_ = [
        ('bustype', ctypes.c_uint),
        ('vendor', ctypes.c_short),
        ('product', ctypes.c_short),
    ]


HIDIOCGRAWINFO = IOR(ord('H'), 0x03, hidraw_devinfo)
HIDIOCGRAWNAME = lambda length: IOC(IOC_READ, ord('H'), 0x04, length)


def get_device_name(fd, length=1024):
    name = (ctypes.c_char * length)()
    actual_length = fcntl.ioctl(fd, HIDIOCGRAWNAME(length), name, True)
    if actual_length < 0:
        raise OSError(-actual_length)
    if name[actual_length - 1] == b'\x00':
        actual_length -= 1
    return name[:actual_length]


def get_device_id(fd, length=1024):
    device_id = hidraw_devinfo()
    actual_length = fcntl.ioctl(fd, HIDIOCGRAWINFO, device_id, True)
    if actual_length < 0:
        raise OSError(-actual_length)
Example #8
0
class raw_vcsm_cma(raw):
    '''
    Methods and constants for the VCSM-CMA kernel driver.

    Copyright (c) 2019 Raspberry Pi (Trading) Ltd. All rights reserved.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; version 2.

    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, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Copyright (c) 2012 Broadcom Europe Ltd.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
        * Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
        * Neither the name of the copyright holder nor the
          names of its contributors may be used to endorse or promote products
          derived from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    References:
    - https://github.com/raspberrypi/linux/blob/rpi-5.10.y/drivers/staging/vc04_services/include/linux/broadcom/vc_sm_cma_ioctl.h
    - https://github.com/raspberrypi/userland/blob/master/host_applications/linux/libs/sm/user-vcsm.c
    '''

    __MAGIC = ord('J')
    __CMD_ALLOC = 0x5a
    __CMD_CLEAN_INVALID2 = 0x5c

    class __st_alloc(Structure):
        _fields_ = [
            # user -> kernel
            ('size', c_uint32),
            ('num', c_uint32),
            ('cached', c_uint32),
            ('pad', c_uint32),
            ('name', c_char * 32),
            # kernel -> user
            ('handle', c_int32),
            ('vc_handle', c_uint32),
            ('dma_addr', c_uint64),
        ]

    class __st_clean_invalid2(Structure):
        class st_clean_invalid_block(Structure):
            _fields_ = [
                ('invalidate_mode', c_uint32),
                ('block_count', c_uint32),
                ('start_address', c_void_p),
                ('block_size', c_uint32),
                ('inter_block_stride', c_uint32),
            ]

        _fields_ = [
            # user -> kernel
            ('op_count', c_uint32),  # Must be 1 for now.
            ('pad', c_uint32),
            ('s', st_clean_invalid_block),
        ]

    __IOCTL_ALLOC = IOR(__MAGIC, __CMD_ALLOC, __st_alloc)
    __IOCTL_CLEAN_INVALID2 = IOR(__MAGIC, __CMD_CLEAN_INVALID2,
                                 __st_clean_invalid2)

    def __ioctl_alloc(self, *, size, num, cached, pad, name):
        s = self.__st_alloc(size=size,
                            num=num,
                            cached=cached,
                            pad=pad,
                            name=name)
        ioctl(self.__fd, self.__IOCTL_ALLOC, s)
        return s.handle, s.vc_handle, s.dma_addr

    def __init__(self, *, path=None):
        if path is None:
            path = '/dev/vcsm-cma'
        self.__fd = os.open(path, os.O_NONBLOCK | os.O_RDWR)

    def close(self):
        os.close(self.__fd)
        del self.__fd

    def alloc(self, *, size, cached, name):
        size_aligned = self.align(size, resource.getpagesize())
        name = bytes(name, 'ascii')

        handle, vc_handle, bus_ptr = self.__ioctl_alloc(size=size_aligned,
                                                        num=1,
                                                        cached=cached,
                                                        pad=0,
                                                        name=name)
        assert 0 <= bus_ptr < 2**32

        usr_buf = mmap.mmap(fileno=handle,
                            length=size,
                            flags=mmap.MAP_SHARED,
                            prot=mmap.PROT_READ | mmap.PROT_WRITE,
                            offset=0)

        dma_buf.ioctl_sync(fd=handle,
                           flags=dma_buf.SYNC_START | dma_buf.SYNC_RW)

        # The reference to this intermediate buffer is immediately removed, but
        # as long as the usr_buf is living, the memory address does not change.
        usr_ptr = addressof(c_byte.from_buffer(usr_buf))

        return handle, bus_ptr, usr_ptr, usr_buf

    def free(self, *, handle, usr_buf):
        dma_buf.ioctl_sync(fd=handle, flags=dma_buf.SYNC_END | dma_buf.SYNC_RW)
        usr_buf.close()
        os.close(handle)

    def clean_invalid(self, *, op, handle):
        if op == CACHE_OP_NOP:
            return
        elif op == CACHE_OP_INVALIDATE:
            flags = dma_buf.SYNC_START | dma_buf.SYNC_RW
        elif op == CACHE_OP_CLEAN or op == CACHE_OP_FLUSH:
            flags = dma_buf.SYNC_END | dma_buf.SYNC_RW
        dma_buf.ioctl_sync(fd=handle, flags=flags)
Example #9
0
class raw_vcsm(raw):
    '''
    Methods and constants for the plain (non-CMA) VCSM kernel driver.

    Copyright (c) 2011 Broadcom Corporation. All rights reserved.

    Unless you and Broadcom execute a separate written software license
    agreement governing use of this software, this software is licensed to you
    under the terms of the GNU General Public License version 2, available at
    http://www.broadcom.com/licenses/GPLv2.php (the "GPL").

    Notwithstanding the above, under no circumstances may you combine this
    software in any way with any other Broadcom software provided under a
    license other than the GPL, without Broadcom's express prior written
    consent.

    Copyright (c) 2012 Broadcom Europe Ltd.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
        * Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
        * Neither the name of the copyright holder nor the
          names of its contributors may be used to endorse or promote products
          derived from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    References:
    - https://github.com/raspberrypi/linux/blob/rpi-5.8.y/include/linux/broadcom/vmcs_sm_ioctl.h
    - https://github.com/raspberrypi/userland/blob/master/host_applications/linux/libs/sm/user-vcsm.c
    '''

    __MAGIC = ord('I')

    __CMD_ALLOC = 0x5a
    __CMD_LOCK = 0x5c
    __CMD_UNLOCK = 0x5e
    __CMD_FREE = 0x61
    __CMD_MAPPED_VC_ADDR_FROM_HDL = 0x6a
    __CMD_CLEAN_INVALID2 = 0x70

    class __st_alloc(Structure):
        _fields_ = [
            # user -> kernel
            ('size', c_uint),
            ('num', c_uint),
            ('cached', c_uint),
            ('name', c_char * 32),
            # kernel -> user
            ('handle', c_uint),
        ]

    class __st_free(Structure):
        _fields_ = [
            # user -> kernel
            ('handle', c_uint),
        ]

    class __st_lock_unlock(Structure):
        _fields_ = [
            # user -> kernel
            ('handle', c_uint),
            # kernel -> user
            ('addr', c_uint),
        ]

    class __st_map(Structure):
        _fields_ = [
            # user -> kernel
            ('pid', c_uint),
            ('handle', c_uint),
            ('addr', c_uint),
            # kernel -> user
            ('size', c_uint),
        ]

    class __st_clean_invalid2(Structure):
        class st_clean_invalid_block(Structure):
            _fields_ = [
                ('invalidate_mode', c_uint16),
                ('block_count', c_uint16),
                ('start_address', c_void_p),
                ('block_size', c_uint32),
                ('inter_block_stride', c_uint32),
            ]

        _fields_ = [
            # user -> kernel
            ('op_count', c_uint8),  # Must be 1 for now.
            ('zero', c_uint8 * 3),
            ('s', st_clean_invalid_block),
        ]

    __IOCTL_ALLOC = IOR(__MAGIC, __CMD_ALLOC, __st_alloc)
    __IOCTL_LOCK = IOR(__MAGIC, __CMD_LOCK, __st_lock_unlock)
    __IOCTL_UNLOCK = IOR(__MAGIC, __CMD_UNLOCK, __st_lock_unlock)
    __IOCTL_FREE = IOR(__MAGIC, __CMD_FREE, __st_free)
    __IOCTL_MAP_VC_ADDR_FR_HDL = IOR(__MAGIC, __CMD_MAPPED_VC_ADDR_FROM_HDL,
                                     __st_map)
    __IOCTL_CLEAN_INVALID2 = IOR(__MAGIC, __CMD_CLEAN_INVALID2,
                                 __st_clean_invalid2)

    def __ioctl_alloc(self, *, size, num, cached, name):
        s = self.__st_alloc(size=size, num=num, cached=cached, name=name)
        ioctl(self.__fd, self.__IOCTL_ALLOC, s)
        return s.handle

    def __ioctl_lock(self, *, handle):
        s = self.__st_lock_unlock(handle=handle)
        ioctl(self.__fd, self.__IOCTL_LOCK, s)
        return s.addr

    def __ioctl_unlock(self, *, handle):
        s = self.__st_lock_unlock(handle=handle)
        ioctl(self.__fd, self.__IOCTL_UNLOCK, s)
        return s.addr

    def __ioctl_free(self, *, handle):
        s = self.__st_free(handle=handle)
        ioctl(self.__fd, self.__IOCTL_FREE, s)

    def __ioctl_map_vc_addr_fr_hdl(self, *, pid, handle):
        s = self.__st_map(pid=pid, handle=handle)
        ioctl(self.__fd, self.__IOCTL_MAP_VC_ADDR_FR_HDL, s)
        return s.addr

    def __ioctl_clean_invalid2(self, *, invalidate_mode, block_count,
                               start_address, block_size, inter_block_stride):
        s = self.__st_clean_invalid2(
            op_count=1,
            s=self.__st_clean_invalid2.st_clean_invalid_block(
                invalidate_mode=invalidate_mode,
                block_count=block_count,
                start_address=start_address,
                block_size=block_size,
                inter_block_stride=inter_block_stride))
        ioctl(self.__fd, self.__IOCTL_CLEAN_INVALID2, s)

    def __init__(self, *, path=None):
        if path is None:
            path = '/dev/vcsm'
        self.__fd = os.open(path, os.O_NONBLOCK | os.O_RDWR)

    def close(self):
        os.close(self.__fd)
        del self.__fd

    def alloc(self, *, size, cached, name):
        size = self.align(size, resource.getpagesize())
        name = bytes(name, 'ascii')

        handle = self.__ioctl_alloc(size=size, num=1, cached=cached, name=name)

        usr_buf = mmap.mmap(fileno=self.__fd,
                            length=size,
                            flags=mmap.MAP_SHARED,
                            prot=mmap.PROT_READ | mmap.PROT_WRITE,
                            offset=handle)

        usr_ptr = self.__ioctl_lock(handle=handle)

        bus_ptr = self.__ioctl_map_vc_addr_fr_hdl(pid=os.getpid(),
                                                  handle=handle)

        return handle, bus_ptr, usr_ptr, usr_buf

    def free(self, *, handle, usr_buf):
        usr_buf.close()
        self.__ioctl_unlock(handle=handle)
        self.__ioctl_free(handle=handle)

    def clean_invalid(self, *, op, usr_ptr, size):
        self.__ioctl_clean_invalid2(invalidate_mode=op,
                                    block_count=1,
                                    start_address=usr_ptr,
                                    block_size=size,
                                    inter_block_stride=0)
Example #10
0
class raw(object):

    MAGIC = ord('I')
    CMD_ALLOC = 0x5a
    CMD_LOCK = 0x5c
    CMD_UNLOCK = 0x5e
    CMD_FREE = 0x61
    CMD_MAPPED_VC_ADDR_FROM_HDL = 0x6a
    CMD_CLEAN_INVALID2 = 0x70

    OP_NOP = 0
    OP_INVALIDATE = 1
    OP_CLEAN = 2
    OP_CLEAN_INVALIDATE = 3

    class st_alloc(Structure):
        _fields_ = [
            # user -> kernel
            ('size', c_uint),
            ('num', c_uint),
            ('cached', c_uint),
            ('name', c_char * 32),
            # kernel -> user
            ('handle', c_uint),
        ]
        pass

    class st_free(Structure):
        _fields_ = [
            # user -> kernel
            ('handle', c_uint),
        ]
        pass

    class st_lock_unlock(Structure):
        _fields_ = [
            # user -> kernel
            ('handle', c_uint),
            # kernel -> user
            ('addr', c_uint),
        ]
        pass

    class st_size(Structure):
        _fields_ = [
            # user -> kernel
            ('handle', c_uint),
            # kernel -> user
            ('size', c_uint),
        ]
        pass

    class st_map(Structure):
        _fields_ = [
            # user -> kernel
            ('pid', c_uint),
            ('handle', c_uint),
            ('addr', c_uint),
            # kernel -> user
            ('size', c_uint),
        ]
        pass

    class st_clean_invalid2(Structure):
        class st_clean_invalid_block(Structure):
            _fields_ = [
                ('invalidate_mode', c_uint16),
                ('block_count', c_uint16),
                ('start_address', c_void_p),
                ('block_size', c_uint32),
                ('inter_block_stride', c_uint32),
            ]
            pass

        _fields_ = [
            # user -> kernel
            ('op_count', c_uint8),  # Must be 1 for now... Sigh...
            ('zero', c_uint8 * 3),
            ('s', st_clean_invalid_block),
        ]
        pass

    IOCTL_ALLOC = IOR(MAGIC, CMD_ALLOC, st_alloc)
    IOCTL_LOCK = IOR(MAGIC, CMD_LOCK, st_lock_unlock)
    IOCTL_UNLOCK = IOR(MAGIC, CMD_UNLOCK, st_lock_unlock)
    IOCTL_FREE = IOR(MAGIC, CMD_FREE, st_free)
    IOCTL_MAP_VC_ADDR_FR_HDL = IOR(MAGIC, CMD_MAPPED_VC_ADDR_FROM_HDL, st_map)
    # Dirty hack! No more zero-sized arrays I hope!
    IOCTL_CLEAN_INVALID2 = IOR(MAGIC, CMD_CLEAN_INVALID2, c_uint8 * 4)

    def __init__(self):
        self.fd = os.open('/dev/vcsm', os.O_NONBLOCK | os.O_RDWR)

    def close(self):
        if self.fd:
            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

    def alloc(self, size, num, cached, name):
        if sys.version_info >= (3, 0):
            name = bytes(name, 'ascii')
        else:
            name = bytes(name).encode('ascii')
        s = self.st_alloc(size=size, num=num, cached=cached, name=name)
        ioctl(self.fd, self.IOCTL_ALLOC, s)
        return s.handle

    def lock(self, handle):
        s = self.st_lock_unlock(handle=handle)
        ioctl(self.fd, self.IOCTL_LOCK, s)
        return s.addr

    def unlock(self, handle):
        s = self.st_lock_unlock(handle=handle)
        ioctl(self.fd, self.IOCTL_UNLOCK, s)

    def free(self, handle):
        s = self.st_free(handle=handle)
        ioctl(self.fd, self.IOCTL_FREE, s)

    def map_vc_addr_fr_hdl(self, handle):
        s = self.st_map(pid=os.getpid(), handle=handle)
        ioctl(self.fd, self.IOCTL_MAP_VC_ADDR_FR_HDL, s)
        return s.addr

    def clean_invalid2(self, op, usr_ptr, block_count, block_size, stride):
        s = self.st_clean_invalid2(
            op_count=1,
            s=self.st_clean_invalid2.st_clean_invalid_block(
                invalidate_mode=op,
                block_count=block_count,
                start_address=usr_ptr,
                block_size=block_size,
                inter_block_stride=stride))
        ioctl(self.fd, self.IOCTL_CLEAN_INVALID2, s)
Example #11
0
# 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
class KVMFixedRegion(Structure):
    _fields_ = [
        ('name', c_char_p),
        ('host_address', c_uint64),
        ('size', c_uint64),