kvm_arm_get_host_cpu_features() already retrieves the values of some
host id registers to analyze the available vcpu features.

Eventually we want to be able to allow the user to change the value
of writable ID reg fields. So we need to store the initial value of all
writable ID regs into isar.idregs[].

Introduce a new get_host_cpu_idregs() helper that populates isar.idregs[]
and call it from kvm_arm_get_host_cpu_features.

This patch has no impact on cpreg values. isar.idregs[] is only
used as a temporary storage for register values to be updated in place
later.  Also it does not handle the writeback of isar.idregs[] into cpreg
value list after user update. This will be handled separately.

Note the host values are retrieved from the scratch vcpu initialized with
all the available capabilities exposed by KVM, independently on the
final vcpu features made by the user through the legacy composite
options such as sve, pauth, virtualization, ...

At the moment, the only caller sets writable to true. Named vcpu models
will use the writable=false mode. Note this will require some extra
handling for ID regs that cannot be read from KVM.

Signed-off-by: Eric Auger <[email protected]>
Signed-off-by: Cornelia Huck <[email protected]>

---
v9 -> v10:
- get rid of spurious kvm_arm_writable_idregs_to_cpreg_list trace point
- add a writable parameter to get_host_cpu_idregs
- some code cleanup

v8 -> v9:
- improve the commit msg. Only initialize in this patch and move the
  write back to cpreg value list in a different patch.
- Do not hack CLIDR here. The correct way to fix that temporarily is to
  do that in the machine instead.

v7 -> v8
- fix indent and added Khushit's R-b

v6 -> v7
- remove vcpu from prototypes (Khushit)

v5 -> v6
- do not check writable_map anymore
---
 target/arm/kvm.c        | 44 ++++++++++++++++++++++++++++++++++++++++-
 target/arm/trace-events |  1 +
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 2e68130611..ac4f307276 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -43,6 +43,7 @@
 #include "hw/acpi/ghes.h"
 #include "target/arm/gtimer.h"
 #include "migration/blocker.h"
+#include "cpu-idregs.h"
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_INFO(DEVICE_CTRL),
@@ -329,7 +330,45 @@ static int kvm_feature_idx_to_idregs_idx(int kidx)
     return get_sysreg_idx(sysreg);
 }
 
-static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
+/*
+ * get_host_cpu_idregs: Read all the ID register values from KVM
+ * vcpu fd and populate @ahcf->isar.idregs[] with those values
+ *
+ * Need to be called once the writable mask has been populated
+ * if @writable is set
+ *
+ * @fd: vcpu fd
+ * @ahcf: ARMHostCPUFeatures whose @ahcf->isar.idregs[] will be
+ *        populated
+ * @writable: if set, only writable ID regs are read
+ */
+static int get_host_cpu_idregs(int fd, ARMHostCPUFeatures *ahcf, bool writable)
+{
+    for (int i = 0; i < NUM_ID_IDX; i++) {
+        ARM64SysReg *sysregdesc = &arm64_id_regs[i];
+        ARMSysRegs sysreg = id_register_sysreg[i];
+        uint64_t *reg;
+        int ret;
+
+        if (writable && !sysregdesc->writable_mask) {
+            continue;
+        }
+
+        reg = &ahcf->isar.idregs[i];
+        ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg));
+        if (ret) {
+            error_report("%s error reading value of host %s register (%m)",
+                         __func__, sysregdesc->name);
+
+            return ret;
+        }
+        trace_get_host_cpu_idregs(sysregdesc->name, *reg);
+    }
+    return 0;
+}
+
+static void
+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
@@ -415,6 +454,9 @@ static void 
kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         SET_IDREG(&ahcf->isar, ID_AA64PFR0, 0x00000011); /* EL1&0, AArch64 
only */
         err = 0;
     } else {
+        /* Make sure all writable ID reg values are initialized */
+        err |= get_host_cpu_idregs(fd, ahcf, true);
+
         err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX);
         err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR2_EL1_IDX);
         err |= get_host_cpu_reg(fd, ahcf, ID_AA64SMFR0_EL1_IDX);
diff --git a/target/arm/trace-events b/target/arm/trace-events
index 8502fb3265..8c7faf57c7 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -13,6 +13,7 @@ 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 host value 
for %s is 0x%"PRIx64
 
 # cpu.c
 arm_cpu_reset(uint64_t mp_aff) "cpu %" PRIu64
-- 
2.53.0


Reply via email to