mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 13:16:22 +00:00
Merge branch kvm-arm64/nv-at-pan into kvmarm-master/next
* kvm-arm64/nv-at-pan: : . : Add NV support for the AT family of instructions, which mostly results : in adding a page table walker that deals with most of the complexity : of the architecture. : : From the cover letter: : : "Another task that a hypervisor supporting NV on arm64 has to deal with : is to emulate the AT instruction, because we multiplex all the S1 : translations on a single set of registers, and the guest S2 is never : truly resident on the CPU. : : So given that we lie about page tables, we also have to lie about : translation instructions, hence the emulation. Things are made : complicated by the fact that guest S1 page tables can be swapped out, : and that our shadow S2 is likely to be incomplete. So while using AT : to emulate AT is tempting (and useful), it is not going to always : work, and we thus need a fallback in the shape of a SW S1 walker." : . KVM: arm64: nv: Add support for FEAT_ATS1A KVM: arm64: nv: Plumb handling of AT S1* traps from EL2 KVM: arm64: nv: Make AT+PAN instructions aware of FEAT_PAN3 KVM: arm64: nv: Sanitise SCTLR_EL1.EPAN according to VM configuration KVM: arm64: nv: Add SW walker for AT S1 emulation KVM: arm64: nv: Make ps_to_output_size() generally available KVM: arm64: nv: Add emulation of AT S12E{0,1}{R,W} KVM: arm64: nv: Add basic emulation of AT S1E2{R,W} KVM: arm64: nv: Add basic emulation of AT S1E1{R,W}P KVM: arm64: nv: Add basic emulation of AT S1E{0,1}{R,W} KVM: arm64: nv: Honor absence of FEAT_PAN2 KVM: arm64: nv: Turn upper_attr for S2 walk into the full descriptor KVM: arm64: nv: Enforce S2 alignment when contiguous bit is set arm64: Add ESR_ELx_FSC_ADDRSZ_L() helper arm64: Add system register encoding for PSTATE.PAN arm64: Add PAR_EL1 field description arm64: Add missing APTable and TCR_ELx.HPD masks KVM: arm64: Make kvm_at() take an OP_AT_* Signed-off-by: Marc Zyngier <maz@kernel.org> # Conflicts: # arch/arm64/kvm/nested.c
This commit is contained in:
commit
2e0f239457
@ -122,8 +122,8 @@
|
||||
#define ESR_ELx_FSC_SECC_TTW(n) (0x1c + (n))
|
||||
|
||||
/* Status codes for individual page table levels */
|
||||
#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + n)
|
||||
#define ESR_ELx_FSC_PERM_L(n) (ESR_ELx_FSC_PERM + n)
|
||||
#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + (n))
|
||||
#define ESR_ELx_FSC_PERM_L(n) (ESR_ELx_FSC_PERM + (n))
|
||||
|
||||
#define ESR_ELx_FSC_FAULT_nL (0x2C)
|
||||
#define ESR_ELx_FSC_FAULT_L(n) (((n) < 0 ? ESR_ELx_FSC_FAULT_nL : \
|
||||
@ -161,6 +161,7 @@
|
||||
|
||||
/* ISS field definitions for exceptions taken in to Hyp */
|
||||
#define ESR_ELx_FSC_ADDRSZ (0x00)
|
||||
#define ESR_ELx_FSC_ADDRSZ_L(n) (ESR_ELx_FSC_ADDRSZ + (n))
|
||||
#define ESR_ELx_CV (UL(1) << 24)
|
||||
#define ESR_ELx_COND_SHIFT (20)
|
||||
#define ESR_ELx_COND_MASK (UL(0xF) << ESR_ELx_COND_SHIFT)
|
||||
|
@ -107,6 +107,7 @@
|
||||
/* TCR_EL2 Registers bits */
|
||||
#define TCR_EL2_DS (1UL << 32)
|
||||
#define TCR_EL2_RES1 ((1U << 31) | (1 << 23))
|
||||
#define TCR_EL2_HPD (1 << 24)
|
||||
#define TCR_EL2_TBI (1 << 20)
|
||||
#define TCR_EL2_PS_SHIFT 16
|
||||
#define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <asm/hyp_image.h>
|
||||
#include <asm/insn.h>
|
||||
#include <asm/virt.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
#define ARM_EXIT_WITH_SERROR_BIT 31
|
||||
#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT))
|
||||
@ -235,6 +236,9 @@ extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu);
|
||||
extern int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding);
|
||||
|
||||
extern void __kvm_timer_set_cntvoff(u64 cntvoff);
|
||||
extern void __kvm_at_s1e01(struct kvm_vcpu *vcpu, u32 op, u64 vaddr);
|
||||
extern void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr);
|
||||
extern void __kvm_at_s12(struct kvm_vcpu *vcpu, u32 op, u64 vaddr);
|
||||
|
||||
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
|
||||
|
||||
@ -259,7 +263,7 @@ extern u64 __kvm_get_mdcr_el2(void);
|
||||
asm volatile( \
|
||||
" mrs %1, spsr_el2\n" \
|
||||
" mrs %2, elr_el2\n" \
|
||||
"1: at "at_op", %3\n" \
|
||||
"1: " __msr_s(at_op, "%3") "\n" \
|
||||
" isb\n" \
|
||||
" b 9f\n" \
|
||||
"2: msr spsr_el2, %1\n" \
|
||||
|
@ -85,7 +85,7 @@ struct kvm_s2_trans {
|
||||
bool readable;
|
||||
int level;
|
||||
u32 esr;
|
||||
u64 upper_attr;
|
||||
u64 desc;
|
||||
};
|
||||
|
||||
static inline phys_addr_t kvm_s2_trans_output(struct kvm_s2_trans *trans)
|
||||
@ -115,7 +115,7 @@ static inline bool kvm_s2_trans_writable(struct kvm_s2_trans *trans)
|
||||
|
||||
static inline bool kvm_s2_trans_executable(struct kvm_s2_trans *trans)
|
||||
{
|
||||
return !(trans->upper_attr & BIT(54));
|
||||
return !(trans->desc & BIT(54));
|
||||
}
|
||||
|
||||
extern int kvm_walk_nested_s2(struct kvm_vcpu *vcpu, phys_addr_t gipa,
|
||||
@ -205,4 +205,40 @@ static inline u64 kvm_encode_nested_level(struct kvm_s2_trans *trans)
|
||||
return FIELD_PREP(KVM_NV_GUEST_MAP_SZ, trans->level);
|
||||
}
|
||||
|
||||
/* Adjust alignment for the contiguous bit as per StageOA() */
|
||||
#define contiguous_bit_shift(d, wi, l) \
|
||||
({ \
|
||||
u8 shift = 0; \
|
||||
\
|
||||
if ((d) & PTE_CONT) { \
|
||||
switch (BIT((wi)->pgshift)) { \
|
||||
case SZ_4K: \
|
||||
shift = 4; \
|
||||
break; \
|
||||
case SZ_16K: \
|
||||
shift = (l) == 2 ? 5 : 7; \
|
||||
break; \
|
||||
case SZ_64K: \
|
||||
shift = 5; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
shift; \
|
||||
})
|
||||
|
||||
static inline unsigned int ps_to_output_size(unsigned int ps)
|
||||
{
|
||||
switch (ps) {
|
||||
case 0: return 32;
|
||||
case 1: return 36;
|
||||
case 2: return 40;
|
||||
case 3: return 42;
|
||||
case 4: return 44;
|
||||
case 5:
|
||||
default:
|
||||
return 48;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ARM64_KVM_NESTED_H */
|
||||
|
@ -204,6 +204,11 @@
|
||||
*/
|
||||
#define PTE_S2_MEMATTR(t) (_AT(pteval_t, (t)) << 2)
|
||||
|
||||
/*
|
||||
* Hierarchical permission for Stage-1 tables
|
||||
*/
|
||||
#define S1_TABLE_AP (_AT(pmdval_t, 3) << 61)
|
||||
|
||||
/*
|
||||
* Highest possible physical address supported.
|
||||
*/
|
||||
@ -298,6 +303,10 @@
|
||||
#define TCR_TBI1 (UL(1) << 38)
|
||||
#define TCR_HA (UL(1) << 39)
|
||||
#define TCR_HD (UL(1) << 40)
|
||||
#define TCR_HPD0_SHIFT 41
|
||||
#define TCR_HPD0 (UL(1) << TCR_HPD0_SHIFT)
|
||||
#define TCR_HPD1_SHIFT 42
|
||||
#define TCR_HPD1 (UL(1) << TCR_HPD1_SHIFT)
|
||||
#define TCR_TBID0 (UL(1) << 51)
|
||||
#define TCR_TBID1 (UL(1) << 52)
|
||||
#define TCR_NFD0 (UL(1) << 53)
|
||||
|
@ -109,6 +109,9 @@
|
||||
#define set_pstate_ssbs(x) asm volatile(SET_PSTATE_SSBS(x))
|
||||
#define set_pstate_dit(x) asm volatile(SET_PSTATE_DIT(x))
|
||||
|
||||
/* Register-based PAN access, for save/restore purposes */
|
||||
#define SYS_PSTATE_PAN sys_reg(3, 0, 4, 2, 3)
|
||||
|
||||
#define __SYS_BARRIER_INSN(CRm, op2, Rt) \
|
||||
__emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f))
|
||||
|
||||
@ -325,7 +328,25 @@
|
||||
#define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0)
|
||||
|
||||
#define SYS_PAR_EL1_F BIT(0)
|
||||
/* When PAR_EL1.F == 1 */
|
||||
#define SYS_PAR_EL1_FST GENMASK(6, 1)
|
||||
#define SYS_PAR_EL1_PTW BIT(8)
|
||||
#define SYS_PAR_EL1_S BIT(9)
|
||||
#define SYS_PAR_EL1_AssuredOnly BIT(12)
|
||||
#define SYS_PAR_EL1_TopLevel BIT(13)
|
||||
#define SYS_PAR_EL1_Overlay BIT(14)
|
||||
#define SYS_PAR_EL1_DirtyBit BIT(15)
|
||||
#define SYS_PAR_EL1_F1_IMPDEF GENMASK_ULL(63, 48)
|
||||
#define SYS_PAR_EL1_F1_RES0 (BIT(7) | BIT(10) | GENMASK_ULL(47, 16))
|
||||
#define SYS_PAR_EL1_RES1 BIT(11)
|
||||
/* When PAR_EL1.F == 0 */
|
||||
#define SYS_PAR_EL1_SH GENMASK_ULL(8, 7)
|
||||
#define SYS_PAR_EL1_NS BIT(9)
|
||||
#define SYS_PAR_EL1_F0_IMPDEF BIT(10)
|
||||
#define SYS_PAR_EL1_NSE BIT(11)
|
||||
#define SYS_PAR_EL1_PA GENMASK_ULL(51, 12)
|
||||
#define SYS_PAR_EL1_ATTR GENMASK_ULL(63, 56)
|
||||
#define SYS_PAR_EL1_F0_RES0 (GENMASK_ULL(6, 1) | GENMASK_ULL(55, 52))
|
||||
|
||||
/*** Statistical Profiling Extension ***/
|
||||
#define PMSEVFR_EL1_RES0_IMP \
|
||||
@ -652,6 +673,7 @@
|
||||
#define OP_AT_S12E1W sys_insn(AT_Op0, 4, AT_CRn, 8, 5)
|
||||
#define OP_AT_S12E0R sys_insn(AT_Op0, 4, AT_CRn, 8, 6)
|
||||
#define OP_AT_S12E0W sys_insn(AT_Op0, 4, AT_CRn, 8, 7)
|
||||
#define OP_AT_S1E2A sys_insn(AT_Op0, 4, AT_CRn, 9, 2)
|
||||
|
||||
/* TLBI instructions */
|
||||
#define TLBI_Op0 1
|
||||
|
@ -17,7 +17,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
|
||||
inject_fault.o va_layout.o handle_exit.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 \
|
||||
arch_timer.o trng.o vmid.o emulate-nested.o nested.o at.o \
|
||||
vgic/vgic.o vgic/vgic-init.o \
|
||||
vgic/vgic-irqfd.o vgic/vgic-v2.o \
|
||||
vgic/vgic-v3.o vgic/vgic-v4.o \
|
||||
|
1101
arch/arm64/kvm/at.c
Normal file
1101
arch/arm64/kvm/at.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -826,6 +826,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
|
||||
SR_TRAP(OP_AT_S12E1W, CGT_HCR_NV),
|
||||
SR_TRAP(OP_AT_S12E0R, CGT_HCR_NV),
|
||||
SR_TRAP(OP_AT_S12E0W, CGT_HCR_NV),
|
||||
SR_TRAP(OP_AT_S1E2A, CGT_HCR_NV),
|
||||
SR_TRAP(OP_TLBI_IPAS2E1, CGT_HCR_NV),
|
||||
SR_TRAP(OP_TLBI_RIPAS2E1, CGT_HCR_NV),
|
||||
SR_TRAP(OP_TLBI_IPAS2LE1, CGT_HCR_NV),
|
||||
@ -907,6 +908,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
|
||||
SR_TRAP(OP_AT_S1E0W, CGT_HCR_AT),
|
||||
SR_TRAP(OP_AT_S1E1RP, CGT_HCR_AT),
|
||||
SR_TRAP(OP_AT_S1E1WP, CGT_HCR_AT),
|
||||
SR_TRAP(OP_AT_S1E1A, CGT_HCR_AT),
|
||||
SR_TRAP(SYS_ERXPFGF_EL1, CGT_HCR_nFIEN),
|
||||
SR_TRAP(SYS_ERXPFGCTL_EL1, CGT_HCR_nFIEN),
|
||||
SR_TRAP(SYS_ERXPFGCDN_EL1, CGT_HCR_nFIEN),
|
||||
|
@ -27,7 +27,7 @@ static inline bool __translate_far_to_hpfar(u64 far, u64 *hpfar)
|
||||
* saved the guest context yet, and we may return early...
|
||||
*/
|
||||
par = read_sysreg_par();
|
||||
if (!__kvm_at("s1e1r", far))
|
||||
if (!__kvm_at(OP_AT_S1E1R, far))
|
||||
tmp = read_sysreg_par();
|
||||
else
|
||||
tmp = SYS_PAR_EL1_F; /* back to the guest */
|
||||
|
@ -103,20 +103,6 @@ struct s2_walk_info {
|
||||
bool be;
|
||||
};
|
||||
|
||||
static unsigned int ps_to_output_size(unsigned int ps)
|
||||
{
|
||||
switch (ps) {
|
||||
case 0: return 32;
|
||||
case 1: return 36;
|
||||
case 2: return 40;
|
||||
case 3: return 42;
|
||||
case 4: return 44;
|
||||
case 5:
|
||||
default:
|
||||
return 48;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 compute_fsc(int level, u32 fsc)
|
||||
{
|
||||
return fsc | (level & 0x3);
|
||||
@ -256,7 +242,7 @@ static int walk_nested_s2_pgd(phys_addr_t ipa,
|
||||
/* Check for valid descriptor at this point */
|
||||
if (!(desc & 1) || ((desc & 3) == 1 && level == 3)) {
|
||||
out->esr = compute_fsc(level, ESR_ELx_FSC_FAULT);
|
||||
out->upper_attr = desc;
|
||||
out->desc = desc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -266,7 +252,7 @@ static int walk_nested_s2_pgd(phys_addr_t ipa,
|
||||
|
||||
if (check_output_size(wi, desc)) {
|
||||
out->esr = compute_fsc(level, ESR_ELx_FSC_ADDRSZ);
|
||||
out->upper_attr = desc;
|
||||
out->desc = desc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -278,27 +264,24 @@ static int walk_nested_s2_pgd(phys_addr_t ipa,
|
||||
|
||||
if (level < first_block_level) {
|
||||
out->esr = compute_fsc(level, ESR_ELx_FSC_FAULT);
|
||||
out->upper_attr = desc;
|
||||
out->desc = desc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't use the contiguous bit in the stage-2 ptes, so skip check
|
||||
* for misprogramming of the contiguous bit.
|
||||
*/
|
||||
|
||||
if (check_output_size(wi, desc)) {
|
||||
out->esr = compute_fsc(level, ESR_ELx_FSC_ADDRSZ);
|
||||
out->upper_attr = desc;
|
||||
out->desc = desc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(desc & BIT(10))) {
|
||||
out->esr = compute_fsc(level, ESR_ELx_FSC_ACCESS);
|
||||
out->upper_attr = desc;
|
||||
out->desc = desc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr_bottom += contiguous_bit_shift(desc, wi, level);
|
||||
|
||||
/* Calculate and return the result */
|
||||
paddr = (desc & GENMASK_ULL(47, addr_bottom)) |
|
||||
(ipa & GENMASK_ULL(addr_bottom - 1, 0));
|
||||
@ -307,7 +290,7 @@ static int walk_nested_s2_pgd(phys_addr_t ipa,
|
||||
out->readable = desc & (0b01 << 6);
|
||||
out->writable = desc & (0b10 << 6);
|
||||
out->level = level;
|
||||
out->upper_attr = desc & GENMASK_ULL(63, 52);
|
||||
out->desc = desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1193,5 +1176,12 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
|
||||
res0 |= ~(res0 | res1);
|
||||
set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
|
||||
|
||||
/* SCTLR_EL1 */
|
||||
res0 = SCTLR_EL1_RES0;
|
||||
res1 = SCTLR_EL1_RES1;
|
||||
if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN3))
|
||||
res0 |= SCTLR_EL1_EPAN;
|
||||
set_sysreg_masks(kvm, SCTLR_EL1, res0, res1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2830,6 +2830,43 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
EL2_REG(SP_EL2, NULL, reset_unknown, 0),
|
||||
};
|
||||
|
||||
static bool handle_at_s1e01(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
u32 op = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
|
||||
|
||||
__kvm_at_s1e01(vcpu, op, p->regval);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handle_at_s1e2(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
u32 op = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
|
||||
|
||||
/* There is no FGT associated with AT S1E2A :-( */
|
||||
if (op == OP_AT_S1E2A &&
|
||||
!kvm_has_feat(vcpu->kvm, ID_AA64ISAR2_EL1, ATS1A, IMP)) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
return false;
|
||||
}
|
||||
|
||||
__kvm_at_s1e2(vcpu, op, p->regval);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handle_at_s12(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
u32 op = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
|
||||
|
||||
__kvm_at_s12(vcpu, op, p->regval);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool kvm_supported_tlbi_s12_op(struct kvm_vcpu *vpcu, u32 instr)
|
||||
{
|
||||
struct kvm *kvm = vpcu->kvm;
|
||||
@ -3082,6 +3119,14 @@ static struct sys_reg_desc sys_insn_descs[] = {
|
||||
{ SYS_DESC(SYS_DC_ISW), access_dcsw },
|
||||
{ SYS_DESC(SYS_DC_IGSW), access_dcgsw },
|
||||
{ SYS_DESC(SYS_DC_IGDSW), access_dcgsw },
|
||||
|
||||
SYS_INSN(AT_S1E1R, handle_at_s1e01),
|
||||
SYS_INSN(AT_S1E1W, handle_at_s1e01),
|
||||
SYS_INSN(AT_S1E0R, handle_at_s1e01),
|
||||
SYS_INSN(AT_S1E0W, handle_at_s1e01),
|
||||
SYS_INSN(AT_S1E1RP, handle_at_s1e01),
|
||||
SYS_INSN(AT_S1E1WP, handle_at_s1e01),
|
||||
|
||||
{ SYS_DESC(SYS_DC_CSW), access_dcsw },
|
||||
{ SYS_DESC(SYS_DC_CGSW), access_dcgsw },
|
||||
{ SYS_DESC(SYS_DC_CGDSW), access_dcgsw },
|
||||
@ -3161,6 +3206,14 @@ static struct sys_reg_desc sys_insn_descs[] = {
|
||||
SYS_INSN(TLBI_VALE1NXS, handle_tlbi_el1),
|
||||
SYS_INSN(TLBI_VAALE1NXS, handle_tlbi_el1),
|
||||
|
||||
SYS_INSN(AT_S1E2R, handle_at_s1e2),
|
||||
SYS_INSN(AT_S1E2W, handle_at_s1e2),
|
||||
SYS_INSN(AT_S12E1R, handle_at_s12),
|
||||
SYS_INSN(AT_S12E1W, handle_at_s12),
|
||||
SYS_INSN(AT_S12E0R, handle_at_s12),
|
||||
SYS_INSN(AT_S12E0W, handle_at_s12),
|
||||
SYS_INSN(AT_S1E2A, handle_at_s1e2),
|
||||
|
||||
SYS_INSN(TLBI_IPAS2E1IS, handle_ipas2e1is),
|
||||
SYS_INSN(TLBI_RIPAS2E1IS, handle_ripas2e1is),
|
||||
SYS_INSN(TLBI_IPAS2LE1IS, handle_ipas2e1is),
|
||||
@ -4642,6 +4695,13 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
|
||||
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_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
|
||||
kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 |
|
||||
HFGxTR_EL2_nPIR_EL1);
|
||||
|
Loading…
Reference in New Issue
Block a user