aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>2018-06-18 19:42:06 +0100
committerWill Deacon <will.deacon@arm.com>2018-06-19 12:26:40 +0100
commit6078a4548cfdca42c766c67947986c90310a8546 (patch)
tree6b0fca0e59226fd272e5db5df98e2056a9fbbdd2 /include
parentac70b5aae6f514465bca744496ce7fb7859c6378 (diff)
downloadkvmtool-6078a4548cfdca42c766c67947986c90310a8546.tar.gz
Add PCI device passthrough using VFIO
Assigning devices using VFIO allows the guest to have direct access to the device, whilst filtering accesses to sensitive areas by trapping config space accesses and mapping DMA with an IOMMU. This patch adds a new option to lkvm run: --vfio-pci=<BDF>. Before assigning a device to a VM, some preparation is required. As described in Linux Documentation/vfio.txt, the device driver needs to be changed to vfio-pci: $ dev=0000:00:00.0 $ echo $dev > /sys/bus/pci/devices/$dev/driver/unbind $ echo vfio-pci > /sys/bus/pci/devices/$dev/driver_override $ echo $dev > /sys/bus/pci/drivers_probe Adding --vfio-pci=$dev to lkvm-run will pass the device to the guest. Multiple devices can be passed to the guest by adding more --vfio-pci parameters. This patch only implements PCI with INTx. MSI-X routing will be added in a subsequent patch, and at some point we might add support for passing platform devices to guests. Reviewed-by: Punit Agrawal <punit.agrawal@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'include')
-rw-r--r--include/kvm/kvm-config.h3
-rw-r--r--include/kvm/pci.h3
-rw-r--r--include/kvm/vfio.h71
3 files changed, 76 insertions, 1 deletions
diff --git a/include/kvm/kvm-config.h b/include/kvm/kvm-config.h
index 386fa8c5..a052b0bc 100644
--- a/include/kvm/kvm-config.h
+++ b/include/kvm/kvm-config.h
@@ -2,6 +2,7 @@
#define KVM_CONFIG_H_
#include "kvm/disk-image.h"
+#include "kvm/vfio.h"
#include "kvm/kvm-config-arch.h"
#define DEFAULT_KVM_DEV "/dev/kvm"
@@ -20,9 +21,11 @@
struct kvm_config {
struct kvm_config_arch arch;
struct disk_image_params disk_image[MAX_DISK_IMAGES];
+ struct vfio_device_params *vfio_devices;
u64 ram_size;
u8 image_count;
u8 num_net_devices;
+ u8 num_vfio_devices;
bool virtio_rng;
int active_console;
int debug_iodelay;
diff --git a/include/kvm/pci.h b/include/kvm/pci.h
index 01c244bc..274b77ea 100644
--- a/include/kvm/pci.h
+++ b/include/kvm/pci.h
@@ -7,7 +7,6 @@
#include <endian.h>
#include "kvm/devices.h"
-#include "kvm/kvm.h"
#include "kvm/msi.h"
#include "kvm/fdt.h"
@@ -22,6 +21,8 @@
#define PCI_IO_SIZE 0x100
#define PCI_CFG_SIZE (1ULL << 24)
+struct kvm;
+
union pci_config_address {
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
diff --git a/include/kvm/vfio.h b/include/kvm/vfio.h
new file mode 100644
index 00000000..c434703a
--- /dev/null
+++ b/include/kvm/vfio.h
@@ -0,0 +1,71 @@
+#ifndef KVM__VFIO_H
+#define KVM__VFIO_H
+
+#include "kvm/parse-options.h"
+#include "kvm/pci.h"
+
+#include <linux/vfio.h>
+
+#define vfio_dev_err(vdev, fmt, ...) \
+ pr_err("%s: " fmt, (vdev)->params->name, ##__VA_ARGS__)
+#define vfio_dev_warn(vdev, fmt, ...) \
+ pr_warning("%s: " fmt, (vdev)->params->name, ##__VA_ARGS__)
+#define vfio_dev_info(vdev, fmt, ...) \
+ pr_info("%s: " fmt, (vdev)->params->name, ##__VA_ARGS__)
+#define vfio_dev_dbg(vdev, fmt, ...) \
+ pr_debug("%s: " fmt, (vdev)->params->name, ##__VA_ARGS__)
+#define vfio_dev_die(vdev, fmt, ...) \
+ die("%s: " fmt, (vdev)->params->name, ##__VA_ARGS__)
+
+/* Currently limited by num_vfio_devices */
+#define MAX_VFIO_DEVICES 256
+
+enum vfio_device_type {
+ VFIO_DEVICE_PCI,
+};
+
+struct vfio_pci_device {
+ struct pci_device_header hdr;
+};
+
+struct vfio_region {
+ struct vfio_region_info info;
+ u64 guest_phys_addr;
+ void *host_addr;
+};
+
+struct vfio_device {
+ struct device_header dev_hdr;
+ struct vfio_device_params *params;
+ struct vfio_group *group;
+
+ int fd;
+ struct vfio_device_info info;
+ struct vfio_region *regions;
+
+ char *sysfs_path;
+
+ struct vfio_pci_device pci;
+};
+
+struct vfio_device_params {
+ char *name;
+ const char *bus;
+ enum vfio_device_type type;
+};
+
+struct vfio_group {
+ unsigned long id; /* iommu_group number in sysfs */
+ int fd;
+ int refs;
+ struct list_head list;
+};
+
+int vfio_device_parser(const struct option *opt, const char *arg, int unset);
+int vfio_map_region(struct kvm *kvm, struct vfio_device *vdev,
+ struct vfio_region *region);
+void vfio_unmap_region(struct kvm *kvm, struct vfio_region *region);
+int vfio_pci_setup_device(struct kvm *kvm, struct vfio_device *device);
+void vfio_pci_teardown_device(struct kvm *kvm, struct vfio_device *vdev);
+
+#endif /* KVM__VFIO_H */