@@ -1045,6 +1045,9 @@ struct ArchCPU {
*/
ARMIdRegsState writable_id_regs;
+ /* ID reg writable bitmask (KVM only) */
+ IdRegMap *writable_map;
+
/* QOM property to indicate we should use the back-compat CNTFRQ default */
bool backcompat_cntfrq;
@@ -143,8 +143,12 @@ uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu);
*
* Set up the ARMCPU struct fields up to match the information probed
* from the host CPU.
+ *
+ * @cpu: cpu object
+ * @exhaustive: if true, all the feature ID regs are queried instead of
+ * a subset
*/
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive);
/**
* kvm_arm_add_vcpu_properties:
@@ -245,7 +249,8 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
/*
* These functions should never actually be called without KVM support.
*/
-static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu,
+ bool exhaustive)
{
g_assert_not_reached();
}
@@ -710,14 +710,14 @@ static void aarch64_host_initfn(Object *obj)
{
#if defined(CONFIG_KVM)
ARMCPU *cpu = ARM_CPU(obj);
- kvm_arm_set_cpu_features_from_host(cpu);
+ kvm_arm_set_cpu_features_from_host(cpu, false);
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
aarch64_add_sve_properties(obj);
aarch64_add_pauth_properties(obj);
}
#elif defined(CONFIG_HVF)
ARMCPU *cpu = ARM_CPU(obj);
- hvf_arm_set_cpu_features_from_host(cpu);
+ hvf_arm_set_cpu_features_from_host(cpu, false);
aarch64_add_pauth_properties(obj);
#else
g_assert_not_reached();
@@ -40,6 +40,7 @@
#include "hw/acpi/acpi.h"
#include "hw/acpi/ghes.h"
#include "target/arm/gtimer.h"
+#include "cpu-custom.h"
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
@@ -255,8 +256,49 @@ static int get_host_cpu_reg64(int fd, ARMHostCPUFeatures *ahcf, ARMSysReg sr)
return ret;
}
+/*
+ * get_host_cpu_idregs: Read all the writable ID reg host values
+ *
+ * Need to be called once the writable mask has been populated
+ * Note we may want to read all the known id regs but some of them are not
+ * writable and return an error, hence the choice of reading only those which
+ * are writable. Those are aslo readable!
+ */
+static int get_host_cpu_idregs(ARMCPU *cpu, int fd, ARMHostCPUFeatures *ahcf)
+{
+ int err = 0;
+ int i;
-static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
+ for (i = 0; i < NR_ID_REGS; i++) {
+ ARM64SysReg *sysregdesc = &arm64_id_regs[i];
+ ARMSysReg *sysreg = sysregdesc->sysreg;
+ uint64_t writable_mask = cpu->writable_map->regs[i];
+ uint64_t *reg;
+ int ret;
+
+ if (!sysreg || !writable_mask) {
+ continue;
+ }
+
+ reg = &ahcf->isar.idregs.regs[i];
+ ret = read_sys_reg64(fd, reg,
+ ARM64_SYS_REG(sysreg->op0, sysreg->op1,
+ sysreg->crn, sysreg->crm,
+ sysreg->op2));
+ trace_get_host_cpu_idregs(sysregdesc->name, *reg);
+ if (ret) {
+ error_report("%s error reading value of host %s register (%m)",
+ __func__, sysregdesc->name);
+
+ err = ret;
+ }
+ }
+ return err;
+}
+
+static bool
+kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf,
+ bool exhaustive)
{
/* Identify the feature bits corresponding to the host CPU, and
* fill out the ARMHostCPUClass fields accordingly. To do this
@@ -383,6 +425,11 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_DFR1_EL1);
err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR5_EL1);
+ /* Make sure writable ID reg values are read */
+ if (exhaustive) {
+ err |= get_host_cpu_idregs(cpu, fd, ahcf);
+ }
+
/*
* DBGDIDR is a bit complicated because the kernel doesn't
* provide an accessor for it in 64-bit mode, which is what this
@@ -453,13 +500,13 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
return true;
}
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive)
{
CPUARMState *env = &cpu->env;
if (!arm_host_cpu_features.dtb_compatible) {
if (!kvm_enabled() ||
- !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) {
+ !kvm_arm_get_host_cpu_features(cpu, &arm_host_cpu_features, exhaustive)) {
/* We can't report this error yet, so flag that we need to
* in arm_cpu_realizefn().
*/
@@ -13,3 +13,4 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
# kvm.c
kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
+get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu gost value for %s is 0x%"PRIx64
At the moment kvm_arm_get_host_cpu_features() reads a subset of the ID regs. As we want to introduce properties for all writable ID reg fields, we want more genericity and read more default host register values. Introduce a new get_host_cpu_idregs() helper and add a new exhaustive boolean parameter to kvm_arm_get_host_cpu_features() and kvm_arm_set_cpu_features_from_host() to select the right behavior. the host cpu model keeps the legacy behavior while the new custom model will read the legacy regs plus all the writable ones. This definitively brings some redundancy. A writable_map IdRegMap is introduced in the CPU object. A subsequent patch will populate it. Signed-off-by: Eric Auger <eric.auger@redhat.com> --- target/arm/cpu.h | 3 +++ target/arm/kvm_arm.h | 9 +++++-- target/arm/cpu64.c | 4 ++-- target/arm/kvm.c | 53 ++++++++++++++++++++++++++++++++++++++--- target/arm/trace-events | 1 + 5 files changed, 63 insertions(+), 7 deletions(-)