summaryrefslogtreecommitdiff
path: root/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/cpu.c13
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/kvm.c36
-rw-r--r--target/arm/kvm32.c8
-rw-r--r--target/arm/kvm64.c8
-rw-r--r--target/arm/kvm_arm.h35
6 files changed, 69 insertions, 36 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3e4e9f1873..5809225a36 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -725,6 +725,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
int pagebits;
Error *local_err = NULL;
+ /* If we needed to query the host kernel for the CPU features
+ * then it's possible that might have failed in the initfn, but
+ * this is the first point where we can report it.
+ */
+ if (cpu->host_cpu_probe_failed) {
+ if (!kvm_enabled()) {
+ error_setg(errp, "The 'host' CPU type can only be used with KVM");
+ } else {
+ error_setg(errp, "Failed to retrieve host CPU features");
+ }
+ return;
+ }
+
cpu_exec_realizefn(cs, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 36711cdb50..1e7e1f8a7e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -745,6 +745,11 @@ struct ARMCPU {
/* Uniprocessor system with MP extensions */
bool mp_is_up;
+ /* True if we tried kvm_arm_host_cpu_features() during CPU instance_init
+ * and the probe failed (so we need to report the error in realize)
+ */
+ bool host_cpu_probe_failed;
+
/* Specify the number of cores in this CPU cluster. Used for the L2CTLR
* register.
*/
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 1219d0062b..1c0e57690a 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -33,6 +33,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
static bool cap_has_mp_state;
+static ARMHostCPUFeatures arm_host_cpu_features;
+
int kvm_arm_vcpu_init(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
@@ -129,30 +131,32 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray)
}
}
-static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data)
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
{
- ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc);
+ CPUARMState *env = &cpu->env;
- /* All we really need to set up for the 'host' CPU
- * is the feature bits -- we rely on the fact that the
- * various ID register values in ARMCPU are only used for
- * TCG CPUs.
- */
- if (!kvm_arm_get_host_cpu_features(ahcc)) {
- fprintf(stderr, "Failed to retrieve host CPU features!\n");
- abort();
+ if (!arm_host_cpu_features.dtb_compatible) {
+ if (!kvm_enabled() ||
+ !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) {
+ /* We can't report this error yet, so flag that we need to
+ * in arm_cpu_realizefn().
+ */
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
+ cpu->host_cpu_probe_failed = true;
+ return;
+ }
}
+
+ cpu->kvm_target = arm_host_cpu_features.target;
+ cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
+ env->features = arm_host_cpu_features.features;
}
static void kvm_arm_host_cpu_initfn(Object *obj)
{
- ARMHostCPUClass *ahcc = ARM_HOST_CPU_GET_CLASS(obj);
ARMCPU *cpu = ARM_CPU(obj);
- CPUARMState *env = &cpu->env;
- cpu->kvm_target = ahcc->target;
- cpu->dtb_compatible = ahcc->dtb_compatible;
- env->features = ahcc->features;
+ kvm_arm_set_cpu_features_from_host(cpu);
}
static const TypeInfo host_arm_cpu_type_info = {
@@ -163,8 +167,6 @@ static const TypeInfo host_arm_cpu_type_info = {
.parent = TYPE_ARM_CPU,
#endif
.instance_init = kvm_arm_host_cpu_initfn,
- .class_init = kvm_arm_host_cpu_class_init,
- .class_size = sizeof(ARMHostCPUClass),
};
int kvm_arch_init(MachineState *ms, KVMState *s)
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index f77c9c494b..1740cda47d 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -28,7 +28,7 @@ static inline void set_feature(uint64_t *features, int feature)
*features |= 1ULL << feature;
}
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
{
/* Identify the feature bits corresponding to the host CPU, and
* fill out the ARMHostCPUClass fields accordingly. To do this
@@ -74,13 +74,13 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
return false;
}
- ahcc->target = init.target;
+ ahcf->target = init.target;
/* This is not strictly blessed by the device tree binding docs yet,
* but in practice the kernel does not care about this string so
* there is no point maintaining an KVM_ARM_TARGET_* -> string table.
*/
- ahcc->dtb_compatible = "arm,arm-v7";
+ ahcf->dtb_compatible = "arm,arm-v7";
for (i = 0; i < ARRAY_SIZE(idregs); i++) {
ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &idregs[i]);
@@ -132,7 +132,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
set_feature(&features, ARM_FEATURE_VFP4);
}
- ahcc->features = features;
+ ahcf->features = features;
return true;
}
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index ac728494a4..e0b8246283 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -443,7 +443,7 @@ static inline void unset_feature(uint64_t *features, int feature)
*features &= ~(1ULL << feature);
}
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
{
/* Identify the feature bits corresponding to the host CPU, and
* fill out the ARMHostCPUClass fields accordingly. To do this
@@ -471,8 +471,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
return false;
}
- ahcc->target = init.target;
- ahcc->dtb_compatible = "arm,arm-v8";
+ ahcf->target = init.target;
+ ahcf->dtb_compatible = "arm,arm-v8";
kvm_arm_destroy_scratch_host_vcpu(fdarray);
@@ -486,7 +486,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
set_feature(&features, ARM_FEATURE_AARCH64);
set_feature(&features, ARM_FEATURE_PMU);
- ahcc->features = features;
+ ahcf->features = features;
return true;
}
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index cfb7e5af72..1e2364007d 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -152,20 +152,16 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
-#define ARM_HOST_CPU_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU)
-#define ARM_HOST_CPU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMHostCPUClass, (obj), TYPE_ARM_HOST_CPU)
-
-typedef struct ARMHostCPUClass {
- /*< private >*/
- ARMCPUClass parent_class;
- /*< public >*/
+/**
+ * ARMHostCPUFeatures: information about the host CPU (identified
+ * by asking the host kernel)
+ */
+typedef struct ARMHostCPUFeatures {
uint64_t features;
uint32_t target;
const char *dtb_compatible;
-} ARMHostCPUClass;
+} ARMHostCPUFeatures;
/**
* kvm_arm_get_host_cpu_features:
@@ -174,8 +170,16 @@ typedef struct ARMHostCPUClass {
* Probe the capabilities of the host kernel's preferred CPU and fill
* in the ARMHostCPUClass struct accordingly.
*/
-bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
+bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
+/**
+ * kvm_arm_set_cpu_features_from_host:
+ * @cpu: ARMCPU to set the features for
+ *
+ * Set up the ARMCPU struct fields up to match the information probed
+ * from the host CPU.
+ */
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
/**
* kvm_arm_sync_mpstate_to_kvm
@@ -200,6 +204,15 @@ void kvm_arm_pmu_init(CPUState *cs);
#else
+static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+{
+ /* This should never actually be called in the "not KVM" case,
+ * but set up the fields to indicate an error anyway.
+ */
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
+ cpu->host_cpu_probe_failed = true;
+}
+
static inline int kvm_arm_vgic_probe(void)
{
return 0;