All of lore.kernel.org
 help / color / mirror / Atom feed
* Dev Passthrough QEMU patch
@ 2013-06-11  8:15 Mario Smarduch
  0 siblings, 0 replies; only message in thread
From: Mario Smarduch @ 2013-06-11  8:15 UTC (permalink / raw)
  To: kvmarm@lists.cs.columbia.edu; +Cc: kvm, christoffer.dall, Marc Zyngier



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


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2013-06-11  8:15 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-11  8:15 Dev Passthrough QEMU patch Mario Smarduch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.