diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-03-12 11:47:52 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-12 11:47:52 +0000 |
commit | 5df089564be6e6a6b1bc79207f74b5b7ed4e1277 (patch) | |
tree | b0bacc6574524443680e0af4f2b27597d3c070de /target | |
parent | 12c06d6f967a63515399b9e1f6a40f5ce871a8b7 (diff) | |
parent | 076a0fc32a73a9b960e0f73f04a531bc1bd94308 (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180309' into staging
target-arm queue:
* i.MX: Add i.MX7 SOC implementation and i.MX7 Sabre board
* Report the correct core count in A53 L2CTLR on the ZynqMP board
* linux-user: preliminary SVE support work (signal handling)
* hw/arm/boot: fix memory leak in case of error loading ELF file
* hw/arm/boot: avoid reading off end of buffer if passed very
small image file
* hw/arm: Use more CONFIG switches for the object files
* target/arm: Add "-cpu max" support
* hw/arm/virt: Support -machine gic-version=max
* hw/sd: improve debug tracing
* hw/sd: sdcard: Add the Tuning Command (CMD 19)
* MAINTAINERS: add Philippe as odd-fixes maintainer for SD
# gpg: Signature made Fri 09 Mar 2018 17:24:23 GMT
# gpg: using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20180309: (25 commits)
MAINTAINERS: Add entries for SD (SDHCI, SDBus, SDCard)
sdhci: Fix a typo in comment
sdcard: Add the Tuning Command (CMD19)
sdcard: Display which protocol is used when tracing (SD or SPI)
sdcard: Display command name when tracing CMD/ACMD
sdcard: Do not trace CMD55, except when we already expect an ACMD
hw/arm/virt: Support -machine gic-version=max
hw/arm/virt: Add "max" to the list of CPU types "virt" supports
target/arm: Make 'any' CPU just an alias for 'max'
target/arm: Add "-cpu max" support
target/arm: Move definition of 'host' cpu type into cpu.c
target/arm: Query host CPU features on-demand at instance init
arm: avoid heap-buffer-overflow in load_aarch64_image
arm: fix load ELF error leak
hw/arm: Use more CONFIG switches for the object files
aarch64-linux-user: Add support for SVE signal frame records
aarch64-linux-user: Add support for EXTRA signal frame records
aarch64-linux-user: Remove struct target_aux_context
aarch64-linux-user: Split out helpers for guest signal handling
linux-user: Implement aarch64 PR_SVE_SET/GET_VL
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/cpu-qom.h | 2 | ||||
-rw-r--r-- | target/arm/cpu.c | 103 | ||||
-rw-r--r-- | target/arm/cpu.h | 11 | ||||
-rw-r--r-- | target/arm/cpu64.c | 113 | ||||
-rw-r--r-- | target/arm/kvm.c | 51 | ||||
-rw-r--r-- | target/arm/kvm32.c | 8 | ||||
-rw-r--r-- | target/arm/kvm64.c | 8 | ||||
-rw-r--r-- | target/arm/kvm_arm.h | 35 |
8 files changed, 236 insertions, 95 deletions
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h index a42495bac9..d135ff8e06 100644 --- a/target/arm/cpu-qom.h +++ b/target/arm/cpu-qom.h @@ -33,6 +33,8 @@ struct arm_boot_info; #define ARM_CPU_GET_CLASS(obj) \ OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU) +#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU + /** * ARMCPUClass: * @parent_realize: The parent class' realize handler. diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 6b77aaa445..022d8c5787 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); @@ -939,6 +952,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cs->num_ases = 1; } cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory); + + /* No core_count specified, default to smp_cpus. */ + if (cpu->core_count == -1) { + cpu->core_count = smp_cpus; + } #endif qemu_init_vcpu(cs); @@ -952,9 +970,19 @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model) ObjectClass *oc; char *typename; char **cpuname; + const char *cpunamestr; cpuname = g_strsplit(cpu_model, ",", 1); - typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpuname[0]); + cpunamestr = cpuname[0]; +#ifdef CONFIG_USER_ONLY + /* For backwards compatibility usermode emulation allows "-cpu any", + * which has the same semantics as "-cpu max". + */ + if (!strcmp(cpunamestr, "any")) { + cpunamestr = "max"; + } +#endif + typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpunamestr); oc = object_class_by_name(typename); g_strfreev(cpuname); g_free(typename); @@ -1684,22 +1712,37 @@ static void pxa270c5_initfn(Object *obj) cpu->reset_sctlr = 0x00000078; } -#ifdef CONFIG_USER_ONLY -static void arm_any_initfn(Object *obj) +#ifndef TARGET_AARCH64 +/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); + * otherwise, a CPU with as many features enabled as our emulation supports. + * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c; + * this only needs to handle 32 bits. + */ +static void arm_max_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_VFP4); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); - set_feature(&cpu->env, ARM_FEATURE_V8_AES); - set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); - set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); - set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); - set_feature(&cpu->env, ARM_FEATURE_CRC); - set_feature(&cpu->env, ARM_FEATURE_V8_RDM); - set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); - cpu->midr = 0xffffffff; + + if (kvm_enabled()) { + kvm_arm_set_cpu_features_from_host(cpu); + } else { + cortex_a15_initfn(obj); +#ifdef CONFIG_USER_ONLY + /* We don't set these in system emulation mode for the moment, + * since we don't correctly set the ID registers to advertise them, + */ + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_VFP4); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); + set_feature(&cpu->env, ARM_FEATURE_V8_AES); + set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); + set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); + set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); + set_feature(&cpu->env, ARM_FEATURE_CRC); + set_feature(&cpu->env, ARM_FEATURE_V8_RDM); + set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); +#endif + } } #endif @@ -1751,8 +1794,11 @@ static const ARMCPUInfo arm_cpus[] = { { .name = "pxa270-b1", .initfn = pxa270b1_initfn }, { .name = "pxa270-c0", .initfn = pxa270c0_initfn }, { .name = "pxa270-c5", .initfn = pxa270c5_initfn }, +#ifndef TARGET_AARCH64 + { .name = "max", .initfn = arm_max_initfn }, +#endif #ifdef CONFIG_USER_ONLY - { .name = "any", .initfn = arm_any_initfn }, + { .name = "any", .initfn = arm_max_initfn }, #endif #endif { .name = NULL } @@ -1765,6 +1811,7 @@ static Property arm_cpu_properties[] = { DEFINE_PROP_UINT64("mp-affinity", ARMCPU, mp_affinity, ARM64_AFFINITY_INVALID), DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID), + DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1), DEFINE_PROP_END_OF_LIST() }; @@ -1845,6 +1892,26 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) #endif } +#ifdef CONFIG_KVM +static void arm_host_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + kvm_arm_set_cpu_features_from_host(cpu); +} + +static const TypeInfo host_arm_cpu_type_info = { + .name = TYPE_ARM_HOST_CPU, +#ifdef TARGET_AARCH64 + .parent = TYPE_AARCH64_CPU, +#else + .parent = TYPE_ARM_CPU, +#endif + .instance_init = arm_host_initfn, +}; + +#endif + static void cpu_register(const ARMCPUInfo *info) { TypeInfo type_info = { @@ -1889,6 +1956,10 @@ static void arm_cpu_register_types(void) cpu_register(info); info++; } + +#ifdef CONFIG_KVM + type_register_static(&host_arm_cpu_type_info); +#endif } type_init(arm_cpu_register_types) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 8dd6b788df..1e7e1f8a7e 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -745,6 +745,16 @@ 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. + */ + int32_t core_count; + /* The instance init functions for implementation-specific subclasses * set these fields to specify the implementation-dependent values of * various constant registers and reset values of non-constant @@ -861,6 +871,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, #ifdef TARGET_AARCH64 int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq); #endif target_ulong do_arm_semihosting(CPUARMState *env); diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 4228713b19..991d764674 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -28,6 +28,7 @@ #include "hw/arm/arm.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" +#include "kvm_arm.h" static inline void set_feature(CPUARMState *env, int feature) { @@ -42,8 +43,10 @@ static inline void unset_feature(CPUARMState *env, int feature) #ifndef CONFIG_USER_ONLY static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri) { - /* Number of processors is in [25:24]; otherwise we RAZ */ - return (smp_cpus - 1) << 24; + ARMCPU *cpu = arm_env_get_cpu(env); + + /* Number of cores is in [25:24]; otherwise we RAZ */ + return (cpu->core_count - 1) << 24; } #endif @@ -212,31 +215,50 @@ static void aarch64_a53_initfn(Object *obj) define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo); } -#ifdef CONFIG_USER_ONLY -static void aarch64_any_initfn(Object *obj) +/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); + * otherwise, a CPU with as many features enabled as our emulation supports. + * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; + * this only needs to handle 64 bits. + */ +static void aarch64_max_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_VFP4); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_V8_AES); - set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); - set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); - set_feature(&cpu->env, ARM_FEATURE_V8_SHA512); - set_feature(&cpu->env, ARM_FEATURE_V8_SHA3); - set_feature(&cpu->env, ARM_FEATURE_V8_SM3); - set_feature(&cpu->env, ARM_FEATURE_V8_SM4); - set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); - set_feature(&cpu->env, ARM_FEATURE_CRC); - set_feature(&cpu->env, ARM_FEATURE_V8_RDM); - set_feature(&cpu->env, ARM_FEATURE_V8_FP16); - set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); - cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ - cpu->dcz_blocksize = 7; /* 512 bytes */ -} + if (kvm_enabled()) { + kvm_arm_set_cpu_features_from_host(cpu); + } else { + aarch64_a57_initfn(obj); +#ifdef CONFIG_USER_ONLY + /* We don't set these in system emulation mode for the moment, + * since we don't correctly set the ID registers to advertise them, + * and in some cases they're only available in AArch64 and not AArch32, + * whereas the architecture requires them to be present in both if + * present in either. + */ + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_VFP4); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_V8_AES); + set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); + set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); + set_feature(&cpu->env, ARM_FEATURE_V8_SHA512); + set_feature(&cpu->env, ARM_FEATURE_V8_SHA3); + set_feature(&cpu->env, ARM_FEATURE_V8_SM3); + set_feature(&cpu->env, ARM_FEATURE_V8_SM4); + set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); + set_feature(&cpu->env, ARM_FEATURE_CRC); + set_feature(&cpu->env, ARM_FEATURE_V8_RDM); + set_feature(&cpu->env, ARM_FEATURE_V8_FP16); + set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); + /* For usermode -cpu max we can use a larger and more efficient DCZ + * blocksize since we don't have to follow what the hardware does. + */ + cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ + cpu->dcz_blocksize = 7; /* 512 bytes */ #endif + } +} typedef struct ARMCPUInfo { const char *name; @@ -247,9 +269,7 @@ typedef struct ARMCPUInfo { static const ARMCPUInfo aarch64_cpus[] = { { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, -#ifdef CONFIG_USER_ONLY - { .name = "any", .initfn = aarch64_any_initfn }, -#endif + { .name = "max", .initfn = aarch64_max_initfn }, { .name = NULL } }; @@ -366,3 +386,44 @@ static void aarch64_cpu_register_types(void) } type_init(aarch64_cpu_register_types) + +/* The manual says that when SVE is enabled and VQ is widened the + * implementation is allowed to zero the previously inaccessible + * portion of the registers. The corollary to that is that when + * SVE is enabled and VQ is narrowed we are also allowed to zero + * the now inaccessible portion of the registers. + * + * The intent of this is that no predicate bit beyond VQ is ever set. + * Which means that some operations on predicate registers themselves + * may operate on full uint64_t or even unrolled across the maximum + * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally + * may well be cheaper than conditionals to restrict the operation + * to the relevant portion of a uint16_t[16]. + * + * TODO: Need to call this for changes to the real system registers + * and EL state changes. + */ +void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) +{ + int i, j; + uint64_t pmask; + + assert(vq >= 1 && vq <= ARM_MAX_VQ); + + /* Zap the high bits of the zregs. */ + for (i = 0; i < 32; i++) { + memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq)); + } + + /* Zap the high bits of the pregs and ffr. */ + pmask = 0; + if (vq & 3) { + pmask = ~(-1ULL << (16 * (vq & 3))); + } + for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) { + for (i = 0; i < 17; ++i) { + env->vfp.pregs[i].p[j] &= pmask; + } + pmask = 0; + } +} diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 1219d0062b..ecc39ac295 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,44 +131,27 @@ 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; + } } -} -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; + 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 const TypeInfo host_arm_cpu_type_info = { - .name = TYPE_ARM_HOST_CPU, -#ifdef TARGET_AARCH64 - .parent = TYPE_AARCH64_CPU, -#else - .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) { /* For ARM interrupt delivery is always asynchronous, @@ -182,8 +167,6 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); - type_register_static(&host_arm_cpu_type_info); - return 0; } 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; |