Browse Source

whpx: arm64: implement -cpu host

Logic to fetch MIDR_EL1 for cpu 0 adapted from:
e6de17e72e/Source/Windows/Common/CPUFeatures.cpp (L62)

Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Mohamed Mediouni 2 months ago
committed by Peter Maydell
parent
commit
f7fa2b8808
  1. 17
      target/arm/cpu64.c
  2. 104
      target/arm/whpx/whpx-all.c
  3. 1
      target/arm/whpx_arm.h

17
target/arm/cpu64.c

@ -26,10 +26,13 @@
#include "qemu/units.h"
#include "system/kvm.h"
#include "system/hvf.h"
#include "system/whpx.h"
#include "system/hw_accel.h"
#include "system/qtest.h"
#include "system/tcg.h"
#include "kvm_arm.h"
#include "hvf_arm.h"
#include "whpx_arm.h"
#include "qapi/visitor.h"
#include "hw/core/qdev-properties.h"
#include "internals.h"
@ -521,7 +524,7 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0);
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0);
if (kvm_enabled() || hvf_enabled()) {
if (hwaccel_enabled()) {
/*
* Exit early if PAuth is enabled and fall through to disable it.
* The algorithm selection properties are not present.
@ -598,10 +601,10 @@ void aarch64_add_pauth_properties(Object *obj)
/* Default to PAUTH on, with the architected algorithm on TCG. */
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property);
if (kvm_enabled() || hvf_enabled()) {
if (hwaccel_enabled()) {
/*
* Mirror PAuth support from the probed sysregs back into the
* property for KVM or hvf. Is it just a bit backward? Yes it is!
* property for HW accel. Is it just a bit backward? Yes it is!
* Note that prop_pauth is true whether the host CPU supports the
* architected QARMA5 algorithm or the IMPDEF one. We don't
* provide the separate pauth-impdef property for KVM or hvf,
@ -769,6 +772,8 @@ static void aarch64_host_initfn(Object *obj)
}
#elif defined(CONFIG_HVF)
hvf_arm_set_cpu_features_from_host(cpu);
#elif defined(CONFIG_WHPX)
whpx_arm_set_cpu_features_from_host(cpu);
#else
g_assert_not_reached();
#endif
@ -779,8 +784,8 @@ static void aarch64_host_initfn(Object *obj)
static void aarch64_max_initfn(Object *obj)
{
if (kvm_enabled() || hvf_enabled()) {
/* With KVM or HVF, '-cpu max' is identical to '-cpu host' */
if (hwaccel_enabled()) {
/* When hardware acceleration enabled, '-cpu max' is identical to '-cpu host' */
aarch64_host_initfn(obj);
return;
}
@ -799,7 +804,7 @@ static const ARMCPUInfo aarch64_cpus[] = {
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
{ .name = "max", .initfn = aarch64_max_initfn },
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
#if defined(CONFIG_KVM) || defined(CONFIG_HVF) || defined(CONFIG_WHPX)
{ .name = "host", .initfn = aarch64_host_initfn },
#endif
};

104
target/arm/whpx/whpx-all.c

@ -41,6 +41,17 @@
#include <winhvplatform.h>
#include <winhvplatformdefs.h>
#include <winreg.h>
typedef struct ARMHostCPUFeatures {
ARMISARegisters isar;
uint64_t features;
uint64_t midr;
uint32_t reset_sctlr;
const char *dtb_compatible;
} ARMHostCPUFeatures;
static ARMHostCPUFeatures arm_host_cpu_features;
typedef struct WHPXRegMatch {
WHV_REGISTER_NAME reg;
@ -668,6 +679,99 @@ static void clamp_id_aa64mmfr0_parange_to_ipa_size(ARMISARegisters *isar)
SET_IDREG(isar, ID_AA64MMFR0, id_aa64mmfr0);
}
static uint64_t whpx_read_midr(void)
{
HKEY key;
uint64_t midr_el1;
DWORD size = sizeof(midr_el1);
const char *path = "Hardware\\Description\\System\\CentralProcessor\\0\\";
assert(!RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &key));
assert(!RegGetValueA(key, NULL, "CP 4000", RRF_RT_REG_QWORD, NULL, &midr_el1, &size));
RegCloseKey(key);
return midr_el1;
}
static bool whpx_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
{
const struct isar_regs {
WHV_REGISTER_NAME reg;
uint64_t *val;
} regs[] = {
{ WHvArm64RegisterIdAa64Pfr0El1, &ahcf->isar.idregs[ID_AA64PFR0_EL1_IDX] },
{ WHvArm64RegisterIdAa64Pfr1El1, &ahcf->isar.idregs[ID_AA64PFR1_EL1_IDX] },
{ WHvArm64RegisterIdAa64Dfr0El1, &ahcf->isar.idregs[ID_AA64DFR0_EL1_IDX] },
{ WHvArm64RegisterIdAa64Dfr1El1 , &ahcf->isar.idregs[ID_AA64DFR1_EL1_IDX] },
{ WHvArm64RegisterIdAa64Isar0El1, &ahcf->isar.idregs[ID_AA64ISAR0_EL1_IDX] },
{ WHvArm64RegisterIdAa64Isar1El1, &ahcf->isar.idregs[ID_AA64ISAR1_EL1_IDX] },
{ WHvArm64RegisterIdAa64Isar2El1, &ahcf->isar.idregs[ID_AA64ISAR2_EL1_IDX] },
{ WHvArm64RegisterIdAa64Mmfr0El1, &ahcf->isar.idregs[ID_AA64MMFR0_EL1_IDX] },
{ WHvArm64RegisterIdAa64Mmfr1El1, &ahcf->isar.idregs[ID_AA64MMFR1_EL1_IDX] },
{ WHvArm64RegisterIdAa64Mmfr2El1, &ahcf->isar.idregs[ID_AA64MMFR2_EL1_IDX] },
{ WHvArm64RegisterIdAa64Mmfr3El1, &ahcf->isar.idregs[ID_AA64MMFR2_EL1_IDX] }
};
int i;
WHV_REGISTER_VALUE val;
ahcf->dtb_compatible = "arm,armv8";
ahcf->features = (1ULL << ARM_FEATURE_V8) |
(1ULL << ARM_FEATURE_NEON) |
(1ULL << ARM_FEATURE_AARCH64) |
(1ULL << ARM_FEATURE_PMU) |
(1ULL << ARM_FEATURE_GENERIC_TIMER);
for (i = 0; i < ARRAY_SIZE(regs); i++) {
clean_whv_register_value(&val);
whpx_get_global_reg(regs[i].reg, &val);
*regs[i].val = val.Reg64;
}
/*
* MIDR_EL1 is not a global register on WHPX
* As such, read the CPU0 from the registry to get a consistent value.
* Otherwise, on heterogenous systems, you'll get variance between CPUs.
*/
ahcf->midr = whpx_read_midr();
clamp_id_aa64mmfr0_parange_to_ipa_size(&ahcf->isar);
/*
* Disable SVE, which is not supported by QEMU whpx yet.
* Work needed for SVE support:
* - SVE state save/restore
* - any potentially needed VL management
* Also disable SME at the same time. (not currently supported by Hyper-V)
*/
SET_IDREG(&ahcf->isar, ID_AA64PFR0,
GET_IDREG(&ahcf->isar, ID_AA64PFR0) & ~R_ID_AA64PFR0_SVE_MASK);
SET_IDREG(&ahcf->isar, ID_AA64PFR1,
GET_IDREG(&ahcf->isar, ID_AA64PFR1) & ~R_ID_AA64PFR1_SME_MASK);
return true;
}
void whpx_arm_set_cpu_features_from_host(ARMCPU *cpu)
{
if (!arm_host_cpu_features.dtb_compatible) {
if (!whpx_enabled() ||
!whpx_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->host_cpu_probe_failed = true;
return;
}
}
cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
cpu->isar = arm_host_cpu_features.isar;
cpu->env.features = arm_host_cpu_features.features;
cpu->midr = arm_host_cpu_features.midr;
cpu->reset_sctlr = arm_host_cpu_features.reset_sctlr;
}
int whpx_init_vcpu(CPUState *cpu)
{
HRESULT hr;

1
target/arm/whpx_arm.h

@ -12,5 +12,6 @@
#include "target/arm/cpu-qom.h"
uint32_t whpx_arm_get_ipa_bit_size(void);
void whpx_arm_set_cpu_features_from_host(ARMCPU *cpu);
#endif

Loading…
Cancel
Save