Try to read all ID registers from KVM. KVM may return ENOENT for
registers that it does not support reading from userspace; ignore
those registers. Some registers may still require special handling.

This exposes a more complete host feature view to the management
stack. For migration, both writable and non-writable ID registers
must match.

Add a tracepoint for ID register reads that fail with ENOENT.

Signed-off-by: Khushit Shah <[email protected]>
---
 target/arm/kvm.c        | 29 ++++++++++++++---------------
 target/arm/trace-events |  1 +
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index f8d349a461..d9d0623a2a 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -330,12 +330,12 @@ static int kvm_feature_idx_to_idregs_idx(int kidx)
 }
 
 /*
- * get_host_cpu_idregs: Read all the writable ID reg host values
+ * get_host_cpu_idregs: Read all the 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 also readable!
+ * We currently try to read all the registers. If the read fails with
+ * ENOENT (KVM does not identify the ID register) ignore it.
+ * Some of the registers that errored with ENOENT will anyway need special
+ * handling.
  */
 static int get_host_cpu_idregs(int fd, ARMHostCPUFeatures *ahcf)
 {
@@ -348,19 +348,18 @@ static int get_host_cpu_idregs(int fd, ARMHostCPUFeatures 
*ahcf)
         uint64_t *reg;
         int ret;
 
-        if (!sysregdesc->writable_mask) {
-            continue;
-        }
-
         reg = &ahcf->isar.idregs[i];
         ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg));
-        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;
+            if (errno == ENOENT) {
+                trace_get_host_cpu_idreg_not_found(sysregdesc->name);
+            } else {
+                error_report("%s error reading value of host %s register"
+                            " (%m)", __func__, sysregdesc->name);
+                err = ret;
+            }
         }
+        trace_get_host_cpu_idregs(sysregdesc->name, *reg);
     }
     return err;
 }
@@ -482,7 +481,7 @@ 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 */
+        /* Try to read all the ID registers */
         err |= get_host_cpu_idregs(fd, ahcf);
 
         /*
diff --git a/target/arm/trace-events b/target/arm/trace-events
index bbf2e5dfa2..2bb7766f7f 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -14,6 +14,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
+get_host_cpu_idreg_not_found(const char *name) "host %s register not readable 
from KVM"
 kvm_arm_writable_idregs_to_cpreg_list(const char *name, uint64_t previous, 
uint64_t new) "%s overwrite default 0x%"PRIx64" with 0x%"PRIx64
 kvm_idreg_write_scratch_vcpu(const char *name, uint64_t oldfv, uint64_t newfv, 
uint64_t actualfv) "successful dry-run for %s old=0x%"PRIx64" new=0x%"PRIx64" 
actual=0x%"PRIx64
 
-- 
2.52.0


Reply via email to