With ARMv8.4-NV, registers that can be directly accessed in memory
by the guest have to live at architected offsets in a special page.

Let's annotate the sysreg enum to reflect the offset at which they
are in this page, whith a little twist:

If running on HW that doesn't have the ARMv8.4-NV feature, or even
a VM that doesn't use NV, we store all the system registers in the
usual sys_regs array. The only difference with the pre-8.4
situation is that VNCR-capable registers are at a "similar" offset
as in the VNCR page (we can compute the actual offset at compile
time), and that the sys_regs array is both bigger and sparse.

Signed-off-by: Marc Zyngier <m...@kernel.org>
---
 arch/arm64/include/asm/kvm_host.h | 99 ++++++++++++++++++++-----------
 1 file changed, 64 insertions(+), 35 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 0ea8cf0eeca7..3f6ddccae310 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -26,6 +26,7 @@
 #include <asm/fpsimd.h>
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
+#include <asm/vncr_mapping.h>
 
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED
 
@@ -180,31 +181,32 @@ struct kvm_vcpu_fault_info {
        u64 disr_el1;           /* Deferred [SError] Status Register */
 };
 
+/*
+ * VNCR() just places the VNCR_capable registers in the enum after
+ * __VNCR_START__, and the value (after correction) to be an 8-byte offset
+ * from the VNCR base. As we don't require the enum to be otherwise ordered,
+ * we need the terrible hack below to ensure that we correctly size the
+ * sys_regs array, no matter what.
+ *
+ * The __MAX__ macro has been lifted from Sean Eron Anderson's wonderful
+ * treasure trove of bit hacks:
+ * https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
+ */
+#define __MAX__(x,y)   ((x) ^ (((x) ^ (y)) & -((x) < (y))))
+#define VNCR(r)                                                \
+       __before_##r,                                   \
+       r = __VNCR_START__ + ((VNCR_ ## r) / 8),        \
+       __after_##r = __MAX__(__before_##r - 1, r)
+
 enum vcpu_sysreg {
        __INVALID_SYSREG__,   /* 0 is reserved as an invalid value */
        MPIDR_EL1,      /* MultiProcessor Affinity Register */
        CSSELR_EL1,     /* Cache Size Selection Register */
-       SCTLR_EL1,      /* System Control Register */
-       ACTLR_EL1,      /* Auxiliary Control Register */
-       CPACR_EL1,      /* Coprocessor Access Control */
-       ZCR_EL1,        /* SVE Control */
-       TTBR0_EL1,      /* Translation Table Base Register 0 */
-       TTBR1_EL1,      /* Translation Table Base Register 1 */
-       TCR_EL1,        /* Translation Control Register */
-       ESR_EL1,        /* Exception Syndrome Register */
-       AFSR0_EL1,      /* Auxiliary Fault Status Register 0 */
-       AFSR1_EL1,      /* Auxiliary Fault Status Register 1 */
-       FAR_EL1,        /* Fault Address Register */
-       MAIR_EL1,       /* Memory Attribute Indirection Register */
-       VBAR_EL1,       /* Vector Base Address Register */
-       CONTEXTIDR_EL1, /* Context ID Register */
        TPIDR_EL0,      /* Thread ID, User R/W */
        TPIDRRO_EL0,    /* Thread ID, User R/O */
        TPIDR_EL1,      /* Thread ID, Privileged */
-       AMAIR_EL1,      /* Aux Memory Attribute Indirection Register */
        CNTKCTL_EL1,    /* Timer Control Register (EL1) */
        PAR_EL1,        /* Physical Address Register */
-       MDSCR_EL1,      /* Monitor Debug System Control Register */
        MDCCINT_EL1,    /* Monitor Debug Comms Channel Interrupt Enable Reg */
        DISR_EL1,       /* Deferred Interrupt Status Register */
 
@@ -234,20 +236,9 @@ enum vcpu_sysreg {
        APGAKEYLO_EL1,
        APGAKEYHI_EL1,
 
-       ELR_EL1,
-       SP_EL1,
-       SPSR_EL1,
-
-       CNTVOFF_EL2,
-       CNTV_CVAL_EL0,
-       CNTV_CTL_EL0,
-       CNTP_CVAL_EL0,
-       CNTP_CTL_EL0,
-
        /* Memory Tagging Extension registers */
        RGSR_EL1,       /* Random Allocation Tag Seed Register */
        GCR_EL1,        /* Tag Control Register */
-       TFSR_EL1,       /* Tag Fault Status Register (EL1) */
        TFSRE0_EL1,     /* Tag Fault Status Register (EL0) */
 
        /* 32bit specific registers. */
@@ -257,20 +248,14 @@ enum vcpu_sysreg {
        DBGVCR32_EL2,   /* Debug Vector Catch Register */
 
        /* EL2 registers */
-       VPIDR_EL2,      /* Virtualization Processor ID Register */
-       VMPIDR_EL2,     /* Virtualization Multiprocessor ID Register */
        SCTLR_EL2,      /* System Control Register (EL2) */
        ACTLR_EL2,      /* Auxiliary Control Register (EL2) */
-       HCR_EL2,        /* Hypervisor Configuration Register */
        MDCR_EL2,       /* Monitor Debug Configuration Register (EL2) */
        CPTR_EL2,       /* Architectural Feature Trap Register (EL2) */
-       HSTR_EL2,       /* Hypervisor System Trap Register */
        HACR_EL2,       /* Hypervisor Auxiliary Control Register */
        TTBR0_EL2,      /* Translation Table Base Register 0 (EL2) */
        TTBR1_EL2,      /* Translation Table Base Register 1 (EL2) */
        TCR_EL2,        /* Translation Control Register (EL2) */
-       VTTBR_EL2,      /* Virtualization Translation Table Base Register */
-       VTCR_EL2,       /* Virtualization Translation Control Register */
        SPSR_EL2,       /* EL2 saved program status register */
        ELR_EL2,        /* EL2 exception link register */
        AFSR0_EL2,      /* Auxiliary Fault Status Register 0 (EL2) */
@@ -283,7 +268,6 @@ enum vcpu_sysreg {
        VBAR_EL2,       /* Vector Base Address Register (EL2) */
        RVBAR_EL2,      /* Reset Vector Base Address Register */
        CONTEXTIDR_EL2, /* Context ID Register (EL2) */
-       TPIDR_EL2,      /* EL2 Software Thread ID Register */
        CNTHCTL_EL2,    /* Counter-timer Hypervisor Control register */
        SP_EL2,         /* EL2 Stack Pointer */
        CNTHP_CTL_EL2,
@@ -291,6 +275,42 @@ enum vcpu_sysreg {
        CNTHV_CTL_EL2,
        CNTHV_CVAL_EL2,
 
+       __VNCR_START__, /* Any VNCR-capable reg goes after this point */
+
+       VNCR(SCTLR_EL1),/* System Control Register */
+       VNCR(ACTLR_EL1),/* Auxiliary Control Register */
+       VNCR(CPACR_EL1),/* Coprocessor Access Control */
+       VNCR(ZCR_EL1),  /* SVE Control */
+       VNCR(TTBR0_EL1),/* Translation Table Base Register 0 */
+       VNCR(TTBR1_EL1),/* Translation Table Base Register 1 */
+       VNCR(TCR_EL1),  /* Translation Control Register */
+       VNCR(ESR_EL1),  /* Exception Syndrome Register */
+       VNCR(AFSR0_EL1),/* Auxiliary Fault Status Register 0 */
+       VNCR(AFSR1_EL1),/* Auxiliary Fault Status Register 1 */
+       VNCR(FAR_EL1),  /* Fault Address Register */
+       VNCR(MAIR_EL1), /* Memory Attribute Indirection Register */
+       VNCR(VBAR_EL1), /* Vector Base Address Register */
+       VNCR(CONTEXTIDR_EL1),   /* Context ID Register */
+       VNCR(AMAIR_EL1),/* Aux Memory Attribute Indirection Register */
+       VNCR(MDSCR_EL1),/* Monitor Debug System Control Register */
+       VNCR(ELR_EL1),
+       VNCR(SP_EL1),
+       VNCR(SPSR_EL1),
+       VNCR(TFSR_EL1), /* Tag Fault Status Register (EL1) */
+       VNCR(VPIDR_EL2),/* Virtualization Processor ID Register */
+       VNCR(VMPIDR_EL2),/* Virtualization Multiprocessor ID Register */
+       VNCR(HCR_EL2),  /* Hypervisor Configuration Register */
+       VNCR(HSTR_EL2), /* Hypervisor System Trap Register */
+       VNCR(VTTBR_EL2),/* Virtualization Translation Table Base Register */
+       VNCR(VTCR_EL2), /* Virtualization Translation Control Register */
+       VNCR(TPIDR_EL2),/* EL2 Software Thread ID Register */
+
+       VNCR(CNTVOFF_EL2),
+       VNCR(CNTV_CVAL_EL0),
+       VNCR(CNTV_CTL_EL0),
+       VNCR(CNTP_CVAL_EL0),
+       VNCR(CNTP_CTL_EL0),
+
        NR_SYS_REGS     /* Nothing after this line! */
 };
 
@@ -307,6 +327,9 @@ struct kvm_cpu_context {
        u64 sys_regs[NR_SYS_REGS];
 
        struct kvm_vcpu *__hyp_running_vcpu;
+
+       /* This pointer has to be 4kB aligned. */
+       u64 *vncr_array;
 };
 
 struct kvm_pmu_events {
@@ -534,7 +557,13 @@ struct kvm_vcpu_arch {
  * for system registers that are never context switched, but only
  * emulated.
  */
-#define __ctxt_sys_reg(c,r)    (&(c)->sys_regs[(r)])
+static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
+{
+       if (unlikely(r >= __VNCR_START__ && ctxt->vncr_array))
+               return &ctxt->vncr_array[r - __VNCR_START__];
+
+       return (u64 *)&ctxt->sys_regs[r];
+}
 
 #define ctxt_sys_reg(c,r)      (*__ctxt_sys_reg(c,r))
 
-- 
2.30.2

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to