Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 1 | /* |
| 2 | * common header for vfio based device assignment support |
| 3 | * |
| 4 | * Copyright Red Hat, Inc. 2012 |
| 5 | * |
| 6 | * Authors: |
| 7 | * Alex Williamson <alex.williamson@redhat.com> |
| 8 | * |
| 9 | * This work is licensed under the terms of the GNU GPL, version 2. See |
| 10 | * the COPYING file in the top-level directory. |
| 11 | * |
| 12 | * Based on qemu-kvm device-assignment: |
| 13 | * Adapted for KVM by Qumranet. |
| 14 | * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) |
| 15 | * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) |
| 16 | * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) |
| 17 | * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) |
| 18 | * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) |
| 19 | */ |
| 20 | #ifndef HW_VFIO_VFIO_COMMON_H |
| 21 | #define HW_VFIO_VFIO_COMMON_H |
| 22 | |
| 23 | #include "qemu-common.h" |
| 24 | #include "exec/address-spaces.h" |
| 25 | #include "exec/memory.h" |
| 26 | #include "qemu/queue.h" |
| 27 | #include "qemu/notify.h" |
| 28 | |
| 29 | /*#define DEBUG_VFIO*/ |
| 30 | #ifdef DEBUG_VFIO |
| 31 | #define DPRINTF(fmt, ...) \ |
| 32 | do { fprintf(stderr, "vfio: " fmt, ## __VA_ARGS__); } while (0) |
| 33 | #else |
| 34 | #define DPRINTF(fmt, ...) \ |
| 35 | do { } while (0) |
| 36 | #endif |
| 37 | |
| 38 | /* Extra debugging, trap acceleration paths for more logging */ |
Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 39 | #define VFIO_ALLOW_KVM_INTX 1 |
| 40 | #define VFIO_ALLOW_KVM_MSI 1 |
| 41 | #define VFIO_ALLOW_KVM_MSIX 1 |
| 42 | |
| 43 | enum { |
| 44 | VFIO_DEVICE_TYPE_PCI = 0, |
Eric Auger | 0ea2730 | 2015-06-08 09:25:25 -0600 | [diff] [blame] | 45 | VFIO_DEVICE_TYPE_PLATFORM = 1, |
Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 46 | }; |
| 47 | |
| 48 | typedef struct VFIORegion { |
| 49 | struct VFIODevice *vbasedev; |
| 50 | off_t fd_offset; /* offset of region within device fd */ |
| 51 | MemoryRegion mem; /* slow, read/write access */ |
| 52 | MemoryRegion mmap_mem; /* direct mapped access */ |
| 53 | void *mmap; |
| 54 | size_t size; |
| 55 | uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ |
| 56 | uint8_t nr; /* cache the region number for debug */ |
| 57 | } VFIORegion; |
| 58 | |
| 59 | typedef struct VFIOAddressSpace { |
| 60 | AddressSpace *as; |
| 61 | QLIST_HEAD(, VFIOContainer) containers; |
| 62 | QLIST_ENTRY(VFIOAddressSpace) list; |
| 63 | } VFIOAddressSpace; |
| 64 | |
| 65 | struct VFIOGroup; |
| 66 | |
| 67 | typedef struct VFIOType1 { |
| 68 | MemoryListener listener; |
| 69 | int error; |
| 70 | bool initialized; |
| 71 | } VFIOType1; |
| 72 | |
| 73 | typedef struct VFIOContainer { |
| 74 | VFIOAddressSpace *space; |
| 75 | int fd; /* /dev/vfio/vfio, empowered by the attached groups */ |
| 76 | struct { |
| 77 | /* enable abstraction to support various iommu backends */ |
| 78 | union { |
| 79 | VFIOType1 type1; |
| 80 | }; |
| 81 | void (*release)(struct VFIOContainer *); |
| 82 | } iommu_data; |
| 83 | QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; |
| 84 | QLIST_HEAD(, VFIOGroup) group_list; |
| 85 | QLIST_ENTRY(VFIOContainer) next; |
| 86 | } VFIOContainer; |
| 87 | |
| 88 | typedef struct VFIOGuestIOMMU { |
| 89 | VFIOContainer *container; |
| 90 | MemoryRegion *iommu; |
| 91 | Notifier n; |
| 92 | QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; |
| 93 | } VFIOGuestIOMMU; |
| 94 | |
| 95 | typedef struct VFIODeviceOps VFIODeviceOps; |
| 96 | |
| 97 | typedef struct VFIODevice { |
| 98 | QLIST_ENTRY(VFIODevice) next; |
| 99 | struct VFIOGroup *group; |
| 100 | char *name; |
| 101 | int fd; |
| 102 | int type; |
| 103 | bool reset_works; |
| 104 | bool needs_reset; |
Samuel Pitoiset | 6ee47c9 | 2015-03-02 11:38:55 -0700 | [diff] [blame] | 105 | bool allow_mmap; |
Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 106 | VFIODeviceOps *ops; |
| 107 | unsigned int num_irqs; |
| 108 | unsigned int num_regions; |
| 109 | unsigned int flags; |
| 110 | } VFIODevice; |
| 111 | |
| 112 | struct VFIODeviceOps { |
| 113 | void (*vfio_compute_needs_reset)(VFIODevice *vdev); |
| 114 | int (*vfio_hot_reset_multi)(VFIODevice *vdev); |
| 115 | void (*vfio_eoi)(VFIODevice *vdev); |
Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 116 | }; |
| 117 | |
| 118 | typedef struct VFIOGroup { |
| 119 | int fd; |
| 120 | int groupid; |
| 121 | VFIOContainer *container; |
| 122 | QLIST_HEAD(, VFIODevice) device_list; |
| 123 | QLIST_ENTRY(VFIOGroup) next; |
| 124 | QLIST_ENTRY(VFIOGroup) container_next; |
| 125 | } VFIOGroup; |
| 126 | |
| 127 | void vfio_put_base_device(VFIODevice *vbasedev); |
| 128 | void vfio_disable_irqindex(VFIODevice *vbasedev, int index); |
| 129 | void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); |
| 130 | void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); |
| 131 | void vfio_region_write(void *opaque, hwaddr addr, |
| 132 | uint64_t data, unsigned size); |
| 133 | uint64_t vfio_region_read(void *opaque, |
| 134 | hwaddr addr, unsigned size); |
Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 135 | int vfio_mmap_region(Object *vdev, VFIORegion *region, |
| 136 | MemoryRegion *mem, MemoryRegion *submem, |
| 137 | void **map, size_t size, off_t offset, |
| 138 | const char *name); |
| 139 | void vfio_reset_handler(void *opaque); |
| 140 | VFIOGroup *vfio_get_group(int groupid, AddressSpace *as); |
| 141 | void vfio_put_group(VFIOGroup *group); |
| 142 | int vfio_get_device(VFIOGroup *group, const char *name, |
| 143 | VFIODevice *vbasedev); |
| 144 | |
| 145 | extern const MemoryRegionOps vfio_region_ops; |
Eric Auger | e2c7d02 | 2014-12-22 09:54:51 -0700 | [diff] [blame] | 146 | extern QLIST_HEAD(vfio_group_head, VFIOGroup) vfio_group_list; |
| 147 | extern QLIST_HEAD(vfio_as_head, VFIOAddressSpace) vfio_address_spaces; |
| 148 | |
| 149 | #endif /* !HW_VFIO_VFIO_COMMON_H */ |