[PATCH 1/7] KVM ARM: Use KVM_ARM_VCPU_INIT to set target model and features.

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

 



This uses a fixed feature bitmap for simplicity: 224 features should
be enough for anyone!

QEMU now needs to explicitly state what CPU a guest vcpu has, and what
optional features (currently, none are defined, but this could be used
to suppress VFP, debug, etc).

Once we know the target (which currently must be 0xCOF), we do the
vcpu reset; trying to run without that will -ENOEXEC.

Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>

diff --git a/arch/arm/include/asm/kvm.h b/arch/arm/include/asm/kvm.h
index 54f301d..6513059 100644
--- a/arch/arm/include/asm/kvm.h
+++ b/arch/arm/include/asm/kvm.h
@@ -68,6 +68,14 @@ struct kvm_regs {
 
 };
 
+/* Supported Processor Types */
+#define KVM_ARM_TARGET_CORTEX_A15	(0xC0F)
+
+struct kvm_vcpu_init {
+	__u32 target;
+	__u32 features[7];
+};
+
 struct kvm_sregs {
 };
 
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 6efd2b7..ddcf8e8 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -22,7 +22,6 @@
 #include <asm/types.h>
 
 /* Supported Processor Types */
-#define CORTEX_A15	(0xC0F)
 #define CORTEX_AEM	(0xC08) /* Hack */
 
 /* Multiprocessor Affinity Register */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 055ca79..9f9ec36 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -26,6 +26,8 @@
 #define KVM_PRIVATE_MEM_SLOTS 4
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 
+#define NUM_FEATURES 0
+
 /* We don't currently support large pages. */
 #define KVM_HPAGE_GFN_SHIFT(x)	0
 #define KVM_NR_PAGE_SIZES	1
@@ -102,6 +104,9 @@ enum cp15_regs {
 struct kvm_vcpu_arch {
 	struct kvm_vcpu_regs regs;
 
+	u32 target; /* Currently KVM_ARM_TARGET_CORTEX_A15 */
+	DECLARE_BITMAP(features, NUM_FEATURES);
+
 	/* System control coprocessor (cp15) */
 	u32 cp15[nr_cp15_regs];
 
@@ -157,4 +162,7 @@ static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
 	return 0;
 }
 
+struct kvm_vcpu_init;
+int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
+			const struct kvm_vcpu_init *init);
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 8b81829..d2c83a6 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -255,10 +255,10 @@ int __attribute_const__ kvm_target_cpu(void)
 
 	midr = read_cpuid_id();
 	switch ((midr >> 4) & 0xfff) {
-	case CORTEX_A15:
-		return CORTEX_A15;
+	case KVM_ARM_TARGET_CORTEX_A15:
+		return KVM_ARM_TARGET_CORTEX_A15;
 	case CORTEX_AEM: /* HACK Alert!!! */
-		return CORTEX_A15;
+		return KVM_ARM_TARGET_CORTEX_A15;
 	default:
 		return -EINVAL;
 	}
@@ -266,12 +266,6 @@ int __attribute_const__ kvm_target_cpu(void)
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
-	int ret;
-
-	ret = kvm_reset_vcpu(vcpu);
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
@@ -517,6 +511,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	int ret;
 	sigset_t sigsaved;
 
+	/* Make sure they initialize the vcpu with KVM_ARM_VCPU_INIT */
+	if (unlikely(!vcpu->arch.target))
+		return -ENOEXEC;
+
 	if (run->exit_reason == KVM_EXIT_MMIO) {
 		ret = kvm_handle_mmio_return(vcpu, vcpu->run);
 		if (ret)
@@ -637,7 +635,22 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level)
 long kvm_arch_vcpu_ioctl(struct file *filp,
 			 unsigned int ioctl, unsigned long arg)
 {
-	return -EINVAL;
+	struct kvm_vcpu *vcpu = filp->private_data;
+	void __user *argp = (void __user *)arg;
+
+	switch (ioctl) {
+	case KVM_ARM_VCPU_INIT: {
+		struct kvm_vcpu_init init;
+
+		if (copy_from_user(&init, argp, sizeof init))
+			return -EFAULT;
+
+		return kvm_vcpu_set_target(vcpu, &init);
+	
+	}
+	default:
+		return -EINVAL;
+	}
 }
 
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 60c5725..61c3eff 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -304,7 +304,7 @@ static const struct coproc_reg cp15_cortex_a15_regs[] = {
 static const struct coproc_reg *get_target_table(unsigned target, size_t *num)
 {
 	switch (target) {
-	case CORTEX_A15:
+	case KVM_ARM_TARGET_CORTEX_A15:
 		*num = ARRAY_SIZE(cp15_cortex_a15_regs);
 		return cp15_cortex_a15_regs;
 	default:
@@ -344,7 +344,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu,
 	size_t num;
 	const struct coproc_reg *table, *r;
 
-	table = get_target_table(kvm_target_cpu(), &num);
+	table = get_target_table(vcpu->arch.target, &num);
 
 	/* Search target-specific then generic table. */
 	r = find_reg(params, table, num);
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 2c5f4b9..5cc273e 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -138,6 +138,31 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	return -EINVAL;
 }
 
+int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
+			const struct kvm_vcpu_init *init)
+{
+	unsigned int i;
+
+	/* We can only do a cortex A15 for now. */
+	if (init->target != kvm_target_cpu())
+		return -EINVAL;
+
+	vcpu->arch.target = init->target;
+	bitmap_zero(vcpu->arch.features, NUM_FEATURES);
+
+	/* -ENOENT for unknown features, -EINVAL for invalid combinations. */
+	for (i = 0; i < sizeof(init->features)*8; i++) {
+		if (init->features[i / 32] & (1 << (i % 32))) {
+			if (i >= NUM_FEATURES)
+				return -ENOENT;
+			set_bit(i, vcpu->arch.features);
+		}
+	}
+
+	/* Now we know what it is, we can reset it. */
+	return kvm_reset_vcpu(vcpu);
+}
+
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
 	return -EINVAL;
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index 78488be..4262d14 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -101,8 +101,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 	u32 (*cp15_reset)[2];
 	void (*cpu_reset_vcpu)(struct kvm_vcpu *vcpu);
 
-	switch (kvm_target_cpu()) {
-	case CORTEX_A15:
+	switch (vcpu->arch.target) {
+	case KVM_ARM_TARGET_CORTEX_A15:
 		if (vcpu->vcpu_id > a15_max_cpu_idx)
 			return -EINVAL;
 		cpu_reset = &a15_regs_reset;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index f978447..c9b2556 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -905,6 +905,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_SET_ONE_REG		  _IOW(KVMIO,  0xac, struct kvm_one_reg)
 /* VM is being stopped by host */
 #define KVM_KVMCLOCK_CTRL	  _IO(KVMIO,   0xad)
+#define KVM_ARM_VCPU_INIT	  _IOW(KVMIO,  0xae, struct kvm_vcpu_init)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
_______________________________________________
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