Merge branch kvm-arm64/nv-trap-forwarding into kvmarm-master/next
* kvm-arm64/nv-trap-forwarding: (30 commits) : . : This implements the so called "trap forwarding" infrastructure, which : gets used when we take a trap from an L2 guest and that the L1 guest : wants to see the trap for itself. : . KVM: arm64: nv: Add trap description for SPSR_EL2 and ELR_EL2 KVM: arm64: nv: Select XARRAY_MULTI to fix build error KVM: arm64: nv: Add support for HCRX_EL2 KVM: arm64: Move HCRX_EL2 switch to load/put on VHE systems KVM: arm64: nv: Expose FGT to nested guests KVM: arm64: nv: Add switching support for HFGxTR/HDFGxTR KVM: arm64: nv: Expand ERET trap forwarding to handle FGT KVM: arm64: nv: Add SVC trap forwarding KVM: arm64: nv: Add trap forwarding for HDFGxTR_EL2 KVM: arm64: nv: Add trap forwarding for HFGITR_EL2 KVM: arm64: nv: Add trap forwarding for HFGxTR_EL2 KVM: arm64: nv: Add fine grained trap forwarding infrastructure KVM: arm64: nv: Add trap forwarding for CNTHCTL_EL2 KVM: arm64: nv: Add trap forwarding for MDCR_EL2 KVM: arm64: nv: Expose FEAT_EVT to nested guests KVM: arm64: nv: Add trap forwarding for HCR_EL2 KVM: arm64: nv: Add trap forwarding infrastructure KVM: arm64: Restructure FGT register switching KVM: arm64: nv: Add FGT registers KVM: arm64: Add missing HCR_EL2 trap bits ... Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
commit
c1907626dd
@ -18,10 +18,19 @@
|
||||
#define HCR_DCT (UL(1) << 57)
|
||||
#define HCR_ATA_SHIFT 56
|
||||
#define HCR_ATA (UL(1) << HCR_ATA_SHIFT)
|
||||
#define HCR_TTLBOS (UL(1) << 55)
|
||||
#define HCR_TTLBIS (UL(1) << 54)
|
||||
#define HCR_ENSCXT (UL(1) << 53)
|
||||
#define HCR_TOCU (UL(1) << 52)
|
||||
#define HCR_AMVOFFEN (UL(1) << 51)
|
||||
#define HCR_TICAB (UL(1) << 50)
|
||||
#define HCR_TID4 (UL(1) << 49)
|
||||
#define HCR_FIEN (UL(1) << 47)
|
||||
#define HCR_FWB (UL(1) << 46)
|
||||
#define HCR_NV2 (UL(1) << 45)
|
||||
#define HCR_AT (UL(1) << 44)
|
||||
#define HCR_NV1 (UL(1) << 43)
|
||||
#define HCR_NV (UL(1) << 42)
|
||||
#define HCR_API (UL(1) << 41)
|
||||
#define HCR_APK (UL(1) << 40)
|
||||
#define HCR_TEA (UL(1) << 37)
|
||||
@ -324,6 +333,47 @@
|
||||
BIT(18) | \
|
||||
GENMASK(16, 15))
|
||||
|
||||
/*
|
||||
* FGT register definitions
|
||||
*
|
||||
* RES0 and polarity masks as of DDI0487J.a, to be updated as needed.
|
||||
* We're not using the generated masks as they are usually ahead of
|
||||
* the published ARM ARM, which we use as a reference.
|
||||
*
|
||||
* Once we get to a point where the two describe the same thing, we'll
|
||||
* merge the definitions. One day.
|
||||
*/
|
||||
#define __HFGRTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51))
|
||||
#define __HFGRTR_EL2_MASK GENMASK(49, 0)
|
||||
#define __HFGRTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
|
||||
|
||||
#define __HFGWTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51) | \
|
||||
BIT(46) | BIT(42) | BIT(40) | BIT(28) | \
|
||||
GENMASK(26, 25) | BIT(21) | BIT(18) | \
|
||||
GENMASK(15, 14) | GENMASK(10, 9) | BIT(2))
|
||||
#define __HFGWTR_EL2_MASK GENMASK(49, 0)
|
||||
#define __HFGWTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
|
||||
|
||||
#define __HFGITR_EL2_RES0 GENMASK(63, 57)
|
||||
#define __HFGITR_EL2_MASK GENMASK(54, 0)
|
||||
#define __HFGITR_EL2_nMASK GENMASK(56, 55)
|
||||
|
||||
#define __HDFGRTR_EL2_RES0 (BIT(49) | BIT(42) | GENMASK(39, 38) | \
|
||||
GENMASK(21, 20) | BIT(8))
|
||||
#define __HDFGRTR_EL2_MASK ~__HDFGRTR_EL2_nMASK
|
||||
#define __HDFGRTR_EL2_nMASK GENMASK(62, 59)
|
||||
|
||||
#define __HDFGWTR_EL2_RES0 (BIT(63) | GENMASK(59, 58) | BIT(51) | BIT(47) | \
|
||||
BIT(43) | GENMASK(40, 38) | BIT(34) | BIT(30) | \
|
||||
BIT(22) | BIT(9) | BIT(6))
|
||||
#define __HDFGWTR_EL2_MASK ~__HDFGWTR_EL2_nMASK
|
||||
#define __HDFGWTR_EL2_nMASK GENMASK(62, 60)
|
||||
|
||||
/* Similar definitions for HCRX_EL2 */
|
||||
#define __HCRX_EL2_RES0 (GENMASK(63, 16) | GENMASK(13, 12))
|
||||
#define __HCRX_EL2_MASK (0)
|
||||
#define __HCRX_EL2_nMASK (GENMASK(15, 14) | GENMASK(4, 0))
|
||||
|
||||
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
|
||||
#define HPFAR_MASK (~UL(0xf))
|
||||
/*
|
||||
|
@ -380,6 +380,7 @@ enum vcpu_sysreg {
|
||||
CPTR_EL2, /* Architectural Feature Trap Register (EL2) */
|
||||
HSTR_EL2, /* Hypervisor System Trap Register */
|
||||
HACR_EL2, /* Hypervisor Auxiliary Control Register */
|
||||
HCRX_EL2, /* Extended Hypervisor Configuration Register */
|
||||
TTBR0_EL2, /* Translation Table Base Register 0 (EL2) */
|
||||
TTBR1_EL2, /* Translation Table Base Register 1 (EL2) */
|
||||
TCR_EL2, /* Translation Control Register (EL2) */
|
||||
@ -400,6 +401,11 @@ enum vcpu_sysreg {
|
||||
TPIDR_EL2, /* EL2 Software Thread ID Register */
|
||||
CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */
|
||||
SP_EL2, /* EL2 Stack Pointer */
|
||||
HFGRTR_EL2,
|
||||
HFGWTR_EL2,
|
||||
HFGITR_EL2,
|
||||
HDFGRTR_EL2,
|
||||
HDFGWTR_EL2,
|
||||
CNTHP_CTL_EL2,
|
||||
CNTHP_CVAL_EL2,
|
||||
CNTHV_CTL_EL2,
|
||||
@ -983,6 +989,7 @@ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu);
|
||||
void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
|
||||
|
||||
int __init kvm_sys_reg_table_init(void);
|
||||
int __init populate_nv_trap_config(void);
|
||||
|
||||
bool lock_all_vcpus(struct kvm *kvm);
|
||||
void unlock_all_vcpus(struct kvm *kvm);
|
||||
|
@ -11,6 +11,8 @@ static inline bool vcpu_has_nv(const struct kvm_vcpu *vcpu)
|
||||
test_bit(KVM_ARM_VCPU_HAS_EL2, vcpu->arch.features));
|
||||
}
|
||||
|
||||
extern bool __check_nv_sr_forward(struct kvm_vcpu *vcpu);
|
||||
|
||||
struct sys_reg_params;
|
||||
struct sys_reg_desc;
|
||||
|
||||
|
@ -124,6 +124,37 @@
|
||||
#define SYS_DC_CIGSW sys_insn(1, 0, 7, 14, 4)
|
||||
#define SYS_DC_CIGDSW sys_insn(1, 0, 7, 14, 6)
|
||||
|
||||
#define SYS_IC_IALLUIS sys_insn(1, 0, 7, 1, 0)
|
||||
#define SYS_IC_IALLU sys_insn(1, 0, 7, 5, 0)
|
||||
#define SYS_IC_IVAU sys_insn(1, 3, 7, 5, 1)
|
||||
|
||||
#define SYS_DC_IVAC sys_insn(1, 0, 7, 6, 1)
|
||||
#define SYS_DC_IGVAC sys_insn(1, 0, 7, 6, 3)
|
||||
#define SYS_DC_IGDVAC sys_insn(1, 0, 7, 6, 5)
|
||||
|
||||
#define SYS_DC_CVAC sys_insn(1, 3, 7, 10, 1)
|
||||
#define SYS_DC_CGVAC sys_insn(1, 3, 7, 10, 3)
|
||||
#define SYS_DC_CGDVAC sys_insn(1, 3, 7, 10, 5)
|
||||
|
||||
#define SYS_DC_CVAU sys_insn(1, 3, 7, 11, 1)
|
||||
|
||||
#define SYS_DC_CVAP sys_insn(1, 3, 7, 12, 1)
|
||||
#define SYS_DC_CGVAP sys_insn(1, 3, 7, 12, 3)
|
||||
#define SYS_DC_CGDVAP sys_insn(1, 3, 7, 12, 5)
|
||||
|
||||
#define SYS_DC_CVADP sys_insn(1, 3, 7, 13, 1)
|
||||
#define SYS_DC_CGVADP sys_insn(1, 3, 7, 13, 3)
|
||||
#define SYS_DC_CGDVADP sys_insn(1, 3, 7, 13, 5)
|
||||
|
||||
#define SYS_DC_CIVAC sys_insn(1, 3, 7, 14, 1)
|
||||
#define SYS_DC_CIGVAC sys_insn(1, 3, 7, 14, 3)
|
||||
#define SYS_DC_CIGDVAC sys_insn(1, 3, 7, 14, 5)
|
||||
|
||||
/* Data cache zero operations */
|
||||
#define SYS_DC_ZVA sys_insn(1, 3, 7, 4, 1)
|
||||
#define SYS_DC_GVA sys_insn(1, 3, 7, 4, 3)
|
||||
#define SYS_DC_GZVA sys_insn(1, 3, 7, 4, 4)
|
||||
|
||||
/*
|
||||
* Automatically generated definitions for system registers, the
|
||||
* manual encodings below are in the process of being converted to
|
||||
@ -163,6 +194,82 @@
|
||||
#define SYS_DBGDTRTX_EL0 sys_reg(2, 3, 0, 5, 0)
|
||||
#define SYS_DBGVCR32_EL2 sys_reg(2, 4, 0, 7, 0)
|
||||
|
||||
#define SYS_BRBINF_EL1(n) sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 0))
|
||||
#define SYS_BRBINFINJ_EL1 sys_reg(2, 1, 9, 1, 0)
|
||||
#define SYS_BRBSRC_EL1(n) sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 1))
|
||||
#define SYS_BRBSRCINJ_EL1 sys_reg(2, 1, 9, 1, 1)
|
||||
#define SYS_BRBTGT_EL1(n) sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 2))
|
||||
#define SYS_BRBTGTINJ_EL1 sys_reg(2, 1, 9, 1, 2)
|
||||
#define SYS_BRBTS_EL1 sys_reg(2, 1, 9, 0, 2)
|
||||
|
||||
#define SYS_BRBCR_EL1 sys_reg(2, 1, 9, 0, 0)
|
||||
#define SYS_BRBFCR_EL1 sys_reg(2, 1, 9, 0, 1)
|
||||
#define SYS_BRBIDR0_EL1 sys_reg(2, 1, 9, 2, 0)
|
||||
|
||||
#define SYS_TRCITECR_EL1 sys_reg(3, 0, 1, 2, 3)
|
||||
#define SYS_TRCACATR(m) sys_reg(2, 1, 2, ((m & 7) << 1), (2 | (m >> 3)))
|
||||
#define SYS_TRCACVR(m) sys_reg(2, 1, 2, ((m & 7) << 1), (0 | (m >> 3)))
|
||||
#define SYS_TRCAUTHSTATUS sys_reg(2, 1, 7, 14, 6)
|
||||
#define SYS_TRCAUXCTLR sys_reg(2, 1, 0, 6, 0)
|
||||
#define SYS_TRCBBCTLR sys_reg(2, 1, 0, 15, 0)
|
||||
#define SYS_TRCCCCTLR sys_reg(2, 1, 0, 14, 0)
|
||||
#define SYS_TRCCIDCCTLR0 sys_reg(2, 1, 3, 0, 2)
|
||||
#define SYS_TRCCIDCCTLR1 sys_reg(2, 1, 3, 1, 2)
|
||||
#define SYS_TRCCIDCVR(m) sys_reg(2, 1, 3, ((m & 7) << 1), 0)
|
||||
#define SYS_TRCCLAIMCLR sys_reg(2, 1, 7, 9, 6)
|
||||
#define SYS_TRCCLAIMSET sys_reg(2, 1, 7, 8, 6)
|
||||
#define SYS_TRCCNTCTLR(m) sys_reg(2, 1, 0, (4 | (m & 3)), 5)
|
||||
#define SYS_TRCCNTRLDVR(m) sys_reg(2, 1, 0, (0 | (m & 3)), 5)
|
||||
#define SYS_TRCCNTVR(m) sys_reg(2, 1, 0, (8 | (m & 3)), 5)
|
||||
#define SYS_TRCCONFIGR sys_reg(2, 1, 0, 4, 0)
|
||||
#define SYS_TRCDEVARCH sys_reg(2, 1, 7, 15, 6)
|
||||
#define SYS_TRCDEVID sys_reg(2, 1, 7, 2, 7)
|
||||
#define SYS_TRCEVENTCTL0R sys_reg(2, 1, 0, 8, 0)
|
||||
#define SYS_TRCEVENTCTL1R sys_reg(2, 1, 0, 9, 0)
|
||||
#define SYS_TRCEXTINSELR(m) sys_reg(2, 1, 0, (8 | (m & 3)), 4)
|
||||
#define SYS_TRCIDR0 sys_reg(2, 1, 0, 8, 7)
|
||||
#define SYS_TRCIDR10 sys_reg(2, 1, 0, 2, 6)
|
||||
#define SYS_TRCIDR11 sys_reg(2, 1, 0, 3, 6)
|
||||
#define SYS_TRCIDR12 sys_reg(2, 1, 0, 4, 6)
|
||||
#define SYS_TRCIDR13 sys_reg(2, 1, 0, 5, 6)
|
||||
#define SYS_TRCIDR1 sys_reg(2, 1, 0, 9, 7)
|
||||
#define SYS_TRCIDR2 sys_reg(2, 1, 0, 10, 7)
|
||||
#define SYS_TRCIDR3 sys_reg(2, 1, 0, 11, 7)
|
||||
#define SYS_TRCIDR4 sys_reg(2, 1, 0, 12, 7)
|
||||
#define SYS_TRCIDR5 sys_reg(2, 1, 0, 13, 7)
|
||||
#define SYS_TRCIDR6 sys_reg(2, 1, 0, 14, 7)
|
||||
#define SYS_TRCIDR7 sys_reg(2, 1, 0, 15, 7)
|
||||
#define SYS_TRCIDR8 sys_reg(2, 1, 0, 0, 6)
|
||||
#define SYS_TRCIDR9 sys_reg(2, 1, 0, 1, 6)
|
||||
#define SYS_TRCIMSPEC(m) sys_reg(2, 1, 0, (m & 7), 7)
|
||||
#define SYS_TRCITEEDCR sys_reg(2, 1, 0, 2, 1)
|
||||
#define SYS_TRCOSLSR sys_reg(2, 1, 1, 1, 4)
|
||||
#define SYS_TRCPRGCTLR sys_reg(2, 1, 0, 1, 0)
|
||||
#define SYS_TRCQCTLR sys_reg(2, 1, 0, 1, 1)
|
||||
#define SYS_TRCRSCTLR(m) sys_reg(2, 1, 1, (m & 15), (0 | (m >> 4)))
|
||||
#define SYS_TRCRSR sys_reg(2, 1, 0, 10, 0)
|
||||
#define SYS_TRCSEQEVR(m) sys_reg(2, 1, 0, (m & 3), 4)
|
||||
#define SYS_TRCSEQRSTEVR sys_reg(2, 1, 0, 6, 4)
|
||||
#define SYS_TRCSEQSTR sys_reg(2, 1, 0, 7, 4)
|
||||
#define SYS_TRCSSCCR(m) sys_reg(2, 1, 1, (m & 7), 2)
|
||||
#define SYS_TRCSSCSR(m) sys_reg(2, 1, 1, (8 | (m & 7)), 2)
|
||||
#define SYS_TRCSSPCICR(m) sys_reg(2, 1, 1, (m & 7), 3)
|
||||
#define SYS_TRCSTALLCTLR sys_reg(2, 1, 0, 11, 0)
|
||||
#define SYS_TRCSTATR sys_reg(2, 1, 0, 3, 0)
|
||||
#define SYS_TRCSYNCPR sys_reg(2, 1, 0, 13, 0)
|
||||
#define SYS_TRCTRACEIDR sys_reg(2, 1, 0, 0, 1)
|
||||
#define SYS_TRCTSCTLR sys_reg(2, 1, 0, 12, 0)
|
||||
#define SYS_TRCVICTLR sys_reg(2, 1, 0, 0, 2)
|
||||
#define SYS_TRCVIIECTLR sys_reg(2, 1, 0, 1, 2)
|
||||
#define SYS_TRCVIPCSSCTLR sys_reg(2, 1, 0, 3, 2)
|
||||
#define SYS_TRCVISSCTLR sys_reg(2, 1, 0, 2, 2)
|
||||
#define SYS_TRCVMIDCCTLR0 sys_reg(2, 1, 3, 2, 2)
|
||||
#define SYS_TRCVMIDCCTLR1 sys_reg(2, 1, 3, 3, 2)
|
||||
#define SYS_TRCVMIDCVR(m) sys_reg(2, 1, 3, ((m & 7) << 1), 1)
|
||||
|
||||
/* ETM */
|
||||
#define SYS_TRCOSLAR sys_reg(2, 1, 1, 0, 4)
|
||||
|
||||
#define SYS_MIDR_EL1 sys_reg(3, 0, 0, 0, 0)
|
||||
#define SYS_MPIDR_EL1 sys_reg(3, 0, 0, 0, 5)
|
||||
#define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6)
|
||||
@ -203,8 +310,13 @@
|
||||
#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_ERXPFGF_EL1 sys_reg(3, 0, 5, 4, 4)
|
||||
#define SYS_ERXPFGCTL_EL1 sys_reg(3, 0, 5, 4, 5)
|
||||
#define SYS_ERXPFGCDN_EL1 sys_reg(3, 0, 5, 4, 6)
|
||||
#define SYS_ERXMISC0_EL1 sys_reg(3, 0, 5, 5, 0)
|
||||
#define SYS_ERXMISC1_EL1 sys_reg(3, 0, 5, 5, 1)
|
||||
#define SYS_ERXMISC2_EL1 sys_reg(3, 0, 5, 5, 2)
|
||||
#define SYS_ERXMISC3_EL1 sys_reg(3, 0, 5, 5, 3)
|
||||
#define SYS_TFSR_EL1 sys_reg(3, 0, 5, 6, 0)
|
||||
#define SYS_TFSRE0_EL1 sys_reg(3, 0, 5, 6, 1)
|
||||
|
||||
@ -275,6 +387,8 @@
|
||||
#define SYS_ICC_IGRPEN0_EL1 sys_reg(3, 0, 12, 12, 6)
|
||||
#define SYS_ICC_IGRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
|
||||
|
||||
#define SYS_ACCDATA_EL1 sys_reg(3, 0, 13, 0, 5)
|
||||
|
||||
#define SYS_CNTKCTL_EL1 sys_reg(3, 0, 14, 1, 0)
|
||||
|
||||
#define SYS_AIDR_EL1 sys_reg(3, 1, 0, 0, 7)
|
||||
@ -383,8 +497,6 @@
|
||||
#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2)
|
||||
|
||||
#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)
|
||||
#define SYS_HDFGRTR_EL2 sys_reg(3, 4, 3, 1, 4)
|
||||
#define SYS_HDFGWTR_EL2 sys_reg(3, 4, 3, 1, 5)
|
||||
#define SYS_HAFGRTR_EL2 sys_reg(3, 4, 3, 1, 6)
|
||||
#define SYS_SPSR_EL2 sys_reg(3, 4, 4, 0, 0)
|
||||
#define SYS_ELR_EL2 sys_reg(3, 4, 4, 0, 1)
|
||||
@ -478,6 +590,158 @@
|
||||
|
||||
#define SYS_SP_EL2 sys_reg(3, 6, 4, 1, 0)
|
||||
|
||||
/* AT instructions */
|
||||
#define AT_Op0 1
|
||||
#define AT_CRn 7
|
||||
|
||||
#define OP_AT_S1E1R sys_insn(AT_Op0, 0, AT_CRn, 8, 0)
|
||||
#define OP_AT_S1E1W sys_insn(AT_Op0, 0, AT_CRn, 8, 1)
|
||||
#define OP_AT_S1E0R sys_insn(AT_Op0, 0, AT_CRn, 8, 2)
|
||||
#define OP_AT_S1E0W sys_insn(AT_Op0, 0, AT_CRn, 8, 3)
|
||||
#define OP_AT_S1E1RP sys_insn(AT_Op0, 0, AT_CRn, 9, 0)
|
||||
#define OP_AT_S1E1WP sys_insn(AT_Op0, 0, AT_CRn, 9, 1)
|
||||
#define OP_AT_S1E2R sys_insn(AT_Op0, 4, AT_CRn, 8, 0)
|
||||
#define OP_AT_S1E2W sys_insn(AT_Op0, 4, AT_CRn, 8, 1)
|
||||
#define OP_AT_S12E1R sys_insn(AT_Op0, 4, AT_CRn, 8, 4)
|
||||
#define OP_AT_S12E1W sys_insn(AT_Op0, 4, AT_CRn, 8, 5)
|
||||
#define OP_AT_S12E0R sys_insn(AT_Op0, 4, AT_CRn, 8, 6)
|
||||
#define OP_AT_S12E0W sys_insn(AT_Op0, 4, AT_CRn, 8, 7)
|
||||
|
||||
/* TLBI instructions */
|
||||
#define OP_TLBI_VMALLE1OS sys_insn(1, 0, 8, 1, 0)
|
||||
#define OP_TLBI_VAE1OS sys_insn(1, 0, 8, 1, 1)
|
||||
#define OP_TLBI_ASIDE1OS sys_insn(1, 0, 8, 1, 2)
|
||||
#define OP_TLBI_VAAE1OS sys_insn(1, 0, 8, 1, 3)
|
||||
#define OP_TLBI_VALE1OS sys_insn(1, 0, 8, 1, 5)
|
||||
#define OP_TLBI_VAALE1OS sys_insn(1, 0, 8, 1, 7)
|
||||
#define OP_TLBI_RVAE1IS sys_insn(1, 0, 8, 2, 1)
|
||||
#define OP_TLBI_RVAAE1IS sys_insn(1, 0, 8, 2, 3)
|
||||
#define OP_TLBI_RVALE1IS sys_insn(1, 0, 8, 2, 5)
|
||||
#define OP_TLBI_RVAALE1IS sys_insn(1, 0, 8, 2, 7)
|
||||
#define OP_TLBI_VMALLE1IS sys_insn(1, 0, 8, 3, 0)
|
||||
#define OP_TLBI_VAE1IS sys_insn(1, 0, 8, 3, 1)
|
||||
#define OP_TLBI_ASIDE1IS sys_insn(1, 0, 8, 3, 2)
|
||||
#define OP_TLBI_VAAE1IS sys_insn(1, 0, 8, 3, 3)
|
||||
#define OP_TLBI_VALE1IS sys_insn(1, 0, 8, 3, 5)
|
||||
#define OP_TLBI_VAALE1IS sys_insn(1, 0, 8, 3, 7)
|
||||
#define OP_TLBI_RVAE1OS sys_insn(1, 0, 8, 5, 1)
|
||||
#define OP_TLBI_RVAAE1OS sys_insn(1, 0, 8, 5, 3)
|
||||
#define OP_TLBI_RVALE1OS sys_insn(1, 0, 8, 5, 5)
|
||||
#define OP_TLBI_RVAALE1OS sys_insn(1, 0, 8, 5, 7)
|
||||
#define OP_TLBI_RVAE1 sys_insn(1, 0, 8, 6, 1)
|
||||
#define OP_TLBI_RVAAE1 sys_insn(1, 0, 8, 6, 3)
|
||||
#define OP_TLBI_RVALE1 sys_insn(1, 0, 8, 6, 5)
|
||||
#define OP_TLBI_RVAALE1 sys_insn(1, 0, 8, 6, 7)
|
||||
#define OP_TLBI_VMALLE1 sys_insn(1, 0, 8, 7, 0)
|
||||
#define OP_TLBI_VAE1 sys_insn(1, 0, 8, 7, 1)
|
||||
#define OP_TLBI_ASIDE1 sys_insn(1, 0, 8, 7, 2)
|
||||
#define OP_TLBI_VAAE1 sys_insn(1, 0, 8, 7, 3)
|
||||
#define OP_TLBI_VALE1 sys_insn(1, 0, 8, 7, 5)
|
||||
#define OP_TLBI_VAALE1 sys_insn(1, 0, 8, 7, 7)
|
||||
#define OP_TLBI_VMALLE1OSNXS sys_insn(1, 0, 9, 1, 0)
|
||||
#define OP_TLBI_VAE1OSNXS sys_insn(1, 0, 9, 1, 1)
|
||||
#define OP_TLBI_ASIDE1OSNXS sys_insn(1, 0, 9, 1, 2)
|
||||
#define OP_TLBI_VAAE1OSNXS sys_insn(1, 0, 9, 1, 3)
|
||||
#define OP_TLBI_VALE1OSNXS sys_insn(1, 0, 9, 1, 5)
|
||||
#define OP_TLBI_VAALE1OSNXS sys_insn(1, 0, 9, 1, 7)
|
||||
#define OP_TLBI_RVAE1ISNXS sys_insn(1, 0, 9, 2, 1)
|
||||
#define OP_TLBI_RVAAE1ISNXS sys_insn(1, 0, 9, 2, 3)
|
||||
#define OP_TLBI_RVALE1ISNXS sys_insn(1, 0, 9, 2, 5)
|
||||
#define OP_TLBI_RVAALE1ISNXS sys_insn(1, 0, 9, 2, 7)
|
||||
#define OP_TLBI_VMALLE1ISNXS sys_insn(1, 0, 9, 3, 0)
|
||||
#define OP_TLBI_VAE1ISNXS sys_insn(1, 0, 9, 3, 1)
|
||||
#define OP_TLBI_ASIDE1ISNXS sys_insn(1, 0, 9, 3, 2)
|
||||
#define OP_TLBI_VAAE1ISNXS sys_insn(1, 0, 9, 3, 3)
|
||||
#define OP_TLBI_VALE1ISNXS sys_insn(1, 0, 9, 3, 5)
|
||||
#define OP_TLBI_VAALE1ISNXS sys_insn(1, 0, 9, 3, 7)
|
||||
#define OP_TLBI_RVAE1OSNXS sys_insn(1, 0, 9, 5, 1)
|
||||
#define OP_TLBI_RVAAE1OSNXS sys_insn(1, 0, 9, 5, 3)
|
||||
#define OP_TLBI_RVALE1OSNXS sys_insn(1, 0, 9, 5, 5)
|
||||
#define OP_TLBI_RVAALE1OSNXS sys_insn(1, 0, 9, 5, 7)
|
||||
#define OP_TLBI_RVAE1NXS sys_insn(1, 0, 9, 6, 1)
|
||||
#define OP_TLBI_RVAAE1NXS sys_insn(1, 0, 9, 6, 3)
|
||||
#define OP_TLBI_RVALE1NXS sys_insn(1, 0, 9, 6, 5)
|
||||
#define OP_TLBI_RVAALE1NXS sys_insn(1, 0, 9, 6, 7)
|
||||
#define OP_TLBI_VMALLE1NXS sys_insn(1, 0, 9, 7, 0)
|
||||
#define OP_TLBI_VAE1NXS sys_insn(1, 0, 9, 7, 1)
|
||||
#define OP_TLBI_ASIDE1NXS sys_insn(1, 0, 9, 7, 2)
|
||||
#define OP_TLBI_VAAE1NXS sys_insn(1, 0, 9, 7, 3)
|
||||
#define OP_TLBI_VALE1NXS sys_insn(1, 0, 9, 7, 5)
|
||||
#define OP_TLBI_VAALE1NXS sys_insn(1, 0, 9, 7, 7)
|
||||
#define OP_TLBI_IPAS2E1IS sys_insn(1, 4, 8, 0, 1)
|
||||
#define OP_TLBI_RIPAS2E1IS sys_insn(1, 4, 8, 0, 2)
|
||||
#define OP_TLBI_IPAS2LE1IS sys_insn(1, 4, 8, 0, 5)
|
||||
#define OP_TLBI_RIPAS2LE1IS sys_insn(1, 4, 8, 0, 6)
|
||||
#define OP_TLBI_ALLE2OS sys_insn(1, 4, 8, 1, 0)
|
||||
#define OP_TLBI_VAE2OS sys_insn(1, 4, 8, 1, 1)
|
||||
#define OP_TLBI_ALLE1OS sys_insn(1, 4, 8, 1, 4)
|
||||
#define OP_TLBI_VALE2OS sys_insn(1, 4, 8, 1, 5)
|
||||
#define OP_TLBI_VMALLS12E1OS sys_insn(1, 4, 8, 1, 6)
|
||||
#define OP_TLBI_RVAE2IS sys_insn(1, 4, 8, 2, 1)
|
||||
#define OP_TLBI_RVALE2IS sys_insn(1, 4, 8, 2, 5)
|
||||
#define OP_TLBI_ALLE2IS sys_insn(1, 4, 8, 3, 0)
|
||||
#define OP_TLBI_VAE2IS sys_insn(1, 4, 8, 3, 1)
|
||||
#define OP_TLBI_ALLE1IS sys_insn(1, 4, 8, 3, 4)
|
||||
#define OP_TLBI_VALE2IS sys_insn(1, 4, 8, 3, 5)
|
||||
#define OP_TLBI_VMALLS12E1IS sys_insn(1, 4, 8, 3, 6)
|
||||
#define OP_TLBI_IPAS2E1OS sys_insn(1, 4, 8, 4, 0)
|
||||
#define OP_TLBI_IPAS2E1 sys_insn(1, 4, 8, 4, 1)
|
||||
#define OP_TLBI_RIPAS2E1 sys_insn(1, 4, 8, 4, 2)
|
||||
#define OP_TLBI_RIPAS2E1OS sys_insn(1, 4, 8, 4, 3)
|
||||
#define OP_TLBI_IPAS2LE1OS sys_insn(1, 4, 8, 4, 4)
|
||||
#define OP_TLBI_IPAS2LE1 sys_insn(1, 4, 8, 4, 5)
|
||||
#define OP_TLBI_RIPAS2LE1 sys_insn(1, 4, 8, 4, 6)
|
||||
#define OP_TLBI_RIPAS2LE1OS sys_insn(1, 4, 8, 4, 7)
|
||||
#define OP_TLBI_RVAE2OS sys_insn(1, 4, 8, 5, 1)
|
||||
#define OP_TLBI_RVALE2OS sys_insn(1, 4, 8, 5, 5)
|
||||
#define OP_TLBI_RVAE2 sys_insn(1, 4, 8, 6, 1)
|
||||
#define OP_TLBI_RVALE2 sys_insn(1, 4, 8, 6, 5)
|
||||
#define OP_TLBI_ALLE2 sys_insn(1, 4, 8, 7, 0)
|
||||
#define OP_TLBI_VAE2 sys_insn(1, 4, 8, 7, 1)
|
||||
#define OP_TLBI_ALLE1 sys_insn(1, 4, 8, 7, 4)
|
||||
#define OP_TLBI_VALE2 sys_insn(1, 4, 8, 7, 5)
|
||||
#define OP_TLBI_VMALLS12E1 sys_insn(1, 4, 8, 7, 6)
|
||||
#define OP_TLBI_IPAS2E1ISNXS sys_insn(1, 4, 9, 0, 1)
|
||||
#define OP_TLBI_RIPAS2E1ISNXS sys_insn(1, 4, 9, 0, 2)
|
||||
#define OP_TLBI_IPAS2LE1ISNXS sys_insn(1, 4, 9, 0, 5)
|
||||
#define OP_TLBI_RIPAS2LE1ISNXS sys_insn(1, 4, 9, 0, 6)
|
||||
#define OP_TLBI_ALLE2OSNXS sys_insn(1, 4, 9, 1, 0)
|
||||
#define OP_TLBI_VAE2OSNXS sys_insn(1, 4, 9, 1, 1)
|
||||
#define OP_TLBI_ALLE1OSNXS sys_insn(1, 4, 9, 1, 4)
|
||||
#define OP_TLBI_VALE2OSNXS sys_insn(1, 4, 9, 1, 5)
|
||||
#define OP_TLBI_VMALLS12E1OSNXS sys_insn(1, 4, 9, 1, 6)
|
||||
#define OP_TLBI_RVAE2ISNXS sys_insn(1, 4, 9, 2, 1)
|
||||
#define OP_TLBI_RVALE2ISNXS sys_insn(1, 4, 9, 2, 5)
|
||||
#define OP_TLBI_ALLE2ISNXS sys_insn(1, 4, 9, 3, 0)
|
||||
#define OP_TLBI_VAE2ISNXS sys_insn(1, 4, 9, 3, 1)
|
||||
#define OP_TLBI_ALLE1ISNXS sys_insn(1, 4, 9, 3, 4)
|
||||
#define OP_TLBI_VALE2ISNXS sys_insn(1, 4, 9, 3, 5)
|
||||
#define OP_TLBI_VMALLS12E1ISNXS sys_insn(1, 4, 9, 3, 6)
|
||||
#define OP_TLBI_IPAS2E1OSNXS sys_insn(1, 4, 9, 4, 0)
|
||||
#define OP_TLBI_IPAS2E1NXS sys_insn(1, 4, 9, 4, 1)
|
||||
#define OP_TLBI_RIPAS2E1NXS sys_insn(1, 4, 9, 4, 2)
|
||||
#define OP_TLBI_RIPAS2E1OSNXS sys_insn(1, 4, 9, 4, 3)
|
||||
#define OP_TLBI_IPAS2LE1OSNXS sys_insn(1, 4, 9, 4, 4)
|
||||
#define OP_TLBI_IPAS2LE1NXS sys_insn(1, 4, 9, 4, 5)
|
||||
#define OP_TLBI_RIPAS2LE1NXS sys_insn(1, 4, 9, 4, 6)
|
||||
#define OP_TLBI_RIPAS2LE1OSNXS sys_insn(1, 4, 9, 4, 7)
|
||||
#define OP_TLBI_RVAE2OSNXS sys_insn(1, 4, 9, 5, 1)
|
||||
#define OP_TLBI_RVALE2OSNXS sys_insn(1, 4, 9, 5, 5)
|
||||
#define OP_TLBI_RVAE2NXS sys_insn(1, 4, 9, 6, 1)
|
||||
#define OP_TLBI_RVALE2NXS sys_insn(1, 4, 9, 6, 5)
|
||||
#define OP_TLBI_ALLE2NXS sys_insn(1, 4, 9, 7, 0)
|
||||
#define OP_TLBI_VAE2NXS sys_insn(1, 4, 9, 7, 1)
|
||||
#define OP_TLBI_ALLE1NXS sys_insn(1, 4, 9, 7, 4)
|
||||
#define OP_TLBI_VALE2NXS sys_insn(1, 4, 9, 7, 5)
|
||||
#define OP_TLBI_VMALLS12E1NXS sys_insn(1, 4, 9, 7, 6)
|
||||
|
||||
/* Misc instructions */
|
||||
#define OP_BRB_IALL sys_insn(1, 1, 7, 2, 4)
|
||||
#define OP_BRB_INJ sys_insn(1, 1, 7, 2, 5)
|
||||
#define OP_CFP_RCTX sys_insn(1, 3, 7, 3, 4)
|
||||
#define OP_DVP_RCTX sys_insn(1, 3, 7, 3, 5)
|
||||
#define OP_CPP_RCTX sys_insn(1, 3, 7, 3, 7)
|
||||
|
||||
/* Common SCTLR_ELx flags. */
|
||||
#define SCTLR_ELx_ENTP2 (BIT(60))
|
||||
#define SCTLR_ELx_DSSBS (BIT(44))
|
||||
|
@ -2627,6 +2627,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
.matches = has_cpuid_feature,
|
||||
ARM64_CPUID_FIELDS(ID_AA64ISAR1_EL1, LRCPC, IMP)
|
||||
},
|
||||
{
|
||||
.desc = "Fine Grained Traps",
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.capability = ARM64_HAS_FGT,
|
||||
.matches = has_cpuid_feature,
|
||||
ARM64_CPUID_FIELDS(ID_AA64MMFR0_EL1, FGT, IMP)
|
||||
},
|
||||
#ifdef CONFIG_ARM64_SME
|
||||
{
|
||||
.desc = "Scalable Matrix Extension",
|
||||
|
@ -43,6 +43,7 @@ menuconfig KVM
|
||||
select SCHED_INFO
|
||||
select GUEST_PERF_EVENTS if PERF_EVENTS
|
||||
select INTERVAL_TREE
|
||||
select XARRAY_MULTI
|
||||
help
|
||||
Support hosting virtualized guest machines.
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <asm/kvm_arm.h>
|
||||
#include <asm/kvm_asm.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
#include <asm/kvm_nested.h>
|
||||
#include <asm/kvm_pkvm.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <asm/sections.h>
|
||||
@ -818,6 +819,9 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
|
||||
if (likely(!vcpu_mode_is_32bit(vcpu)))
|
||||
return false;
|
||||
|
||||
if (vcpu_has_nv(vcpu))
|
||||
return true;
|
||||
|
||||
return !kvm_supports_32bit_el0();
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -222,7 +222,33 @@ static int kvm_handle_eret(struct kvm_vcpu *vcpu)
|
||||
if (kvm_vcpu_get_esr(vcpu) & ESR_ELx_ERET_ISS_ERET)
|
||||
return kvm_handle_ptrauth(vcpu);
|
||||
|
||||
kvm_emulate_nested_eret(vcpu);
|
||||
/*
|
||||
* If we got here, two possibilities:
|
||||
*
|
||||
* - the guest is in EL2, and we need to fully emulate ERET
|
||||
*
|
||||
* - the guest is in EL1, and we need to reinject the
|
||||
* exception into the L1 hypervisor.
|
||||
*
|
||||
* If KVM ever traps ERET for its own use, we'll have to
|
||||
* revisit this.
|
||||
*/
|
||||
if (is_hyp_ctxt(vcpu))
|
||||
kvm_emulate_nested_eret(vcpu);
|
||||
else
|
||||
kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_svc(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/*
|
||||
* So far, SVC traps only for NV via HFGITR_EL2. A SVC from a
|
||||
* 32bit guest would be caught by vpcu_mode_is_bad_32bit(), so
|
||||
* we should only have to deal with a 64 bit exception.
|
||||
*/
|
||||
kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -239,6 +265,7 @@ static exit_handle_fn arm_exit_handlers[] = {
|
||||
[ESR_ELx_EC_SMC32] = handle_smc,
|
||||
[ESR_ELx_EC_HVC64] = handle_hvc,
|
||||
[ESR_ELx_EC_SMC64] = handle_smc,
|
||||
[ESR_ELx_EC_SVC64] = handle_svc,
|
||||
[ESR_ELx_EC_SYS64] = kvm_handle_sys_reg,
|
||||
[ESR_ELx_EC_SVE] = handle_sve,
|
||||
[ESR_ELx_EC_ERET] = kvm_handle_eret,
|
||||
|
@ -70,20 +70,26 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool __hfgxtr_traps_required(void)
|
||||
{
|
||||
if (cpus_have_final_cap(ARM64_SME))
|
||||
return true;
|
||||
|
||||
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void __activate_traps_hfgxtr(void)
|
||||
#define compute_clr_set(vcpu, reg, clr, set) \
|
||||
do { \
|
||||
u64 hfg; \
|
||||
hfg = __vcpu_sys_reg(vcpu, reg) & ~__ ## reg ## _RES0; \
|
||||
set |= hfg & __ ## reg ## _MASK; \
|
||||
clr |= ~hfg & __ ## reg ## _nMASK; \
|
||||
} while(0)
|
||||
|
||||
|
||||
static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpu_context *hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
|
||||
u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp;
|
||||
u64 r_val, w_val;
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT))
|
||||
return;
|
||||
|
||||
ctxt_sys_reg(hctxt, HFGRTR_EL2) = read_sysreg_s(SYS_HFGRTR_EL2);
|
||||
ctxt_sys_reg(hctxt, HFGWTR_EL2) = read_sysreg_s(SYS_HFGWTR_EL2);
|
||||
|
||||
if (cpus_have_final_cap(ARM64_SME)) {
|
||||
tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK;
|
||||
@ -98,26 +104,72 @@ static inline void __activate_traps_hfgxtr(void)
|
||||
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38))
|
||||
w_set |= HFGxTR_EL2_TCR_EL1_MASK;
|
||||
|
||||
sysreg_clear_set_s(SYS_HFGRTR_EL2, r_clr, r_set);
|
||||
sysreg_clear_set_s(SYS_HFGWTR_EL2, w_clr, w_set);
|
||||
}
|
||||
|
||||
static inline void __deactivate_traps_hfgxtr(void)
|
||||
{
|
||||
u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp;
|
||||
|
||||
if (cpus_have_final_cap(ARM64_SME)) {
|
||||
tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK;
|
||||
|
||||
r_set |= tmp;
|
||||
w_set |= tmp;
|
||||
if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
|
||||
compute_clr_set(vcpu, HFGRTR_EL2, r_clr, r_set);
|
||||
compute_clr_set(vcpu, HFGWTR_EL2, w_clr, w_set);
|
||||
}
|
||||
|
||||
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38))
|
||||
w_clr |= HFGxTR_EL2_TCR_EL1_MASK;
|
||||
/* The default is not to trap anything but ACCDATA_EL1 */
|
||||
r_val = __HFGRTR_EL2_nMASK & ~HFGxTR_EL2_nACCDATA_EL1;
|
||||
r_val |= r_set;
|
||||
r_val &= ~r_clr;
|
||||
|
||||
sysreg_clear_set_s(SYS_HFGRTR_EL2, r_clr, r_set);
|
||||
sysreg_clear_set_s(SYS_HFGWTR_EL2, w_clr, w_set);
|
||||
w_val = __HFGWTR_EL2_nMASK & ~HFGxTR_EL2_nACCDATA_EL1;
|
||||
w_val |= w_set;
|
||||
w_val &= ~w_clr;
|
||||
|
||||
write_sysreg_s(r_val, SYS_HFGRTR_EL2);
|
||||
write_sysreg_s(w_val, SYS_HFGWTR_EL2);
|
||||
|
||||
if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
|
||||
return;
|
||||
|
||||
ctxt_sys_reg(hctxt, HFGITR_EL2) = read_sysreg_s(SYS_HFGITR_EL2);
|
||||
|
||||
r_set = r_clr = 0;
|
||||
compute_clr_set(vcpu, HFGITR_EL2, r_clr, r_set);
|
||||
r_val = __HFGITR_EL2_nMASK;
|
||||
r_val |= r_set;
|
||||
r_val &= ~r_clr;
|
||||
|
||||
write_sysreg_s(r_val, SYS_HFGITR_EL2);
|
||||
|
||||
ctxt_sys_reg(hctxt, HDFGRTR_EL2) = read_sysreg_s(SYS_HDFGRTR_EL2);
|
||||
ctxt_sys_reg(hctxt, HDFGWTR_EL2) = read_sysreg_s(SYS_HDFGWTR_EL2);
|
||||
|
||||
r_clr = r_set = w_clr = w_set = 0;
|
||||
|
||||
compute_clr_set(vcpu, HDFGRTR_EL2, r_clr, r_set);
|
||||
compute_clr_set(vcpu, HDFGWTR_EL2, w_clr, w_set);
|
||||
|
||||
r_val = __HDFGRTR_EL2_nMASK;
|
||||
r_val |= r_set;
|
||||
r_val &= ~r_clr;
|
||||
|
||||
w_val = __HDFGWTR_EL2_nMASK;
|
||||
w_val |= w_set;
|
||||
w_val &= ~w_clr;
|
||||
|
||||
write_sysreg_s(r_val, SYS_HDFGRTR_EL2);
|
||||
write_sysreg_s(w_val, SYS_HDFGWTR_EL2);
|
||||
}
|
||||
|
||||
static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpu_context *hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT))
|
||||
return;
|
||||
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, HFGRTR_EL2), SYS_HFGRTR_EL2);
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, HFGWTR_EL2), SYS_HFGWTR_EL2);
|
||||
|
||||
if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
|
||||
return;
|
||||
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, HFGITR_EL2), SYS_HFGITR_EL2);
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, HDFGRTR_EL2), SYS_HDFGRTR_EL2);
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, HDFGWTR_EL2), SYS_HDFGWTR_EL2);
|
||||
}
|
||||
|
||||
static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
|
||||
@ -145,8 +197,21 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2);
|
||||
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
|
||||
|
||||
if (__hfgxtr_traps_required())
|
||||
__activate_traps_hfgxtr();
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX)) {
|
||||
u64 hcrx = HCRX_GUEST_FLAGS;
|
||||
if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
|
||||
u64 clr = 0, set = 0;
|
||||
|
||||
compute_clr_set(vcpu, HCRX_EL2, clr, set);
|
||||
|
||||
hcrx |= set;
|
||||
hcrx &= ~clr;
|
||||
}
|
||||
|
||||
write_sysreg_s(hcrx, SYS_HCRX_EL2);
|
||||
}
|
||||
|
||||
__activate_traps_hfgxtr(vcpu);
|
||||
}
|
||||
|
||||
static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
|
||||
@ -162,8 +227,10 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
|
||||
vcpu_clear_flag(vcpu, PMUSERENR_ON_CPU);
|
||||
}
|
||||
|
||||
if (__hfgxtr_traps_required())
|
||||
__deactivate_traps_hfgxtr();
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX))
|
||||
write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2);
|
||||
|
||||
__deactivate_traps_hfgxtr(vcpu);
|
||||
}
|
||||
|
||||
static inline void ___activate_traps(struct kvm_vcpu *vcpu)
|
||||
@ -177,9 +244,6 @@ static inline void ___activate_traps(struct kvm_vcpu *vcpu)
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE))
|
||||
write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2);
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX))
|
||||
write_sysreg_s(HCRX_GUEST_FLAGS, SYS_HCRX_EL2);
|
||||
}
|
||||
|
||||
static inline void ___deactivate_traps(struct kvm_vcpu *vcpu)
|
||||
@ -194,9 +258,6 @@ static inline void ___deactivate_traps(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.hcr_el2 &= ~HCR_VSE;
|
||||
vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE;
|
||||
}
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX))
|
||||
write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2);
|
||||
}
|
||||
|
||||
static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
|
||||
|
@ -71,8 +71,9 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
|
||||
break;
|
||||
|
||||
case SYS_ID_AA64MMFR0_EL1:
|
||||
/* Hide ECV, FGT, ExS, Secure Memory */
|
||||
val &= ~(GENMASK_ULL(63, 43) |
|
||||
/* Hide ECV, ExS, Secure Memory */
|
||||
val &= ~(NV_FTR(MMFR0, ECV) |
|
||||
NV_FTR(MMFR0, EXS) |
|
||||
NV_FTR(MMFR0, TGRAN4_2) |
|
||||
NV_FTR(MMFR0, TGRAN16_2) |
|
||||
NV_FTR(MMFR0, TGRAN64_2) |
|
||||
@ -116,7 +117,8 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
|
||||
break;
|
||||
|
||||
case SYS_ID_AA64MMFR1_EL1:
|
||||
val &= (NV_FTR(MMFR1, PAN) |
|
||||
val &= (NV_FTR(MMFR1, HCX) |
|
||||
NV_FTR(MMFR1, PAN) |
|
||||
NV_FTR(MMFR1, LO) |
|
||||
NV_FTR(MMFR1, HPDS) |
|
||||
NV_FTR(MMFR1, VH) |
|
||||
@ -124,8 +126,7 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
|
||||
break;
|
||||
|
||||
case SYS_ID_AA64MMFR2_EL1:
|
||||
val &= ~(NV_FTR(MMFR2, EVT) |
|
||||
NV_FTR(MMFR2, BBM) |
|
||||
val &= ~(NV_FTR(MMFR2, BBM) |
|
||||
NV_FTR(MMFR2, TTL) |
|
||||
GENMASK_ULL(47, 44) |
|
||||
NV_FTR(MMFR2, ST) |
|
||||
|
@ -2151,6 +2151,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
{ SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
|
||||
{ SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 },
|
||||
|
||||
{ SYS_DESC(SYS_ACCDATA_EL1), undef_access },
|
||||
|
||||
{ SYS_DESC(SYS_SCXTNUM_EL1), undef_access },
|
||||
|
||||
{ SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0},
|
||||
@ -2365,8 +2367,13 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
EL2_REG(MDCR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(CPTR_EL2, access_rw, reset_val, CPTR_NVHE_EL2_RES1),
|
||||
EL2_REG(HSTR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(HFGRTR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(HFGWTR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(HFGITR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(HACR_EL2, access_rw, reset_val, 0),
|
||||
|
||||
EL2_REG(HCRX_EL2, access_rw, reset_val, 0),
|
||||
|
||||
EL2_REG(TTBR0_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(TTBR1_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1),
|
||||
@ -2374,6 +2381,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
EL2_REG(VTCR_EL2, access_rw, reset_val, 0),
|
||||
|
||||
{ SYS_DESC(SYS_DACR32_EL2), NULL, reset_unknown, DACR32_EL2 },
|
||||
EL2_REG(HDFGRTR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(HDFGWTR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(SPSR_EL2, access_rw, reset_val, 0),
|
||||
EL2_REG(ELR_EL2, access_rw, reset_val, 0),
|
||||
{ SYS_DESC(SYS_SP_EL1), access_sp_el1},
|
||||
@ -3170,6 +3179,9 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu)
|
||||
|
||||
trace_kvm_handle_sys_reg(esr);
|
||||
|
||||
if (__check_nv_sr_forward(vcpu))
|
||||
return 1;
|
||||
|
||||
params = esr_sys64_to_params(esr);
|
||||
params.regval = vcpu_get_reg(vcpu, Rt);
|
||||
|
||||
@ -3587,5 +3599,8 @@ int __init kvm_sys_reg_table_init(void)
|
||||
if (!first_idreg)
|
||||
return -EINVAL;
|
||||
|
||||
if (kvm_get_mode() == KVM_MODE_NV)
|
||||
return populate_nv_trap_config();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -364,6 +364,32 @@ TRACE_EVENT(kvm_inject_nested_exception,
|
||||
__entry->hcr_el2)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_forward_sysreg_trap,
|
||||
TP_PROTO(struct kvm_vcpu *vcpu, u32 sysreg, bool is_read),
|
||||
TP_ARGS(vcpu, sysreg, is_read),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u64, pc)
|
||||
__field(u32, sysreg)
|
||||
__field(bool, is_read)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->pc = *vcpu_pc(vcpu);
|
||||
__entry->sysreg = sysreg;
|
||||
__entry->is_read = is_read;
|
||||
),
|
||||
|
||||
TP_printk("%llx %c (%d,%d,%d,%d,%d)",
|
||||
__entry->pc,
|
||||
__entry->is_read ? 'R' : 'W',
|
||||
sys_reg_Op0(__entry->sysreg),
|
||||
sys_reg_Op1(__entry->sysreg),
|
||||
sys_reg_CRn(__entry->sysreg),
|
||||
sys_reg_CRm(__entry->sysreg),
|
||||
sys_reg_Op2(__entry->sysreg))
|
||||
);
|
||||
|
||||
#endif /* _TRACE_ARM_ARM64_KVM_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -26,6 +26,7 @@ HAS_ECV
|
||||
HAS_ECV_CNTPOFF
|
||||
HAS_EPAN
|
||||
HAS_EVT
|
||||
HAS_FGT
|
||||
HAS_GENERIC_AUTH
|
||||
HAS_GENERIC_AUTH_ARCH_QARMA3
|
||||
HAS_GENERIC_AUTH_ARCH_QARMA5
|
||||
|
@ -2156,6 +2156,135 @@ Field 1 ICIALLU
|
||||
Field 0 ICIALLUIS
|
||||
EndSysreg
|
||||
|
||||
Sysreg HDFGRTR_EL2 3 4 3 1 4
|
||||
Field 63 PMBIDR_EL1
|
||||
Field 62 nPMSNEVFR_EL1
|
||||
Field 61 nBRBDATA
|
||||
Field 60 nBRBCTL
|
||||
Field 59 nBRBIDR
|
||||
Field 58 PMCEIDn_EL0
|
||||
Field 57 PMUSERENR_EL0
|
||||
Field 56 TRBTRG_EL1
|
||||
Field 55 TRBSR_EL1
|
||||
Field 54 TRBPTR_EL1
|
||||
Field 53 TRBMAR_EL1
|
||||
Field 52 TRBLIMITR_EL1
|
||||
Field 51 TRBIDR_EL1
|
||||
Field 50 TRBBASER_EL1
|
||||
Res0 49
|
||||
Field 48 TRCVICTLR
|
||||
Field 47 TRCSTATR
|
||||
Field 46 TRCSSCSRn
|
||||
Field 45 TRCSEQSTR
|
||||
Field 44 TRCPRGCTLR
|
||||
Field 43 TRCOSLSR
|
||||
Res0 42
|
||||
Field 41 TRCIMSPECn
|
||||
Field 40 TRCID
|
||||
Res0 39:38
|
||||
Field 37 TRCCNTVRn
|
||||
Field 36 TRCCLAIM
|
||||
Field 35 TRCAUXCTLR
|
||||
Field 34 TRCAUTHSTATUS
|
||||
Field 33 TRC
|
||||
Field 32 PMSLATFR_EL1
|
||||
Field 31 PMSIRR_EL1
|
||||
Field 30 PMSIDR_EL1
|
||||
Field 29 PMSICR_EL1
|
||||
Field 28 PMSFCR_EL1
|
||||
Field 27 PMSEVFR_EL1
|
||||
Field 26 PMSCR_EL1
|
||||
Field 25 PMBSR_EL1
|
||||
Field 24 PMBPTR_EL1
|
||||
Field 23 PMBLIMITR_EL1
|
||||
Field 22 PMMIR_EL1
|
||||
Res0 21:20
|
||||
Field 19 PMSELR_EL0
|
||||
Field 18 PMOVS
|
||||
Field 17 PMINTEN
|
||||
Field 16 PMCNTEN
|
||||
Field 15 PMCCNTR_EL0
|
||||
Field 14 PMCCFILTR_EL0
|
||||
Field 13 PMEVTYPERn_EL0
|
||||
Field 12 PMEVCNTRn_EL0
|
||||
Field 11 OSDLR_EL1
|
||||
Field 10 OSECCR_EL1
|
||||
Field 9 OSLSR_EL1
|
||||
Res0 8
|
||||
Field 7 DBGPRCR_EL1
|
||||
Field 6 DBGAUTHSTATUS_EL1
|
||||
Field 5 DBGCLAIM
|
||||
Field 4 MDSCR_EL1
|
||||
Field 3 DBGWVRn_EL1
|
||||
Field 2 DBGWCRn_EL1
|
||||
Field 1 DBGBVRn_EL1
|
||||
Field 0 DBGBCRn_EL1
|
||||
EndSysreg
|
||||
|
||||
Sysreg HDFGWTR_EL2 3 4 3 1 5
|
||||
Res0 63
|
||||
Field 62 nPMSNEVFR_EL1
|
||||
Field 61 nBRBDATA
|
||||
Field 60 nBRBCTL
|
||||
Res0 59:58
|
||||
Field 57 PMUSERENR_EL0
|
||||
Field 56 TRBTRG_EL1
|
||||
Field 55 TRBSR_EL1
|
||||
Field 54 TRBPTR_EL1
|
||||
Field 53 TRBMAR_EL1
|
||||
Field 52 TRBLIMITR_EL1
|
||||
Res0 51
|
||||
Field 50 TRBBASER_EL1
|
||||
Field 49 TRFCR_EL1
|
||||
Field 48 TRCVICTLR
|
||||
Res0 47
|
||||
Field 46 TRCSSCSRn
|
||||
Field 45 TRCSEQSTR
|
||||
Field 44 TRCPRGCTLR
|
||||
Res0 43
|
||||
Field 42 TRCOSLAR
|
||||
Field 41 TRCIMSPECn
|
||||
Res0 40:38
|
||||
Field 37 TRCCNTVRn
|
||||
Field 36 TRCCLAIM
|
||||
Field 35 TRCAUXCTLR
|
||||
Res0 34
|
||||
Field 33 TRC
|
||||
Field 32 PMSLATFR_EL1
|
||||
Field 31 PMSIRR_EL1
|
||||
Res0 30
|
||||
Field 29 PMSICR_EL1
|
||||
Field 28 PMSFCR_EL1
|
||||
Field 27 PMSEVFR_EL1
|
||||
Field 26 PMSCR_EL1
|
||||
Field 25 PMBSR_EL1
|
||||
Field 24 PMBPTR_EL1
|
||||
Field 23 PMBLIMITR_EL1
|
||||
Res0 22
|
||||
Field 21 PMCR_EL0
|
||||
Field 20 PMSWINC_EL0
|
||||
Field 19 PMSELR_EL0
|
||||
Field 18 PMOVS
|
||||
Field 17 PMINTEN
|
||||
Field 16 PMCNTEN
|
||||
Field 15 PMCCNTR_EL0
|
||||
Field 14 PMCCFILTR_EL0
|
||||
Field 13 PMEVTYPERn_EL0
|
||||
Field 12 PMEVCNTRn_EL0
|
||||
Field 11 OSDLR_EL1
|
||||
Field 10 OSECCR_EL1
|
||||
Res0 9
|
||||
Field 8 OSLAR_EL1
|
||||
Field 7 DBGPRCR_EL1
|
||||
Res0 6
|
||||
Field 5 DBGCLAIM
|
||||
Field 4 MDSCR_EL1
|
||||
Field 3 DBGWVRn_EL1
|
||||
Field 2 DBGWCRn_EL1
|
||||
Field 1 DBGBVRn_EL1
|
||||
Field 0 DBGBCRn_EL1
|
||||
EndSysreg
|
||||
|
||||
Sysreg ZCR_EL2 3 4 1 2 0
|
||||
Fields ZCR_ELx
|
||||
EndSysreg
|
||||
|
Loading…
x
Reference in New Issue
Block a user