Dev Passthrough QEMU patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




This patch is for testing only and goes along with other
two patches for priodrop and dev passthrough, it should apply against
1.4.5. 

diff --git a/cpus.c b/cpus.c
index c15ff6c..0c19214 100644
--- a/cpus.c
+++ b/cpus.c
@@ -737,6 +737,26 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     CPUState *cpu = ENV_GET_CPU(env);
     int r;
 
+    /* For now just do a 1:1 vCPU binding as they come online for device
+     * pass through
+     */
+    cpu_set_t cpuset;
+    int ret, i;
+    unsigned long cpu_index = kvm_arch_vcpu_id(cpu);
+
+    CPU_ZERO(&cpuset);
+    CPU_SET(cpu_index, &cpuset);
+    ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+    if(ret != 0) {
+    	printf("pthread_setaffinity_np failed to setaffinity to CPU 0\n");
+        exit(-1);
+    }
+    
+    CPU_ZERO(&cpuset);
+    pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+    if(CPU_ISSET(cpu_index,&cpuset))
+        printf("Binding: vCPU %ld --> CPU %d\n", cpu_index, i);
+
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_get_self(cpu->thread);
     cpu->thread_id = qemu_get_thread_id();
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index caca979..46c2c59 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -904,6 +904,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 /* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
 #define KVM_ARM_SET_DEVICE_ADDR	  _IOW(KVMIO,  0xab, struct kvm_arm_device_addr)
+#define KVM_ARM_GET_DEVICE_RESOURCES _IOW(KVMIO,  0xe1, struct kvm_arm_get_device_resources)
+#define KVM_ARM_ASSIGN_DEVICE	  _IOW(KVMIO,  0xe2, struct kvm_arm_assigned_device)
 
 /*
  * ioctls for vcpu fds
@@ -1013,6 +1015,7 @@ struct kvm_assigned_irq {
 	};
 };
 
+
 struct kvm_assigned_msix_nr {
 	__u32 assigned_dev_id;
 	__u16 entry_nr;
@@ -1027,4 +1030,33 @@ struct kvm_assigned_msix_entry {
 	__u16 padding[3];
 };
 
+
+/* MAX 6 MMIO resources per device */
+#define MAX_RES_PER_DEVICE      6
+struct kvm_arm_get_device_resources {
+        char    devname[128];
+        __u32   resource_cnt;
+        struct {
+                __u64   hpa;
+                __u32   size;
+                __u32   attr;
+		char    host_name[64];
+        } host_resources[MAX_RES_PER_DEVICE];
+	struct {
+		__u32	hwirq;
+		__u32	attr;	
+		char    host_name[64];
+	} hostirq;
+};
+
+struct kvm_guest_device_resources {
+        __u64   gpa[MAX_RES_PER_DEVICE];
+        __u32   girq;
+};
+
+struct kvm_arm_assigned_device {
+        struct  kvm_arm_get_device_resources dev_res;
+        struct  kvm_guest_device_resources guest_res;
+};
+
 #endif /* __LINUX_KVM_H */
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index d89b57c..9aee84e 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,5 +1,5 @@
 obj-y += arm-semi.o
 obj-$(CONFIG_SOFTMMU) += machine.o
