/* * \brief Qemu emulation environment * \author Josef Soentgen * \author Sebastian Sumpf * \date 2015-12-14 */ /* * Copyright (C) 2015-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _INCLUDE__QEMU_EMUL_H_ #define _INCLUDE__QEMU_EMUL_H_ #include #include void q_printf(char const *, ...) __attribute__((format(printf, 1, 2))); void q_vprintf(char const *, va_list); typedef genode_uint8_t uint8_t; typedef genode_uint16_t uint16_t; typedef genode_uint32_t uint32_t; typedef genode_uint64_t uint64_t; typedef genode_int32_t int32_t; typedef genode_int64_t int64_t; typedef signed long ssize_t; #ifndef __cplusplus typedef _Bool bool; enum { false = 0, true = 1 }; #endif typedef __SIZE_TYPE__ size_t; typedef unsigned long dma_addr_t; typedef uint64_t hwaddr; typedef struct uint16List { union { uint16_t value; uint64_t padding; }; struct uint16List *next; } uint16List; /********** ** libc ** **********/ enum { EINVAL = 22, }; void *memset(void *s, int c, size_t n); void *memcpy(void *dest, const void *src, size_t n); void abort(); #define fprintf(fd, fmt, ...) q_printf(fmt, ##__VA_ARGS__) int snprintf(char *buf, size_t size, const char *fmt, ...); int strcmp(const char *s1, const char *s2); size_t strlen(char const *s); long int strtol(const char *nptr, char **endptr, int base); char *strchr(const char *s, int c); /************* ** defines ** *************/ #define NULL (void *)0 #define QEMU_SENTINEL #define le32_to_cpu(x) (x) #define cpu_to_le32(x) (x) #define cpu_to_le64(x) (x) #define le32_to_cpus(x) #define le64_to_cpus(x) /** * Forward declarations */ typedef struct Monitor Monitor; typedef struct QDict QDict; typedef struct CPUReadMemoryFunc CPUReadMemoryFunc; typedef struct CPUWriteMemoryFunc CPUWriteMemoryFunc; typedef struct MemoryRegion { unsigned dummy; } MemoryRegion; struct tm; /****************** ** qapi/error.h ** ******************/ typedef struct Error { char string[256]; } Error; void error_setg(Error **errp, const char *fmt, ...); const char *error_get_pretty(Error *err); void error_report(const char *fmt, ...); void error_free(Error *err); void error_propagate(Error **dst_errp, Error *local_err); extern Error *error_abort; /******************* ** qemu/bitops.h ** *******************/ #define BITS_PER_BYTE 8 #define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] static inline void set_bit(long nr, unsigned long *addr) { unsigned long mask = BIT_MASK(nr); unsigned long *p = addr + BIT_WORD(nr); *p |= mask; } /******************* ** qemu-common.h ** *******************/ struct iovec { void *iov_base; size_t iov_len; }; typedef struct QEMUIOVector { struct iovec *iov; int niov; size_t size; int alloc_hint; } QEMUIOVector; void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len); void qemu_iovec_reset(QEMUIOVector *qiov); void qemu_iovec_destroy(QEMUIOVector *qiov); void pstrcpy(char *buf, int buf_size, const char *str); /**************** ** qemu/iov.h ** ****************/ size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, size_t offset, const void *buf, size_t bytes); size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, size_t offset, void *buf, size_t bytes); size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt, size_t offset, int fillc, size_t bytes); /****************** ** qom/object.h ** ******************/ typedef struct Object { unsigned dummy; } Object; typedef struct ObjectClass { unsigned dummy; } ObjectClass; struct DeviceState; struct PCIDevice; struct XHCIState; struct PCIDevice *cast_PCIDevice(void *); struct XHCIState *cast_XHCIState(void *); struct DeviceState *cast_DeviceState(void *); struct BusState *cast_BusState(void *); struct Object *cast_object(void *); struct USBDevice *cast_USBDevice(void *); struct USBHostDevice *cast_USBHostDevice(void *); struct PCIDeviceClass *cast_PCIDeviceClass(void *); struct DeviceClass *cast_DeviceClass(void *); struct BusClass *cast_BusClass(void *); struct HotplugHandlerClass *cast_HotplugHandlerClass(void *); struct USBDeviceClass *cast_USBDeviceClass(void *); #define OBJECT_CHECK(type, obj, str) \ cast_##type((void *)obj) #define OBJECT_CLASS_CHECK(type, klass, str) \ OBJECT_CHECK(type, (klass), str) #define OBJECT(obj) \ cast_object(obj) #define OBJECT_GET_CLASS(klass, obj, str) \ OBJECT_CHECK(klass, obj, str) typedef struct InterfaceInfo { const char *type; } InterfaceInfo; typedef struct TypeInfo { char const *name; char const *parent; size_t instance_size; bool abstract; size_t class_size; void (*class_init)(ObjectClass *klass, void *data); InterfaceInfo *interfaces; } TypeInfo; struct Type_impl { unsigned dummy; }; typedef struct Type_impl *Type; Type type_register_static(const TypeInfo *info); #define object_property_set_bool(...) #define object_unparent(...) const char *object_get_typename(Object *obj); /******************** ** glib emulation ** ********************/ void *g_malloc(size_t size); void g_free(void *ptr); #define g_new0(type, count)({ \ typeof(type) *t = (typeof(type)*)g_malloc(sizeof(type) * count); \ memset(t, 0, sizeof(type) * count); \ t; \ }) #define g_malloc0(size) ({ \ void *t = g_malloc((size)); \ memset(t, 0, (size)); \ t; \ }) typedef void* gpointer; typedef struct GSList GSList; struct GSList { gpointer data; GSList *next; }; GSList *g_slist_append(GSList *list, gpointer data); typedef char gchar; gchar *g_strdup(gchar const *str); gchar *g_strdup_printf(gchar const *fmt, ...); /******************** ** hw/qdev-core.h ** ********************/ typedef enum DeviceCategory { DEVICE_CATEGORY_USB = 1, DEVICE_CATEGORY_MAX } DeviceCategory; typedef struct BusState BusState; typedef struct DeviceState { BusState *parent_bus; } DeviceState; struct VMStateDescription; struct Property; typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); typedef struct DeviceClass { DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX); struct Property *props; void (*reset)(DeviceState *dev); DeviceRealize realize; DeviceUnrealize unrealize; const struct VMStateDescription *vmsd; const char *bus_type; } DeviceClass; #define DEVICE_CLASS(klass) OBJECT_CHECK(DeviceClass, (klass), "device") typedef struct BusState { DeviceState *parent; char *name; } BusState; typedef struct BusClass { void (*print_dev)(Monitor *mon, DeviceState *dev, int indent); char *(*get_dev_path)(DeviceState *dev); char *(*get_fw_dev_path)(DeviceState *dev); } BusClass; #define TYPE_BUS "bus" #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) #define TYPE_DEVICE "device" #define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE) enum Prop_type { BIT, UINT32, END }; typedef struct Property { enum Prop_type type; unsigned offset; unsigned long value; } Property; #define DEFINE_PROP_BIT(_name, _state, _field, _bit, _bool) \ { .type = BIT, .offset = offsetof(_state, _field), .value = (_bool << _bit) } #define DEFINE_PROP_UINT32(_name, _state, _field, _value) \ { .type = UINT32, .offset = offsetof(_state, _field), .value = _value } #define DEFINE_PROP_END_OF_LIST() { .type = END } #define DEFINE_PROP_STRING(...) {} /* forward */ typedef struct DeviceState DeviceState; typedef struct HotplugHandler HotplugHandler; void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name); void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp); DeviceState *qdev_create(BusState *bus, const char *name); DeviceState *qdev_try_create(BusState *bus, const char *name); char *qdev_get_dev_path(DeviceState *dev); const char *qdev_fw_name(DeviceState *dev); /****************** ** hw/hotplug.h ** ******************/ typedef struct HotplugHandler { unsigned dummy; } HotplugHandler; typedef void (*hotplug_fn)(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp); typedef struct HotplugHandlerClass { hotplug_fn unplug; } HotplugHandlerClass; #define TYPE_HOTPLUG_HANDLER "hotplug-handler" #define HOTPLUG_HANDLER_CLASS(klass) \ OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER) /**************** ** hw/osdep.h ** ****************/ #define offsetof(type, member) ((size_t) &((type *)0)->member) #define container_of(ptr, type, member) ({ \ const typeof(((type *) 0)->member) *__mptr = (ptr); \ (type *) ((char *) __mptr - offsetof(type, member));}) #define DO_UPCAST(type, field, dev) cast_DeviceStateToUSBBus() struct USBBus *cast_DeviceStateToUSBBus(void); #define MAX(a, b) ((a) < (b) ? (b) : (a)) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /****************** ** qemu/timer.h ** ******************/ enum QEMUClockType { QEMU_CLOCK_VIRTUAL = 1, }; typedef enum QEMUClockType QEMUClockType; typedef struct QEMUTimer { unsigned dummy; } QEMUTimer; typedef void QEMUTimerCB(void *opaque); QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb, void *opaque); void timer_mod(QEMUTimer *ts, int64_t expire_timer); void timer_del(QEMUTimer *ts); void timer_free(QEMUTimer *ts); int64_t qemu_clock_get_ns(QEMUClockType type); /*********************** ** exec/cpu-common.h ** ***********************/ enum device_endian { DEVICE_LITTLE_ENDIAN = 2 }; /******************* ** exec/memory.h ** *******************/ typedef struct AddressSpace { unsigned dummy; } AddressSpace; typedef struct MemoryRegionOps { uint64_t (*read)(void *opaque, hwaddr addr, unsigned size); void (*write)(void *opaque, hwaddr addr, uint64_t data, unsigned size); enum device_endian endianness; struct { unsigned min_access_size; unsigned max_access_size; } valid; struct { unsigned min_access_size; unsigned max_access_size; } impl; } MemoryRegionOps; void memory_region_init(MemoryRegion *mr, struct Object *owner, const char *name, uint64_t size); void memory_region_init_io(MemoryRegion *mr, struct Object *owner, const MemoryRegionOps *ops, void *opaque, const char *name, uint64_t size); void memory_region_add_subregion(MemoryRegion *mr, hwaddr offset, MemoryRegion *subregion); void memory_region_del_subregion(MemoryRegion *mr, MemoryRegion *subregion); /****************** ** sysemu/dma.h ** ******************/ typedef struct QEMUIOVector QEMUSGList; void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); int dma_memory_read(AddressSpace *as, dma_addr_t addr, void *buf, dma_addr_t len); static inline uint64_t ldq_le_dma(AddressSpace *as, dma_addr_t addr) { uint64_t val; dma_memory_read(as, addr, &val, 8); return val; } static inline uint64_t ldq_le_pci_dma(void *dev, dma_addr_t addr) { return ldq_le_dma(0, addr); } /************** ** hw/pci.h ** **************/ enum Pci_regs { PCI_BASE_ADDRESS_SPACE_MEMORY = 0, PCI_BASE_ADDRESS_MEM_TYPE_64 = 0x04, PCI_CLASS_PROG = 0x09, PCI_CACHE_LINE_SIZE = 0x0c, PCI_INTERRUPT_PIN = 0x3d, }; enum Pci_ids { PCI_CLASS_SERIAL_USB = 0x0c03, PCI_VENDOR_ID_NEC = 0x1033, PCI_DEVICE_ID_NEC_UPD720200 = 0x0194, }; typedef struct PCIBus { unsigned dummy; } PCIBus; typedef struct PCIDevice { uint8_t config[0x1000]; /* PCIe config space */ PCIBus *bus; uint8_t *msix_table; uint8_t *msix_pba; MemoryRegion msix_table_mmio; MemoryRegion msix_pba_mmio; unsigned *msix_entry_used; } PCIDevice; typedef void PCIUnregisterFunc(PCIDevice *pci_dev); typedef struct PCIDeviceClass { void (*realize)(PCIDevice *dev, Error **errp); PCIUnregisterFunc *exit; uint16_t vendor_id; uint16_t device_id; uint8_t revision; uint16_t class_id; int is_express; } PCIDeviceClass; #define TYPE_PCI_DEVICE "pci-device" #define PCI_DEVICE(obj) \ OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE) #define PCI_DEVICE_CLASS(klass) \ OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE) int pci_dma_read(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len); int pci_dma_write(PCIDevice *dev, dma_addr_t addr, const void *buf, dma_addr_t len); void pci_set_irq(PCIDevice *pci_dev, int level); void pci_irq_assert(PCIDevice *pci_dev); void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev, int alloc_hint); AddressSpace *pci_get_address_space(PCIDevice *dev); void pci_register_bar(PCIDevice *pci_dev, int region_num, uint8_t attr, MemoryRegion *memory); bool pci_bus_is_express(PCIBus *bus); int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset); /********************* ** hw/pci/msi(x).h ** *********************/ int msi_init(struct PCIDevice *dev, uint8_t offset, unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask); int msix_init(PCIDevice *dev, unsigned short nentries, MemoryRegion *table_bar, uint8_t table_bar_nr, unsigned table_offset, MemoryRegion *pba_bar, uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos); bool msi_enabled(const PCIDevice *dev); int msix_enabled(PCIDevice *dev); int msix_vector_use(PCIDevice *dev, unsigned vector); void msix_vector_unuse(PCIDevice *dev, unsigned vector); void msi_notify(PCIDevice *dev, unsigned int vector); void msix_notify(PCIDevice *dev, unsigned vector); /************************* ** migration/vmstate.h ** *************************/ #define VMSTATE_BOOL(...) {} #define VMSTATE_UINT8(...) {} #define VMSTATE_UINT32(...) {} #define VMSTATE_UINT32_TEST(...) {} #define VMSTATE_UINT64(...) {} #define VMSTATE_INT32(...) {} #define VMSTATE_INT64(...) {} #define VMSTATE_STRUCT_ARRAY_TEST(...) {} #define VMSTATE_UINT8_ARRAY(...) {} #define VMSTATE_STRUCT_VARRAY_UINT32(...) {} #define VMSTATE_PCIE_DEVICE(...) {} #define VMSTATE_MSIX(...) {} #define VMSTATE_TIMER_PTR(...) {} #define VMSTATE_STRUCT(...) {} #define VMSTATE_END_OF_LIST() {} typedef struct VMStateField { unsigned dummy; } VMStateField; typedef struct VMStateDescription { char const *name; int version_id; int minimum_version_id; int (*post_load)(void *opaque, int version_id); VMStateField *fields; } VMStateDescription; /************** ** assert.h ** **************/ #define assert(cond) do { \ if (!(cond)) { \ q_printf("assertion faied: %s:%d\n", __FILE__, __LINE__); \ int *d = (int *)0x0; \ *d = 1; \ }} while (0) /************ ** traces ** ************/ #define trace_usb_xhci_irq_msix_use(v) #define trace_usb_xhci_irq_msix_unuse(v) #define trace_usb_xhci_irq_msix(v) #define trace_usb_xhci_irq_msi(v) #define trace_usb_xhci_queue_event(...) #define trace_usb_xhci_fetch_trb(...) #define trace_usb_xhci_run(...) #define trace_usb_xhci_stop(...) #define trace_usb_xhci_ep_state(...) #define trace_usb_xhci_ep_enable(...) #define trace_usb_xhci_ep_disable(...) #define trace_usb_xhci_ep_stop(...) #define trace_usb_xhci_ep_reset(...) #define trace_usb_xhci_ep_set_dequeue(...) #define trace_usb_xhci_xfer_async(...) #define trace_usb_xhci_xfer_nak(...) #define trace_usb_xhci_xfer_success(...) #define trace_usb_xhci_xfer_error(...) #define trace_usb_xhci_xfer_start(...) #define trace_usb_xhci_unimplemented(...) #define trace_usb_xhci_ep_kick(...) #define trace_usb_xhci_xfer_retry(...) #define trace_usb_xhci_slot_enable(...) #define trace_usb_xhci_slot_disable(...) #define trace_usb_xhci_slot_address(...) #define trace_usb_xhci_slot_configure(...) #define trace_usb_xhci_irq_intx(...) #define trace_usb_xhci_slot_reset(...) #define trace_usb_xhci_slot_evaluate(...) #define trace_usb_xhci_port_notify(...) #define trace_usb_xhci_port_link(...) #define trace_usb_xhci_port_reset(...) #define trace_usb_xhci_reset(...) #define trace_usb_xhci_cap_read(...) #define trace_usb_xhci_port_read(...) #define trace_usb_xhci_port_write(...) #define trace_usb_xhci_oper_read(...) #define trace_usb_xhci_oper_write(...) #define trace_usb_xhci_runtime_read(...) #define trace_usb_xhci_runtime_write(...) #define trace_usb_xhci_doorbell_read(...) #define trace_usb_xhci_doorbell_write(...) #define trace_usb_xhci_exit(...) #define trace_usb_port_claim(...) #define trace_usb_port_release(...) #define trace_usb_port_attach(...) #define trace_usb_port_detach(...) #define trace_usb_packet_state_fault(...) #define trace_usb_packet_state_change(...) /*********************** ** library interface ** ***********************/ #define type_init(func) void _type_init_##func(void) { func(); } #define TYPE_USB_HOST_DEVICE "usb-host" typedef struct USBHostDevice { void *data; } USBHostDevice; USBHostDevice *create_usbdevice(void *data); void remove_usbdevice(USBHostDevice *device); void usb_host_destroy(); void usb_host_update_devices(); /*********************** ** monitor/monitor.h ** ***********************/ void monitor_printf(Monitor *mon, const char *fmt, ...); #endif /* _INCLUDE__QEMU_EMUL_H_ */