Skip to content

Commit e6c9a30

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: nv: Handle TLBI VMALLS12E1{,IS} operations
Emulating TLBI VMALLS12E1* results in tearing down all the shadow S2 PTs that match the current VMID, since our shadow S2s are just some form of SW-managed TLBs. That teardown itself results in a full TLB invalidation for both S1 and S2. This can result in over-invalidation if two vcpus use the same VMID to tag private S2 PTs, but this is still correct from an architecture perspective. Co-developed-by: Jintack Lim <[email protected]> Co-developed-by: Christoffer Dall <[email protected]> Signed-off-by: Jintack Lim <[email protected]> Signed-off-by: Christoffer Dall <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 8e236ef commit e6c9a30

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

arch/arm64/kvm/sys_regs.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,22 @@ static const struct sys_reg_desc sys_reg_descs[] = {
27412741
EL2_REG(SP_EL2, NULL, reset_unknown, 0),
27422742
};
27432743

2744+
static bool kvm_supported_tlbi_s12_op(struct kvm_vcpu *vpcu, u32 instr)
2745+
{
2746+
struct kvm *kvm = vpcu->kvm;
2747+
u8 CRm = sys_reg_CRm(instr);
2748+
2749+
if (sys_reg_CRn(instr) == TLBI_CRn_nXS &&
2750+
!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, XS, IMP))
2751+
return false;
2752+
2753+
if (CRm == TLBI_CRm_nROS &&
2754+
!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
2755+
return false;
2756+
2757+
return true;
2758+
}
2759+
27442760
/* Only defined here as this is an internal "abstraction" */
27452761
union tlbi_info {
27462762
struct {
@@ -2758,6 +2774,38 @@ union tlbi_info {
27582774
} va;
27592775
};
27602776

2777+
static void s2_mmu_unmap_range(struct kvm_s2_mmu *mmu,
2778+
const union tlbi_info *info)
2779+
{
2780+
kvm_stage2_unmap_range(mmu, info->range.start, info->range.size);
2781+
}
2782+
2783+
static bool handle_vmalls12e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
2784+
const struct sys_reg_desc *r)
2785+
{
2786+
u32 sys_encoding = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
2787+
u64 limit, vttbr;
2788+
2789+
if (!kvm_supported_tlbi_s12_op(vcpu, sys_encoding)) {
2790+
kvm_inject_undefined(vcpu);
2791+
return false;
2792+
}
2793+
2794+
vttbr = vcpu_read_sys_reg(vcpu, VTTBR_EL2);
2795+
limit = BIT_ULL(kvm_get_pa_bits(vcpu->kvm));
2796+
2797+
kvm_s2_mmu_iterate_by_vmid(vcpu->kvm, get_vmid(vttbr),
2798+
&(union tlbi_info) {
2799+
.range = {
2800+
.start = 0,
2801+
.size = limit,
2802+
},
2803+
},
2804+
s2_mmu_unmap_range);
2805+
2806+
return true;
2807+
}
2808+
27612809
static void s2_mmu_tlbi_s1e1(struct kvm_s2_mmu *mmu,
27622810
const union tlbi_info *info)
27632811
{
@@ -2831,6 +2879,9 @@ static struct sys_reg_desc sys_insn_descs[] = {
28312879
SYS_INSN(TLBI_VAAE1, handle_tlbi_el1),
28322880
SYS_INSN(TLBI_VALE1, handle_tlbi_el1),
28332881
SYS_INSN(TLBI_VAALE1, handle_tlbi_el1),
2882+
2883+
SYS_INSN(TLBI_VMALLS12E1IS, handle_vmalls12e1is),
2884+
SYS_INSN(TLBI_VMALLS12E1, handle_vmalls12e1is),
28342885
};
28352886

28362887
static const struct sys_reg_desc *first_idreg;

0 commit comments

Comments
 (0)