aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/arm/cpu64.c17
-rw-r--r--target/arm/kvm.c5
-rw-r--r--target/arm/kvm64.c20
-rw-r--r--target/arm/kvm_arm.h27
-rw-r--r--tests/arm-cpu-features.c4
5 files changed, 69 insertions, 4 deletions
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 34b0ba2cf6..a771a28daa 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -493,6 +493,11 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
return;
}
+ if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
+ error_setg(errp, "'sve' feature not supported by KVM on this host");
+ return;
+ }
+
t = cpu->isar.id_aa64pfr0;
t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
cpu->isar.id_aa64pfr0 = t;
@@ -507,11 +512,16 @@ static void aarch64_max_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
uint32_t vq;
+ uint64_t t;
if (kvm_enabled()) {
kvm_arm_set_cpu_features_from_host(cpu);
+ if (kvm_arm_sve_supported(CPU(cpu))) {
+ t = cpu->isar.id_aa64pfr0;
+ t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
+ cpu->isar.id_aa64pfr0 = t;
+ }
} else {
- uint64_t t;
uint32_t u;
aarch64_a57_initfn(obj);
@@ -612,8 +622,6 @@ static void aarch64_max_initfn(Object *obj)
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
- object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
- cpu_arm_set_sve, NULL, NULL, &error_fatal);
for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
char name[8];
@@ -622,6 +630,9 @@ static void aarch64_max_initfn(Object *obj)
cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
}
}
+
+ object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
+ cpu_arm_set_sve, NULL, NULL, &error_fatal);
}
struct ARMCPUInfo {
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index b473c63edb..f07332bbda 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -51,6 +51,11 @@ int kvm_arm_vcpu_init(CPUState *cs)
return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
}
+int kvm_arm_vcpu_finalize(CPUState *cs, int feature)
+{
+ return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_FINALIZE, &feature);
+}
+
void kvm_arm_init_serror_injection(CPUState *cs)
{
cap_has_inject_serror_esr = kvm_check_extension(cs->kvm_state,
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 4c0b11d105..850da1b5e6 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -602,6 +602,13 @@ bool kvm_arm_aarch32_supported(CPUState *cpu)
return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT);
}
+bool kvm_arm_sve_supported(CPUState *cpu)
+{
+ KVMState *s = KVM_STATE(current_machine->accelerator);
+
+ return kvm_check_extension(s, KVM_CAP_ARM_SVE);
+}
+
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
int kvm_arch_init_vcpu(CPUState *cs)
@@ -630,13 +637,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT;
}
if (!kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
- cpu->has_pmu = false;
+ cpu->has_pmu = false;
}
if (cpu->has_pmu) {
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PMU_V3;
} else {
unset_feature(&env->features, ARM_FEATURE_PMU);
}
+ if (cpu_isar_feature(aa64_sve, cpu)) {
+ assert(kvm_arm_sve_supported(cs));
+ cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE;
+ }
/* Do KVM_ARM_VCPU_INIT ioctl */
ret = kvm_arm_vcpu_init(cs);
@@ -644,6 +655,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
+ if (cpu_isar_feature(aa64_sve, cpu)) {
+ ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_SVE);
+ if (ret) {
+ return ret;
+ }
+ }
+
/*
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
* Currently KVM has its own idea about MPIDR assignment, so we
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index b4e19457a0..7c12f1501a 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -28,6 +28,20 @@
int kvm_arm_vcpu_init(CPUState *cs);
/**
+ * kvm_arm_vcpu_finalize
+ * @cs: CPUState
+ * @feature: int
+ *
+ * Finalizes the configuration of the specified VCPU feature by
+ * invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
+ * this are documented in the "KVM_ARM_VCPU_FINALIZE" section of
+ * KVM's API documentation.
+ *
+ * Returns: 0 if success else < 0 error code
+ */
+int kvm_arm_vcpu_finalize(CPUState *cs, int feature);
+
+/**
* kvm_arm_register_device:
* @mr: memory region for this device
* @devid: the KVM device ID
@@ -226,6 +240,14 @@ bool kvm_arm_aarch32_supported(CPUState *cs);
bool kvm_arm_pmu_supported(CPUState *cs);
/**
+ * bool kvm_arm_sve_supported:
+ * @cs: CPUState
+ *
+ * Returns true if the KVM VCPU can enable SVE and false otherwise.
+ */
+bool kvm_arm_sve_supported(CPUState *cs);
+
+/**
* kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
* IPA address space supported by KVM
*
@@ -276,6 +298,11 @@ static inline bool kvm_arm_pmu_supported(CPUState *cs)
return false;
}
+static inline bool kvm_arm_sve_supported(CPUState *cs)
+{
+ return false;
+}
+
static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
{
return -ENOENT;
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
index 5eecd38f6c..3efc168d62 100644
--- a/tests/arm-cpu-features.c
+++ b/tests/arm-cpu-features.c
@@ -391,12 +391,16 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
assert_has_feature(qts, "host", "aarch64");
assert_has_feature(qts, "host", "pmu");
+ assert_has_feature(qts, "max", "sve");
+
assert_error(qts, "cortex-a15",
"We cannot guarantee the CPU type 'cortex-a15' works "
"with KVM on this host", NULL);
} else {
assert_has_not_feature(qts, "host", "aarch64");
assert_has_not_feature(qts, "host", "pmu");
+
+ assert_has_not_feature(qts, "max", "sve");
}
qtest_quit(qts);