KVM: arm64: Emulate RAS error registers and set HCR_EL2's TERR & TEA
authorDongjiu Geng <gengdongjiu@huawei.com>
Mon, 15 Jan 2018 19:39:06 +0000 (19:39 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Tue, 16 Jan 2018 15:09:47 +0000 (15:09 +0000)
ARMv8.2 adds a new bit HCR_EL2.TEA which routes synchronous external
aborts to EL2, and adds a trap control bit HCR_EL2.TERR which traps
all Non-secure EL1&0 error record accesses to EL2.

This patch enables the two bits for the guest OS, guaranteeing that
KVM takes external aborts and traps attempts to access the physical
error registers.

ERRIDR_EL1 advertises the number of error records, we return
zero meaning we can treat all the other registers as RAZ/WI too.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
[removed specific emulation, use trap_raz_wi() directly for everything,
 rephrased parts of the commit message]
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kvm/sys_regs.c

index 715d395ef45bb23f072b34f88116b36940346e95..b0c84171e6a315391ad9c04cd008a4d18b45fd2d 100644 (file)
@@ -23,6 +23,8 @@
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_TEA                (UL(1) << 37)
+#define HCR_TERR       (UL(1) << 36)
 #define HCR_E2H                (UL(1) << 34)
 #define HCR_ID         (UL(1) << 33)
 #define HCR_CD         (UL(1) << 32)
index e002ab7f919a7ea55740bb8e361a0a8f41a06501..413dc82b1e89cbef4c30dd825fc130df9bd225d5 100644 (file)
@@ -50,6 +50,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
        vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
        if (is_kernel_in_hyp_mode())
                vcpu->arch.hcr_el2 |= HCR_E2H;
+       if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) {
+               /* route synchronous external abort exceptions to EL2 */
+               vcpu->arch.hcr_el2 |= HCR_TEA;
+               /* trap error record accesses */
+               vcpu->arch.hcr_el2 |= HCR_TERR;
+       }
+
        if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
                vcpu->arch.hcr_el2 &= ~HCR_RW;
 }
index 53d99c0944b100f095487a8377d87aed946f30c4..0e1960c59197aa581c4c0e1ee4fb1f5558f902f6 100644 (file)
 #define SYS_AFSR0_EL1                  sys_reg(3, 0, 5, 1, 0)
 #define SYS_AFSR1_EL1                  sys_reg(3, 0, 5, 1, 1)
 #define SYS_ESR_EL1                    sys_reg(3, 0, 5, 2, 0)
+
+#define SYS_ERRIDR_EL1                 sys_reg(3, 0, 5, 3, 0)
+#define SYS_ERRSELR_EL1                        sys_reg(3, 0, 5, 3, 1)
+#define SYS_ERXFR_EL1                  sys_reg(3, 0, 5, 4, 0)
+#define SYS_ERXCTLR_EL1                        sys_reg(3, 0, 5, 4, 1)
+#define SYS_ERXSTATUS_EL1              sys_reg(3, 0, 5, 4, 2)
+#define SYS_ERXADDR_EL1                        sys_reg(3, 0, 5, 4, 3)
+#define SYS_ERXMISC0_EL1               sys_reg(3, 0, 5, 5, 0)
+#define SYS_ERXMISC1_EL1               sys_reg(3, 0, 5, 5, 1)
+
 #define SYS_FAR_EL1                    sys_reg(3, 0, 6, 0, 0)
 #define SYS_PAR_EL1                    sys_reg(3, 0, 7, 4, 0)
 
index 9edf4ac8a3207502a6618c56764f9fd06caaf571..50a43c7b97ca0f0a7e38b2e47f3034ecbb75cb9e 100644 (file)
@@ -1159,6 +1159,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_AFSR0_EL1), access_vm_reg, reset_unknown, AFSR0_EL1 },
        { SYS_DESC(SYS_AFSR1_EL1), access_vm_reg, reset_unknown, AFSR1_EL1 },
        { SYS_DESC(SYS_ESR_EL1), access_vm_reg, reset_unknown, ESR_EL1 },
+
+       { SYS_DESC(SYS_ERRIDR_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERRSELR_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERXFR_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERXCTLR_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERXSTATUS_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERXADDR_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi },
+       { SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi },
+
        { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 },
        { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },