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
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html