Merge branch kvm-arm64/fgt-masks into kvmarm-master/next
* kvm-arm64/fgt-masks: (43 commits) : . : Large rework of the way KVM deals with trap bits in conjunction with : the CPU feature registers. It now draws a direct link between which : the feature set, the system registers that need to UNDEF to match : the configuration and bits that need to behave as RES0 or RES1 in : the trap registers that are visible to the guest. : : Best of all, these definitions are mostly automatically generated : from the JSON description published by ARM under a permissive : license. : . KVM: arm64: Handle TSB CSYNC traps KVM: arm64: Add FGT descriptors for FEAT_FGT2 KVM: arm64: Allow sysreg ranges for FGT descriptors KVM: arm64: Add context-switch for FEAT_FGT2 registers KVM: arm64: Add trap routing for FEAT_FGT2 registers KVM: arm64: Add sanitisation for FEAT_FGT2 registers KVM: arm64: Add FEAT_FGT2 registers to the VNCR page KVM: arm64: Use HCR_EL2 feature map to drive fixed-value bits KVM: arm64: Use HCRX_EL2 feature map to drive fixed-value bits KVM: arm64: Allow kvm_has_feat() to take variable arguments KVM: arm64: Use FGT feature maps to drive RES0 bits KVM: arm64: Validate FGT register descriptions against RES0 masks KVM: arm64: Switch to table-driven FGU configuration KVM: arm64: Handle PSB CSYNC traps KVM: arm64: Use KVM-specific HCRX_EL2 RES0 mask KVM: arm64: Remove hand-crafted masks for FGT registers KVM: arm64: Use computed FGT masks to setup FGT registers KVM: arm64: Propagate FGT masks to the nVHE hypervisor KVM: arm64: Unconditionally configure fine-grain traps KVM: arm64: Use computed masks as sanitisers for FGT registers ... Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
@@ -213,8 +213,8 @@
|
||||
cbz x1, .Lskip_debug_fgt_\@
|
||||
|
||||
/* Disable nVHE traps of TPIDR2 and SMPRI */
|
||||
orr x0, x0, #HFGxTR_EL2_nSMPRI_EL1_MASK
|
||||
orr x0, x0, #HFGxTR_EL2_nTPIDR2_EL0_MASK
|
||||
orr x0, x0, #HFGRTR_EL2_nSMPRI_EL1_MASK
|
||||
orr x0, x0, #HFGRTR_EL2_nTPIDR2_EL0_MASK
|
||||
|
||||
.Lskip_debug_fgt_\@:
|
||||
mrs_s x1, SYS_ID_AA64MMFR3_EL1
|
||||
@@ -222,8 +222,8 @@
|
||||
cbz x1, .Lskip_pie_fgt_\@
|
||||
|
||||
/* Disable trapping of PIR_EL1 / PIRE0_EL1 */
|
||||
orr x0, x0, #HFGxTR_EL2_nPIR_EL1
|
||||
orr x0, x0, #HFGxTR_EL2_nPIRE0_EL1
|
||||
orr x0, x0, #HFGRTR_EL2_nPIR_EL1
|
||||
orr x0, x0, #HFGRTR_EL2_nPIRE0_EL1
|
||||
|
||||
.Lskip_pie_fgt_\@:
|
||||
mrs_s x1, SYS_ID_AA64MMFR3_EL1
|
||||
@@ -231,7 +231,7 @@
|
||||
cbz x1, .Lskip_poe_fgt_\@
|
||||
|
||||
/* Disable trapping of POR_EL0 */
|
||||
orr x0, x0, #HFGxTR_EL2_nPOR_EL0
|
||||
orr x0, x0, #HFGRTR_EL2_nPOR_EL0
|
||||
|
||||
.Lskip_poe_fgt_\@:
|
||||
/* GCS depends on PIE so we don't check it if PIE is absent */
|
||||
@@ -240,8 +240,8 @@
|
||||
cbz x1, .Lset_fgt_\@
|
||||
|
||||
/* Disable traps of access to GCS registers at EL0 and EL1 */
|
||||
orr x0, x0, #HFGxTR_EL2_nGCS_EL1_MASK
|
||||
orr x0, x0, #HFGxTR_EL2_nGCS_EL0_MASK
|
||||
orr x0, x0, #HFGRTR_EL2_nGCS_EL1_MASK
|
||||
orr x0, x0, #HFGRTR_EL2_nGCS_EL0_MASK
|
||||
|
||||
.Lset_fgt_\@:
|
||||
msr_s SYS_HFGRTR_EL2, x0
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#define ESR_ELx_EC_FP_ASIMD UL(0x07)
|
||||
#define ESR_ELx_EC_CP10_ID UL(0x08) /* EL2 only */
|
||||
#define ESR_ELx_EC_PAC UL(0x09) /* EL2 and above */
|
||||
/* Unallocated EC: 0x0A - 0x0B */
|
||||
#define ESR_ELx_EC_OTHER UL(0x0A)
|
||||
/* Unallocated EC: 0x0B */
|
||||
#define ESR_ELx_EC_CP14_64 UL(0x0C)
|
||||
#define ESR_ELx_EC_BTI UL(0x0D)
|
||||
#define ESR_ELx_EC_ILL UL(0x0E)
|
||||
@@ -181,6 +182,13 @@
|
||||
#define ESR_ELx_WFx_ISS_WFE (UL(1) << 0)
|
||||
#define ESR_ELx_xVC_IMM_MASK ((UL(1) << 16) - 1)
|
||||
|
||||
/* ISS definitions for LD64B/ST64B/{T,P}SBCSYNC instructions */
|
||||
#define ESR_ELx_ISS_OTHER_ST64BV (0)
|
||||
#define ESR_ELx_ISS_OTHER_ST64BV0 (1)
|
||||
#define ESR_ELx_ISS_OTHER_LDST64B (2)
|
||||
#define ESR_ELx_ISS_OTHER_TSBCSYNC (3)
|
||||
#define ESR_ELx_ISS_OTHER_PSBCSYNC (4)
|
||||
|
||||
#define DISR_EL1_IDS (UL(1) << 24)
|
||||
/*
|
||||
* DISR_EL1 and ESR_ELx share the bottom 13 bits, but the RES0 bits may mean
|
||||
|
||||
@@ -12,67 +12,70 @@
|
||||
#include <asm/sysreg.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
/* Hyp Configuration Register (HCR) bits */
|
||||
/*
|
||||
* Because I'm terribly lazy and that repainting the whole of the KVM
|
||||
* code with the proper names is a pain, use a helper to map the names
|
||||
* inherited from AArch32 with the new fancy nomenclature. One day...
|
||||
*/
|
||||
#define __HCR(x) HCR_EL2_##x
|
||||
|
||||
#define HCR_TID5 (UL(1) << 58)
|
||||
#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)
|
||||
#define HCR_TERR (UL(1) << 36)
|
||||
#define HCR_TLOR (UL(1) << 35)
|
||||
#define HCR_E2H (UL(1) << 34)
|
||||
#define HCR_ID (UL(1) << 33)
|
||||
#define HCR_CD (UL(1) << 32)
|
||||
#define HCR_RW_SHIFT 31
|
||||
#define HCR_RW (UL(1) << HCR_RW_SHIFT)
|
||||
#define HCR_TRVM (UL(1) << 30)
|
||||
#define HCR_HCD (UL(1) << 29)
|
||||
#define HCR_TDZ (UL(1) << 28)
|
||||
#define HCR_TGE (UL(1) << 27)
|
||||
#define HCR_TVM (UL(1) << 26)
|
||||
#define HCR_TTLB (UL(1) << 25)
|
||||
#define HCR_TPU (UL(1) << 24)
|
||||
#define HCR_TPC (UL(1) << 23) /* HCR_TPCP if FEAT_DPB */
|
||||
#define HCR_TSW (UL(1) << 22)
|
||||
#define HCR_TACR (UL(1) << 21)
|
||||
#define HCR_TIDCP (UL(1) << 20)
|
||||
#define HCR_TSC (UL(1) << 19)
|
||||
#define HCR_TID3 (UL(1) << 18)
|
||||
#define HCR_TID2 (UL(1) << 17)
|
||||
#define HCR_TID1 (UL(1) << 16)
|
||||
#define HCR_TID0 (UL(1) << 15)
|
||||
#define HCR_TWE (UL(1) << 14)
|
||||
#define HCR_TWI (UL(1) << 13)
|
||||
#define HCR_DC (UL(1) << 12)
|
||||
#define HCR_BSU (3 << 10)
|
||||
#define HCR_BSU_IS (UL(1) << 10)
|
||||
#define HCR_FB (UL(1) << 9)
|
||||
#define HCR_VSE (UL(1) << 8)
|
||||
#define HCR_VI (UL(1) << 7)
|
||||
#define HCR_VF (UL(1) << 6)
|
||||
#define HCR_AMO (UL(1) << 5)
|
||||
#define HCR_IMO (UL(1) << 4)
|
||||
#define HCR_FMO (UL(1) << 3)
|
||||
#define HCR_PTW (UL(1) << 2)
|
||||
#define HCR_SWIO (UL(1) << 1)
|
||||
#define HCR_VM (UL(1) << 0)
|
||||
#define HCR_RES0 ((UL(1) << 48) | (UL(1) << 39))
|
||||
#define HCR_TID5 __HCR(TID5)
|
||||
#define HCR_DCT __HCR(DCT)
|
||||
#define HCR_ATA_SHIFT __HCR(ATA_SHIFT)
|
||||
#define HCR_ATA __HCR(ATA)
|
||||
#define HCR_TTLBOS __HCR(TTLBOS)
|
||||
#define HCR_TTLBIS __HCR(TTLBIS)
|
||||
#define HCR_ENSCXT __HCR(EnSCXT)
|
||||
#define HCR_TOCU __HCR(TOCU)
|
||||
#define HCR_AMVOFFEN __HCR(AMVOFFEN)
|
||||
#define HCR_TICAB __HCR(TICAB)
|
||||
#define HCR_TID4 __HCR(TID4)
|
||||
#define HCR_FIEN __HCR(FIEN)
|
||||
#define HCR_FWB __HCR(FWB)
|
||||
#define HCR_NV2 __HCR(NV2)
|
||||
#define HCR_AT __HCR(AT)
|
||||
#define HCR_NV1 __HCR(NV1)
|
||||
#define HCR_NV __HCR(NV)
|
||||
#define HCR_API __HCR(API)
|
||||
#define HCR_APK __HCR(APK)
|
||||
#define HCR_TEA __HCR(TEA)
|
||||
#define HCR_TERR __HCR(TERR)
|
||||
#define HCR_TLOR __HCR(TLOR)
|
||||
#define HCR_E2H __HCR(E2H)
|
||||
#define HCR_ID __HCR(ID)
|
||||
#define HCR_CD __HCR(CD)
|
||||
#define HCR_RW __HCR(RW)
|
||||
#define HCR_TRVM __HCR(TRVM)
|
||||
#define HCR_HCD __HCR(HCD)
|
||||
#define HCR_TDZ __HCR(TDZ)
|
||||
#define HCR_TGE __HCR(TGE)
|
||||
#define HCR_TVM __HCR(TVM)
|
||||
#define HCR_TTLB __HCR(TTLB)
|
||||
#define HCR_TPU __HCR(TPU)
|
||||
#define HCR_TPC __HCR(TPCP)
|
||||
#define HCR_TSW __HCR(TSW)
|
||||
#define HCR_TACR __HCR(TACR)
|
||||
#define HCR_TIDCP __HCR(TIDCP)
|
||||
#define HCR_TSC __HCR(TSC)
|
||||
#define HCR_TID3 __HCR(TID3)
|
||||
#define HCR_TID2 __HCR(TID2)
|
||||
#define HCR_TID1 __HCR(TID1)
|
||||
#define HCR_TID0 __HCR(TID0)
|
||||
#define HCR_TWE __HCR(TWE)
|
||||
#define HCR_TWI __HCR(TWI)
|
||||
#define HCR_DC __HCR(DC)
|
||||
#define HCR_BSU __HCR(BSU)
|
||||
#define HCR_BSU_IS __HCR(BSU_IS)
|
||||
#define HCR_FB __HCR(FB)
|
||||
#define HCR_VSE __HCR(VSE)
|
||||
#define HCR_VI __HCR(VI)
|
||||
#define HCR_VF __HCR(VF)
|
||||
#define HCR_AMO __HCR(AMO)
|
||||
#define HCR_IMO __HCR(IMO)
|
||||
#define HCR_FMO __HCR(FMO)
|
||||
#define HCR_PTW __HCR(PTW)
|
||||
#define HCR_SWIO __HCR(SWIO)
|
||||
#define HCR_VM __HCR(VM)
|
||||
|
||||
/*
|
||||
* The bits we set in HCR:
|
||||
@@ -313,56 +316,19 @@
|
||||
GENMASK(15, 0))
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Polarity masks for HCRX_EL2, limited to the bits that we know about
|
||||
* at this point in time. It doesn't mean that we actually *handle*
|
||||
* them, but that at least those that are not advertised to a guest
|
||||
* will be RES0 for that guest.
|
||||
*/
|
||||
#define __HFGRTR_EL2_RES0 HFGxTR_EL2_RES0
|
||||
#define __HFGRTR_EL2_MASK GENMASK(49, 0)
|
||||
#define __HFGRTR_EL2_nMASK ~(__HFGRTR_EL2_RES0 | __HFGRTR_EL2_MASK)
|
||||
|
||||
/*
|
||||
* The HFGWTR bits are a subset of HFGRTR bits. To ensure we don't miss any
|
||||
* future additions, define __HFGWTR* macros relative to __HFGRTR* ones.
|
||||
*/
|
||||
#define __HFGRTR_ONLY_MASK (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_RES0 (__HFGRTR_EL2_RES0 | __HFGRTR_ONLY_MASK)
|
||||
#define __HFGWTR_EL2_MASK (__HFGRTR_EL2_MASK & ~__HFGRTR_ONLY_MASK)
|
||||
#define __HFGWTR_EL2_nMASK ~(__HFGWTR_EL2_RES0 | __HFGWTR_EL2_MASK)
|
||||
|
||||
#define __HFGITR_EL2_RES0 HFGITR_EL2_RES0
|
||||
#define __HFGITR_EL2_MASK (BIT(62) | BIT(60) | GENMASK(54, 0))
|
||||
#define __HFGITR_EL2_nMASK ~(__HFGITR_EL2_RES0 | __HFGITR_EL2_MASK)
|
||||
|
||||
#define __HDFGRTR_EL2_RES0 HDFGRTR_EL2_RES0
|
||||
#define __HDFGRTR_EL2_MASK (BIT(63) | GENMASK(58, 50) | GENMASK(48, 43) | \
|
||||
GENMASK(41, 40) | GENMASK(37, 22) | \
|
||||
GENMASK(19, 9) | GENMASK(7, 0))
|
||||
#define __HDFGRTR_EL2_nMASK ~(__HDFGRTR_EL2_RES0 | __HDFGRTR_EL2_MASK)
|
||||
|
||||
#define __HDFGWTR_EL2_RES0 HDFGWTR_EL2_RES0
|
||||
#define __HDFGWTR_EL2_MASK (GENMASK(57, 52) | GENMASK(50, 48) | \
|
||||
GENMASK(46, 44) | GENMASK(42, 41) | \
|
||||
GENMASK(37, 35) | GENMASK(33, 31) | \
|
||||
GENMASK(29, 23) | GENMASK(21, 10) | \
|
||||
GENMASK(8, 7) | GENMASK(5, 0))
|
||||
#define __HDFGWTR_EL2_nMASK ~(__HDFGWTR_EL2_RES0 | __HDFGWTR_EL2_MASK)
|
||||
|
||||
#define __HAFGRTR_EL2_RES0 HAFGRTR_EL2_RES0
|
||||
#define __HAFGRTR_EL2_MASK (GENMASK(49, 17) | GENMASK(4, 0))
|
||||
#define __HAFGRTR_EL2_nMASK ~(__HAFGRTR_EL2_RES0 | __HAFGRTR_EL2_MASK)
|
||||
|
||||
/* Similar definitions for HCRX_EL2 */
|
||||
#define __HCRX_EL2_RES0 HCRX_EL2_RES0
|
||||
#define __HCRX_EL2_MASK (BIT(6))
|
||||
#define __HCRX_EL2_nMASK ~(__HCRX_EL2_RES0 | __HCRX_EL2_MASK)
|
||||
#define __HCRX_EL2_MASK (BIT_ULL(6))
|
||||
#define __HCRX_EL2_nMASK (GENMASK_ULL(24, 14) | \
|
||||
GENMASK_ULL(11, 7) | \
|
||||
GENMASK_ULL(5, 0))
|
||||
#define __HCRX_EL2_RES0 ~(__HCRX_EL2_nMASK | __HCRX_EL2_MASK)
|
||||
#define __HCRX_EL2_RES1 ~(__HCRX_EL2_nMASK | \
|
||||
__HCRX_EL2_MASK | \
|
||||
__HCRX_EL2_RES0)
|
||||
|
||||
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
|
||||
#define HPFAR_MASK (~UL(0xf))
|
||||
|
||||
@@ -273,11 +273,17 @@ struct kvm_sysreg_masks;
|
||||
|
||||
enum fgt_group_id {
|
||||
__NO_FGT_GROUP__,
|
||||
HFGxTR_GROUP,
|
||||
HFGRTR_GROUP,
|
||||
HFGWTR_GROUP = HFGRTR_GROUP,
|
||||
HDFGRTR_GROUP,
|
||||
HDFGWTR_GROUP = HDFGRTR_GROUP,
|
||||
HFGITR_GROUP,
|
||||
HAFGRTR_GROUP,
|
||||
HFGRTR2_GROUP,
|
||||
HFGWTR2_GROUP = HFGRTR2_GROUP,
|
||||
HDFGRTR2_GROUP,
|
||||
HDFGWTR2_GROUP = HDFGRTR2_GROUP,
|
||||
HFGITR2_GROUP,
|
||||
|
||||
/* Must be last */
|
||||
__NR_FGT_GROUP_IDS__
|
||||
@@ -561,6 +567,11 @@ enum vcpu_sysreg {
|
||||
VNCR(HDFGRTR_EL2),
|
||||
VNCR(HDFGWTR_EL2),
|
||||
VNCR(HAFGRTR_EL2),
|
||||
VNCR(HFGRTR2_EL2),
|
||||
VNCR(HFGWTR2_EL2),
|
||||
VNCR(HFGITR2_EL2),
|
||||
VNCR(HDFGRTR2_EL2),
|
||||
VNCR(HDFGWTR2_EL2),
|
||||
|
||||
VNCR(CNTVOFF_EL2),
|
||||
VNCR(CNTV_CVAL_EL0),
|
||||
@@ -606,6 +617,37 @@ struct kvm_sysreg_masks {
|
||||
} mask[NR_SYS_REGS - __SANITISED_REG_START__];
|
||||
};
|
||||
|
||||
struct fgt_masks {
|
||||
const char *str;
|
||||
u64 mask;
|
||||
u64 nmask;
|
||||
u64 res0;
|
||||
};
|
||||
|
||||
extern struct fgt_masks hfgrtr_masks;
|
||||
extern struct fgt_masks hfgwtr_masks;
|
||||
extern struct fgt_masks hfgitr_masks;
|
||||
extern struct fgt_masks hdfgrtr_masks;
|
||||
extern struct fgt_masks hdfgwtr_masks;
|
||||
extern struct fgt_masks hafgrtr_masks;
|
||||
extern struct fgt_masks hfgrtr2_masks;
|
||||
extern struct fgt_masks hfgwtr2_masks;
|
||||
extern struct fgt_masks hfgitr2_masks;
|
||||
extern struct fgt_masks hdfgrtr2_masks;
|
||||
extern struct fgt_masks hdfgwtr2_masks;
|
||||
|
||||
extern struct fgt_masks kvm_nvhe_sym(hfgrtr_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hfgwtr_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hfgitr_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hdfgrtr_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hdfgwtr_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hafgrtr_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hfgrtr2_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hfgwtr2_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hfgitr2_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hdfgrtr2_masks);
|
||||
extern struct fgt_masks kvm_nvhe_sym(hdfgwtr2_masks);
|
||||
|
||||
struct kvm_cpu_context {
|
||||
struct user_pt_regs regs; /* sp = sp_el0 */
|
||||
|
||||
@@ -1552,12 +1594,16 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
|
||||
kvm_cmp_feat_signed(kvm, id, fld, op, limit) : \
|
||||
kvm_cmp_feat_unsigned(kvm, id, fld, op, limit))
|
||||
|
||||
#define kvm_has_feat(kvm, id, fld, limit) \
|
||||
#define __kvm_has_feat(kvm, id, fld, limit) \
|
||||
kvm_cmp_feat(kvm, id, fld, >=, limit)
|
||||
|
||||
#define kvm_has_feat_enum(kvm, id, fld, val) \
|
||||
#define kvm_has_feat(kvm, ...) __kvm_has_feat(kvm, __VA_ARGS__)
|
||||
|
||||
#define __kvm_has_feat_enum(kvm, id, fld, val) \
|
||||
kvm_cmp_feat_unsigned(kvm, id, fld, ==, val)
|
||||
|
||||
#define kvm_has_feat_enum(kvm, ...) __kvm_has_feat_enum(kvm, __VA_ARGS__)
|
||||
|
||||
#define kvm_has_feat_range(kvm, id, fld, min, max) \
|
||||
(kvm_cmp_feat(kvm, id, fld, >=, min) && \
|
||||
kvm_cmp_feat(kvm, id, fld, <=, max))
|
||||
@@ -1595,4 +1641,9 @@ static inline bool kvm_arch_has_irq_bypass(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt);
|
||||
void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *res1);
|
||||
void check_feature_map(void);
|
||||
|
||||
|
||||
#endif /* __ARM64_KVM_HOST_H__ */
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
|
||||
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
|
||||
|
||||
/* Data cache zero operations */
|
||||
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
|
||||
#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
|
||||
#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
|
||||
@@ -153,11 +154,13 @@
|
||||
#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)
|
||||
|
||||
#define SYS_DC_CIVAPS sys_insn(1, 0, 7, 15, 1)
|
||||
#define SYS_DC_CIGDVAPS sys_insn(1, 0, 7, 15, 5)
|
||||
|
||||
/*
|
||||
* Automatically generated definitions for system registers, the
|
||||
* manual encodings below are in the process of being converted to
|
||||
@@ -497,12 +500,22 @@
|
||||
|
||||
#define __PMEV_op2(n) ((n) & 0x7)
|
||||
#define __CNTR_CRm(n) (0x8 | (((n) >> 3) & 0x3))
|
||||
#define SYS_PMEVCNTSVRn_EL1(n) sys_reg(2, 0, 14, __CNTR_CRm(n), __PMEV_op2(n))
|
||||
#define SYS_PMEVCNTRn_EL0(n) sys_reg(3, 3, 14, __CNTR_CRm(n), __PMEV_op2(n))
|
||||
#define __TYPER_CRm(n) (0xc | (((n) >> 3) & 0x3))
|
||||
#define SYS_PMEVTYPERn_EL0(n) sys_reg(3, 3, 14, __TYPER_CRm(n), __PMEV_op2(n))
|
||||
|
||||
#define SYS_PMCCFILTR_EL0 sys_reg(3, 3, 14, 15, 7)
|
||||
|
||||
#define SYS_SPMCGCRn_EL1(n) sys_reg(2, 0, 9, 13, ((n) & 1))
|
||||
|
||||
#define __SPMEV_op2(n) ((n) & 0x7)
|
||||
#define __SPMEV_crm(p, n) ((((p) & 7) << 1) | (((n) >> 3) & 1))
|
||||
#define SYS_SPMEVCNTRn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b000, n), __SPMEV_op2(n))
|
||||
#define SYS_SPMEVFILT2Rn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b011, n), __SPMEV_op2(n))
|
||||
#define SYS_SPMEVFILTRn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b010, n), __SPMEV_op2(n))
|
||||
#define SYS_SPMEVTYPERn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b001, n), __SPMEV_op2(n))
|
||||
|
||||
#define SYS_VPIDR_EL2 sys_reg(3, 4, 0, 0, 0)
|
||||
#define SYS_VMPIDR_EL2 sys_reg(3, 4, 0, 0, 5)
|
||||
|
||||
@@ -522,7 +535,6 @@
|
||||
#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2)
|
||||
|
||||
#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
|
||||
#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)
|
||||
#define SYS_SP_EL1 sys_reg(3, 4, 4, 1, 0)
|
||||
@@ -608,28 +620,18 @@
|
||||
|
||||
/* VHE encodings for architectural EL0/1 system registers */
|
||||
#define SYS_BRBCR_EL12 sys_reg(2, 5, 9, 0, 0)
|
||||
#define SYS_SCTLR_EL12 sys_reg(3, 5, 1, 0, 0)
|
||||
#define SYS_CPACR_EL12 sys_reg(3, 5, 1, 0, 2)
|
||||
#define SYS_SCTLR2_EL12 sys_reg(3, 5, 1, 0, 3)
|
||||
#define SYS_ZCR_EL12 sys_reg(3, 5, 1, 2, 0)
|
||||
#define SYS_TRFCR_EL12 sys_reg(3, 5, 1, 2, 1)
|
||||
#define SYS_SMCR_EL12 sys_reg(3, 5, 1, 2, 6)
|
||||
#define SYS_TTBR0_EL12 sys_reg(3, 5, 2, 0, 0)
|
||||
#define SYS_TTBR1_EL12 sys_reg(3, 5, 2, 0, 1)
|
||||
#define SYS_TCR_EL12 sys_reg(3, 5, 2, 0, 2)
|
||||
#define SYS_TCR2_EL12 sys_reg(3, 5, 2, 0, 3)
|
||||
#define SYS_SPSR_EL12 sys_reg(3, 5, 4, 0, 0)
|
||||
#define SYS_ELR_EL12 sys_reg(3, 5, 4, 0, 1)
|
||||
#define SYS_AFSR0_EL12 sys_reg(3, 5, 5, 1, 0)
|
||||
#define SYS_AFSR1_EL12 sys_reg(3, 5, 5, 1, 1)
|
||||
#define SYS_ESR_EL12 sys_reg(3, 5, 5, 2, 0)
|
||||
#define SYS_TFSR_EL12 sys_reg(3, 5, 5, 6, 0)
|
||||
#define SYS_FAR_EL12 sys_reg(3, 5, 6, 0, 0)
|
||||
#define SYS_PMSCR_EL12 sys_reg(3, 5, 9, 9, 0)
|
||||
#define SYS_MAIR_EL12 sys_reg(3, 5, 10, 2, 0)
|
||||
#define SYS_AMAIR_EL12 sys_reg(3, 5, 10, 3, 0)
|
||||
#define SYS_VBAR_EL12 sys_reg(3, 5, 12, 0, 0)
|
||||
#define SYS_CONTEXTIDR_EL12 sys_reg(3, 5, 13, 0, 1)
|
||||
#define SYS_SCXTNUM_EL12 sys_reg(3, 5, 13, 0, 7)
|
||||
#define SYS_CNTKCTL_EL12 sys_reg(3, 5, 14, 1, 0)
|
||||
#define SYS_CNTP_TVAL_EL02 sys_reg(3, 5, 14, 2, 0)
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#define VNCR_CNTP_CTL_EL0 0x180
|
||||
#define VNCR_SCXTNUM_EL1 0x188
|
||||
#define VNCR_TFSR_EL1 0x190
|
||||
#define VNCR_HDFGRTR2_EL2 0x1A0
|
||||
#define VNCR_HDFGWTR2_EL2 0x1B0
|
||||
#define VNCR_HFGRTR_EL2 0x1B8
|
||||
#define VNCR_HFGWTR_EL2 0x1C0
|
||||
#define VNCR_HFGITR_EL2 0x1C8
|
||||
@@ -52,6 +54,9 @@
|
||||
#define VNCR_PIRE0_EL1 0x290
|
||||
#define VNCR_PIR_EL1 0x2A0
|
||||
#define VNCR_POR_EL1 0x2A8
|
||||
#define VNCR_HFGRTR2_EL2 0x2C0
|
||||
#define VNCR_HFGWTR2_EL2 0x2C8
|
||||
#define VNCR_HFGITR2_EL2 0x310
|
||||
#define VNCR_ICH_LR0_EL2 0x400
|
||||
#define VNCR_ICH_LR1_EL2 0x408
|
||||
#define VNCR_ICH_LR2_EL2 0x410
|
||||
|
||||
@@ -2877,6 +2877,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
.matches = has_cpuid_feature,
|
||||
ARM64_CPUID_FIELDS(ID_AA64MMFR0_EL1, FGT, IMP)
|
||||
},
|
||||
{
|
||||
.desc = "Fine Grained Traps 2",
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.capability = ARM64_HAS_FGT2,
|
||||
.matches = has_cpuid_feature,
|
||||
ARM64_CPUID_FIELDS(ID_AA64MMFR0_EL1, FGT, FGT2)
|
||||
},
|
||||
#ifdef CONFIG_ARM64_SME
|
||||
{
|
||||
.desc = "Scalable Matrix Extension",
|
||||
|
||||
@@ -14,7 +14,7 @@ CFLAGS_sys_regs.o += -Wno-override-init
|
||||
CFLAGS_handle_exit.o += -Wno-override-init
|
||||
|
||||
kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
|
||||
inject_fault.o va_layout.o handle_exit.o \
|
||||
inject_fault.o va_layout.o handle_exit.o config.o \
|
||||
guest.o debug.o reset.o sys_regs.o stacktrace.o \
|
||||
vgic-sys-reg-v3.o fpsimd.o pkvm.o \
|
||||
arch_timer.o trng.o vmid.o emulate-nested.o nested.o at.o \
|
||||
|
||||
@@ -2450,6 +2450,19 @@ static void kvm_hyp_init_symbols(void)
|
||||
kvm_nvhe_sym(__icache_flags) = __icache_flags;
|
||||
kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits;
|
||||
|
||||
/* Propagate the FGT state to the the nVHE side */
|
||||
kvm_nvhe_sym(hfgrtr_masks) = hfgrtr_masks;
|
||||
kvm_nvhe_sym(hfgwtr_masks) = hfgwtr_masks;
|
||||
kvm_nvhe_sym(hfgitr_masks) = hfgitr_masks;
|
||||
kvm_nvhe_sym(hdfgrtr_masks) = hdfgrtr_masks;
|
||||
kvm_nvhe_sym(hdfgwtr_masks) = hdfgwtr_masks;
|
||||
kvm_nvhe_sym(hafgrtr_masks) = hafgrtr_masks;
|
||||
kvm_nvhe_sym(hfgrtr2_masks) = hfgrtr2_masks;
|
||||
kvm_nvhe_sym(hfgwtr2_masks) = hfgwtr2_masks;
|
||||
kvm_nvhe_sym(hfgitr2_masks) = hfgitr2_masks;
|
||||
kvm_nvhe_sym(hdfgrtr2_masks)= hdfgrtr2_masks;
|
||||
kvm_nvhe_sym(hdfgwtr2_masks)= hdfgwtr2_masks;
|
||||
|
||||
/*
|
||||
* Flush entire BSS since part of its data containing init symbols is read
|
||||
* while the MMU is off.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+387
-196
@@ -622,6 +622,11 @@ struct encoding_to_trap_config {
|
||||
const unsigned int line;
|
||||
};
|
||||
|
||||
/*
|
||||
* WARNING: using ranges is a treacherous endeavour, as sysregs that
|
||||
* are part of an architectural range are not necessarily contiguous
|
||||
* in the [Op0,Op1,CRn,CRm,Ops] space. Tread carefully.
|
||||
*/
|
||||
#define SR_RANGE_TRAP(sr_start, sr_end, trap_id) \
|
||||
{ \
|
||||
.encoding = sr_start, \
|
||||
@@ -1279,98 +1284,128 @@ enum fg_filter_id {
|
||||
__NR_FG_FILTER_IDS__
|
||||
};
|
||||
|
||||
#define SR_FGF(sr, g, b, p, f) \
|
||||
{ \
|
||||
.encoding = sr, \
|
||||
.end = sr, \
|
||||
.tc = { \
|
||||
#define __FGT(g, b, p, f) \
|
||||
{ \
|
||||
.fgt = g ## _GROUP, \
|
||||
.bit = g ## _EL2_ ## b ## _SHIFT, \
|
||||
.pol = p, \
|
||||
.fgf = f, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define FGT(g, b, p) __FGT(g, b, p, __NO_FGF__)
|
||||
|
||||
/*
|
||||
* See the warning next to SR_RANGE_TRAP(), and apply the same
|
||||
* level of caution.
|
||||
*/
|
||||
#define SR_FGF_RANGE(sr, e, g, b, p, f) \
|
||||
{ \
|
||||
.encoding = sr, \
|
||||
.end = e, \
|
||||
.tc = __FGT(g, b, p, f), \
|
||||
.line = __LINE__, \
|
||||
}
|
||||
|
||||
#define SR_FGT(sr, g, b, p) SR_FGF(sr, g, b, p, __NO_FGF__)
|
||||
#define SR_FGF(sr, g, b, p, f) SR_FGF_RANGE(sr, sr, g, b, p, f)
|
||||
#define SR_FGT(sr, g, b, p) SR_FGF_RANGE(sr, sr, g, b, p, __NO_FGF__)
|
||||
#define SR_FGT_RANGE(sr, end, g, b, p) \
|
||||
SR_FGF_RANGE(sr, end, g, b, p, __NO_FGF__)
|
||||
|
||||
static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
|
||||
/* HFGRTR_EL2, HFGWTR_EL2 */
|
||||
SR_FGT(SYS_AMAIR2_EL1, HFGxTR, nAMAIR2_EL1, 0),
|
||||
SR_FGT(SYS_MAIR2_EL1, HFGxTR, nMAIR2_EL1, 0),
|
||||
SR_FGT(SYS_S2POR_EL1, HFGxTR, nS2POR_EL1, 0),
|
||||
SR_FGT(SYS_POR_EL1, HFGxTR, nPOR_EL1, 0),
|
||||
SR_FGT(SYS_POR_EL0, HFGxTR, nPOR_EL0, 0),
|
||||
SR_FGT(SYS_PIR_EL1, HFGxTR, nPIR_EL1, 0),
|
||||
SR_FGT(SYS_PIRE0_EL1, HFGxTR, nPIRE0_EL1, 0),
|
||||
SR_FGT(SYS_RCWMASK_EL1, HFGxTR, nRCWMASK_EL1, 0),
|
||||
SR_FGT(SYS_TPIDR2_EL0, HFGxTR, nTPIDR2_EL0, 0),
|
||||
SR_FGT(SYS_SMPRI_EL1, HFGxTR, nSMPRI_EL1, 0),
|
||||
SR_FGT(SYS_GCSCR_EL1, HFGxTR, nGCS_EL1, 0),
|
||||
SR_FGT(SYS_GCSPR_EL1, HFGxTR, nGCS_EL1, 0),
|
||||
SR_FGT(SYS_GCSCRE0_EL1, HFGxTR, nGCS_EL0, 0),
|
||||
SR_FGT(SYS_GCSPR_EL0, HFGxTR, nGCS_EL0, 0),
|
||||
SR_FGT(SYS_ACCDATA_EL1, HFGxTR, nACCDATA_EL1, 0),
|
||||
SR_FGT(SYS_ERXADDR_EL1, HFGxTR, ERXADDR_EL1, 1),
|
||||
SR_FGT(SYS_ERXPFGCDN_EL1, HFGxTR, ERXPFGCDN_EL1, 1),
|
||||
SR_FGT(SYS_ERXPFGCTL_EL1, HFGxTR, ERXPFGCTL_EL1, 1),
|
||||
SR_FGT(SYS_ERXPFGF_EL1, HFGxTR, ERXPFGF_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC0_EL1, HFGxTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC1_EL1, HFGxTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC2_EL1, HFGxTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC3_EL1, HFGxTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXSTATUS_EL1, HFGxTR, ERXSTATUS_EL1, 1),
|
||||
SR_FGT(SYS_ERXCTLR_EL1, HFGxTR, ERXCTLR_EL1, 1),
|
||||
SR_FGT(SYS_ERXFR_EL1, HFGxTR, ERXFR_EL1, 1),
|
||||
SR_FGT(SYS_ERRSELR_EL1, HFGxTR, ERRSELR_EL1, 1),
|
||||
SR_FGT(SYS_ERRIDR_EL1, HFGxTR, ERRIDR_EL1, 1),
|
||||
SR_FGT(SYS_ICC_IGRPEN0_EL1, HFGxTR, ICC_IGRPENn_EL1, 1),
|
||||
SR_FGT(SYS_ICC_IGRPEN1_EL1, HFGxTR, ICC_IGRPENn_EL1, 1),
|
||||
SR_FGT(SYS_VBAR_EL1, HFGxTR, VBAR_EL1, 1),
|
||||
SR_FGT(SYS_TTBR1_EL1, HFGxTR, TTBR1_EL1, 1),
|
||||
SR_FGT(SYS_TTBR0_EL1, HFGxTR, TTBR0_EL1, 1),
|
||||
SR_FGT(SYS_TPIDR_EL0, HFGxTR, TPIDR_EL0, 1),
|
||||
SR_FGT(SYS_TPIDRRO_EL0, HFGxTR, TPIDRRO_EL0, 1),
|
||||
SR_FGT(SYS_TPIDR_EL1, HFGxTR, TPIDR_EL1, 1),
|
||||
SR_FGT(SYS_TCR_EL1, HFGxTR, TCR_EL1, 1),
|
||||
SR_FGT(SYS_TCR2_EL1, HFGxTR, TCR_EL1, 1),
|
||||
SR_FGT(SYS_SCXTNUM_EL0, HFGxTR, SCXTNUM_EL0, 1),
|
||||
SR_FGT(SYS_SCXTNUM_EL1, HFGxTR, SCXTNUM_EL1, 1),
|
||||
SR_FGT(SYS_SCTLR_EL1, HFGxTR, SCTLR_EL1, 1),
|
||||
SR_FGT(SYS_REVIDR_EL1, HFGxTR, REVIDR_EL1, 1),
|
||||
SR_FGT(SYS_PAR_EL1, HFGxTR, PAR_EL1, 1),
|
||||
SR_FGT(SYS_MPIDR_EL1, HFGxTR, MPIDR_EL1, 1),
|
||||
SR_FGT(SYS_MIDR_EL1, HFGxTR, MIDR_EL1, 1),
|
||||
SR_FGT(SYS_MAIR_EL1, HFGxTR, MAIR_EL1, 1),
|
||||
SR_FGT(SYS_LORSA_EL1, HFGxTR, LORSA_EL1, 1),
|
||||
SR_FGT(SYS_LORN_EL1, HFGxTR, LORN_EL1, 1),
|
||||
SR_FGT(SYS_LORID_EL1, HFGxTR, LORID_EL1, 1),
|
||||
SR_FGT(SYS_LOREA_EL1, HFGxTR, LOREA_EL1, 1),
|
||||
SR_FGT(SYS_LORC_EL1, HFGxTR, LORC_EL1, 1),
|
||||
SR_FGT(SYS_ISR_EL1, HFGxTR, ISR_EL1, 1),
|
||||
SR_FGT(SYS_FAR_EL1, HFGxTR, FAR_EL1, 1),
|
||||
SR_FGT(SYS_ESR_EL1, HFGxTR, ESR_EL1, 1),
|
||||
SR_FGT(SYS_DCZID_EL0, HFGxTR, DCZID_EL0, 1),
|
||||
SR_FGT(SYS_CTR_EL0, HFGxTR, CTR_EL0, 1),
|
||||
SR_FGT(SYS_CSSELR_EL1, HFGxTR, CSSELR_EL1, 1),
|
||||
SR_FGT(SYS_CPACR_EL1, HFGxTR, CPACR_EL1, 1),
|
||||
SR_FGT(SYS_CONTEXTIDR_EL1, HFGxTR, CONTEXTIDR_EL1, 1),
|
||||
SR_FGT(SYS_CLIDR_EL1, HFGxTR, CLIDR_EL1, 1),
|
||||
SR_FGT(SYS_CCSIDR_EL1, HFGxTR, CCSIDR_EL1, 1),
|
||||
SR_FGT(SYS_APIBKEYLO_EL1, HFGxTR, APIBKey, 1),
|
||||
SR_FGT(SYS_APIBKEYHI_EL1, HFGxTR, APIBKey, 1),
|
||||
SR_FGT(SYS_APIAKEYLO_EL1, HFGxTR, APIAKey, 1),
|
||||
SR_FGT(SYS_APIAKEYHI_EL1, HFGxTR, APIAKey, 1),
|
||||
SR_FGT(SYS_APGAKEYLO_EL1, HFGxTR, APGAKey, 1),
|
||||
SR_FGT(SYS_APGAKEYHI_EL1, HFGxTR, APGAKey, 1),
|
||||
SR_FGT(SYS_APDBKEYLO_EL1, HFGxTR, APDBKey, 1),
|
||||
SR_FGT(SYS_APDBKEYHI_EL1, HFGxTR, APDBKey, 1),
|
||||
SR_FGT(SYS_APDAKEYLO_EL1, HFGxTR, APDAKey, 1),
|
||||
SR_FGT(SYS_APDAKEYHI_EL1, HFGxTR, APDAKey, 1),
|
||||
SR_FGT(SYS_AMAIR_EL1, HFGxTR, AMAIR_EL1, 1),
|
||||
SR_FGT(SYS_AIDR_EL1, HFGxTR, AIDR_EL1, 1),
|
||||
SR_FGT(SYS_AFSR1_EL1, HFGxTR, AFSR1_EL1, 1),
|
||||
SR_FGT(SYS_AFSR0_EL1, HFGxTR, AFSR0_EL1, 1),
|
||||
SR_FGT(SYS_AMAIR2_EL1, HFGRTR, nAMAIR2_EL1, 0),
|
||||
SR_FGT(SYS_MAIR2_EL1, HFGRTR, nMAIR2_EL1, 0),
|
||||
SR_FGT(SYS_S2POR_EL1, HFGRTR, nS2POR_EL1, 0),
|
||||
SR_FGT(SYS_POR_EL1, HFGRTR, nPOR_EL1, 0),
|
||||
SR_FGT(SYS_POR_EL0, HFGRTR, nPOR_EL0, 0),
|
||||
SR_FGT(SYS_PIR_EL1, HFGRTR, nPIR_EL1, 0),
|
||||
SR_FGT(SYS_PIRE0_EL1, HFGRTR, nPIRE0_EL1, 0),
|
||||
SR_FGT(SYS_RCWMASK_EL1, HFGRTR, nRCWMASK_EL1, 0),
|
||||
SR_FGT(SYS_TPIDR2_EL0, HFGRTR, nTPIDR2_EL0, 0),
|
||||
SR_FGT(SYS_SMPRI_EL1, HFGRTR, nSMPRI_EL1, 0),
|
||||
SR_FGT(SYS_GCSCR_EL1, HFGRTR, nGCS_EL1, 0),
|
||||
SR_FGT(SYS_GCSPR_EL1, HFGRTR, nGCS_EL1, 0),
|
||||
SR_FGT(SYS_GCSCRE0_EL1, HFGRTR, nGCS_EL0, 0),
|
||||
SR_FGT(SYS_GCSPR_EL0, HFGRTR, nGCS_EL0, 0),
|
||||
SR_FGT(SYS_ACCDATA_EL1, HFGRTR, nACCDATA_EL1, 0),
|
||||
SR_FGT(SYS_ERXADDR_EL1, HFGRTR, ERXADDR_EL1, 1),
|
||||
SR_FGT(SYS_ERXPFGCDN_EL1, HFGRTR, ERXPFGCDN_EL1, 1),
|
||||
SR_FGT(SYS_ERXPFGCTL_EL1, HFGRTR, ERXPFGCTL_EL1, 1),
|
||||
SR_FGT(SYS_ERXPFGF_EL1, HFGRTR, ERXPFGF_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC0_EL1, HFGRTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC1_EL1, HFGRTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC2_EL1, HFGRTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXMISC3_EL1, HFGRTR, ERXMISCn_EL1, 1),
|
||||
SR_FGT(SYS_ERXSTATUS_EL1, HFGRTR, ERXSTATUS_EL1, 1),
|
||||
SR_FGT(SYS_ERXCTLR_EL1, HFGRTR, ERXCTLR_EL1, 1),
|
||||
SR_FGT(SYS_ERXFR_EL1, HFGRTR, ERXFR_EL1, 1),
|
||||
SR_FGT(SYS_ERRSELR_EL1, HFGRTR, ERRSELR_EL1, 1),
|
||||
SR_FGT(SYS_ERRIDR_EL1, HFGRTR, ERRIDR_EL1, 1),
|
||||
SR_FGT(SYS_ICC_IGRPEN0_EL1, HFGRTR, ICC_IGRPENn_EL1, 1),
|
||||
SR_FGT(SYS_ICC_IGRPEN1_EL1, HFGRTR, ICC_IGRPENn_EL1, 1),
|
||||
SR_FGT(SYS_VBAR_EL1, HFGRTR, VBAR_EL1, 1),
|
||||
SR_FGT(SYS_TTBR1_EL1, HFGRTR, TTBR1_EL1, 1),
|
||||
SR_FGT(SYS_TTBR0_EL1, HFGRTR, TTBR0_EL1, 1),
|
||||
SR_FGT(SYS_TPIDR_EL0, HFGRTR, TPIDR_EL0, 1),
|
||||
SR_FGT(SYS_TPIDRRO_EL0, HFGRTR, TPIDRRO_EL0, 1),
|
||||
SR_FGT(SYS_TPIDR_EL1, HFGRTR, TPIDR_EL1, 1),
|
||||
SR_FGT(SYS_TCR_EL1, HFGRTR, TCR_EL1, 1),
|
||||
SR_FGT(SYS_TCR2_EL1, HFGRTR, TCR_EL1, 1),
|
||||
SR_FGT(SYS_SCXTNUM_EL0, HFGRTR, SCXTNUM_EL0, 1),
|
||||
SR_FGT(SYS_SCXTNUM_EL1, HFGRTR, SCXTNUM_EL1, 1),
|
||||
SR_FGT(SYS_SCTLR_EL1, HFGRTR, SCTLR_EL1, 1),
|
||||
SR_FGT(SYS_REVIDR_EL1, HFGRTR, REVIDR_EL1, 1),
|
||||
SR_FGT(SYS_PAR_EL1, HFGRTR, PAR_EL1, 1),
|
||||
SR_FGT(SYS_MPIDR_EL1, HFGRTR, MPIDR_EL1, 1),
|
||||
SR_FGT(SYS_MIDR_EL1, HFGRTR, MIDR_EL1, 1),
|
||||
SR_FGT(SYS_MAIR_EL1, HFGRTR, MAIR_EL1, 1),
|
||||
SR_FGT(SYS_LORSA_EL1, HFGRTR, LORSA_EL1, 1),
|
||||
SR_FGT(SYS_LORN_EL1, HFGRTR, LORN_EL1, 1),
|
||||
SR_FGT(SYS_LORID_EL1, HFGRTR, LORID_EL1, 1),
|
||||
SR_FGT(SYS_LOREA_EL1, HFGRTR, LOREA_EL1, 1),
|
||||
SR_FGT(SYS_LORC_EL1, HFGRTR, LORC_EL1, 1),
|
||||
SR_FGT(SYS_ISR_EL1, HFGRTR, ISR_EL1, 1),
|
||||
SR_FGT(SYS_FAR_EL1, HFGRTR, FAR_EL1, 1),
|
||||
SR_FGT(SYS_ESR_EL1, HFGRTR, ESR_EL1, 1),
|
||||
SR_FGT(SYS_DCZID_EL0, HFGRTR, DCZID_EL0, 1),
|
||||
SR_FGT(SYS_CTR_EL0, HFGRTR, CTR_EL0, 1),
|
||||
SR_FGT(SYS_CSSELR_EL1, HFGRTR, CSSELR_EL1, 1),
|
||||
SR_FGT(SYS_CPACR_EL1, HFGRTR, CPACR_EL1, 1),
|
||||
SR_FGT(SYS_CONTEXTIDR_EL1, HFGRTR, CONTEXTIDR_EL1, 1),
|
||||
SR_FGT(SYS_CLIDR_EL1, HFGRTR, CLIDR_EL1, 1),
|
||||
SR_FGT(SYS_CCSIDR_EL1, HFGRTR, CCSIDR_EL1, 1),
|
||||
SR_FGT(SYS_APIBKEYLO_EL1, HFGRTR, APIBKey, 1),
|
||||
SR_FGT(SYS_APIBKEYHI_EL1, HFGRTR, APIBKey, 1),
|
||||
SR_FGT(SYS_APIAKEYLO_EL1, HFGRTR, APIAKey, 1),
|
||||
SR_FGT(SYS_APIAKEYHI_EL1, HFGRTR, APIAKey, 1),
|
||||
SR_FGT(SYS_APGAKEYLO_EL1, HFGRTR, APGAKey, 1),
|
||||
SR_FGT(SYS_APGAKEYHI_EL1, HFGRTR, APGAKey, 1),
|
||||
SR_FGT(SYS_APDBKEYLO_EL1, HFGRTR, APDBKey, 1),
|
||||
SR_FGT(SYS_APDBKEYHI_EL1, HFGRTR, APDBKey, 1),
|
||||
SR_FGT(SYS_APDAKEYLO_EL1, HFGRTR, APDAKey, 1),
|
||||
SR_FGT(SYS_APDAKEYHI_EL1, HFGRTR, APDAKey, 1),
|
||||
SR_FGT(SYS_AMAIR_EL1, HFGRTR, AMAIR_EL1, 1),
|
||||
SR_FGT(SYS_AIDR_EL1, HFGRTR, AIDR_EL1, 1),
|
||||
SR_FGT(SYS_AFSR1_EL1, HFGRTR, AFSR1_EL1, 1),
|
||||
SR_FGT(SYS_AFSR0_EL1, HFGRTR, AFSR0_EL1, 1),
|
||||
|
||||
/* HFGRTR2_EL2, HFGWTR2_EL2 */
|
||||
SR_FGT(SYS_ACTLRALIAS_EL1, HFGRTR2, nACTLRALIAS_EL1, 0),
|
||||
SR_FGT(SYS_ACTLRMASK_EL1, HFGRTR2, nACTLRMASK_EL1, 0),
|
||||
SR_FGT(SYS_CPACRALIAS_EL1, HFGRTR2, nCPACRALIAS_EL1, 0),
|
||||
SR_FGT(SYS_CPACRMASK_EL1, HFGRTR2, nCPACRMASK_EL1, 0),
|
||||
SR_FGT(SYS_PFAR_EL1, HFGRTR2, nPFAR_EL1, 0),
|
||||
SR_FGT(SYS_RCWSMASK_EL1, HFGRTR2, nRCWSMASK_EL1, 0),
|
||||
SR_FGT(SYS_SCTLR2ALIAS_EL1, HFGRTR2, nSCTLRALIAS2_EL1, 0),
|
||||
SR_FGT(SYS_SCTLR2MASK_EL1, HFGRTR2, nSCTLR2MASK_EL1, 0),
|
||||
SR_FGT(SYS_SCTLRALIAS_EL1, HFGRTR2, nSCTLRALIAS_EL1, 0),
|
||||
SR_FGT(SYS_SCTLRMASK_EL1, HFGRTR2, nSCTLRMASK_EL1, 0),
|
||||
SR_FGT(SYS_TCR2ALIAS_EL1, HFGRTR2, nTCR2ALIAS_EL1, 0),
|
||||
SR_FGT(SYS_TCR2MASK_EL1, HFGRTR2, nTCR2MASK_EL1, 0),
|
||||
SR_FGT(SYS_TCRALIAS_EL1, HFGRTR2, nTCRALIAS_EL1, 0),
|
||||
SR_FGT(SYS_TCRMASK_EL1, HFGRTR2, nTCRMASK_EL1, 0),
|
||||
SR_FGT(SYS_ERXGSR_EL1, HFGRTR2, nERXGSR_EL1, 0),
|
||||
|
||||
/* HFGITR_EL2 */
|
||||
SR_FGT(OP_AT_S1E1A, HFGITR, ATS1E1A, 1),
|
||||
SR_FGT(OP_COSP_RCTX, HFGITR, COSPRCTX, 1),
|
||||
@@ -1480,6 +1515,11 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
|
||||
SR_FGT(SYS_IC_IVAU, HFGITR, ICIVAU, 1),
|
||||
SR_FGT(SYS_IC_IALLU, HFGITR, ICIALLU, 1),
|
||||
SR_FGT(SYS_IC_IALLUIS, HFGITR, ICIALLUIS, 1),
|
||||
|
||||
/* HFGITR2_EL2 */
|
||||
SR_FGT(SYS_DC_CIGDVAPS, HFGITR2, nDCCIVAPS, 0),
|
||||
SR_FGT(SYS_DC_CIVAPS, HFGITR2, nDCCIVAPS, 0),
|
||||
|
||||
/* HDFGRTR_EL2 */
|
||||
SR_FGT(SYS_PMBIDR_EL1, HDFGRTR, PMBIDR_EL1, 1),
|
||||
SR_FGT(SYS_PMSNEVFR_EL1, HDFGRTR, nPMSNEVFR_EL1, 0),
|
||||
@@ -1789,68 +1829,12 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
|
||||
SR_FGT(SYS_PMCNTENSET_EL0, HDFGRTR, PMCNTEN, 1),
|
||||
SR_FGT(SYS_PMCCNTR_EL0, HDFGRTR, PMCCNTR_EL0, 1),
|
||||
SR_FGT(SYS_PMCCFILTR_EL0, HDFGRTR, PMCCFILTR_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(0), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(1), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(2), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(3), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(4), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(5), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(6), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(7), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(8), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(9), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(10), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(11), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(12), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(13), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(14), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(15), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(16), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(17), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(18), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(19), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(20), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(21), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(22), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(23), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(24), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(25), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(26), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(27), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(28), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(29), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVTYPERn_EL0(30), HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(0), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(1), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(2), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(3), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(4), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(5), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(6), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(7), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(8), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(9), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(10), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(11), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(12), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(13), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(14), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(15), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(16), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(17), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(18), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(19), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(20), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(21), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(22), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(23), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(24), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(25), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(26), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(27), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(28), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(29), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_PMEVCNTRn_EL0(30), HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT_RANGE(SYS_PMEVTYPERn_EL0(0),
|
||||
SYS_PMEVTYPERn_EL0(30),
|
||||
HDFGRTR, PMEVTYPERn_EL0, 1),
|
||||
SR_FGT_RANGE(SYS_PMEVCNTRn_EL0(0),
|
||||
SYS_PMEVCNTRn_EL0(30),
|
||||
HDFGRTR, PMEVCNTRn_EL0, 1),
|
||||
SR_FGT(SYS_OSDLR_EL1, HDFGRTR, OSDLR_EL1, 1),
|
||||
SR_FGT(SYS_OSECCR_EL1, HDFGRTR, OSECCR_EL1, 1),
|
||||
SR_FGT(SYS_OSLSR_EL1, HDFGRTR, OSLSR_EL1, 1),
|
||||
@@ -1928,6 +1912,59 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
|
||||
SR_FGT(SYS_DBGBCRn_EL1(13), HDFGRTR, DBGBCRn_EL1, 1),
|
||||
SR_FGT(SYS_DBGBCRn_EL1(14), HDFGRTR, DBGBCRn_EL1, 1),
|
||||
SR_FGT(SYS_DBGBCRn_EL1(15), HDFGRTR, DBGBCRn_EL1, 1),
|
||||
|
||||
/* HDFGRTR2_EL2 */
|
||||
SR_FGT(SYS_MDSELR_EL1, HDFGRTR2, nMDSELR_EL1, 0),
|
||||
SR_FGT(SYS_MDSTEPOP_EL1, HDFGRTR2, nMDSTEPOP_EL1, 0),
|
||||
SR_FGT(SYS_PMCCNTSVR_EL1, HDFGRTR2, nPMSSDATA, 0),
|
||||
SR_FGT_RANGE(SYS_PMEVCNTSVRn_EL1(0),
|
||||
SYS_PMEVCNTSVRn_EL1(30),
|
||||
HDFGRTR2, nPMSSDATA, 0),
|
||||
SR_FGT(SYS_PMICNTSVR_EL1, HDFGRTR2, nPMSSDATA, 0),
|
||||
SR_FGT(SYS_PMECR_EL1, HDFGRTR2, nPMECR_EL1, 0),
|
||||
SR_FGT(SYS_PMIAR_EL1, HDFGRTR2, nPMIAR_EL1, 0),
|
||||
SR_FGT(SYS_PMICFILTR_EL0, HDFGRTR2, nPMICFILTR_EL0, 0),
|
||||
SR_FGT(SYS_PMICNTR_EL0, HDFGRTR2, nPMICNTR_EL0, 0),
|
||||
SR_FGT(SYS_PMSSCR_EL1, HDFGRTR2, nPMSSCR_EL1, 0),
|
||||
SR_FGT(SYS_PMUACR_EL1, HDFGRTR2, nPMUACR_EL1, 0),
|
||||
SR_FGT(SYS_SPMACCESSR_EL1, HDFGRTR2, nSPMACCESSR_EL1, 0),
|
||||
SR_FGT(SYS_SPMCFGR_EL1, HDFGRTR2, nSPMID, 0),
|
||||
SR_FGT(SYS_SPMDEVARCH_EL1, HDFGRTR2, nSPMID, 0),
|
||||
SR_FGT(SYS_SPMCGCRn_EL1(0), HDFGRTR2, nSPMID, 0),
|
||||
SR_FGT(SYS_SPMCGCRn_EL1(1), HDFGRTR2, nSPMID, 0),
|
||||
SR_FGT(SYS_SPMIIDR_EL1, HDFGRTR2, nSPMID, 0),
|
||||
SR_FGT(SYS_SPMCNTENCLR_EL0, HDFGRTR2, nSPMCNTEN, 0),
|
||||
SR_FGT(SYS_SPMCNTENSET_EL0, HDFGRTR2, nSPMCNTEN, 0),
|
||||
SR_FGT(SYS_SPMCR_EL0, HDFGRTR2, nSPMCR_EL0, 0),
|
||||
SR_FGT(SYS_SPMDEVAFF_EL1, HDFGRTR2, nSPMDEVAFF_EL1, 0),
|
||||
/*
|
||||
* We have up to 64 of these registers in ranges of 16, banked via
|
||||
* SPMSELR_EL0.BANK. We're only concerned with the accessors here,
|
||||
* not the architectural registers.
|
||||
*/
|
||||
SR_FGT_RANGE(SYS_SPMEVCNTRn_EL0(0),
|
||||
SYS_SPMEVCNTRn_EL0(15),
|
||||
HDFGRTR2, nSPMEVCNTRn_EL0, 0),
|
||||
SR_FGT_RANGE(SYS_SPMEVFILT2Rn_EL0(0),
|
||||
SYS_SPMEVFILT2Rn_EL0(15),
|
||||
HDFGRTR2, nSPMEVTYPERn_EL0, 0),
|
||||
SR_FGT_RANGE(SYS_SPMEVFILTRn_EL0(0),
|
||||
SYS_SPMEVFILTRn_EL0(15),
|
||||
HDFGRTR2, nSPMEVTYPERn_EL0, 0),
|
||||
SR_FGT_RANGE(SYS_SPMEVTYPERn_EL0(0),
|
||||
SYS_SPMEVTYPERn_EL0(15),
|
||||
HDFGRTR2, nSPMEVTYPERn_EL0, 0),
|
||||
SR_FGT(SYS_SPMINTENCLR_EL1, HDFGRTR2, nSPMINTEN, 0),
|
||||
SR_FGT(SYS_SPMINTENSET_EL1, HDFGRTR2, nSPMINTEN, 0),
|
||||
SR_FGT(SYS_SPMOVSCLR_EL0, HDFGRTR2, nSPMOVS, 0),
|
||||
SR_FGT(SYS_SPMOVSSET_EL0, HDFGRTR2, nSPMOVS, 0),
|
||||
SR_FGT(SYS_SPMSCR_EL1, HDFGRTR2, nSPMSCR_EL1, 0),
|
||||
SR_FGT(SYS_SPMSELR_EL0, HDFGRTR2, nSPMSELR_EL0, 0),
|
||||
SR_FGT(SYS_TRCITECR_EL1, HDFGRTR2, nTRCITECR_EL1, 0),
|
||||
SR_FGT(SYS_PMBMAR_EL1, HDFGRTR2, nPMBMAR_EL1, 0),
|
||||
SR_FGT(SYS_PMSDSFR_EL1, HDFGRTR2, nPMSDSFR_EL1, 0),
|
||||
SR_FGT(SYS_TRBMPAM_EL1, HDFGRTR2, nTRBMPAM_EL1, 0),
|
||||
|
||||
/*
|
||||
* HDFGWTR_EL2
|
||||
*
|
||||
@@ -1938,12 +1975,19 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
|
||||
* read-side mappings, and only the write-side mappings that
|
||||
* differ from the read side, and the trap handler will pick
|
||||
* the correct shadow register based on the access type.
|
||||
*
|
||||
* Same model applies to the FEAT_FGT2 registers.
|
||||
*/
|
||||
SR_FGT(SYS_TRFCR_EL1, HDFGWTR, TRFCR_EL1, 1),
|
||||
SR_FGT(SYS_TRCOSLAR, HDFGWTR, TRCOSLAR, 1),
|
||||
SR_FGT(SYS_PMCR_EL0, HDFGWTR, PMCR_EL0, 1),
|
||||
SR_FGT(SYS_PMSWINC_EL0, HDFGWTR, PMSWINC_EL0, 1),
|
||||
SR_FGT(SYS_OSLAR_EL1, HDFGWTR, OSLAR_EL1, 1),
|
||||
|
||||
/* HDFGWTR2_EL2 */
|
||||
SR_FGT(SYS_PMZR_EL0, HDFGWTR2, nPMZR_EL0, 0),
|
||||
SR_FGT(SYS_SPMZR_EL0, HDFGWTR2, nSPMEVCNTRn_EL0, 0),
|
||||
|
||||
/*
|
||||
* HAFGRTR_EL2
|
||||
*/
|
||||
@@ -1989,6 +2033,20 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
|
||||
SR_FGT(SYS_AMEVCNTR0_EL0(0), HAFGRTR, AMEVCNTR00_EL0, 1),
|
||||
};
|
||||
|
||||
/*
|
||||
* Additional FGTs that do not fire with ESR_EL2.EC==0x18. This table
|
||||
* isn't used for exception routing, but only as a promise that the
|
||||
* trap is handled somewhere else.
|
||||
*/
|
||||
static const union trap_config non_0x18_fgt[] __initconst = {
|
||||
FGT(HFGITR, PSBCSYNC, 1),
|
||||
FGT(HFGITR, nGCSSTR_EL1, 0),
|
||||
FGT(HFGITR, SVC_EL1, 1),
|
||||
FGT(HFGITR, SVC_EL0, 1),
|
||||
FGT(HFGITR, ERET, 1),
|
||||
FGT(HFGITR2, TSBCSYNC, 1),
|
||||
};
|
||||
|
||||
static union trap_config get_trap_config(u32 sysreg)
|
||||
{
|
||||
return (union trap_config) {
|
||||
@@ -2033,6 +2091,130 @@ static u32 encoding_next(u32 encoding)
|
||||
return sys_reg(op0 + 1, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define FGT_MASKS(__n, __m) \
|
||||
struct fgt_masks __n = { .str = #__m, .res0 = __m, }
|
||||
|
||||
FGT_MASKS(hfgrtr_masks, HFGRTR_EL2_RES0);
|
||||
FGT_MASKS(hfgwtr_masks, HFGWTR_EL2_RES0);
|
||||
FGT_MASKS(hfgitr_masks, HFGITR_EL2_RES0);
|
||||
FGT_MASKS(hdfgrtr_masks, HDFGRTR_EL2_RES0);
|
||||
FGT_MASKS(hdfgwtr_masks, HDFGWTR_EL2_RES0);
|
||||
FGT_MASKS(hafgrtr_masks, HAFGRTR_EL2_RES0);
|
||||
FGT_MASKS(hfgrtr2_masks, HFGRTR2_EL2_RES0);
|
||||
FGT_MASKS(hfgwtr2_masks, HFGWTR2_EL2_RES0);
|
||||
FGT_MASKS(hfgitr2_masks, HFGITR2_EL2_RES0);
|
||||
FGT_MASKS(hdfgrtr2_masks, HDFGRTR2_EL2_RES0);
|
||||
FGT_MASKS(hdfgwtr2_masks, HDFGWTR2_EL2_RES0);
|
||||
|
||||
static __init bool aggregate_fgt(union trap_config tc)
|
||||
{
|
||||
struct fgt_masks *rmasks, *wmasks;
|
||||
|
||||
switch (tc.fgt) {
|
||||
case HFGRTR_GROUP:
|
||||
rmasks = &hfgrtr_masks;
|
||||
wmasks = &hfgwtr_masks;
|
||||
break;
|
||||
case HDFGRTR_GROUP:
|
||||
rmasks = &hdfgrtr_masks;
|
||||
wmasks = &hdfgwtr_masks;
|
||||
break;
|
||||
case HAFGRTR_GROUP:
|
||||
rmasks = &hafgrtr_masks;
|
||||
wmasks = NULL;
|
||||
break;
|
||||
case HFGITR_GROUP:
|
||||
rmasks = &hfgitr_masks;
|
||||
wmasks = NULL;
|
||||
break;
|
||||
case HFGRTR2_GROUP:
|
||||
rmasks = &hfgrtr2_masks;
|
||||
wmasks = &hfgwtr2_masks;
|
||||
break;
|
||||
case HDFGRTR2_GROUP:
|
||||
rmasks = &hdfgrtr2_masks;
|
||||
wmasks = &hdfgwtr2_masks;
|
||||
break;
|
||||
case HFGITR2_GROUP:
|
||||
rmasks = &hfgitr2_masks;
|
||||
wmasks = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* A bit can be reserved in either the R or W register, but
|
||||
* not both.
|
||||
*/
|
||||
if ((BIT(tc.bit) & rmasks->res0) &&
|
||||
(!wmasks || (BIT(tc.bit) & wmasks->res0)))
|
||||
return false;
|
||||
|
||||
if (tc.pol)
|
||||
rmasks->mask |= BIT(tc.bit) & ~rmasks->res0;
|
||||
else
|
||||
rmasks->nmask |= BIT(tc.bit) & ~rmasks->res0;
|
||||
|
||||
if (wmasks) {
|
||||
if (tc.pol)
|
||||
wmasks->mask |= BIT(tc.bit) & ~wmasks->res0;
|
||||
else
|
||||
wmasks->nmask |= BIT(tc.bit) & ~wmasks->res0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static __init int check_fgt_masks(struct fgt_masks *masks)
|
||||
{
|
||||
unsigned long duplicate = masks->mask & masks->nmask;
|
||||
u64 res0 = masks->res0;
|
||||
int ret = 0;
|
||||
|
||||
if (duplicate) {
|
||||
int i;
|
||||
|
||||
for_each_set_bit(i, &duplicate, 64) {
|
||||
kvm_err("%s[%d] bit has both polarities\n",
|
||||
masks->str, i);
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
masks->res0 = ~(masks->mask | masks->nmask);
|
||||
if (masks->res0 != res0)
|
||||
kvm_info("Implicit %s = %016llx, expecting %016llx\n",
|
||||
masks->str, masks->res0, res0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __init int check_all_fgt_masks(int ret)
|
||||
{
|
||||
static struct fgt_masks * const masks[] __initconst = {
|
||||
&hfgrtr_masks,
|
||||
&hfgwtr_masks,
|
||||
&hfgitr_masks,
|
||||
&hdfgrtr_masks,
|
||||
&hdfgwtr_masks,
|
||||
&hafgrtr_masks,
|
||||
&hfgrtr2_masks,
|
||||
&hfgwtr2_masks,
|
||||
&hfgitr2_masks,
|
||||
&hdfgrtr2_masks,
|
||||
&hdfgwtr2_masks,
|
||||
};
|
||||
int err = 0;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(masks); i++)
|
||||
err |= check_fgt_masks(masks[i]);
|
||||
|
||||
return ret ?: err;
|
||||
}
|
||||
|
||||
#define for_each_encoding_in(__x, __s, __e) \
|
||||
for (u32 __x = __s; __x <= __e; __x = encoding_next(__x))
|
||||
|
||||
int __init populate_nv_trap_config(void)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -2041,6 +2223,7 @@ int __init populate_nv_trap_config(void)
|
||||
BUILD_BUG_ON(__NR_CGT_GROUP_IDS__ > BIT(TC_CGT_BITS));
|
||||
BUILD_BUG_ON(__NR_FGT_GROUP_IDS__ > BIT(TC_FGT_BITS));
|
||||
BUILD_BUG_ON(__NR_FG_FILTER_IDS__ > BIT(TC_FGF_BITS));
|
||||
BUILD_BUG_ON(__HCRX_EL2_MASK & __HCRX_EL2_nMASK);
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(encoding_to_cgt); i++) {
|
||||
const struct encoding_to_trap_config *cgt = &encoding_to_cgt[i];
|
||||
@@ -2051,7 +2234,7 @@ int __init populate_nv_trap_config(void)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
for (u32 enc = cgt->encoding; enc <= cgt->end; enc = encoding_next(enc)) {
|
||||
for_each_encoding_in(enc, cgt->encoding, cgt->end) {
|
||||
prev = xa_store(&sr_forward_xa, enc,
|
||||
xa_mk_value(cgt->tc.val), GFP_KERNEL);
|
||||
if (prev && !xa_is_err(prev)) {
|
||||
@@ -2066,6 +2249,10 @@ int __init populate_nv_trap_config(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (__HCRX_EL2_RES0 != HCRX_EL2_RES0)
|
||||
kvm_info("Sanitised HCR_EL2_RES0 = %016llx, expecting %016llx\n",
|
||||
__HCRX_EL2_RES0, HCRX_EL2_RES0);
|
||||
|
||||
kvm_info("nv: %ld coarse grained trap handlers\n",
|
||||
ARRAY_SIZE(encoding_to_cgt));
|
||||
|
||||
@@ -2082,23 +2269,39 @@ int __init populate_nv_trap_config(void)
|
||||
print_nv_trap_error(fgt, "Invalid FGT", ret);
|
||||
}
|
||||
|
||||
tc = get_trap_config(fgt->encoding);
|
||||
for_each_encoding_in(enc, fgt->encoding, fgt->end) {
|
||||
tc = get_trap_config(enc);
|
||||
|
||||
if (tc.fgt) {
|
||||
ret = -EINVAL;
|
||||
print_nv_trap_error(fgt, "Duplicate FGT", ret);
|
||||
}
|
||||
if (tc.fgt) {
|
||||
ret = -EINVAL;
|
||||
print_nv_trap_error(fgt, "Duplicate FGT", ret);
|
||||
}
|
||||
|
||||
tc.val |= fgt->tc.val;
|
||||
prev = xa_store(&sr_forward_xa, fgt->encoding,
|
||||
xa_mk_value(tc.val), GFP_KERNEL);
|
||||
tc.val |= fgt->tc.val;
|
||||
prev = xa_store(&sr_forward_xa, enc,
|
||||
xa_mk_value(tc.val), GFP_KERNEL);
|
||||
|
||||
if (xa_is_err(prev)) {
|
||||
ret = xa_err(prev);
|
||||
print_nv_trap_error(fgt, "Failed FGT insertion", ret);
|
||||
if (xa_is_err(prev)) {
|
||||
ret = xa_err(prev);
|
||||
print_nv_trap_error(fgt, "Failed FGT insertion", ret);
|
||||
}
|
||||
|
||||
if (!aggregate_fgt(tc)) {
|
||||
ret = -EINVAL;
|
||||
print_nv_trap_error(fgt, "FGT bit is reserved", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(non_0x18_fgt); i++) {
|
||||
if (!aggregate_fgt(non_0x18_fgt[i])) {
|
||||
ret = -EINVAL;
|
||||
kvm_err("non_0x18_fgt[%d] is reserved\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
ret = check_all_fgt_masks(ret);
|
||||
|
||||
kvm_info("nv: %ld fine grained trap handlers\n",
|
||||
ARRAY_SIZE(encoding_to_fgt));
|
||||
|
||||
@@ -2215,11 +2418,11 @@ static u64 kvm_get_sysreg_res0(struct kvm *kvm, enum vcpu_sysreg sr)
|
||||
return masks->mask[sr - __VNCR_START__].res0;
|
||||
}
|
||||
|
||||
static bool check_fgt_bit(struct kvm_vcpu *vcpu, bool is_read,
|
||||
u64 val, const union trap_config tc)
|
||||
static bool check_fgt_bit(struct kvm_vcpu *vcpu, enum vcpu_sysreg sr,
|
||||
const union trap_config tc)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
enum vcpu_sysreg sr;
|
||||
u64 val;
|
||||
|
||||
/*
|
||||
* KVM doesn't know about any FGTs that apply to the host, and hopefully
|
||||
@@ -2228,6 +2431,8 @@ static bool check_fgt_bit(struct kvm_vcpu *vcpu, bool is_read,
|
||||
if (is_hyp_ctxt(vcpu))
|
||||
return false;
|
||||
|
||||
val = __vcpu_sys_reg(vcpu, sr);
|
||||
|
||||
if (tc.pol)
|
||||
return (val & BIT(tc.bit));
|
||||
|
||||
@@ -2242,38 +2447,17 @@ static bool check_fgt_bit(struct kvm_vcpu *vcpu, bool is_read,
|
||||
if (val & BIT(tc.bit))
|
||||
return false;
|
||||
|
||||
switch ((enum fgt_group_id)tc.fgt) {
|
||||
case HFGxTR_GROUP:
|
||||
sr = is_read ? HFGRTR_EL2 : HFGWTR_EL2;
|
||||
break;
|
||||
|
||||
case HDFGRTR_GROUP:
|
||||
sr = is_read ? HDFGRTR_EL2 : HDFGWTR_EL2;
|
||||
break;
|
||||
|
||||
case HAFGRTR_GROUP:
|
||||
sr = HAFGRTR_EL2;
|
||||
break;
|
||||
|
||||
case HFGITR_GROUP:
|
||||
sr = HFGITR_EL2;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ONCE(1, "Unhandled FGT group");
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(kvm_get_sysreg_res0(kvm, sr) & BIT(tc.bit));
|
||||
}
|
||||
|
||||
bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
|
||||
{
|
||||
enum vcpu_sysreg fgtreg;
|
||||
union trap_config tc;
|
||||
enum trap_behaviour b;
|
||||
bool is_read;
|
||||
u32 sysreg;
|
||||
u64 esr, val;
|
||||
u64 esr;
|
||||
|
||||
esr = kvm_vcpu_get_esr(vcpu);
|
||||
sysreg = esr_sys64_to_sysreg(esr);
|
||||
@@ -2319,26 +2503,20 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
|
||||
case __NO_FGT_GROUP__:
|
||||
break;
|
||||
|
||||
case HFGxTR_GROUP:
|
||||
if (is_read)
|
||||
val = __vcpu_sys_reg(vcpu, HFGRTR_EL2);
|
||||
else
|
||||
val = __vcpu_sys_reg(vcpu, HFGWTR_EL2);
|
||||
case HFGRTR_GROUP:
|
||||
fgtreg = is_read ? HFGRTR_EL2 : HFGWTR_EL2;
|
||||
break;
|
||||
|
||||
case HDFGRTR_GROUP:
|
||||
if (is_read)
|
||||
val = __vcpu_sys_reg(vcpu, HDFGRTR_EL2);
|
||||
else
|
||||
val = __vcpu_sys_reg(vcpu, HDFGWTR_EL2);
|
||||
fgtreg = is_read ? HDFGRTR_EL2 : HDFGWTR_EL2;
|
||||
break;
|
||||
|
||||
case HAFGRTR_GROUP:
|
||||
val = __vcpu_sys_reg(vcpu, HAFGRTR_EL2);
|
||||
fgtreg = HAFGRTR_EL2;
|
||||
break;
|
||||
|
||||
case HFGITR_GROUP:
|
||||
val = __vcpu_sys_reg(vcpu, HFGITR_EL2);
|
||||
fgtreg = HFGITR_EL2;
|
||||
switch (tc.fgf) {
|
||||
u64 tmp;
|
||||
|
||||
@@ -2352,13 +2530,26 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
|
||||
}
|
||||
break;
|
||||
|
||||
case __NR_FGT_GROUP_IDS__:
|
||||
case HFGRTR2_GROUP:
|
||||
fgtreg = is_read ? HFGRTR2_EL2 : HFGWTR2_EL2;
|
||||
break;
|
||||
|
||||
case HDFGRTR2_GROUP:
|
||||
fgtreg = is_read ? HDFGRTR2_EL2 : HDFGWTR2_EL2;
|
||||
break;
|
||||
|
||||
case HFGITR2_GROUP:
|
||||
fgtreg = HFGITR2_EL2;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Something is really wrong, bail out */
|
||||
WARN_ONCE(1, "__NR_FGT_GROUP_IDS__");
|
||||
WARN_ONCE(1, "Bad FGT group (encoding %08x, config %016llx)\n",
|
||||
sysreg, tc.val);
|
||||
goto local;
|
||||
}
|
||||
|
||||
if (tc.fgt != __NO_FGT_GROUP__ && check_fgt_bit(vcpu, is_read, val, tc))
|
||||
if (tc.fgt != __NO_FGT_GROUP__ && check_fgt_bit(vcpu, fgtreg, tc))
|
||||
goto inject;
|
||||
|
||||
b = compute_trap_behaviour(vcpu, tc);
|
||||
|
||||
@@ -299,6 +299,81 @@ static int handle_svc(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int kvm_handle_gcs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/* We don't expect GCS, so treat it with contempt */
|
||||
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, GCS, IMP))
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
kvm_inject_undefined(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_other(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
bool is_l2 = vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu);
|
||||
u64 hcrx = __vcpu_sys_reg(vcpu, HCRX_EL2);
|
||||
u64 esr = kvm_vcpu_get_esr(vcpu);
|
||||
u64 iss = ESR_ELx_ISS(esr);
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
bool allowed, fwd = false;
|
||||
|
||||
/*
|
||||
* We only trap for two reasons:
|
||||
*
|
||||
* - the feature is disabled, and the only outcome is to
|
||||
* generate an UNDEF.
|
||||
*
|
||||
* - the feature is enabled, but a NV guest wants to trap the
|
||||
* feature used by its L2 guest. We forward the exception in
|
||||
* this case.
|
||||
*
|
||||
* What we don't expect is to end-up here if the guest is
|
||||
* expected be be able to directly use the feature, hence the
|
||||
* WARN_ON below.
|
||||
*/
|
||||
switch (iss) {
|
||||
case ESR_ELx_ISS_OTHER_ST64BV:
|
||||
allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V);
|
||||
if (is_l2)
|
||||
fwd = !(hcrx & HCRX_EL2_EnASR);
|
||||
break;
|
||||
case ESR_ELx_ISS_OTHER_ST64BV0:
|
||||
allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA);
|
||||
if (is_l2)
|
||||
fwd = !(hcrx & HCRX_EL2_EnAS0);
|
||||
break;
|
||||
case ESR_ELx_ISS_OTHER_LDST64B:
|
||||
allowed = kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64);
|
||||
if (is_l2)
|
||||
fwd = !(hcrx & HCRX_EL2_EnALS);
|
||||
break;
|
||||
case ESR_ELx_ISS_OTHER_TSBCSYNC:
|
||||
allowed = kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceBuffer, TRBE_V1P1);
|
||||
if (is_l2)
|
||||
fwd = (__vcpu_sys_reg(vcpu, HFGITR2_EL2) & HFGITR2_EL2_TSBCSYNC);
|
||||
break;
|
||||
case ESR_ELx_ISS_OTHER_PSBCSYNC:
|
||||
allowed = kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P5);
|
||||
if (is_l2)
|
||||
fwd = (__vcpu_sys_reg(vcpu, HFGITR_EL2) & HFGITR_EL2_PSBCSYNC);
|
||||
break;
|
||||
default:
|
||||
/* Clearly, we're missing something. */
|
||||
WARN_ON_ONCE(1);
|
||||
allowed = false;
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(allowed && !fwd);
|
||||
|
||||
if (allowed && fwd)
|
||||
kvm_inject_nested_sync(vcpu, esr);
|
||||
else
|
||||
kvm_inject_undefined(vcpu);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static exit_handle_fn arm_exit_handlers[] = {
|
||||
[0 ... ESR_ELx_EC_MAX] = kvm_handle_unknown_ec,
|
||||
[ESR_ELx_EC_WFx] = kvm_handle_wfx,
|
||||
@@ -308,6 +383,7 @@ static exit_handle_fn arm_exit_handlers[] = {
|
||||
[ESR_ELx_EC_CP14_LS] = kvm_handle_cp14_load_store,
|
||||
[ESR_ELx_EC_CP10_ID] = kvm_handle_cp10_id,
|
||||
[ESR_ELx_EC_CP14_64] = kvm_handle_cp14_64,
|
||||
[ESR_ELx_EC_OTHER] = handle_other,
|
||||
[ESR_ELx_EC_HVC32] = handle_hvc,
|
||||
[ESR_ELx_EC_SMC32] = handle_smc,
|
||||
[ESR_ELx_EC_HVC64] = handle_hvc,
|
||||
@@ -325,6 +401,7 @@ static exit_handle_fn arm_exit_handlers[] = {
|
||||
[ESR_ELx_EC_BRK64] = kvm_handle_guest_debug,
|
||||
[ESR_ELx_EC_FP_ASIMD] = kvm_handle_fpasimd,
|
||||
[ESR_ELx_EC_PAC] = kvm_handle_ptrauth,
|
||||
[ESR_ELx_EC_GCS] = kvm_handle_gcs,
|
||||
};
|
||||
|
||||
static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -65,12 +65,56 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
#define reg_to_fgt_masks(reg) \
|
||||
({ \
|
||||
struct fgt_masks *m; \
|
||||
switch(reg) { \
|
||||
case HFGRTR_EL2: \
|
||||
m = &hfgrtr_masks; \
|
||||
break; \
|
||||
case HFGWTR_EL2: \
|
||||
m = &hfgwtr_masks; \
|
||||
break; \
|
||||
case HFGITR_EL2: \
|
||||
m = &hfgitr_masks; \
|
||||
break; \
|
||||
case HDFGRTR_EL2: \
|
||||
m = &hdfgrtr_masks; \
|
||||
break; \
|
||||
case HDFGWTR_EL2: \
|
||||
m = &hdfgwtr_masks; \
|
||||
break; \
|
||||
case HAFGRTR_EL2: \
|
||||
m = &hafgrtr_masks; \
|
||||
break; \
|
||||
case HFGRTR2_EL2: \
|
||||
m = &hfgrtr2_masks; \
|
||||
break; \
|
||||
case HFGWTR2_EL2: \
|
||||
m = &hfgwtr2_masks; \
|
||||
break; \
|
||||
case HFGITR2_EL2: \
|
||||
m = &hfgitr2_masks; \
|
||||
break; \
|
||||
case HDFGRTR2_EL2: \
|
||||
m = &hdfgrtr2_masks; \
|
||||
break; \
|
||||
case HDFGWTR2_EL2: \
|
||||
m = &hdfgwtr2_masks; \
|
||||
break; \
|
||||
default: \
|
||||
BUILD_BUG_ON(1); \
|
||||
} \
|
||||
\
|
||||
m; \
|
||||
})
|
||||
|
||||
#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; \
|
||||
u64 hfg = __vcpu_sys_reg(vcpu, reg); \
|
||||
struct fgt_masks *m = reg_to_fgt_masks(reg); \
|
||||
set |= hfg & m->mask; \
|
||||
clr |= ~hfg & m->nmask; \
|
||||
} while(0)
|
||||
|
||||
#define reg_to_fgt_group_id(reg) \
|
||||
@@ -79,7 +123,7 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
|
||||
switch(reg) { \
|
||||
case HFGRTR_EL2: \
|
||||
case HFGWTR_EL2: \
|
||||
id = HFGxTR_GROUP; \
|
||||
id = HFGRTR_GROUP; \
|
||||
break; \
|
||||
case HFGITR_EL2: \
|
||||
id = HFGITR_GROUP; \
|
||||
@@ -91,6 +135,17 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
|
||||
case HAFGRTR_EL2: \
|
||||
id = HAFGRTR_GROUP; \
|
||||
break; \
|
||||
case HFGRTR2_EL2: \
|
||||
case HFGWTR2_EL2: \
|
||||
id = HFGRTR2_GROUP; \
|
||||
break; \
|
||||
case HFGITR2_EL2: \
|
||||
id = HFGITR2_GROUP; \
|
||||
break; \
|
||||
case HDFGRTR2_EL2: \
|
||||
case HDFGWTR2_EL2: \
|
||||
id = HDFGRTR2_GROUP; \
|
||||
break; \
|
||||
default: \
|
||||
BUILD_BUG_ON(1); \
|
||||
} \
|
||||
@@ -101,13 +156,16 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
|
||||
#define compute_undef_clr_set(vcpu, kvm, reg, clr, set) \
|
||||
do { \
|
||||
u64 hfg = kvm->arch.fgu[reg_to_fgt_group_id(reg)]; \
|
||||
set |= hfg & __ ## reg ## _MASK; \
|
||||
clr |= hfg & __ ## reg ## _nMASK; \
|
||||
struct fgt_masks *m = reg_to_fgt_masks(reg); \
|
||||
set |= hfg & m->mask; \
|
||||
clr |= hfg & m->nmask; \
|
||||
} while(0)
|
||||
|
||||
#define update_fgt_traps_cs(hctxt, vcpu, kvm, reg, clr, set) \
|
||||
do { \
|
||||
u64 c = 0, s = 0; \
|
||||
struct fgt_masks *m = reg_to_fgt_masks(reg); \
|
||||
u64 c = clr, s = set; \
|
||||
u64 val; \
|
||||
\
|
||||
ctxt_sys_reg(hctxt, reg) = read_sysreg_s(SYS_ ## reg); \
|
||||
if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) \
|
||||
@@ -115,30 +173,15 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
|
||||
\
|
||||
compute_undef_clr_set(vcpu, kvm, reg, c, s); \
|
||||
\
|
||||
s |= set; \
|
||||
c |= clr; \
|
||||
if (c || s) { \
|
||||
u64 val = __ ## reg ## _nMASK; \
|
||||
val |= s; \
|
||||
val &= ~c; \
|
||||
write_sysreg_s(val, SYS_ ## reg); \
|
||||
} \
|
||||
val = m->nmask; \
|
||||
val |= s; \
|
||||
val &= ~c; \
|
||||
write_sysreg_s(val, SYS_ ## reg); \
|
||||
} while(0)
|
||||
|
||||
#define update_fgt_traps(hctxt, vcpu, kvm, reg) \
|
||||
update_fgt_traps_cs(hctxt, vcpu, kvm, reg, 0, 0)
|
||||
|
||||
/*
|
||||
* Validate the fine grain trap masks.
|
||||
* Check that the masks do not overlap and that all bits are accounted for.
|
||||
*/
|
||||
#define CHECK_FGT_MASKS(reg) \
|
||||
do { \
|
||||
BUILD_BUG_ON((__ ## reg ## _MASK) & (__ ## reg ## _nMASK)); \
|
||||
BUILD_BUG_ON(~((__ ## reg ## _RES0) ^ (__ ## reg ## _MASK) ^ \
|
||||
(__ ## reg ## _nMASK))); \
|
||||
} while(0)
|
||||
|
||||
static inline bool cpu_has_amu(void)
|
||||
{
|
||||
u64 pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1);
|
||||
@@ -152,56 +195,60 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
|
||||
struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);
|
||||
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
|
||||
|
||||
CHECK_FGT_MASKS(HFGRTR_EL2);
|
||||
CHECK_FGT_MASKS(HFGWTR_EL2);
|
||||
CHECK_FGT_MASKS(HFGITR_EL2);
|
||||
CHECK_FGT_MASKS(HDFGRTR_EL2);
|
||||
CHECK_FGT_MASKS(HDFGWTR_EL2);
|
||||
CHECK_FGT_MASKS(HAFGRTR_EL2);
|
||||
CHECK_FGT_MASKS(HCRX_EL2);
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT))
|
||||
return;
|
||||
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HFGRTR_EL2);
|
||||
update_fgt_traps_cs(hctxt, vcpu, kvm, HFGWTR_EL2, 0,
|
||||
cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38) ?
|
||||
HFGxTR_EL2_TCR_EL1_MASK : 0);
|
||||
HFGWTR_EL2_TCR_EL1_MASK : 0);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HFGITR_EL2);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HDFGRTR_EL2);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HDFGWTR_EL2);
|
||||
|
||||
if (cpu_has_amu())
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HAFGRTR_EL2);
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT2))
|
||||
return;
|
||||
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HFGRTR2_EL2);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HFGWTR2_EL2);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HFGITR2_EL2);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HDFGRTR2_EL2);
|
||||
update_fgt_traps(hctxt, vcpu, kvm, HDFGWTR2_EL2);
|
||||
}
|
||||
|
||||
#define __deactivate_fgt(htcxt, vcpu, kvm, reg) \
|
||||
#define __deactivate_fgt(htcxt, vcpu, reg) \
|
||||
do { \
|
||||
if ((vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) || \
|
||||
kvm->arch.fgu[reg_to_fgt_group_id(reg)]) \
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, reg), \
|
||||
SYS_ ## reg); \
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, reg), \
|
||||
SYS_ ## reg); \
|
||||
} while(0)
|
||||
|
||||
static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);
|
||||
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT))
|
||||
return;
|
||||
|
||||
__deactivate_fgt(hctxt, vcpu, kvm, HFGRTR_EL2);
|
||||
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38))
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, HFGWTR_EL2), SYS_HFGWTR_EL2);
|
||||
else
|
||||
__deactivate_fgt(hctxt, vcpu, kvm, HFGWTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, kvm, HFGITR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, kvm, HDFGRTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, kvm, HDFGWTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HFGRTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HFGWTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HFGITR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HDFGRTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HDFGWTR_EL2);
|
||||
|
||||
if (cpu_has_amu())
|
||||
__deactivate_fgt(hctxt, vcpu, kvm, HAFGRTR_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HAFGRTR_EL2);
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT2))
|
||||
return;
|
||||
|
||||
__deactivate_fgt(hctxt, vcpu, HFGRTR2_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HFGWTR2_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HFGITR2_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HDFGRTR2_EL2);
|
||||
__deactivate_fgt(hctxt, vcpu, HDFGWTR2_EL2);
|
||||
}
|
||||
|
||||
static inline void __activate_traps_mpam(struct kvm_vcpu *vcpu)
|
||||
@@ -261,12 +308,9 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX)) {
|
||||
u64 hcrx = vcpu->arch.hcrx_el2;
|
||||
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;
|
||||
u64 val = __vcpu_sys_reg(vcpu, HCRX_EL2);
|
||||
hcrx |= val & __HCRX_EL2_MASK;
|
||||
hcrx &= ~(~val & __HCRX_EL2_nMASK);
|
||||
}
|
||||
|
||||
write_sysreg_s(hcrx, SYS_HCRX_EL2);
|
||||
|
||||
@@ -33,6 +33,18 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);
|
||||
DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
|
||||
DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
|
||||
|
||||
struct fgt_masks hfgrtr_masks;
|
||||
struct fgt_masks hfgwtr_masks;
|
||||
struct fgt_masks hfgitr_masks;
|
||||
struct fgt_masks hdfgrtr_masks;
|
||||
struct fgt_masks hdfgwtr_masks;
|
||||
struct fgt_masks hafgrtr_masks;
|
||||
struct fgt_masks hfgrtr2_masks;
|
||||
struct fgt_masks hfgwtr2_masks;
|
||||
struct fgt_masks hfgitr2_masks;
|
||||
struct fgt_masks hdfgrtr2_masks;
|
||||
struct fgt_masks hdfgwtr2_masks;
|
||||
|
||||
extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
|
||||
|
||||
static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -1052,11 +1052,11 @@ static bool __vgic_v3_check_trap_forwarding(struct kvm_vcpu *vcpu,
|
||||
switch (sysreg) {
|
||||
case SYS_ICC_IGRPEN0_EL1:
|
||||
if (is_read &&
|
||||
(__vcpu_sys_reg(vcpu, HFGRTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1))
|
||||
(__vcpu_sys_reg(vcpu, HFGRTR_EL2) & HFGRTR_EL2_ICC_IGRPENn_EL1))
|
||||
return true;
|
||||
|
||||
if (!is_read &&
|
||||
(__vcpu_sys_reg(vcpu, HFGWTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1))
|
||||
(__vcpu_sys_reg(vcpu, HFGWTR_EL2) & HFGWTR_EL2_ICC_IGRPENn_EL1))
|
||||
return true;
|
||||
|
||||
fallthrough;
|
||||
@@ -1073,11 +1073,11 @@ static bool __vgic_v3_check_trap_forwarding(struct kvm_vcpu *vcpu,
|
||||
|
||||
case SYS_ICC_IGRPEN1_EL1:
|
||||
if (is_read &&
|
||||
(__vcpu_sys_reg(vcpu, HFGRTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1))
|
||||
(__vcpu_sys_reg(vcpu, HFGRTR_EL2) & HFGRTR_EL2_ICC_IGRPENn_EL1))
|
||||
return true;
|
||||
|
||||
if (!is_read &&
|
||||
(__vcpu_sys_reg(vcpu, HFGWTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1))
|
||||
(__vcpu_sys_reg(vcpu, HFGWTR_EL2) & HFGWTR_EL2_ICC_IGRPENn_EL1))
|
||||
return true;
|
||||
|
||||
fallthrough;
|
||||
|
||||
+28
-195
@@ -1018,216 +1018,49 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
|
||||
set_sysreg_masks(kvm, VMPIDR_EL2, res0, res1);
|
||||
|
||||
/* HCR_EL2 */
|
||||
res0 = BIT(48);
|
||||
res1 = HCR_RW;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, TWED, IMP))
|
||||
res0 |= GENMASK(63, 59);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, MTE, MTE2))
|
||||
res0 |= (HCR_TID5 | HCR_DCT | HCR_ATA);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, EVT, TTLBxS))
|
||||
res0 |= (HCR_TTLBIS | HCR_TTLBOS);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, CSV2, CSV2_2) &&
|
||||
!kvm_has_feat(kvm, ID_AA64PFR1_EL1, CSV2_frac, CSV2_1p2))
|
||||
res0 |= HCR_ENSCXT;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, EVT, IMP))
|
||||
res0 |= (HCR_TOCU | HCR_TICAB | HCR_TID4);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
|
||||
res0 |= HCR_AMVOFFEN;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, V1P1))
|
||||
res0 |= HCR_FIEN;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, FWB, IMP))
|
||||
res0 |= HCR_FWB;
|
||||
/* Implementation choice: NV2 is the only supported config */
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY))
|
||||
res0 |= (HCR_NV2 | HCR_NV | HCR_AT);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, NI))
|
||||
res0 |= HCR_NV1;
|
||||
if (!(kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_ADDRESS) &&
|
||||
kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_GENERIC)))
|
||||
res0 |= (HCR_API | HCR_APK);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TME, IMP))
|
||||
res0 |= BIT(39);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP))
|
||||
res0 |= (HCR_TEA | HCR_TERR);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
|
||||
res0 |= HCR_TLOR;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
|
||||
res0 |= HCR_E2H;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, E2H0, IMP))
|
||||
res1 |= HCR_E2H;
|
||||
get_reg_fixed_bits(kvm, HCR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HCR_EL2, res0, res1);
|
||||
|
||||
/* HCRX_EL2 */
|
||||
res0 = HCRX_EL2_RES0;
|
||||
res1 = HCRX_EL2_RES1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR3_EL1, PACM, TRIVIAL_IMP))
|
||||
res0 |= HCRX_EL2_PACMEn;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR2_EL1, FPMR, IMP))
|
||||
res0 |= HCRX_EL2_EnFPM;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP))
|
||||
res0 |= HCRX_EL2_GCSEn;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, SYSREG_128, IMP))
|
||||
res0 |= HCRX_EL2_EnIDCP128;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, ADERR, DEV_ASYNC))
|
||||
res0 |= (HCRX_EL2_EnSDERR | HCRX_EL2_EnSNERR);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, DF2, IMP))
|
||||
res0 |= HCRX_EL2_TMEA;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, D128, IMP))
|
||||
res0 |= HCRX_EL2_D128En;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
|
||||
res0 |= HCRX_EL2_PTTWI;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, SCTLRX, IMP))
|
||||
res0 |= HCRX_EL2_SCTLR2En;
|
||||
if (!kvm_has_tcr2(kvm))
|
||||
res0 |= HCRX_EL2_TCR2En;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
|
||||
res0 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, CMOW, IMP))
|
||||
res0 |= HCRX_EL2_CMOW;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, NMI, IMP))
|
||||
res0 |= (HCRX_EL2_VFNMI | HCRX_EL2_VINMI | HCRX_EL2_TALLINT);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, SME, IMP) ||
|
||||
!(read_sysreg_s(SYS_SMIDR_EL1) & SMIDR_EL1_SMPS))
|
||||
res0 |= HCRX_EL2_SMPME;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, XS, IMP))
|
||||
res0 |= (HCRX_EL2_FGTnXS | HCRX_EL2_FnXS);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V))
|
||||
res0 |= HCRX_EL2_EnASR;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64))
|
||||
res0 |= HCRX_EL2_EnALS;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA))
|
||||
res0 |= HCRX_EL2_EnAS0;
|
||||
get_reg_fixed_bits(kvm, HCRX_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HCRX_EL2, res0, res1);
|
||||
|
||||
/* HFG[RW]TR_EL2 */
|
||||
res0 = res1 = 0;
|
||||
if (!(kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_ADDRESS) &&
|
||||
kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_GENERIC)))
|
||||
res0 |= (HFGxTR_EL2_APDAKey | HFGxTR_EL2_APDBKey |
|
||||
HFGxTR_EL2_APGAKey | HFGxTR_EL2_APIAKey |
|
||||
HFGxTR_EL2_APIBKey);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
|
||||
res0 |= (HFGxTR_EL2_LORC_EL1 | HFGxTR_EL2_LOREA_EL1 |
|
||||
HFGxTR_EL2_LORID_EL1 | HFGxTR_EL2_LORN_EL1 |
|
||||
HFGxTR_EL2_LORSA_EL1);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, CSV2, CSV2_2) &&
|
||||
!kvm_has_feat(kvm, ID_AA64PFR1_EL1, CSV2_frac, CSV2_1p2))
|
||||
res0 |= (HFGxTR_EL2_SCXTNUM_EL1 | HFGxTR_EL2_SCXTNUM_EL0);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, GIC, IMP))
|
||||
res0 |= HFGxTR_EL2_ICC_IGRPENn_EL1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP))
|
||||
res0 |= (HFGxTR_EL2_ERRIDR_EL1 | HFGxTR_EL2_ERRSELR_EL1 |
|
||||
HFGxTR_EL2_ERXFR_EL1 | HFGxTR_EL2_ERXCTLR_EL1 |
|
||||
HFGxTR_EL2_ERXSTATUS_EL1 | HFGxTR_EL2_ERXMISCn_EL1 |
|
||||
HFGxTR_EL2_ERXPFGF_EL1 | HFGxTR_EL2_ERXPFGCTL_EL1 |
|
||||
HFGxTR_EL2_ERXPFGCDN_EL1 | HFGxTR_EL2_ERXADDR_EL1);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_ACCDATA))
|
||||
res0 |= HFGxTR_EL2_nACCDATA_EL1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP))
|
||||
res0 |= (HFGxTR_EL2_nGCS_EL0 | HFGxTR_EL2_nGCS_EL1);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, SME, IMP))
|
||||
res0 |= (HFGxTR_EL2_nSMPRI_EL1 | HFGxTR_EL2_nTPIDR2_EL0);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
|
||||
res0 |= HFGxTR_EL2_nRCWMASK_EL1;
|
||||
if (!kvm_has_s1pie(kvm))
|
||||
res0 |= (HFGxTR_EL2_nPIRE0_EL1 | HFGxTR_EL2_nPIR_EL1);
|
||||
if (!kvm_has_s1poe(kvm))
|
||||
res0 |= (HFGxTR_EL2_nPOR_EL0 | HFGxTR_EL2_nPOR_EL1);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S2POE, IMP))
|
||||
res0 |= HFGxTR_EL2_nS2POR_EL1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, AIE, IMP))
|
||||
res0 |= (HFGxTR_EL2_nMAIR2_EL1 | HFGxTR_EL2_nAMAIR2_EL1);
|
||||
set_sysreg_masks(kvm, HFGRTR_EL2, res0 | __HFGRTR_EL2_RES0, res1);
|
||||
set_sysreg_masks(kvm, HFGWTR_EL2, res0 | __HFGWTR_EL2_RES0, res1);
|
||||
get_reg_fixed_bits(kvm, HFGRTR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGRTR_EL2, res0, res1);
|
||||
get_reg_fixed_bits(kvm, HFGWTR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGWTR_EL2, res0, res1);
|
||||
|
||||
/* HDFG[RW]TR_EL2 */
|
||||
res0 = res1 = 0;
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, DoubleLock, IMP))
|
||||
res0 |= HDFGRTR_EL2_OSDLR_EL1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP))
|
||||
res0 |= (HDFGRTR_EL2_PMEVCNTRn_EL0 | HDFGRTR_EL2_PMEVTYPERn_EL0 |
|
||||
HDFGRTR_EL2_PMCCFILTR_EL0 | HDFGRTR_EL2_PMCCNTR_EL0 |
|
||||
HDFGRTR_EL2_PMCNTEN | HDFGRTR_EL2_PMINTEN |
|
||||
HDFGRTR_EL2_PMOVS | HDFGRTR_EL2_PMSELR_EL0 |
|
||||
HDFGRTR_EL2_PMMIR_EL1 | HDFGRTR_EL2_PMUSERENR_EL0 |
|
||||
HDFGRTR_EL2_PMCEIDn_EL0);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, IMP))
|
||||
res0 |= (HDFGRTR_EL2_PMBLIMITR_EL1 | HDFGRTR_EL2_PMBPTR_EL1 |
|
||||
HDFGRTR_EL2_PMBSR_EL1 | HDFGRTR_EL2_PMSCR_EL1 |
|
||||
HDFGRTR_EL2_PMSEVFR_EL1 | HDFGRTR_EL2_PMSFCR_EL1 |
|
||||
HDFGRTR_EL2_PMSICR_EL1 | HDFGRTR_EL2_PMSIDR_EL1 |
|
||||
HDFGRTR_EL2_PMSIRR_EL1 | HDFGRTR_EL2_PMSLATFR_EL1 |
|
||||
HDFGRTR_EL2_PMBIDR_EL1);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceVer, IMP))
|
||||
res0 |= (HDFGRTR_EL2_TRC | HDFGRTR_EL2_TRCAUTHSTATUS |
|
||||
HDFGRTR_EL2_TRCAUXCTLR | HDFGRTR_EL2_TRCCLAIM |
|
||||
HDFGRTR_EL2_TRCCNTVRn | HDFGRTR_EL2_TRCID |
|
||||
HDFGRTR_EL2_TRCIMSPECn | HDFGRTR_EL2_TRCOSLSR |
|
||||
HDFGRTR_EL2_TRCPRGCTLR | HDFGRTR_EL2_TRCSEQSTR |
|
||||
HDFGRTR_EL2_TRCSSCSRn | HDFGRTR_EL2_TRCSTATR |
|
||||
HDFGRTR_EL2_TRCVICTLR);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceBuffer, IMP))
|
||||
res0 |= (HDFGRTR_EL2_TRBBASER_EL1 | HDFGRTR_EL2_TRBIDR_EL1 |
|
||||
HDFGRTR_EL2_TRBLIMITR_EL1 | HDFGRTR_EL2_TRBMAR_EL1 |
|
||||
HDFGRTR_EL2_TRBPTR_EL1 | HDFGRTR_EL2_TRBSR_EL1 |
|
||||
HDFGRTR_EL2_TRBTRG_EL1);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, BRBE, IMP))
|
||||
res0 |= (HDFGRTR_EL2_nBRBIDR | HDFGRTR_EL2_nBRBCTL |
|
||||
HDFGRTR_EL2_nBRBDATA);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P2))
|
||||
res0 |= HDFGRTR_EL2_nPMSNEVFR_EL1;
|
||||
set_sysreg_masks(kvm, HDFGRTR_EL2, res0 | HDFGRTR_EL2_RES0, res1);
|
||||
|
||||
/* Reuse the bits from the read-side and add the write-specific stuff */
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP))
|
||||
res0 |= (HDFGWTR_EL2_PMCR_EL0 | HDFGWTR_EL2_PMSWINC_EL0);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceVer, IMP))
|
||||
res0 |= HDFGWTR_EL2_TRCOSLAR;
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceFilt, IMP))
|
||||
res0 |= HDFGWTR_EL2_TRFCR_EL1;
|
||||
set_sysreg_masks(kvm, HFGWTR_EL2, res0 | HDFGWTR_EL2_RES0, res1);
|
||||
get_reg_fixed_bits(kvm, HDFGRTR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HDFGRTR_EL2, res0, res1);
|
||||
get_reg_fixed_bits(kvm, HDFGWTR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HDFGWTR_EL2, res0, res1);
|
||||
|
||||
/* HFGITR_EL2 */
|
||||
res0 = HFGITR_EL2_RES0;
|
||||
res1 = HFGITR_EL2_RES1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, DPB, DPB2))
|
||||
res0 |= HFGITR_EL2_DCCVADP;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN2))
|
||||
res0 |= (HFGITR_EL2_ATS1E1RP | HFGITR_EL2_ATS1E1WP);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
|
||||
res0 |= (HFGITR_EL2_TLBIRVAALE1OS | HFGITR_EL2_TLBIRVALE1OS |
|
||||
HFGITR_EL2_TLBIRVAAE1OS | HFGITR_EL2_TLBIRVAE1OS |
|
||||
HFGITR_EL2_TLBIVAALE1OS | HFGITR_EL2_TLBIVALE1OS |
|
||||
HFGITR_EL2_TLBIVAAE1OS | HFGITR_EL2_TLBIASIDE1OS |
|
||||
HFGITR_EL2_TLBIVAE1OS | HFGITR_EL2_TLBIVMALLE1OS);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, RANGE))
|
||||
res0 |= (HFGITR_EL2_TLBIRVAALE1 | HFGITR_EL2_TLBIRVALE1 |
|
||||
HFGITR_EL2_TLBIRVAAE1 | HFGITR_EL2_TLBIRVAE1 |
|
||||
HFGITR_EL2_TLBIRVAALE1IS | HFGITR_EL2_TLBIRVALE1IS |
|
||||
HFGITR_EL2_TLBIRVAAE1IS | HFGITR_EL2_TLBIRVAE1IS |
|
||||
HFGITR_EL2_TLBIRVAALE1OS | HFGITR_EL2_TLBIRVALE1OS |
|
||||
HFGITR_EL2_TLBIRVAAE1OS | HFGITR_EL2_TLBIRVAE1OS);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, SPECRES, IMP))
|
||||
res0 |= (HFGITR_EL2_CFPRCTX | HFGITR_EL2_DVPRCTX |
|
||||
HFGITR_EL2_CPPRCTX);
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, BRBE, IMP))
|
||||
res0 |= (HFGITR_EL2_nBRBINJ | HFGITR_EL2_nBRBIALL);
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, GCS, IMP))
|
||||
res0 |= (HFGITR_EL2_nGCSPUSHM_EL1 | HFGITR_EL2_nGCSSTR_EL1 |
|
||||
HFGITR_EL2_nGCSEPP);
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, SPECRES, COSP_RCTX))
|
||||
res0 |= HFGITR_EL2_COSPRCTX;
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, ATS1A, IMP))
|
||||
res0 |= HFGITR_EL2_ATS1E1A;
|
||||
get_reg_fixed_bits(kvm, HFGITR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGITR_EL2, res0, res1);
|
||||
|
||||
/* HAFGRTR_EL2 - not a lot to see here */
|
||||
res0 = HAFGRTR_EL2_RES0;
|
||||
res1 = HAFGRTR_EL2_RES1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
|
||||
res0 |= ~(res0 | res1);
|
||||
get_reg_fixed_bits(kvm, HAFGRTR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
|
||||
|
||||
/* HFG[RW]TR2_EL2 */
|
||||
get_reg_fixed_bits(kvm, HFGRTR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGRTR2_EL2, res0, res1);
|
||||
get_reg_fixed_bits(kvm, HFGWTR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGWTR2_EL2, res0, res1);
|
||||
|
||||
/* HDFG[RW]TR2_EL2 */
|
||||
get_reg_fixed_bits(kvm, HDFGRTR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HDFGRTR2_EL2, res0, res1);
|
||||
get_reg_fixed_bits(kvm, HDFGWTR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HDFGWTR2_EL2, res0, res1);
|
||||
|
||||
/* HFGITR2_EL2 */
|
||||
get_reg_fixed_bits(kvm, HFGITR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGITR2_EL2, res0, res1);
|
||||
|
||||
/* TCR2_EL2 */
|
||||
res0 = TCR2_EL2_RES0;
|
||||
res1 = TCR2_EL2_RES1;
|
||||
|
||||
@@ -5195,65 +5195,13 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
|
||||
if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))
|
||||
goto out;
|
||||
|
||||
kvm->arch.fgu[HFGxTR_GROUP] = (HFGxTR_EL2_nAMAIR2_EL1 |
|
||||
HFGxTR_EL2_nMAIR2_EL1 |
|
||||
HFGxTR_EL2_nS2POR_EL1 |
|
||||
HFGxTR_EL2_nACCDATA_EL1 |
|
||||
HFGxTR_EL2_nSMPRI_EL1_MASK |
|
||||
HFGxTR_EL2_nTPIDR2_EL0_MASK);
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
|
||||
kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_TLBIRVAALE1OS|
|
||||
HFGITR_EL2_TLBIRVALE1OS |
|
||||
HFGITR_EL2_TLBIRVAAE1OS |
|
||||
HFGITR_EL2_TLBIRVAE1OS |
|
||||
HFGITR_EL2_TLBIVAALE1OS |
|
||||
HFGITR_EL2_TLBIVALE1OS |
|
||||
HFGITR_EL2_TLBIVAAE1OS |
|
||||
HFGITR_EL2_TLBIASIDE1OS |
|
||||
HFGITR_EL2_TLBIVAE1OS |
|
||||
HFGITR_EL2_TLBIVMALLE1OS);
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, RANGE))
|
||||
kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_TLBIRVAALE1 |
|
||||
HFGITR_EL2_TLBIRVALE1 |
|
||||
HFGITR_EL2_TLBIRVAAE1 |
|
||||
HFGITR_EL2_TLBIRVAE1 |
|
||||
HFGITR_EL2_TLBIRVAALE1IS|
|
||||
HFGITR_EL2_TLBIRVALE1IS |
|
||||
HFGITR_EL2_TLBIRVAAE1IS |
|
||||
HFGITR_EL2_TLBIRVAE1IS |
|
||||
HFGITR_EL2_TLBIRVAALE1OS|
|
||||
HFGITR_EL2_TLBIRVALE1OS |
|
||||
HFGITR_EL2_TLBIRVAAE1OS |
|
||||
HFGITR_EL2_TLBIRVAE1OS);
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, ATS1A, IMP))
|
||||
kvm->arch.fgu[HFGITR_GROUP] |= HFGITR_EL2_ATS1E1A;
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN2))
|
||||
kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_ATS1E1RP |
|
||||
HFGITR_EL2_ATS1E1WP);
|
||||
|
||||
if (!kvm_has_s1pie(kvm))
|
||||
kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 |
|
||||
HFGxTR_EL2_nPIR_EL1);
|
||||
|
||||
if (!kvm_has_s1poe(kvm))
|
||||
kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPOR_EL1 |
|
||||
HFGxTR_EL2_nPOR_EL0);
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, IMP))
|
||||
kvm->arch.fgu[HAFGRTR_GROUP] |= ~(HAFGRTR_EL2_RES0 |
|
||||
HAFGRTR_EL2_RES1);
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, BRBE, IMP)) {
|
||||
kvm->arch.fgu[HDFGRTR_GROUP] |= (HDFGRTR_EL2_nBRBDATA |
|
||||
HDFGRTR_EL2_nBRBCTL |
|
||||
HDFGRTR_EL2_nBRBIDR);
|
||||
kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_nBRBINJ |
|
||||
HFGITR_EL2_nBRBIALL);
|
||||
}
|
||||
compute_fgu(kvm, HFGRTR_GROUP);
|
||||
compute_fgu(kvm, HFGITR_GROUP);
|
||||
compute_fgu(kvm, HDFGRTR_GROUP);
|
||||
compute_fgu(kvm, HAFGRTR_GROUP);
|
||||
compute_fgu(kvm, HFGRTR2_GROUP);
|
||||
compute_fgu(kvm, HFGITR2_GROUP);
|
||||
compute_fgu(kvm, HDFGRTR2_GROUP);
|
||||
|
||||
set_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags);
|
||||
out:
|
||||
@@ -5311,6 +5259,8 @@ int __init kvm_sys_reg_table_init(void)
|
||||
|
||||
ret = populate_nv_trap_config();
|
||||
|
||||
check_feature_map();
|
||||
|
||||
for (i = 0; !ret && i < ARRAY_SIZE(sys_reg_descs); i++)
|
||||
ret = populate_sysreg_config(sys_reg_descs + i, i);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ HAS_EPAN
|
||||
HAS_EVT
|
||||
HAS_FPMR
|
||||
HAS_FGT
|
||||
HAS_FGT2
|
||||
HAS_FPSIMD
|
||||
HAS_GCS
|
||||
HAS_GENERIC_AUTH
|
||||
|
||||
+957
-49
File diff suppressed because it is too large
Load Diff
@@ -117,6 +117,7 @@
|
||||
|
||||
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
|
||||
|
||||
/* Data cache zero operations */
|
||||
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
|
||||
#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
|
||||
#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
|
||||
@@ -153,11 +154,13 @@
|
||||
#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)
|
||||
|
||||
#define SYS_DC_CIVAPS sys_insn(1, 0, 7, 15, 1)
|
||||
#define SYS_DC_CIGDVAPS sys_insn(1, 0, 7, 15, 5)
|
||||
|
||||
/*
|
||||
* Automatically generated definitions for system registers, the
|
||||
* manual encodings below are in the process of being converted to
|
||||
@@ -475,6 +478,7 @@
|
||||
#define SYS_CNTFRQ_EL0 sys_reg(3, 3, 14, 0, 0)
|
||||
|
||||
#define SYS_CNTPCT_EL0 sys_reg(3, 3, 14, 0, 1)
|
||||
#define SYS_CNTVCT_EL0 sys_reg(3, 3, 14, 0, 2)
|
||||
#define SYS_CNTPCTSS_EL0 sys_reg(3, 3, 14, 0, 5)
|
||||
#define SYS_CNTVCTSS_EL0 sys_reg(3, 3, 14, 0, 6)
|
||||
|
||||
@@ -482,23 +486,36 @@
|
||||
#define SYS_CNTP_CTL_EL0 sys_reg(3, 3, 14, 2, 1)
|
||||
#define SYS_CNTP_CVAL_EL0 sys_reg(3, 3, 14, 2, 2)
|
||||
|
||||
#define SYS_CNTV_TVAL_EL0 sys_reg(3, 3, 14, 3, 0)
|
||||
#define SYS_CNTV_CTL_EL0 sys_reg(3, 3, 14, 3, 1)
|
||||
#define SYS_CNTV_CVAL_EL0 sys_reg(3, 3, 14, 3, 2)
|
||||
|
||||
#define SYS_AARCH32_CNTP_TVAL sys_reg(0, 0, 14, 2, 0)
|
||||
#define SYS_AARCH32_CNTP_CTL sys_reg(0, 0, 14, 2, 1)
|
||||
#define SYS_AARCH32_CNTPCT sys_reg(0, 0, 0, 14, 0)
|
||||
#define SYS_AARCH32_CNTVCT sys_reg(0, 1, 0, 14, 0)
|
||||
#define SYS_AARCH32_CNTP_CVAL sys_reg(0, 2, 0, 14, 0)
|
||||
#define SYS_AARCH32_CNTPCTSS sys_reg(0, 8, 0, 14, 0)
|
||||
#define SYS_AARCH32_CNTVCTSS sys_reg(0, 9, 0, 14, 0)
|
||||
|
||||
#define __PMEV_op2(n) ((n) & 0x7)
|
||||
#define __CNTR_CRm(n) (0x8 | (((n) >> 3) & 0x3))
|
||||
#define SYS_PMEVCNTSVRn_EL1(n) sys_reg(2, 0, 14, __CNTR_CRm(n), __PMEV_op2(n))
|
||||
#define SYS_PMEVCNTRn_EL0(n) sys_reg(3, 3, 14, __CNTR_CRm(n), __PMEV_op2(n))
|
||||
#define __TYPER_CRm(n) (0xc | (((n) >> 3) & 0x3))
|
||||
#define SYS_PMEVTYPERn_EL0(n) sys_reg(3, 3, 14, __TYPER_CRm(n), __PMEV_op2(n))
|
||||
|
||||
#define SYS_PMCCFILTR_EL0 sys_reg(3, 3, 14, 15, 7)
|
||||
|
||||
#define SYS_SPMCGCRn_EL1(n) sys_reg(2, 0, 9, 13, ((n) & 1))
|
||||
|
||||
#define __SPMEV_op2(n) ((n) & 0x7)
|
||||
#define __SPMEV_crm(p, n) ((((p) & 7) << 1) | (((n) >> 3) & 1))
|
||||
#define SYS_SPMEVCNTRn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b000, n), __SPMEV_op2(n))
|
||||
#define SYS_SPMEVFILT2Rn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b011, n), __SPMEV_op2(n))
|
||||
#define SYS_SPMEVFILTRn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b010, n), __SPMEV_op2(n))
|
||||
#define SYS_SPMEVTYPERn_EL0(n) sys_reg(2, 3, 14, __SPMEV_crm(0b001, n), __SPMEV_op2(n))
|
||||
|
||||
#define SYS_VPIDR_EL2 sys_reg(3, 4, 0, 0, 0)
|
||||
#define SYS_VMPIDR_EL2 sys_reg(3, 4, 0, 0, 5)
|
||||
|
||||
@@ -518,7 +535,6 @@
|
||||
#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2)
|
||||
|
||||
#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
|
||||
#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)
|
||||
#define SYS_SP_EL1 sys_reg(3, 4, 4, 1, 0)
|
||||
@@ -604,28 +620,18 @@
|
||||
|
||||
/* VHE encodings for architectural EL0/1 system registers */
|
||||
#define SYS_BRBCR_EL12 sys_reg(2, 5, 9, 0, 0)
|
||||
#define SYS_SCTLR_EL12 sys_reg(3, 5, 1, 0, 0)
|
||||
#define SYS_CPACR_EL12 sys_reg(3, 5, 1, 0, 2)
|
||||
#define SYS_SCTLR2_EL12 sys_reg(3, 5, 1, 0, 3)
|
||||
#define SYS_ZCR_EL12 sys_reg(3, 5, 1, 2, 0)
|
||||
#define SYS_TRFCR_EL12 sys_reg(3, 5, 1, 2, 1)
|
||||
#define SYS_SMCR_EL12 sys_reg(3, 5, 1, 2, 6)
|
||||
#define SYS_TTBR0_EL12 sys_reg(3, 5, 2, 0, 0)
|
||||
#define SYS_TTBR1_EL12 sys_reg(3, 5, 2, 0, 1)
|
||||
#define SYS_TCR_EL12 sys_reg(3, 5, 2, 0, 2)
|
||||
#define SYS_TCR2_EL12 sys_reg(3, 5, 2, 0, 3)
|
||||
#define SYS_SPSR_EL12 sys_reg(3, 5, 4, 0, 0)
|
||||
#define SYS_ELR_EL12 sys_reg(3, 5, 4, 0, 1)
|
||||
#define SYS_AFSR0_EL12 sys_reg(3, 5, 5, 1, 0)
|
||||
#define SYS_AFSR1_EL12 sys_reg(3, 5, 5, 1, 1)
|
||||
#define SYS_ESR_EL12 sys_reg(3, 5, 5, 2, 0)
|
||||
#define SYS_TFSR_EL12 sys_reg(3, 5, 5, 6, 0)
|
||||
#define SYS_FAR_EL12 sys_reg(3, 5, 6, 0, 0)
|
||||
#define SYS_PMSCR_EL12 sys_reg(3, 5, 9, 9, 0)
|
||||
#define SYS_MAIR_EL12 sys_reg(3, 5, 10, 2, 0)
|
||||
#define SYS_AMAIR_EL12 sys_reg(3, 5, 10, 3, 0)
|
||||
#define SYS_VBAR_EL12 sys_reg(3, 5, 12, 0, 0)
|
||||
#define SYS_CONTEXTIDR_EL12 sys_reg(3, 5, 13, 0, 1)
|
||||
#define SYS_SCXTNUM_EL12 sys_reg(3, 5, 13, 0, 7)
|
||||
#define SYS_CNTKCTL_EL12 sys_reg(3, 5, 14, 1, 0)
|
||||
#define SYS_CNTP_TVAL_EL02 sys_reg(3, 5, 14, 2, 0)
|
||||
@@ -1028,8 +1034,11 @@
|
||||
#define PIE_RX UL(0xa)
|
||||
#define PIE_RW UL(0xc)
|
||||
#define PIE_RWX UL(0xe)
|
||||
#define PIE_MASK UL(0xf)
|
||||
|
||||
#define PIRx_ELx_PERM(idx, perm) ((perm) << ((idx) * 4))
|
||||
#define PIRx_ELx_BITS_PER_IDX 4
|
||||
#define PIRx_ELx_PERM_SHIFT(idx) ((idx) * PIRx_ELx_BITS_PER_IDX)
|
||||
#define PIRx_ELx_PERM_PREP(idx, perm) (((perm) & PIE_MASK) << PIRx_ELx_PERM_SHIFT(idx))
|
||||
|
||||
/*
|
||||
* Permission Overlay Extension (POE) permission encodings.
|
||||
@@ -1040,12 +1049,34 @@
|
||||
#define POE_RX UL(0x3)
|
||||
#define POE_W UL(0x4)
|
||||
#define POE_RW UL(0x5)
|
||||
#define POE_XW UL(0x6)
|
||||
#define POE_RXW UL(0x7)
|
||||
#define POE_WX UL(0x6)
|
||||
#define POE_RWX UL(0x7)
|
||||
#define POE_MASK UL(0xf)
|
||||
|
||||
/* Initial value for Permission Overlay Extension for EL0 */
|
||||
#define POR_EL0_INIT POE_RXW
|
||||
#define POR_ELx_BITS_PER_IDX 4
|
||||
#define POR_ELx_PERM_SHIFT(idx) ((idx) * POR_ELx_BITS_PER_IDX)
|
||||
#define POR_ELx_PERM_GET(idx, reg) (((reg) >> POR_ELx_PERM_SHIFT(idx)) & POE_MASK)
|
||||
#define POR_ELx_PERM_PREP(idx, perm) (((perm) & POE_MASK) << POR_ELx_PERM_SHIFT(idx))
|
||||
|
||||
/*
|
||||
* Definitions for Guarded Control Stack
|
||||
*/
|
||||
|
||||
#define GCS_CAP_ADDR_MASK GENMASK(63, 12)
|
||||
#define GCS_CAP_ADDR_SHIFT 12
|
||||
#define GCS_CAP_ADDR_WIDTH 52
|
||||
#define GCS_CAP_ADDR(x) FIELD_GET(GCS_CAP_ADDR_MASK, x)
|
||||
|
||||
#define GCS_CAP_TOKEN_MASK GENMASK(11, 0)
|
||||
#define GCS_CAP_TOKEN_SHIFT 0
|
||||
#define GCS_CAP_TOKEN_WIDTH 12
|
||||
#define GCS_CAP_TOKEN(x) FIELD_GET(GCS_CAP_TOKEN_MASK, x)
|
||||
|
||||
#define GCS_CAP_VALID_TOKEN 0x1
|
||||
#define GCS_CAP_IN_PROGRESS_TOKEN 0x5
|
||||
|
||||
#define GCS_CAP(x) ((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \
|
||||
GCS_CAP_VALID_TOKEN)
|
||||
|
||||
#define ARM64_FEATURE_FIELD_BITS 4
|
||||
|
||||
|
||||
Reference in New Issue
Block a user