Some EL2 system registers immediately affect the current execution
of the system, so we need to use their respective EL1 counterparts.
For this we need to define a mapping between the two.

These helpers will get used in subsequent patches.

Co-developed-by: Andre Przywara <andre.przyw...@arm.com>
Signed-off-by: Andre Przywara <andre.przyw...@arm.com>
Signed-off-by: Marc Zyngier <m...@kernel.org>
---
 arch/arm64/include/asm/kvm_emulate.h |  6 ++++
 arch/arm64/kvm/sys_regs.c            | 48 ++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_emulate.h 
b/arch/arm64/include/asm/kvm_emulate.h
index 282e9ddbe1bc..486978d0346b 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -58,6 +58,12 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu);
 int kvm_inject_nested_sync(struct kvm_vcpu *vcpu, u64 esr_el2);
 int kvm_inject_nested_irq(struct kvm_vcpu *vcpu);
 
+u64 translate_tcr(u64 tcr);
+u64 translate_cptr(u64 tcr);
+u64 translate_sctlr(u64 tcr);
+u64 translate_ttbr0(u64 tcr);
+u64 translate_cnthctl(u64 tcr);
+
 static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
 {
        return !(vcpu->arch.hcr_el2 & HCR_RW);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 4b5310ea3bf8..634d3ee6799c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -65,6 +65,54 @@ static bool write_to_read_only(struct kvm_vcpu *vcpu,
        return false;
 }
 
+static u64 tcr_el2_ips_to_tcr_el1_ps(u64 tcr_el2)
+{
+       return ((tcr_el2 & TCR_EL2_PS_MASK) >> TCR_EL2_PS_SHIFT)
+               << TCR_IPS_SHIFT;
+}
+
+u64 translate_tcr(u64 tcr)
+{
+       return TCR_EPD1_MASK |                          /* disable TTBR1_EL1 */
+              ((tcr & TCR_EL2_TBI) ? TCR_TBI0 : 0) |
+              tcr_el2_ips_to_tcr_el1_ps(tcr) |
+              (tcr & TCR_EL2_TG0_MASK) |
+              (tcr & TCR_EL2_ORGN0_MASK) |
+              (tcr & TCR_EL2_IRGN0_MASK) |
+              (tcr & TCR_EL2_T0SZ_MASK);
+}
+
+u64 translate_cptr(u64 cptr_el2)
+{
+       u64 cpacr_el1 = 0;
+
+       if (!(cptr_el2 & CPTR_EL2_TFP))
+               cpacr_el1 |= CPACR_EL1_FPEN;
+       if (cptr_el2 & CPTR_EL2_TTA)
+               cpacr_el1 |= CPACR_EL1_TTA;
+       if (!(cptr_el2 & CPTR_EL2_TZ))
+               cpacr_el1 |= CPACR_EL1_ZEN;
+
+       return cpacr_el1;
+}
+
+u64 translate_sctlr(u64 sctlr)
+{
+       /* Bit 20 is RES1 in SCTLR_EL1, but RES0 in SCTLR_EL2 */
+       return sctlr | BIT(20);
+}
+
+u64 translate_ttbr0(u64 ttbr0)
+{
+       /* Force ASID to 0 (ASID 0 or RES0) */
+       return ttbr0 & ~GENMASK_ULL(63, 48);
+}
+
+u64 translate_cnthctl(u64 cnthctl)
+{
+       return ((cnthctl & 0x3) << 10) | (cnthctl & 0xfc);
+}
+
 u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
 {
        if (!vcpu->arch.sysregs_loaded_on_cpu)
-- 
2.20.1

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

Reply via email to