/* * VFIO Device interface * * Copyright Red Hat, Inc. 2012 * * Authors: * Alex Williamson * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. * * Based on qemu-kvm device-assignment: * Adapted for KVM by Qumranet. * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) */ #ifndef HW_VFIO_VFIO_COMMON_H #define HW_VFIO_VFIO_COMMON_H #include "system/memory.h" #include "qemu/queue.h" #ifdef CONFIG_LINUX #include #endif #include "system/system.h" #include "hw/vfio/vfio-container-base.h" #include "system/host_iommu_device.h" #include "system/iommufd.h" #define VFIO_MSG_PREFIX "vfio %s: " enum { VFIO_DEVICE_TYPE_PCI = 0, VFIO_DEVICE_TYPE_PLATFORM = 1, VFIO_DEVICE_TYPE_CCW = 2, VFIO_DEVICE_TYPE_AP = 3, }; typedef struct VFIODeviceOps VFIODeviceOps; typedef struct VFIODeviceIOOps VFIODeviceIOOps; typedef struct VFIOMigration VFIOMigration; typedef struct IOMMUFDBackend IOMMUFDBackend; typedef struct VFIOIOASHwpt VFIOIOASHwpt; typedef struct VFIODevice { QLIST_ENTRY(VFIODevice) next; QLIST_ENTRY(VFIODevice) container_next; QLIST_ENTRY(VFIODevice) global_next; struct VFIOGroup *group; VFIOContainerBase *bcontainer; char *sysfsdev; char *name; DeviceState *dev; int fd; int type; bool mdev; bool reset_works; bool needs_reset; bool no_mmap; bool ram_block_discard_allowed; OnOffAuto enable_migration; OnOffAuto migration_multifd_transfer; bool migration_events; VFIODeviceOps *ops; VFIODeviceIOOps *io_ops; unsigned int num_irqs; unsigned int num_regions; unsigned int flags; VFIOMigration *migration; Error *migration_blocker; OnOffAuto pre_copy_dirty_page_tracking; OnOffAuto device_dirty_page_tracking; bool dirty_pages_supported; bool dirty_tracking; /* Protected by BQL */ bool iommu_dirty_tracking; HostIOMMUDevice *hiod; int devid; IOMMUFDBackend *iommufd; VFIOIOASHwpt *hwpt; QLIST_ENTRY(VFIODevice) hwpt_next; struct vfio_region_info **reginfo; } VFIODevice; struct VFIODeviceOps { void (*vfio_compute_needs_reset)(VFIODevice *vdev); int (*vfio_hot_reset_multi)(VFIODevice *vdev); void (*vfio_eoi)(VFIODevice *vdev); Object *(*vfio_get_object)(VFIODevice *vdev); /** * @vfio_save_config * * Save device config state * * @vdev: #VFIODevice for which to save the config * @f: #QEMUFile where to send the data * @errp: pointer to Error*, to store an error if it happens. * * Returns zero to indicate success and negative for error */ int (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f, Error **errp); /** * @vfio_load_config * * Load device config state * * @vdev: #VFIODevice for which to load the config * @f: #QEMUFile where to get the data * * Returns zero to indicate success and negative for error */ int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); }; /* * Given a return value of either a short number of bytes read or -errno, * construct a meaningful error message. */ #define strreaderror(ret) \ (ret < 0 ? strerror(-ret) : "short read") /* * Given a return value of either a short number of bytes written or -errno, * construct a meaningful error message. */ #define strwriteerror(ret) \ (ret < 0 ? strerror(-ret) : "short write") void vfio_device_irq_disable(VFIODevice *vbasedev, int index); void vfio_device_irq_unmask(VFIODevice *vbasedev, int index); void vfio_device_irq_mask(VFIODevice *vbasedev, int index); bool vfio_device_irq_set_signaling(VFIODevice *vbasedev, int index, int subindex, int action, int fd, Error **errp); void vfio_device_reset_handler(void *opaque); bool vfio_device_is_mdev(VFIODevice *vbasedev); bool vfio_device_hiod_create_and_realize(VFIODevice *vbasedev, const char *typename, Error **errp); bool vfio_device_attach(char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp); bool vfio_device_attach_by_iommu_type(const char *iommu_type, char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp); void vfio_device_detach(VFIODevice *vbasedev); VFIODevice *vfio_get_vfio_device(Object *obj); typedef QLIST_HEAD(VFIODeviceList, VFIODevice) VFIODeviceList; extern VFIODeviceList vfio_device_list; #ifdef CONFIG_LINUX /* * How devices communicate with the server. The default option is through * ioctl() to the kernel VFIO driver, but vfio-user can use a socket to a remote * process. */ struct VFIODeviceIOOps { /** * @device_feature * * Fill in feature info for the given device. */ int (*device_feature)(VFIODevice *vdev, struct vfio_device_feature *); /** * @get_region_info * * Fill in @info with information on the region given by @info->index. */ int (*get_region_info)(VFIODevice *vdev, struct vfio_region_info *info); /** * @get_irq_info * * Fill in @irq with information on the IRQ given by @info->index. */ int (*get_irq_info)(VFIODevice *vdev, struct vfio_irq_info *irq); /** * @set_irqs * * Configure IRQs as defined by @irqs. */ int (*set_irqs)(VFIODevice *vdev, struct vfio_irq_set *irqs); /** * @region_read * * Read @size bytes from the region @nr at offset @off into the buffer * @data. */ int (*region_read)(VFIODevice *vdev, uint8_t nr, off_t off, uint32_t size, void *data); /** * @region_write * * Write @size bytes to the region @nr at offset @off from the buffer * @data. */ int (*region_write)(VFIODevice *vdev, uint8_t nr, off_t off, uint32_t size, void *data); }; void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainerBase *bcontainer, struct vfio_device_info *info); void vfio_device_unprepare(VFIODevice *vbasedev); int vfio_device_get_region_info(VFIODevice *vbasedev, int index, struct vfio_region_info **info); int vfio_device_get_region_info_type(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info); bool vfio_device_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); int vfio_device_get_irq_info(VFIODevice *vbasedev, int index, struct vfio_irq_info *info); #endif /* Returns 0 on success, or a negative errno. */ bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp); void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp); void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, DeviceState *dev, bool ram_discard); int vfio_device_get_aw_bits(VFIODevice *vdev); #endif /* HW_VFIO_VFIO_COMMON_H */