-obj-$(CONFIG_KVM) += kvm.o
+obj-$(CONFIG_KVM) += kvm.o device-assign.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
diff --git a/target-arm/device-assign.c b/target-arm/device-assign.c
new file mode 100644
index 0000000..e4d0e97
--- /dev/null
+++ b/target-arm/device-assign.c
@@ -0,0 +1,118 @@
+
+#include "hw/sysbus.h"
+#include "qemu-common.h"
+#include "hw/qdev.h"
+#include "hw/ptimer.h"
+#include "kvm_arm.h"
+#include "qemu/error-report.h"
+
+#define IORESOURCE_TYPE_BITS    0x00001f00      /* Resource type */
+#define IORESOURCE_IO           0x00000100      /* PCI/ISA I/O ports */
+#define IORESOURCE_MEM          0x00000200
+#define IORESOURCE_REG          0x00000300      /* Register offsets */
+#define IORESOURCE_IRQ          0x00000400
+#define IORESOURCE_DMA          0x00000800
+
+#define IORESOURCE_PREFETCH     0x00002000      /* No side effects */
+#define IORESOURCE_READONLY     0x00004000
+#define IORESOURCE_CACHEABLE    0x00008000
+
+typedef struct {
+    SysBusDevice busdev;
+    char	*devname;
+    uint64_t 	hpa, gpa;
+    uint32_t	dev_size;
+    uint32_t	hirq,girq;
+} AssignedDevice;
+
+static Property device_assign_properties[] = {
+    DEFINE_PROP_STRING("host", AssignedDevice, devname),
+    DEFINE_PROP_UINT64("hpa", AssignedDevice, hpa, 0),
+    DEFINE_PROP_UINT64("gpa", AssignedDevice, gpa, 0),
+    DEFINE_PROP_UINT32("size", AssignedDevice, dev_size, 0),
+    DEFINE_PROP_UINT32("hostirq", AssignedDevice, hirq, 0),
+    DEFINE_PROP_UINT32("guestirq", AssignedDevice, girq, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int assign_device(AssignedDevice *dev)
+{
+    int ret,i;
+    struct kvm_arm_get_device_resources dev_res;
+    struct kvm_arm_assigned_device dev_assigned;
+    char *p, c='-';
+
+    memset(&dev_res,0,sizeof(dev_res));
+    memset(&dev_assigned,0,sizeof(dev_assigned));
+
+    if((p = strstr(dev->devname, (char *)&c)) != (char *) NULL)
+	*p = ',';
+    if(dev->devname) 
+	strcpy(dev_res.devname, dev->devname);
+    else
+	goto assign_failed; 
+   
+    ret = kvm_vm_ioctl(kvm_state, KVM_ARM_GET_DEVICE_RESOURCES, &dev_res);
+    if(ret)
+	goto assign_failed;
+
+    dev_assigned.dev_res = dev_res;
+    /* 
+     * Assigning GPA to same value as HPA and Guest IRQ to same value as
+     * Host IRQ. The machine model is the same as host, it can be done.
+     * Proposed Solution is:
+     * -  Get the values from Guest device tree, this would assume the
+     *    passthrough device has been configured for the guest. 
+     */
+
+    for(i=0; i < dev_res.resource_cnt; i++) {
+	dev_assigned.guest_res.gpa[i] = dev_res.host_resources[i].hpa; 
+    } 
+    dev_assigned.guest_res.girq = dev_res.hostirq.hwirq; 
+    ret = kvm_vm_ioctl(kvm_state, KVM_ARM_ASSIGN_DEVICE, &dev_assigned);
+    return ret; 
+assign_failed:
+    return -1;
+}
+
+static int assign_devinit(SysBusDevice *dev)
+{
+    AssignedDevice *d = FROM_SYSBUS(AssignedDevice, dev);
+    int ret;
+
+    if (!kvm_enabled()) {
+	error_report("device-assign: error: requires KVM support");
+    }
+    ret = assign_device(d);
+    if(ret) {
+	error_report("device-assign: error: internal error");
+	exit(-1);
+    }
+    return 0;
+}
+
+static void device_assign_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *k = DEVICE_CLASS(klass);
+    sdc->init = assign_devinit;
+    /* need to add - exit, and reset */
+    k->props = device_assign_properties;
+    k->desc = "KVM-based ARM Device Passthrouhg";
+}
+
+
+
+static const TypeInfo dev_assign_info = {
+    .name		= "kvm-device-assign",
+    .parent		= TYPE_SYS_BUS_DEVICE,
+    .instance_size	= sizeof(AssignedDevice),
+    .class_init		= device_assign_class_init,
+};
+
+static void assign_device_init(void)
+{
+   type_register_static(&dev_assign_info);
+}
+
+type_init(assign_device_init)
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index d8acace..5e9bcd0 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -22,6 +22,7 @@
 #include "kvm_arm.h"
 #include "cpu.h"
 #include "hw/arm/arm.h"
+#include "qemu/error-report.h"
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index b1c54ff..8cb94e3 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -29,4 +29,6 @@
  */
 void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid);
 
+int kvm_device_assign(KVMState *s, char *, ...);
+
 #endif

_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm




[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux