* 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.