mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
Merge branch kvm-arm64/resx into kvmarm-master/next
* kvm-arm64/resx:
: .
: Add infrastructure to deal with the full gamut of RESx bits
: for NV. As a result, it is now possible to have the expected
: semantics for some bits such as SCTLR_EL2.SPAN.
: .
KVM: arm64: Add debugfs file dumping computed RESx values
KVM: arm64: Add sanitisation to SCTLR_EL2
KVM: arm64: Remove all traces of HCR_EL2.MIOCNCE
KVM: arm64: Remove all traces of FEAT_TME
KVM: arm64: Simplify handling of full register invalid constraint
KVM: arm64: Get rid of FIXED_VALUE altogether
KVM: arm64: Simplify handling of HCR_EL2.E2H RESx
KVM: arm64: Move RESx into individual register descriptors
KVM: arm64: Add RES1_WHEN_E2Hx constraints as configuration flags
KVM: arm64: Add REQUIRES_E2H1 constraint as configuration flags
KVM: arm64: Simplify FIXED_VALUE handling
KVM: arm64: Convert HCR_EL2.RW to AS_RES1
KVM: arm64: Correctly handle SCTLR_EL1 RES1 bits for unsupported features
KVM: arm64: Allow RES1 bits to be inferred from configuration
KVM: arm64: Inherit RESx bits from FGT register descriptors
KVM: arm64: Extend unified RESx handling to runtime sanitisation
KVM: arm64: Introduce data structure tracking both RES0 and RES1 bits
KVM: arm64: Introduce standalone FGU computing primitive
KVM: arm64: Remove duplicate configuration for SCTLR_EL1.{EE,E0E}
arm64: Convert SCTLR_EL2 to sysreg infrastructure
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
commit
1df3f01ebf
|
|
@ -492,7 +492,6 @@ enum vcpu_sysreg {
|
|||
DBGVCR32_EL2, /* Debug Vector Catch Register */
|
||||
|
||||
/* EL2 registers */
|
||||
SCTLR_EL2, /* System Control Register (EL2) */
|
||||
ACTLR_EL2, /* Auxiliary Control Register (EL2) */
|
||||
CPTR_EL2, /* Architectural Feature Trap Register (EL2) */
|
||||
HACR_EL2, /* Hypervisor Auxiliary Control Register */
|
||||
|
|
@ -523,6 +522,7 @@ enum vcpu_sysreg {
|
|||
|
||||
/* Anything from this can be RES0/RES1 sanitised */
|
||||
MARKER(__SANITISED_REG_START__),
|
||||
SCTLR_EL2, /* System Control Register (EL2) */
|
||||
TCR2_EL2, /* Extended Translation Control Register (EL2) */
|
||||
SCTLR2_EL2, /* System Control Register 2 (EL2) */
|
||||
MDCR_EL2, /* Monitor Debug Configuration Register (EL2) */
|
||||
|
|
@ -623,13 +623,39 @@ enum vcpu_sysreg {
|
|||
NR_SYS_REGS /* Nothing after this line! */
|
||||
};
|
||||
|
||||
struct kvm_sysreg_masks {
|
||||
struct {
|
||||
u64 res0;
|
||||
u64 res1;
|
||||
} mask[NR_SYS_REGS - __SANITISED_REG_START__];
|
||||
struct resx {
|
||||
u64 res0;
|
||||
u64 res1;
|
||||
};
|
||||
|
||||
struct kvm_sysreg_masks {
|
||||
struct resx mask[NR_SYS_REGS - __SANITISED_REG_START__];
|
||||
};
|
||||
|
||||
static inline struct resx __kvm_get_sysreg_resx(struct kvm_arch *arch,
|
||||
enum vcpu_sysreg sr)
|
||||
{
|
||||
struct kvm_sysreg_masks *masks;
|
||||
|
||||
masks = arch->sysreg_masks;
|
||||
if (likely(masks &&
|
||||
sr >= __SANITISED_REG_START__ && sr < NR_SYS_REGS))
|
||||
return masks->mask[sr - __SANITISED_REG_START__];
|
||||
|
||||
return (struct resx){};
|
||||
}
|
||||
|
||||
#define kvm_get_sysreg_resx(k, sr) __kvm_get_sysreg_resx(&(k)->arch, (sr))
|
||||
|
||||
static inline void __kvm_set_sysreg_resx(struct kvm_arch *arch,
|
||||
enum vcpu_sysreg sr, struct resx resx)
|
||||
{
|
||||
arch->sysreg_masks->mask[sr - __SANITISED_REG_START__] = resx;
|
||||
}
|
||||
|
||||
#define kvm_set_sysreg_resx(k, sr, resx) \
|
||||
__kvm_set_sysreg_resx(&(k)->arch, (sr), (resx))
|
||||
|
||||
struct fgt_masks {
|
||||
const char *str;
|
||||
u64 mask;
|
||||
|
|
@ -1604,7 +1630,7 @@ static inline bool kvm_arch_has_irq_bypass(void)
|
|||
}
|
||||
|
||||
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);
|
||||
struct resx get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg);
|
||||
void check_feature_map(void);
|
||||
void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu);
|
||||
|
||||
|
|
|
|||
|
|
@ -504,7 +504,6 @@
|
|||
#define SYS_VPIDR_EL2 sys_reg(3, 4, 0, 0, 0)
|
||||
#define SYS_VMPIDR_EL2 sys_reg(3, 4, 0, 0, 5)
|
||||
|
||||
#define SYS_SCTLR_EL2 sys_reg(3, 4, 1, 0, 0)
|
||||
#define SYS_ACTLR_EL2 sys_reg(3, 4, 1, 0, 1)
|
||||
#define SYS_SCTLR2_EL2 sys_reg(3, 4, 1, 0, 3)
|
||||
#define SYS_HCR_EL2 sys_reg(3, 4, 1, 1, 0)
|
||||
|
|
@ -836,12 +835,6 @@
|
|||
#define SCTLR_ELx_A (BIT(1))
|
||||
#define SCTLR_ELx_M (BIT(0))
|
||||
|
||||
/* SCTLR_EL2 specific flags. */
|
||||
#define SCTLR_EL2_RES1 ((BIT(4)) | (BIT(5)) | (BIT(11)) | (BIT(16)) | \
|
||||
(BIT(18)) | (BIT(22)) | (BIT(23)) | (BIT(28)) | \
|
||||
(BIT(29)))
|
||||
|
||||
#define SCTLR_EL2_BT (BIT(36))
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define ENDIAN_SET_EL2 SCTLR_ELx_EE
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@ struct reg_bits_to_feat_map {
|
|||
|
||||
#define NEVER_FGU BIT(0) /* Can trap, but never UNDEF */
|
||||
#define CALL_FUNC BIT(1) /* Needs to evaluate tons of crap */
|
||||
#define FIXED_VALUE BIT(2) /* RAZ/WI or RAO/WI in KVM */
|
||||
#define FORCE_RESx BIT(2) /* Unconditional RESx */
|
||||
#define MASKS_POINTER BIT(3) /* Pointer to fgt_masks struct instead of bits */
|
||||
#define AS_RES1 BIT(4) /* RES1 when not supported */
|
||||
#define REQUIRES_E2H1 BIT(5) /* Add HCR_EL2.E2H RES1 as a pre-condition */
|
||||
#define RES1_WHEN_E2H0 BIT(6) /* RES1 when E2H=0 and not supported */
|
||||
#define RES1_WHEN_E2H1 BIT(7) /* RES1 when E2H=1 and not supported */
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -36,7 +40,6 @@ struct reg_bits_to_feat_map {
|
|||
s8 lo_lim;
|
||||
};
|
||||
bool (*match)(struct kvm *);
|
||||
bool (*fval)(struct kvm *, u64 *);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -69,13 +72,6 @@ struct reg_feat_map_desc {
|
|||
.lo_lim = id ##_## fld ##_## lim \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_2(m, f, w, fun, dummy) \
|
||||
{ \
|
||||
.w = (m), \
|
||||
.flags = (f) | CALL_FUNC, \
|
||||
.fval = (fun), \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_1(m, f, w, fun) \
|
||||
{ \
|
||||
.w = (m), \
|
||||
|
|
@ -83,15 +79,18 @@ struct reg_feat_map_desc {
|
|||
.match = (fun), \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_0(m, f, w, ...) \
|
||||
{ \
|
||||
.w = (m), \
|
||||
.flags = (f), \
|
||||
}
|
||||
|
||||
#define __NEEDS_FEAT_FLAG(m, f, w, ...) \
|
||||
CONCATENATE(__NEEDS_FEAT_, COUNT_ARGS(__VA_ARGS__))(m, f, w, __VA_ARGS__)
|
||||
|
||||
#define NEEDS_FEAT_FLAG(m, f, ...) \
|
||||
__NEEDS_FEAT_FLAG(m, f, bits, __VA_ARGS__)
|
||||
|
||||
#define NEEDS_FEAT_FIXED(m, ...) \
|
||||
__NEEDS_FEAT_FLAG(m, FIXED_VALUE, bits, __VA_ARGS__, 0)
|
||||
|
||||
#define NEEDS_FEAT_MASKS(p, ...) \
|
||||
__NEEDS_FEAT_FLAG(p, MASKS_POINTER, masks, __VA_ARGS__)
|
||||
|
||||
|
|
@ -101,10 +100,14 @@ struct reg_feat_map_desc {
|
|||
*/
|
||||
#define NEEDS_FEAT(m, ...) NEEDS_FEAT_FLAG(m, 0, __VA_ARGS__)
|
||||
|
||||
/* Declare fixed RESx bits */
|
||||
#define FORCE_RES0(m) NEEDS_FEAT_FLAG(m, FORCE_RESx)
|
||||
#define FORCE_RES1(m) NEEDS_FEAT_FLAG(m, FORCE_RESx | AS_RES1)
|
||||
|
||||
/*
|
||||
* Declare the dependency between a non-FGT register, a set of
|
||||
* feature, and the set of individual bits it contains. This generates
|
||||
* a struct reg_feat_map_desc.
|
||||
* Declare the dependency between a non-FGT register, a set of features,
|
||||
* and the set of individual bits it contains. This generates a struct
|
||||
* reg_feat_map_desc.
|
||||
*/
|
||||
#define DECLARE_FEAT_MAP(n, r, m, f) \
|
||||
struct reg_feat_map_desc n = { \
|
||||
|
|
@ -184,7 +187,6 @@ struct reg_feat_map_desc {
|
|||
#define FEAT_RME ID_AA64PFR0_EL1, RME, IMP
|
||||
#define FEAT_MPAM ID_AA64PFR0_EL1, MPAM, 1
|
||||
#define FEAT_S2FWB ID_AA64MMFR2_EL1, FWB, IMP
|
||||
#define FEAT_TME ID_AA64ISAR0_EL1, TME, IMP
|
||||
#define FEAT_TWED ID_AA64MMFR1_EL1, TWED, IMP
|
||||
#define FEAT_E2H0 ID_AA64MMFR4_EL1, E2H0, IMP
|
||||
#define FEAT_SRMASK ID_AA64MMFR4_EL1, SRMASK, IMP
|
||||
|
|
@ -310,21 +312,6 @@ static bool feat_trbe_mpam(struct kvm *kvm)
|
|||
(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_MPAM));
|
||||
}
|
||||
|
||||
static bool feat_asid2_e2h1(struct kvm *kvm)
|
||||
{
|
||||
return kvm_has_feat(kvm, FEAT_ASID2) && !kvm_has_feat(kvm, FEAT_E2H0);
|
||||
}
|
||||
|
||||
static bool feat_d128_e2h1(struct kvm *kvm)
|
||||
{
|
||||
return kvm_has_feat(kvm, FEAT_D128) && !kvm_has_feat(kvm, FEAT_E2H0);
|
||||
}
|
||||
|
||||
static bool feat_mec_e2h1(struct kvm *kvm)
|
||||
{
|
||||
return kvm_has_feat(kvm, FEAT_MEC) && !kvm_has_feat(kvm, FEAT_E2H0);
|
||||
}
|
||||
|
||||
static bool feat_ebep_pmuv3_ss(struct kvm *kvm)
|
||||
{
|
||||
return kvm_has_feat(kvm, FEAT_EBEP) || kvm_has_feat(kvm, FEAT_PMUv3_SS);
|
||||
|
|
@ -388,31 +375,6 @@ static bool feat_vmid16(struct kvm *kvm)
|
|||
return kvm_has_feat_enum(kvm, ID_AA64MMFR1_EL1, VMIDBits, 16);
|
||||
}
|
||||
|
||||
static bool compute_hcr_rw(struct kvm *kvm, u64 *bits)
|
||||
{
|
||||
/* This is purely academic: AArch32 and NV are mutually exclusive */
|
||||
if (bits) {
|
||||
if (kvm_has_feat(kvm, FEAT_AA32EL1))
|
||||
*bits &= ~HCR_EL2_RW;
|
||||
else
|
||||
*bits |= HCR_EL2_RW;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool compute_hcr_e2h(struct kvm *kvm, u64 *bits)
|
||||
{
|
||||
if (bits) {
|
||||
if (kvm_has_feat(kvm, FEAT_E2H0))
|
||||
*bits &= ~HCR_EL2_E2H;
|
||||
else
|
||||
*bits |= HCR_EL2_E2H;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct reg_bits_to_feat_map hfgrtr_feat_map[] = {
|
||||
NEEDS_FEAT(HFGRTR_EL2_nAMAIR2_EL1 |
|
||||
HFGRTR_EL2_nMAIR2_EL1,
|
||||
|
|
@ -966,7 +928,7 @@ static const DECLARE_FEAT_MAP(hcrx_desc, __HCRX_EL2,
|
|||
|
||||
static const struct reg_bits_to_feat_map hcr_feat_map[] = {
|
||||
NEEDS_FEAT(HCR_EL2_TID0, FEAT_AA32EL0),
|
||||
NEEDS_FEAT_FIXED(HCR_EL2_RW, compute_hcr_rw),
|
||||
NEEDS_FEAT_FLAG(HCR_EL2_RW, AS_RES1, FEAT_AA32EL1),
|
||||
NEEDS_FEAT(HCR_EL2_HCD, not_feat_aa64el3),
|
||||
NEEDS_FEAT(HCR_EL2_AMO |
|
||||
HCR_EL2_BSU |
|
||||
|
|
@ -976,7 +938,6 @@ static const struct reg_bits_to_feat_map hcr_feat_map[] = {
|
|||
HCR_EL2_FMO |
|
||||
HCR_EL2_ID |
|
||||
HCR_EL2_IMO |
|
||||
HCR_EL2_MIOCNCE |
|
||||
HCR_EL2_PTW |
|
||||
HCR_EL2_SWIO |
|
||||
HCR_EL2_TACR |
|
||||
|
|
@ -1028,11 +989,12 @@ static const struct reg_bits_to_feat_map hcr_feat_map[] = {
|
|||
NEEDS_FEAT(HCR_EL2_FIEN, feat_rasv1p1),
|
||||
NEEDS_FEAT(HCR_EL2_GPF, FEAT_RME),
|
||||
NEEDS_FEAT(HCR_EL2_FWB, FEAT_S2FWB),
|
||||
NEEDS_FEAT(HCR_EL2_TME, FEAT_TME),
|
||||
NEEDS_FEAT(HCR_EL2_TWEDEL |
|
||||
HCR_EL2_TWEDEn,
|
||||
FEAT_TWED),
|
||||
NEEDS_FEAT_FIXED(HCR_EL2_E2H, compute_hcr_e2h),
|
||||
NEEDS_FEAT_FLAG(HCR_EL2_E2H, RES1_WHEN_E2H1 | FORCE_RESx),
|
||||
FORCE_RES0(HCR_EL2_RES0),
|
||||
FORCE_RES1(HCR_EL2_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(hcr_desc, HCR_EL2,
|
||||
|
|
@ -1053,21 +1015,23 @@ static const struct reg_bits_to_feat_map sctlr2_feat_map[] = {
|
|||
SCTLR2_EL1_CPTM |
|
||||
SCTLR2_EL1_CPTM0,
|
||||
FEAT_CPA2),
|
||||
FORCE_RES0(SCTLR2_EL1_RES0),
|
||||
FORCE_RES1(SCTLR2_EL1_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(sctlr2_desc, SCTLR2_EL1,
|
||||
sctlr2_feat_map, FEAT_SCTLR2);
|
||||
|
||||
static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = {
|
||||
NEEDS_FEAT(TCR2_EL2_FNG1 |
|
||||
TCR2_EL2_FNG0 |
|
||||
TCR2_EL2_A2,
|
||||
feat_asid2_e2h1),
|
||||
NEEDS_FEAT(TCR2_EL2_DisCH1 |
|
||||
TCR2_EL2_DisCH0 |
|
||||
TCR2_EL2_D128,
|
||||
feat_d128_e2h1),
|
||||
NEEDS_FEAT(TCR2_EL2_AMEC1, feat_mec_e2h1),
|
||||
NEEDS_FEAT_FLAG(TCR2_EL2_FNG1 |
|
||||
TCR2_EL2_FNG0 |
|
||||
TCR2_EL2_A2,
|
||||
REQUIRES_E2H1, FEAT_ASID2),
|
||||
NEEDS_FEAT_FLAG(TCR2_EL2_DisCH1 |
|
||||
TCR2_EL2_DisCH0 |
|
||||
TCR2_EL2_D128,
|
||||
REQUIRES_E2H1, FEAT_D128),
|
||||
NEEDS_FEAT_FLAG(TCR2_EL2_AMEC1, REQUIRES_E2H1, FEAT_MEC),
|
||||
NEEDS_FEAT(TCR2_EL2_AMEC0, FEAT_MEC),
|
||||
NEEDS_FEAT(TCR2_EL2_HAFT, FEAT_HAFT),
|
||||
NEEDS_FEAT(TCR2_EL2_PTTWI |
|
||||
|
|
@ -1078,33 +1042,36 @@ static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = {
|
|||
TCR2_EL2_E0POE,
|
||||
FEAT_S1POE),
|
||||
NEEDS_FEAT(TCR2_EL2_PIE, FEAT_S1PIE),
|
||||
FORCE_RES0(TCR2_EL2_RES0),
|
||||
FORCE_RES1(TCR2_EL2_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(tcr2_el2_desc, TCR2_EL2,
|
||||
tcr2_el2_feat_map, FEAT_TCR2);
|
||||
|
||||
static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
|
||||
NEEDS_FEAT(SCTLR_EL1_CP15BEN |
|
||||
SCTLR_EL1_ITD |
|
||||
SCTLR_EL1_SED,
|
||||
FEAT_AA32EL0),
|
||||
NEEDS_FEAT(SCTLR_EL1_CP15BEN, FEAT_AA32EL0),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL1_ITD |
|
||||
SCTLR_EL1_SED,
|
||||
AS_RES1, FEAT_AA32EL0),
|
||||
NEEDS_FEAT(SCTLR_EL1_BT0 |
|
||||
SCTLR_EL1_BT1,
|
||||
FEAT_BTI),
|
||||
NEEDS_FEAT(SCTLR_EL1_CMOW, FEAT_CMOW),
|
||||
NEEDS_FEAT(SCTLR_EL1_TSCXT, feat_csv2_2_csv2_1p2),
|
||||
NEEDS_FEAT(SCTLR_EL1_EIS |
|
||||
SCTLR_EL1_EOS,
|
||||
FEAT_ExS),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL1_TSCXT,
|
||||
AS_RES1, feat_csv2_2_csv2_1p2),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL1_EIS |
|
||||
SCTLR_EL1_EOS,
|
||||
AS_RES1, FEAT_ExS),
|
||||
NEEDS_FEAT(SCTLR_EL1_EnFPM, FEAT_FPMR),
|
||||
NEEDS_FEAT(SCTLR_EL1_IESB, FEAT_IESB),
|
||||
NEEDS_FEAT(SCTLR_EL1_EnALS, FEAT_LS64),
|
||||
NEEDS_FEAT(SCTLR_EL1_EnAS0, FEAT_LS64_ACCDATA),
|
||||
NEEDS_FEAT(SCTLR_EL1_EnASR, FEAT_LS64_V),
|
||||
NEEDS_FEAT(SCTLR_EL1_nAA, FEAT_LSE2),
|
||||
NEEDS_FEAT(SCTLR_EL1_LSMAOE |
|
||||
SCTLR_EL1_nTLSMD,
|
||||
FEAT_LSMAOC),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL1_LSMAOE |
|
||||
SCTLR_EL1_nTLSMD,
|
||||
AS_RES1, FEAT_LSMAOC),
|
||||
NEEDS_FEAT(SCTLR_EL1_EE, FEAT_MixedEnd),
|
||||
NEEDS_FEAT(SCTLR_EL1_E0E, feat_mixedendel0),
|
||||
NEEDS_FEAT(SCTLR_EL1_MSCEn, FEAT_MOPS),
|
||||
|
|
@ -1120,7 +1087,8 @@ static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
|
|||
NEEDS_FEAT(SCTLR_EL1_NMI |
|
||||
SCTLR_EL1_SPINTMASK,
|
||||
FEAT_NMI),
|
||||
NEEDS_FEAT(SCTLR_EL1_SPAN, FEAT_PAN),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL1_SPAN,
|
||||
AS_RES1, FEAT_PAN),
|
||||
NEEDS_FEAT(SCTLR_EL1_EPAN, FEAT_PAN3),
|
||||
NEEDS_FEAT(SCTLR_EL1_EnDA |
|
||||
SCTLR_EL1_EnDB |
|
||||
|
|
@ -1131,17 +1099,10 @@ static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
|
|||
NEEDS_FEAT(SCTLR_EL1_EnRCTX, FEAT_SPECRES),
|
||||
NEEDS_FEAT(SCTLR_EL1_DSSBS, FEAT_SSBS),
|
||||
NEEDS_FEAT(SCTLR_EL1_TIDCP, FEAT_TIDCP1),
|
||||
NEEDS_FEAT(SCTLR_EL1_TME0 |
|
||||
SCTLR_EL1_TME |
|
||||
SCTLR_EL1_TMT0 |
|
||||
SCTLR_EL1_TMT,
|
||||
FEAT_TME),
|
||||
NEEDS_FEAT(SCTLR_EL1_TWEDEL |
|
||||
SCTLR_EL1_TWEDEn,
|
||||
FEAT_TWED),
|
||||
NEEDS_FEAT(SCTLR_EL1_UCI |
|
||||
SCTLR_EL1_EE |
|
||||
SCTLR_EL1_E0E |
|
||||
SCTLR_EL1_WXN |
|
||||
SCTLR_EL1_nTWE |
|
||||
SCTLR_EL1_nTWI |
|
||||
|
|
@ -1155,11 +1116,91 @@ static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
|
|||
SCTLR_EL1_A |
|
||||
SCTLR_EL1_M,
|
||||
FEAT_AA64EL1),
|
||||
FORCE_RES0(SCTLR_EL1_RES0),
|
||||
FORCE_RES1(SCTLR_EL1_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(sctlr_el1_desc, SCTLR_EL1,
|
||||
sctlr_el1_feat_map, FEAT_AA64EL1);
|
||||
|
||||
static const struct reg_bits_to_feat_map sctlr_el2_feat_map[] = {
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_CP15BEN,
|
||||
RES1_WHEN_E2H0 | REQUIRES_E2H1,
|
||||
FEAT_AA32EL0),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_ITD |
|
||||
SCTLR_EL2_SED,
|
||||
RES1_WHEN_E2H1 | REQUIRES_E2H1,
|
||||
FEAT_AA32EL0),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_BT0, REQUIRES_E2H1, FEAT_BTI),
|
||||
NEEDS_FEAT(SCTLR_EL2_BT, FEAT_BTI),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_CMOW, REQUIRES_E2H1, FEAT_CMOW),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_TSCXT,
|
||||
RES1_WHEN_E2H1 | REQUIRES_E2H1,
|
||||
feat_csv2_2_csv2_1p2),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_EIS |
|
||||
SCTLR_EL2_EOS,
|
||||
AS_RES1, FEAT_ExS),
|
||||
NEEDS_FEAT(SCTLR_EL2_EnFPM, FEAT_FPMR),
|
||||
NEEDS_FEAT(SCTLR_EL2_IESB, FEAT_IESB),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_EnALS, REQUIRES_E2H1, FEAT_LS64),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_EnAS0, REQUIRES_E2H1, FEAT_LS64_ACCDATA),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_EnASR, REQUIRES_E2H1, FEAT_LS64_V),
|
||||
NEEDS_FEAT(SCTLR_EL2_nAA, FEAT_LSE2),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_LSMAOE |
|
||||
SCTLR_EL2_nTLSMD,
|
||||
AS_RES1 | REQUIRES_E2H1, FEAT_LSMAOC),
|
||||
NEEDS_FEAT(SCTLR_EL2_EE, FEAT_MixedEnd),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_E0E, REQUIRES_E2H1, feat_mixedendel0),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_MSCEn, REQUIRES_E2H1, FEAT_MOPS),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_ATA0 |
|
||||
SCTLR_EL2_TCF0,
|
||||
REQUIRES_E2H1, FEAT_MTE2),
|
||||
NEEDS_FEAT(SCTLR_EL2_ATA |
|
||||
SCTLR_EL2_TCF,
|
||||
FEAT_MTE2),
|
||||
NEEDS_FEAT(SCTLR_EL2_ITFSB, feat_mte_async),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_TCSO0, REQUIRES_E2H1, FEAT_MTE_STORE_ONLY),
|
||||
NEEDS_FEAT(SCTLR_EL2_TCSO,
|
||||
FEAT_MTE_STORE_ONLY),
|
||||
NEEDS_FEAT(SCTLR_EL2_NMI |
|
||||
SCTLR_EL2_SPINTMASK,
|
||||
FEAT_NMI),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_SPAN, AS_RES1 | REQUIRES_E2H1, FEAT_PAN),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_EPAN, REQUIRES_E2H1, FEAT_PAN3),
|
||||
NEEDS_FEAT(SCTLR_EL2_EnDA |
|
||||
SCTLR_EL2_EnDB |
|
||||
SCTLR_EL2_EnIA |
|
||||
SCTLR_EL2_EnIB,
|
||||
feat_pauth),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_EnTP2, REQUIRES_E2H1, FEAT_SME),
|
||||
NEEDS_FEAT(SCTLR_EL2_EnRCTX, FEAT_SPECRES),
|
||||
NEEDS_FEAT(SCTLR_EL2_DSSBS, FEAT_SSBS),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_TIDCP, REQUIRES_E2H1, FEAT_TIDCP1),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_TWEDEL |
|
||||
SCTLR_EL2_TWEDEn,
|
||||
REQUIRES_E2H1, FEAT_TWED),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_nTWE |
|
||||
SCTLR_EL2_nTWI,
|
||||
AS_RES1 | REQUIRES_E2H1, FEAT_AA64EL2),
|
||||
NEEDS_FEAT_FLAG(SCTLR_EL2_UCI |
|
||||
SCTLR_EL2_UCT |
|
||||
SCTLR_EL2_DZE |
|
||||
SCTLR_EL2_SA0,
|
||||
REQUIRES_E2H1, FEAT_AA64EL2),
|
||||
NEEDS_FEAT(SCTLR_EL2_WXN |
|
||||
SCTLR_EL2_I |
|
||||
SCTLR_EL2_SA |
|
||||
SCTLR_EL2_C |
|
||||
SCTLR_EL2_A |
|
||||
SCTLR_EL2_M,
|
||||
FEAT_AA64EL2),
|
||||
FORCE_RES0(SCTLR_EL2_RES0),
|
||||
FORCE_RES1(SCTLR_EL2_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(sctlr_el2_desc, SCTLR_EL2,
|
||||
sctlr_el2_feat_map, FEAT_AA64EL2);
|
||||
|
||||
static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = {
|
||||
NEEDS_FEAT(MDCR_EL2_EBWE, FEAT_Debugv8p9),
|
||||
NEEDS_FEAT(MDCR_EL2_TDOSA, FEAT_DoubleLock),
|
||||
|
|
@ -1189,6 +1230,8 @@ static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = {
|
|||
MDCR_EL2_TDE |
|
||||
MDCR_EL2_TDRA,
|
||||
FEAT_AA64EL1),
|
||||
FORCE_RES0(MDCR_EL2_RES0),
|
||||
FORCE_RES1(MDCR_EL2_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(mdcr_el2_desc, MDCR_EL2,
|
||||
|
|
@ -1227,6 +1270,8 @@ static const struct reg_bits_to_feat_map vtcr_el2_feat_map[] = {
|
|||
VTCR_EL2_SL0 |
|
||||
VTCR_EL2_T0SZ,
|
||||
FEAT_AA64EL1),
|
||||
FORCE_RES0(VTCR_EL2_RES0),
|
||||
FORCE_RES1(VTCR_EL2_RES1),
|
||||
};
|
||||
|
||||
static const DECLARE_FEAT_MAP(vtcr_el2_desc, VTCR_EL2,
|
||||
|
|
@ -1237,8 +1282,14 @@ static void __init check_feat_map(const struct reg_bits_to_feat_map *map,
|
|||
{
|
||||
u64 mask = 0;
|
||||
|
||||
/*
|
||||
* Don't account for FORCE_RESx that are architectural, and
|
||||
* therefore part of the resx parameter. Other FORCE_RESx bits
|
||||
* are implementation choices, and therefore accounted for.
|
||||
*/
|
||||
for (int i = 0; i < map_size; i++)
|
||||
mask |= map[i].bits;
|
||||
if (!((map[i].flags & FORCE_RESx) && (map[i].bits & resx)))
|
||||
mask |= map[i].bits;
|
||||
|
||||
if (mask != ~resx)
|
||||
kvm_err("Undefined %s behaviour, bits %016llx\n",
|
||||
|
|
@ -1274,6 +1325,7 @@ void __init check_feature_map(void)
|
|||
check_reg_desc(&sctlr2_desc);
|
||||
check_reg_desc(&tcr2_el2_desc);
|
||||
check_reg_desc(&sctlr_el1_desc);
|
||||
check_reg_desc(&sctlr_el2_desc);
|
||||
check_reg_desc(&mdcr_el2_desc);
|
||||
check_reg_desc(&vtcr_el2_desc);
|
||||
}
|
||||
|
|
@ -1292,14 +1344,14 @@ static bool idreg_feat_match(struct kvm *kvm, const struct reg_bits_to_feat_map
|
|||
}
|
||||
}
|
||||
|
||||
static u64 __compute_fixed_bits(struct kvm *kvm,
|
||||
const struct reg_bits_to_feat_map *map,
|
||||
int map_size,
|
||||
u64 *fixed_bits,
|
||||
unsigned long require,
|
||||
unsigned long exclude)
|
||||
static struct resx compute_resx_bits(struct kvm *kvm,
|
||||
const struct reg_bits_to_feat_map *map,
|
||||
int map_size,
|
||||
unsigned long require,
|
||||
unsigned long exclude)
|
||||
{
|
||||
u64 val = 0;
|
||||
bool e2h0 = kvm_has_feat(kvm, FEAT_E2H0);
|
||||
struct resx resx = {};
|
||||
|
||||
for (int i = 0; i < map_size; i++) {
|
||||
bool match;
|
||||
|
|
@ -1310,60 +1362,72 @@ static u64 __compute_fixed_bits(struct kvm *kvm,
|
|||
if (map[i].flags & exclude)
|
||||
continue;
|
||||
|
||||
if (map[i].flags & CALL_FUNC)
|
||||
match = (map[i].flags & FIXED_VALUE) ?
|
||||
map[i].fval(kvm, fixed_bits) :
|
||||
map[i].match(kvm);
|
||||
if (map[i].flags & FORCE_RESx)
|
||||
match = false;
|
||||
else if (map[i].flags & CALL_FUNC)
|
||||
match = map[i].match(kvm);
|
||||
else
|
||||
match = idreg_feat_match(kvm, &map[i]);
|
||||
|
||||
if (!match || (map[i].flags & FIXED_VALUE))
|
||||
val |= reg_feat_map_bits(&map[i]);
|
||||
if (map[i].flags & REQUIRES_E2H1)
|
||||
match &= !e2h0;
|
||||
|
||||
if (!match) {
|
||||
u64 bits = reg_feat_map_bits(&map[i]);
|
||||
|
||||
if ((map[i].flags & AS_RES1) ||
|
||||
(e2h0 && (map[i].flags & RES1_WHEN_E2H0)) ||
|
||||
(!e2h0 && (map[i].flags & RES1_WHEN_E2H1)))
|
||||
resx.res1 |= bits;
|
||||
else
|
||||
resx.res0 |= bits;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
return resx;
|
||||
}
|
||||
|
||||
static u64 compute_res0_bits(struct kvm *kvm,
|
||||
const struct reg_bits_to_feat_map *map,
|
||||
int map_size,
|
||||
unsigned long require,
|
||||
unsigned long exclude)
|
||||
static struct resx compute_reg_resx_bits(struct kvm *kvm,
|
||||
const struct reg_feat_map_desc *r,
|
||||
unsigned long require,
|
||||
unsigned long exclude)
|
||||
{
|
||||
return __compute_fixed_bits(kvm, map, map_size, NULL,
|
||||
require, exclude | FIXED_VALUE);
|
||||
}
|
||||
struct resx resx;
|
||||
|
||||
static u64 compute_reg_res0_bits(struct kvm *kvm,
|
||||
const struct reg_feat_map_desc *r,
|
||||
unsigned long require, unsigned long exclude)
|
||||
|
||||
{
|
||||
u64 res0;
|
||||
|
||||
res0 = compute_res0_bits(kvm, r->bit_feat_map, r->bit_feat_map_sz,
|
||||
resx = compute_resx_bits(kvm, r->bit_feat_map, r->bit_feat_map_sz,
|
||||
require, exclude);
|
||||
|
||||
/*
|
||||
* If computing FGUs, don't take RES0 or register existence
|
||||
* into account -- we're not computing bits for the register
|
||||
* itself.
|
||||
*/
|
||||
if (!(exclude & NEVER_FGU)) {
|
||||
res0 |= compute_res0_bits(kvm, &r->feat_map, 1, require, exclude);
|
||||
res0 |= ~reg_feat_map_bits(&r->feat_map);
|
||||
if (r->feat_map.flags & MASKS_POINTER) {
|
||||
resx.res0 |= r->feat_map.masks->res0;
|
||||
resx.res1 |= r->feat_map.masks->res1;
|
||||
}
|
||||
|
||||
return res0;
|
||||
/*
|
||||
* If the register itself was not valid, all the non-RESx bits are
|
||||
* now considered RES0 (this matches the behaviour of registers such
|
||||
* as SCTLR2 and TCR2). Weed out any potential (though unlikely)
|
||||
* overlap with RES1 bits coming from the previous computation.
|
||||
*/
|
||||
resx.res0 |= compute_resx_bits(kvm, &r->feat_map, 1, require, exclude).res0;
|
||||
resx.res1 &= ~resx.res0;
|
||||
|
||||
return resx;
|
||||
}
|
||||
|
||||
static u64 compute_reg_fixed_bits(struct kvm *kvm,
|
||||
const struct reg_feat_map_desc *r,
|
||||
u64 *fixed_bits, unsigned long require,
|
||||
unsigned long exclude)
|
||||
static u64 compute_fgu_bits(struct kvm *kvm, const struct reg_feat_map_desc *r)
|
||||
{
|
||||
return __compute_fixed_bits(kvm, r->bit_feat_map, r->bit_feat_map_sz,
|
||||
fixed_bits, require | FIXED_VALUE, exclude);
|
||||
struct resx resx;
|
||||
|
||||
/*
|
||||
* If computing FGUs, we collect the unsupported feature bits as
|
||||
* RESx bits, but don't take the actual RESx bits or register
|
||||
* existence into account -- we're not computing bits for the
|
||||
* register itself.
|
||||
*/
|
||||
resx = compute_resx_bits(kvm, r->bit_feat_map, r->bit_feat_map_sz,
|
||||
0, NEVER_FGU);
|
||||
|
||||
return resx.res0 | resx.res1;
|
||||
}
|
||||
|
||||
void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
|
||||
|
|
@ -1372,40 +1436,29 @@ void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
|
|||
|
||||
switch (fgt) {
|
||||
case HFGRTR_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hfgrtr_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_reg_res0_bits(kvm, &hfgwtr_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hfgrtr_desc);
|
||||
val |= compute_fgu_bits(kvm, &hfgwtr_desc);
|
||||
break;
|
||||
case HFGITR_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hfgitr_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hfgitr_desc);
|
||||
break;
|
||||
case HDFGRTR_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hdfgrtr_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_reg_res0_bits(kvm, &hdfgwtr_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hdfgrtr_desc);
|
||||
val |= compute_fgu_bits(kvm, &hdfgwtr_desc);
|
||||
break;
|
||||
case HAFGRTR_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hafgrtr_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hafgrtr_desc);
|
||||
break;
|
||||
case HFGRTR2_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hfgrtr2_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_reg_res0_bits(kvm, &hfgwtr2_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hfgrtr2_desc);
|
||||
val |= compute_fgu_bits(kvm, &hfgwtr2_desc);
|
||||
break;
|
||||
case HFGITR2_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hfgitr2_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hfgitr2_desc);
|
||||
break;
|
||||
case HDFGRTR2_GROUP:
|
||||
val |= compute_reg_res0_bits(kvm, &hdfgrtr2_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_reg_res0_bits(kvm, &hdfgwtr2_desc,
|
||||
0, NEVER_FGU);
|
||||
val |= compute_fgu_bits(kvm, &hdfgrtr2_desc);
|
||||
val |= compute_fgu_bits(kvm, &hdfgwtr2_desc);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -1414,91 +1467,77 @@ void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
|
|||
kvm->arch.fgu[fgt] = val;
|
||||
}
|
||||
|
||||
void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *res1)
|
||||
struct resx get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg)
|
||||
{
|
||||
u64 fixed = 0, mask;
|
||||
struct resx resx;
|
||||
|
||||
switch (reg) {
|
||||
case HFGRTR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hfgrtr_desc, 0, 0);
|
||||
*res1 = HFGRTR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hfgrtr_desc, 0, 0);
|
||||
break;
|
||||
case HFGWTR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hfgwtr_desc, 0, 0);
|
||||
*res1 = HFGWTR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hfgwtr_desc, 0, 0);
|
||||
break;
|
||||
case HFGITR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hfgitr_desc, 0, 0);
|
||||
*res1 = HFGITR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hfgitr_desc, 0, 0);
|
||||
break;
|
||||
case HDFGRTR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hdfgrtr_desc, 0, 0);
|
||||
*res1 = HDFGRTR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hdfgrtr_desc, 0, 0);
|
||||
break;
|
||||
case HDFGWTR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hdfgwtr_desc, 0, 0);
|
||||
*res1 = HDFGWTR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hdfgwtr_desc, 0, 0);
|
||||
break;
|
||||
case HAFGRTR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hafgrtr_desc, 0, 0);
|
||||
*res1 = HAFGRTR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hafgrtr_desc, 0, 0);
|
||||
break;
|
||||
case HFGRTR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hfgrtr2_desc, 0, 0);
|
||||
*res1 = HFGRTR2_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hfgrtr2_desc, 0, 0);
|
||||
break;
|
||||
case HFGWTR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hfgwtr2_desc, 0, 0);
|
||||
*res1 = HFGWTR2_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hfgwtr2_desc, 0, 0);
|
||||
break;
|
||||
case HFGITR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hfgitr2_desc, 0, 0);
|
||||
*res1 = HFGITR2_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hfgitr2_desc, 0, 0);
|
||||
break;
|
||||
case HDFGRTR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hdfgrtr2_desc, 0, 0);
|
||||
*res1 = HDFGRTR2_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hdfgrtr2_desc, 0, 0);
|
||||
break;
|
||||
case HDFGWTR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hdfgwtr2_desc, 0, 0);
|
||||
*res1 = HDFGWTR2_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hdfgwtr2_desc, 0, 0);
|
||||
break;
|
||||
case HCRX_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &hcrx_desc, 0, 0);
|
||||
*res1 = __HCRX_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &hcrx_desc, 0, 0);
|
||||
resx.res1 |= __HCRX_EL2_RES1;
|
||||
break;
|
||||
case HCR_EL2:
|
||||
mask = compute_reg_fixed_bits(kvm, &hcr_desc, &fixed, 0, 0);
|
||||
*res0 = compute_reg_res0_bits(kvm, &hcr_desc, 0, 0);
|
||||
*res0 |= (mask & ~fixed);
|
||||
*res1 = HCR_EL2_RES1 | (mask & fixed);
|
||||
resx = compute_reg_resx_bits(kvm, &hcr_desc, 0, 0);
|
||||
break;
|
||||
case SCTLR2_EL1:
|
||||
case SCTLR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &sctlr2_desc, 0, 0);
|
||||
*res1 = SCTLR2_EL1_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &sctlr2_desc, 0, 0);
|
||||
break;
|
||||
case TCR2_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &tcr2_el2_desc, 0, 0);
|
||||
*res1 = TCR2_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &tcr2_el2_desc, 0, 0);
|
||||
break;
|
||||
case SCTLR_EL1:
|
||||
*res0 = compute_reg_res0_bits(kvm, &sctlr_el1_desc, 0, 0);
|
||||
*res1 = SCTLR_EL1_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &sctlr_el1_desc, 0, 0);
|
||||
break;
|
||||
case SCTLR_EL2:
|
||||
resx = compute_reg_resx_bits(kvm, &sctlr_el2_desc, 0, 0);
|
||||
break;
|
||||
case MDCR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &mdcr_el2_desc, 0, 0);
|
||||
*res1 = MDCR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &mdcr_el2_desc, 0, 0);
|
||||
break;
|
||||
case VTCR_EL2:
|
||||
*res0 = compute_reg_res0_bits(kvm, &vtcr_el2_desc, 0, 0);
|
||||
*res1 = VTCR_EL2_RES1;
|
||||
resx = compute_reg_resx_bits(kvm, &vtcr_el2_desc, 0, 0);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
*res0 = *res1 = 0;
|
||||
resx = (typeof(resx)){};
|
||||
break;
|
||||
}
|
||||
|
||||
return resx;
|
||||
}
|
||||
|
||||
static __always_inline struct fgt_masks *__fgt_reg_to_masks(enum vcpu_sysreg reg)
|
||||
|
|
|
|||
|
|
@ -2435,15 +2435,7 @@ static enum trap_behaviour compute_trap_behaviour(struct kvm_vcpu *vcpu,
|
|||
|
||||
static u64 kvm_get_sysreg_res0(struct kvm *kvm, enum vcpu_sysreg sr)
|
||||
{
|
||||
struct kvm_sysreg_masks *masks;
|
||||
|
||||
/* Only handle the VNCR-backed regs for now */
|
||||
if (sr < __VNCR_START__)
|
||||
return 0;
|
||||
|
||||
masks = kvm->arch.sysreg_masks;
|
||||
|
||||
return masks->mask[sr - __SANITISED_REG_START__].res0;
|
||||
return kvm_get_sysreg_resx(kvm, sr).res0;
|
||||
}
|
||||
|
||||
static bool check_fgt_bit(struct kvm_vcpu *vcpu, enum vcpu_sysreg sr,
|
||||
|
|
|
|||
|
|
@ -1505,11 +1505,6 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
|
|||
u64 orig_val = val;
|
||||
|
||||
switch (reg) {
|
||||
case SYS_ID_AA64ISAR0_EL1:
|
||||
/* Support everything but TME */
|
||||
val &= ~ID_AA64ISAR0_EL1_TME;
|
||||
break;
|
||||
|
||||
case SYS_ID_AA64ISAR1_EL1:
|
||||
/* Support everything but LS64 and Spec Invalidation */
|
||||
val &= ~(ID_AA64ISAR1_EL1_LS64 |
|
||||
|
|
@ -1669,36 +1664,28 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
|
|||
u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *vcpu,
|
||||
enum vcpu_sysreg sr, u64 v)
|
||||
{
|
||||
struct kvm_sysreg_masks *masks;
|
||||
struct resx resx;
|
||||
|
||||
masks = vcpu->kvm->arch.sysreg_masks;
|
||||
|
||||
if (masks) {
|
||||
sr -= __SANITISED_REG_START__;
|
||||
|
||||
v &= ~masks->mask[sr].res0;
|
||||
v |= masks->mask[sr].res1;
|
||||
}
|
||||
resx = kvm_get_sysreg_resx(vcpu->kvm, sr);
|
||||
v &= ~resx.res0;
|
||||
v |= resx.res1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static __always_inline void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
|
||||
static __always_inline void set_sysreg_masks(struct kvm *kvm, int sr, struct resx resx)
|
||||
{
|
||||
int i = sr - __SANITISED_REG_START__;
|
||||
|
||||
BUILD_BUG_ON(!__builtin_constant_p(sr));
|
||||
BUILD_BUG_ON(sr < __SANITISED_REG_START__);
|
||||
BUILD_BUG_ON(sr >= NR_SYS_REGS);
|
||||
|
||||
kvm->arch.sysreg_masks->mask[i].res0 = res0;
|
||||
kvm->arch.sysreg_masks->mask[i].res1 = res1;
|
||||
kvm_set_sysreg_resx(kvm, sr, resx);
|
||||
}
|
||||
|
||||
int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
u64 res0, res1;
|
||||
struct resx resx;
|
||||
|
||||
lockdep_assert_held(&kvm->arch.config_lock);
|
||||
|
||||
|
|
@ -1711,110 +1698,116 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
|
|||
return -ENOMEM;
|
||||
|
||||
/* VTTBR_EL2 */
|
||||
res0 = res1 = 0;
|
||||
resx = (typeof(resx)){};
|
||||
if (!kvm_has_feat_enum(kvm, ID_AA64MMFR1_EL1, VMIDBits, 16))
|
||||
res0 |= GENMASK(63, 56);
|
||||
resx.res0 |= GENMASK(63, 56);
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR2_EL1, CnP, IMP))
|
||||
res0 |= VTTBR_CNP_BIT;
|
||||
set_sysreg_masks(kvm, VTTBR_EL2, res0, res1);
|
||||
resx.res0 |= VTTBR_CNP_BIT;
|
||||
set_sysreg_masks(kvm, VTTBR_EL2, resx);
|
||||
|
||||
/* VTCR_EL2 */
|
||||
get_reg_fixed_bits(kvm, VTCR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, VTCR_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, VTCR_EL2);
|
||||
set_sysreg_masks(kvm, VTCR_EL2, resx);
|
||||
|
||||
/* VMPIDR_EL2 */
|
||||
res0 = GENMASK(63, 40) | GENMASK(30, 24);
|
||||
res1 = BIT(31);
|
||||
set_sysreg_masks(kvm, VMPIDR_EL2, res0, res1);
|
||||
resx.res0 = GENMASK(63, 40) | GENMASK(30, 24);
|
||||
resx.res1 = BIT(31);
|
||||
set_sysreg_masks(kvm, VMPIDR_EL2, resx);
|
||||
|
||||
/* HCR_EL2 */
|
||||
get_reg_fixed_bits(kvm, HCR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HCR_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, HCR_EL2);
|
||||
set_sysreg_masks(kvm, HCR_EL2, resx);
|
||||
|
||||
/* HCRX_EL2 */
|
||||
get_reg_fixed_bits(kvm, HCRX_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HCRX_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, HCRX_EL2);
|
||||
set_sysreg_masks(kvm, HCRX_EL2, resx);
|
||||
|
||||
/* HFG[RW]TR_EL2 */
|
||||
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);
|
||||
resx = get_reg_fixed_bits(kvm, HFGRTR_EL2);
|
||||
set_sysreg_masks(kvm, HFGRTR_EL2, resx);
|
||||
resx = get_reg_fixed_bits(kvm, HFGWTR_EL2);
|
||||
set_sysreg_masks(kvm, HFGWTR_EL2, resx);
|
||||
|
||||
/* HDFG[RW]TR_EL2 */
|
||||
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);
|
||||
resx = get_reg_fixed_bits(kvm, HDFGRTR_EL2);
|
||||
set_sysreg_masks(kvm, HDFGRTR_EL2, resx);
|
||||
resx = get_reg_fixed_bits(kvm, HDFGWTR_EL2);
|
||||
set_sysreg_masks(kvm, HDFGWTR_EL2, resx);
|
||||
|
||||
/* HFGITR_EL2 */
|
||||
get_reg_fixed_bits(kvm, HFGITR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGITR_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, HFGITR_EL2);
|
||||
set_sysreg_masks(kvm, HFGITR_EL2, resx);
|
||||
|
||||
/* HAFGRTR_EL2 - not a lot to see here */
|
||||
get_reg_fixed_bits(kvm, HAFGRTR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, HAFGRTR_EL2);
|
||||
set_sysreg_masks(kvm, HAFGRTR_EL2, resx);
|
||||
|
||||
/* 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);
|
||||
resx = get_reg_fixed_bits(kvm, HFGRTR2_EL2);
|
||||
set_sysreg_masks(kvm, HFGRTR2_EL2, resx);
|
||||
resx = get_reg_fixed_bits(kvm, HFGWTR2_EL2);
|
||||
set_sysreg_masks(kvm, HFGWTR2_EL2, resx);
|
||||
|
||||
/* 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);
|
||||
resx = get_reg_fixed_bits(kvm, HDFGRTR2_EL2);
|
||||
set_sysreg_masks(kvm, HDFGRTR2_EL2, resx);
|
||||
resx = get_reg_fixed_bits(kvm, HDFGWTR2_EL2);
|
||||
set_sysreg_masks(kvm, HDFGWTR2_EL2, resx);
|
||||
|
||||
/* HFGITR2_EL2 */
|
||||
get_reg_fixed_bits(kvm, HFGITR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, HFGITR2_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, HFGITR2_EL2);
|
||||
set_sysreg_masks(kvm, HFGITR2_EL2, resx);
|
||||
|
||||
/* TCR2_EL2 */
|
||||
get_reg_fixed_bits(kvm, TCR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, TCR2_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, TCR2_EL2);
|
||||
set_sysreg_masks(kvm, TCR2_EL2, resx);
|
||||
|
||||
/* SCTLR_EL1 */
|
||||
get_reg_fixed_bits(kvm, SCTLR_EL1, &res0, &res1);
|
||||
set_sysreg_masks(kvm, SCTLR_EL1, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, SCTLR_EL1);
|
||||
set_sysreg_masks(kvm, SCTLR_EL1, resx);
|
||||
|
||||
/* SCTLR_EL2 */
|
||||
resx = get_reg_fixed_bits(kvm, SCTLR_EL2);
|
||||
set_sysreg_masks(kvm, SCTLR_EL2, resx);
|
||||
|
||||
/* SCTLR2_ELx */
|
||||
get_reg_fixed_bits(kvm, SCTLR2_EL1, &res0, &res1);
|
||||
set_sysreg_masks(kvm, SCTLR2_EL1, res0, res1);
|
||||
get_reg_fixed_bits(kvm, SCTLR2_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, SCTLR2_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, SCTLR2_EL1);
|
||||
set_sysreg_masks(kvm, SCTLR2_EL1, resx);
|
||||
resx = get_reg_fixed_bits(kvm, SCTLR2_EL2);
|
||||
set_sysreg_masks(kvm, SCTLR2_EL2, resx);
|
||||
|
||||
/* MDCR_EL2 */
|
||||
get_reg_fixed_bits(kvm, MDCR_EL2, &res0, &res1);
|
||||
set_sysreg_masks(kvm, MDCR_EL2, res0, res1);
|
||||
resx = get_reg_fixed_bits(kvm, MDCR_EL2);
|
||||
set_sysreg_masks(kvm, MDCR_EL2, resx);
|
||||
|
||||
/* CNTHCTL_EL2 */
|
||||
res0 = GENMASK(63, 20);
|
||||
res1 = 0;
|
||||
resx.res0 = GENMASK(63, 20);
|
||||
resx.res1 = 0;
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RME, IMP))
|
||||
res0 |= CNTHCTL_CNTPMASK | CNTHCTL_CNTVMASK;
|
||||
resx.res0 |= CNTHCTL_CNTPMASK | CNTHCTL_CNTVMASK;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR0_EL1, ECV, CNTPOFF)) {
|
||||
res0 |= CNTHCTL_ECV;
|
||||
resx.res0 |= CNTHCTL_ECV;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR0_EL1, ECV, IMP))
|
||||
res0 |= (CNTHCTL_EL1TVT | CNTHCTL_EL1TVCT |
|
||||
CNTHCTL_EL1NVPCT | CNTHCTL_EL1NVVCT);
|
||||
resx.res0 |= (CNTHCTL_EL1TVT | CNTHCTL_EL1TVCT |
|
||||
CNTHCTL_EL1NVPCT | CNTHCTL_EL1NVVCT);
|
||||
}
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
|
||||
res0 |= GENMASK(11, 8);
|
||||
set_sysreg_masks(kvm, CNTHCTL_EL2, res0, res1);
|
||||
resx.res0 |= GENMASK(11, 8);
|
||||
set_sysreg_masks(kvm, CNTHCTL_EL2, resx);
|
||||
|
||||
/* ICH_HCR_EL2 */
|
||||
res0 = ICH_HCR_EL2_RES0;
|
||||
res1 = ICH_HCR_EL2_RES1;
|
||||
resx.res0 = ICH_HCR_EL2_RES0;
|
||||
resx.res1 = ICH_HCR_EL2_RES1;
|
||||
if (!(kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_EL2_TDS))
|
||||
res0 |= ICH_HCR_EL2_TDIR;
|
||||
resx.res0 |= ICH_HCR_EL2_TDIR;
|
||||
/* No GICv4 is presented to the guest */
|
||||
res0 |= ICH_HCR_EL2_DVIM | ICH_HCR_EL2_vSGIEOICount;
|
||||
set_sysreg_masks(kvm, ICH_HCR_EL2, res0, res1);
|
||||
resx.res0 |= ICH_HCR_EL2_DVIM | ICH_HCR_EL2_vSGIEOICount;
|
||||
set_sysreg_masks(kvm, ICH_HCR_EL2, resx);
|
||||
|
||||
/* VNCR_EL2 */
|
||||
set_sysreg_masks(kvm, VNCR_EL2, VNCR_EL2_RES0, VNCR_EL2_RES1);
|
||||
resx.res0 = VNCR_EL2_RES0;
|
||||
resx.res1 = VNCR_EL2_RES1;
|
||||
set_sysreg_masks(kvm, VNCR_EL2, resx);
|
||||
|
||||
out:
|
||||
for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++)
|
||||
|
|
|
|||
|
|
@ -5056,10 +5056,78 @@ static const struct seq_operations idregs_debug_sops = {
|
|||
|
||||
DEFINE_SEQ_ATTRIBUTE(idregs_debug);
|
||||
|
||||
static const struct sys_reg_desc *sr_resx_find(struct kvm *kvm, loff_t pos)
|
||||
{
|
||||
unsigned long i, sr_idx = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) {
|
||||
const struct sys_reg_desc *r = &sys_reg_descs[i];
|
||||
|
||||
if (r->reg < __SANITISED_REG_START__)
|
||||
continue;
|
||||
|
||||
if (sr_idx++ == pos)
|
||||
return r;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *sr_resx_start(struct seq_file *s, loff_t *pos)
|
||||
{
|
||||
struct kvm *kvm = s->private;
|
||||
|
||||
if (!kvm->arch.sysreg_masks)
|
||||
return NULL;
|
||||
|
||||
return (void *)sr_resx_find(kvm, *pos);
|
||||
}
|
||||
|
||||
static void *sr_resx_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
struct kvm *kvm = s->private;
|
||||
|
||||
(*pos)++;
|
||||
|
||||
return (void *)sr_resx_find(kvm, *pos);
|
||||
}
|
||||
|
||||
static void sr_resx_stop(struct seq_file *s, void *v)
|
||||
{
|
||||
}
|
||||
|
||||
static int sr_resx_show(struct seq_file *s, void *v)
|
||||
{
|
||||
const struct sys_reg_desc *desc = v;
|
||||
struct kvm *kvm = s->private;
|
||||
struct resx resx;
|
||||
|
||||
if (!desc)
|
||||
return 0;
|
||||
|
||||
resx = kvm_get_sysreg_resx(kvm, desc->reg);
|
||||
|
||||
seq_printf(s, "%20s:\tRES0:%016llx\tRES1:%016llx\n",
|
||||
desc->name, resx.res0, resx.res1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations sr_resx_sops = {
|
||||
.start = sr_resx_start,
|
||||
.next = sr_resx_next,
|
||||
.stop = sr_resx_stop,
|
||||
.show = sr_resx_show,
|
||||
};
|
||||
|
||||
DEFINE_SEQ_ATTRIBUTE(sr_resx);
|
||||
|
||||
void kvm_sys_regs_create_debugfs(struct kvm *kvm)
|
||||
{
|
||||
debugfs_create_file("idregs", 0444, kvm->debugfs_dentry, kvm,
|
||||
&idregs_debug_fops);
|
||||
debugfs_create_file("resx", 0444, kvm->debugfs_dentry, kvm,
|
||||
&sr_resx_fops);
|
||||
}
|
||||
|
||||
static void reset_vm_ftr_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *reg)
|
||||
|
|
|
|||
|
|
@ -1856,10 +1856,7 @@ UnsignedEnum 31:28 RDM
|
|||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 27:24 TME
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
Res0 27:24
|
||||
UnsignedEnum 23:20 ATOMIC
|
||||
0b0000 NI
|
||||
0b0010 IMP
|
||||
|
|
@ -2433,10 +2430,7 @@ Field 57 EPAN
|
|||
Field 56 EnALS
|
||||
Field 55 EnAS0
|
||||
Field 54 EnASR
|
||||
Field 53 TME
|
||||
Field 52 TME0
|
||||
Field 51 TMT
|
||||
Field 50 TMT0
|
||||
Res0 53:50
|
||||
Field 49:46 TWEDEL
|
||||
Field 45 TWEDEn
|
||||
Field 44 DSSBS
|
||||
|
|
@ -3750,6 +3744,75 @@ UnsignedEnum 2:0 F8S1
|
|||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg SCTLR_EL2 3 4 1 0 0
|
||||
Field 63 TIDCP
|
||||
Field 62 SPINTMASK
|
||||
Field 61 NMI
|
||||
Field 60 EnTP2
|
||||
Field 59 TCSO
|
||||
Field 58 TCSO0
|
||||
Field 57 EPAN
|
||||
Field 56 EnALS
|
||||
Field 55 EnAS0
|
||||
Field 54 EnASR
|
||||
Res0 53:50
|
||||
Field 49:46 TWEDEL
|
||||
Field 45 TWEDEn
|
||||
Field 44 DSSBS
|
||||
Field 43 ATA
|
||||
Field 42 ATA0
|
||||
Enum 41:40 TCF
|
||||
0b00 NONE
|
||||
0b01 SYNC
|
||||
0b10 ASYNC
|
||||
0b11 ASYMM
|
||||
EndEnum
|
||||
Enum 39:38 TCF0
|
||||
0b00 NONE
|
||||
0b01 SYNC
|
||||
0b10 ASYNC
|
||||
0b11 ASYMM
|
||||
EndEnum
|
||||
Field 37 ITFSB
|
||||
Field 36 BT
|
||||
Field 35 BT0
|
||||
Field 34 EnFPM
|
||||
Field 33 MSCEn
|
||||
Field 32 CMOW
|
||||
Field 31 EnIA
|
||||
Field 30 EnIB
|
||||
Field 29 LSMAOE
|
||||
Field 28 nTLSMD
|
||||
Field 27 EnDA
|
||||
Field 26 UCI
|
||||
Field 25 EE
|
||||
Field 24 E0E
|
||||
Field 23 SPAN
|
||||
Field 22 EIS
|
||||
Field 21 IESB
|
||||
Field 20 TSCXT
|
||||
Field 19 WXN
|
||||
Field 18 nTWE
|
||||
Res0 17
|
||||
Field 16 nTWI
|
||||
Field 15 UCT
|
||||
Field 14 DZE
|
||||
Field 13 EnDB
|
||||
Field 12 I
|
||||
Field 11 EOS
|
||||
Field 10 EnRCTX
|
||||
Res0 9
|
||||
Field 8 SED
|
||||
Field 7 ITD
|
||||
Field 6 nAA
|
||||
Field 5 CP15BEN
|
||||
Field 4 SA0
|
||||
Field 3 SA
|
||||
Field 2 C
|
||||
Field 1 A
|
||||
Field 0 M
|
||||
EndSysreg
|
||||
|
||||
Sysreg HCR_EL2 3 4 1 1 0
|
||||
Field 63:60 TWEDEL
|
||||
Field 59 TWEDEn
|
||||
|
|
@ -3772,8 +3835,7 @@ Field 43 NV1
|
|||
Field 42 NV
|
||||
Field 41 API
|
||||
Field 40 APK
|
||||
Field 39 TME
|
||||
Field 38 MIOCNCE
|
||||
Res0 39:38
|
||||
Field 37 TEA
|
||||
Field 36 TERR
|
||||
Field 35 TLOR
|
||||
|
|
|
|||
|
|
@ -847,12 +847,6 @@
|
|||
#define SCTLR_ELx_A (BIT(1))
|
||||
#define SCTLR_ELx_M (BIT(0))
|
||||
|
||||
/* SCTLR_EL2 specific flags. */
|
||||
#define SCTLR_EL2_RES1 ((BIT(4)) | (BIT(5)) | (BIT(11)) | (BIT(16)) | \
|
||||
(BIT(18)) | (BIT(22)) | (BIT(23)) | (BIT(28)) | \
|
||||
(BIT(29)))
|
||||
|
||||
#define SCTLR_EL2_BT (BIT(36))
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define ENDIAN_SET_EL2 SCTLR_ELx_EE
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -176,7 +176,6 @@ and inv_event_filter are:
|
|||
bit 10 - Remote access (FEAT_SPEv1p4)
|
||||
bit 11 - Misaligned access (FEAT_SPEv1p1)
|
||||
bit 12-15 - IMPLEMENTATION DEFINED events (when implemented)
|
||||
bit 16 - Transaction (FEAT_TME)
|
||||
bit 17 - Partial or empty SME or SVE predicate (FEAT_SPEv1p1)
|
||||
bit 18 - Empty SME or SVE predicate (FEAT_SPEv1p1)
|
||||
bit 19 - L2D access (FEAT_SPEv1p4)
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ static const struct reg_ftr_bits ftr_id_aa64isar0_el1[] = {
|
|||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, SM3, 0),
|
||||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, SHA3, 0),
|
||||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, RDM, 0),
|
||||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, TME, 0),
|
||||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, ATOMIC, 0),
|
||||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, CRC32, 0),
|
||||
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ISAR0_EL1, SHA2, 0),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user