Skip to content

Commit 70109bc

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: nv: Handle TLBI IPAS2E1{,IS} operations
TLBI IPAS2E1* are the last class of TLBI instructions we need to handle. For each matching S2 MMU context, we invalidate a range corresponding to the largest possible mapping for that context. At this stage, we don't handle TTL, which means we are likely over-invalidating. Further patches will aim at making this a bit better. 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 5cfb6ce commit 70109bc

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

arch/arm64/kvm/sys_regs.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,6 +2780,31 @@ static bool handle_alle1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
27802780
return true;
27812781
}
27822782

2783+
static bool kvm_supported_tlbi_ipas2_op(struct kvm_vcpu *vpcu, u32 instr)
2784+
{
2785+
struct kvm *kvm = vpcu->kvm;
2786+
u8 CRm = sys_reg_CRm(instr);
2787+
u8 Op2 = sys_reg_Op2(instr);
2788+
2789+
if (sys_reg_CRn(instr) == TLBI_CRn_nXS &&
2790+
!kvm_has_feat(kvm, ID_AA64ISAR1_EL1, XS, IMP))
2791+
return false;
2792+
2793+
if (CRm == TLBI_CRm_IPAIS && (Op2 == 2 || Op2 == 6) &&
2794+
!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, RANGE))
2795+
return false;
2796+
2797+
if (CRm == TLBI_CRm_IPAONS && (Op2 == 0 || Op2 == 4) &&
2798+
!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, OS))
2799+
return false;
2800+
2801+
if (CRm == TLBI_CRm_IPAONS && (Op2 == 3 || Op2 == 7) &&
2802+
!kvm_has_feat(kvm, ID_AA64ISAR0_EL1, TLB, RANGE))
2803+
return false;
2804+
2805+
return true;
2806+
}
2807+
27832808
/* Only defined here as this is an internal "abstraction" */
27842809
union tlbi_info {
27852810
struct {
@@ -2829,6 +2854,72 @@ static bool handle_vmalls12e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
28292854
return true;
28302855
}
28312856

2857+
static void s2_mmu_unmap_ipa(struct kvm_s2_mmu *mmu,
2858+
const union tlbi_info *info)
2859+
{
2860+
unsigned long max_size;
2861+
u64 base_addr;
2862+
2863+
/*
2864+
* We drop a number of things from the supplied value:
2865+
*
2866+
* - NS bit: we're non-secure only.
2867+
*
2868+
* - TTL field: We already have the granule size from the
2869+
* VTCR_EL2.TG0 field, and the level is only relevant to the
2870+
* guest's S2PT.
2871+
*
2872+
* - IPA[51:48]: We don't support 52bit IPA just yet...
2873+
*
2874+
* And of course, adjust the IPA to be on an actual address.
2875+
*/
2876+
base_addr = (info->ipa.addr & GENMASK_ULL(35, 0)) << 12;
2877+
2878+
/* Compute the maximum extent of the invalidation */
2879+
switch (mmu->tlb_vtcr & VTCR_EL2_TG0_MASK) {
2880+
case VTCR_EL2_TG0_4K:
2881+
max_size = SZ_1G;
2882+
break;
2883+
case VTCR_EL2_TG0_16K:
2884+
max_size = SZ_32M;
2885+
break;
2886+
case VTCR_EL2_TG0_64K:
2887+
default: /* IMPDEF: treat any other value as 64k */
2888+
/*
2889+
* No, we do not support 52bit IPA in nested yet. Once
2890+
* we do, this should be 4TB.
2891+
*/
2892+
max_size = SZ_512M;
2893+
break;
2894+
}
2895+
2896+
base_addr &= ~(max_size - 1);
2897+
2898+
kvm_stage2_unmap_range(mmu, base_addr, max_size);
2899+
}
2900+
2901+
static bool handle_ipas2e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
2902+
const struct sys_reg_desc *r)
2903+
{
2904+
u32 sys_encoding = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
2905+
u64 vttbr = vcpu_read_sys_reg(vcpu, VTTBR_EL2);
2906+
2907+
if (!kvm_supported_tlbi_ipas2_op(vcpu, sys_encoding)) {
2908+
kvm_inject_undefined(vcpu);
2909+
return false;
2910+
}
2911+
2912+
kvm_s2_mmu_iterate_by_vmid(vcpu->kvm, get_vmid(vttbr),
2913+
&(union tlbi_info) {
2914+
.ipa = {
2915+
.addr = p->regval,
2916+
},
2917+
},
2918+
s2_mmu_unmap_ipa);
2919+
2920+
return true;
2921+
}
2922+
28322923
static void s2_mmu_tlbi_s1e1(struct kvm_s2_mmu *mmu,
28332924
const union tlbi_info *info)
28342925
{
@@ -2903,8 +2994,13 @@ static struct sys_reg_desc sys_insn_descs[] = {
29032994
SYS_INSN(TLBI_VALE1, handle_tlbi_el1),
29042995
SYS_INSN(TLBI_VAALE1, handle_tlbi_el1),
29052996

2997+
SYS_INSN(TLBI_IPAS2E1IS, handle_ipas2e1is),
2998+
SYS_INSN(TLBI_IPAS2LE1IS, handle_ipas2e1is),
2999+
29063000
SYS_INSN(TLBI_ALLE1IS, handle_alle1is),
29073001
SYS_INSN(TLBI_VMALLS12E1IS, handle_vmalls12e1is),
3002+
SYS_INSN(TLBI_IPAS2E1, handle_ipas2e1is),
3003+
SYS_INSN(TLBI_IPAS2LE1, handle_ipas2e1is),
29083004
SYS_INSN(TLBI_ALLE1, handle_alle1is),
29093005
SYS_INSN(TLBI_VMALLS12E1, handle_vmalls12e1is),
29103006
};

0 commit comments

Comments
 (0)