Skip to content

Commit 5d476ca

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: nv: Add handling of range-based TLBI operations
We already support some form of range operation by handling FEAT_TTL, but so far the "arbitrary" range operations are unsupported. Let's fix that. For EL2 S1, this is simple enough: we just map both NSH, ISH and OSH instructions onto the ISH version for EL1. For TLBI instructions affecting EL1 S1, we use the same model as their non-range counterpart to invalidate in the context of the correct VMID. For TLBI instructions affecting S2, we interpret the data passed by the guest to compute the range and use that to tear-down part of the shadow S2 range and invalidate the TLBs. Finally, we advertise FEAT_TLBIRANGE if the host supports it. Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 0cb8aae commit 5d476ca

File tree

3 files changed

+108
-6
lines changed

3 files changed

+108
-6
lines changed

arch/arm64/kvm/hyp/vhe/tlb.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,32 @@ int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding)
283283
case OP_TLBI_VAALE1OS:
284284
__tlbi(vaale1is, va);
285285
break;
286+
case OP_TLBI_RVAE2:
287+
case OP_TLBI_RVAE2IS:
288+
case OP_TLBI_RVAE2OS:
289+
case OP_TLBI_RVAE1:
290+
case OP_TLBI_RVAE1IS:
291+
case OP_TLBI_RVAE1OS:
292+
__tlbi(rvae1is, va);
293+
break;
294+
case OP_TLBI_RVALE2:
295+
case OP_TLBI_RVALE2IS:
296+
case OP_TLBI_RVALE2OS:
297+
case OP_TLBI_RVALE1:
298+
case OP_TLBI_RVALE1IS:
299+
case OP_TLBI_RVALE1OS:
300+
__tlbi(rvale1is, va);
301+
break;
302+
case OP_TLBI_RVAAE1:
303+
case OP_TLBI_RVAAE1IS:
304+
case OP_TLBI_RVAAE1OS:
305+
__tlbi(rvaae1is, va);
306+
break;
307+
case OP_TLBI_RVAALE1:
308+
case OP_TLBI_RVAALE1IS:
309+
case OP_TLBI_RVAALE1OS:
310+
__tlbi(rvaale1is, va);
311+
break;
286312
default:
287313
ret = -EINVAL;
288314
}

arch/arm64/kvm/nested.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -805,12 +805,8 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
805805

806806
switch (id) {
807807
case SYS_ID_AA64ISAR0_EL1:
808-
/* Support everything but TME and Range TLBIs */
809-
tmp = FIELD_GET(NV_FTR(ISAR0, TLB), val);
810-
tmp = min(tmp, ID_AA64ISAR0_EL1_TLB_OS);
811-
val &= ~(NV_FTR(ISAR0, TLB) |
812-
NV_FTR(ISAR0, TME));
813-
val |= FIELD_PREP(NV_FTR(ISAR0, TLB), tmp);
808+
/* Support everything but TME */
809+
val &= ~NV_FTR(ISAR0, TME);
814810
break;
815811

816812
case SYS_ID_AA64ISAR1_EL1:

arch/arm64/kvm/sys_regs.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2854,6 +2854,57 @@ static bool handle_vmalls12e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
28542854
return true;
28552855
}
28562856

2857+
static bool handle_ripas2e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
2858+
const struct sys_reg_desc *r)
2859+
{
2860+
u32 sys_encoding = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2);
2861+
u64 vttbr = vcpu_read_sys_reg(vcpu, VTTBR_EL2);
2862+
u64 base, range, tg, num, scale;
2863+
int shift;
2864+
2865+
if (!kvm_supported_tlbi_ipas2_op(vcpu, sys_encoding)) {
2866+
kvm_inject_undefined(vcpu);
2867+
return false;
2868+
}
2869+
2870+
/*
2871+
* Because the shadow S2 structure doesn't necessarily reflect that
2872+
* of the guest's S2 (different base granule size, for example), we
2873+
* decide to ignore TTL and only use the described range.
2874+
*/
2875+
tg = FIELD_GET(GENMASK(47, 46), p->regval);
2876+
scale = FIELD_GET(GENMASK(45, 44), p->regval);
2877+
num = FIELD_GET(GENMASK(43, 39), p->regval);
2878+
base = p->regval & GENMASK(36, 0);
2879+
2880+
switch(tg) {
2881+
case 1:
2882+
shift = 12;
2883+
break;
2884+
case 2:
2885+
shift = 14;
2886+
break;
2887+
case 3:
2888+
default: /* IMPDEF: handle tg==0 as 64k */
2889+
shift = 16;
2890+
break;
2891+
}
2892+
2893+
base <<= shift;
2894+
range = __TLBI_RANGE_PAGES(num, scale) << shift;
2895+
2896+
kvm_s2_mmu_iterate_by_vmid(vcpu->kvm, get_vmid(vttbr),
2897+
&(union tlbi_info) {
2898+
.range = {
2899+
.start = base,
2900+
.size = range,
2901+
},
2902+
},
2903+
s2_mmu_unmap_range);
2904+
2905+
return true;
2906+
}
2907+
28572908
static void s2_mmu_unmap_ipa(struct kvm_s2_mmu *mmu,
28582909
const union tlbi_info *info)
28592910
{
@@ -2966,12 +3017,28 @@ static struct sys_reg_desc sys_insn_descs[] = {
29663017
SYS_INSN(TLBI_VALE1OS, handle_tlbi_el1),
29673018
SYS_INSN(TLBI_VAALE1OS, handle_tlbi_el1),
29683019

3020+
SYS_INSN(TLBI_RVAE1IS, handle_tlbi_el1),
3021+
SYS_INSN(TLBI_RVAAE1IS, handle_tlbi_el1),
3022+
SYS_INSN(TLBI_RVALE1IS, handle_tlbi_el1),
3023+
SYS_INSN(TLBI_RVAALE1IS, handle_tlbi_el1),
3024+
29693025
SYS_INSN(TLBI_VMALLE1IS, handle_tlbi_el1),
29703026
SYS_INSN(TLBI_VAE1IS, handle_tlbi_el1),
29713027
SYS_INSN(TLBI_ASIDE1IS, handle_tlbi_el1),
29723028
SYS_INSN(TLBI_VAAE1IS, handle_tlbi_el1),
29733029
SYS_INSN(TLBI_VALE1IS, handle_tlbi_el1),
29743030
SYS_INSN(TLBI_VAALE1IS, handle_tlbi_el1),
3031+
3032+
SYS_INSN(TLBI_RVAE1OS, handle_tlbi_el1),
3033+
SYS_INSN(TLBI_RVAAE1OS, handle_tlbi_el1),
3034+
SYS_INSN(TLBI_RVALE1OS, handle_tlbi_el1),
3035+
SYS_INSN(TLBI_RVAALE1OS, handle_tlbi_el1),
3036+
3037+
SYS_INSN(TLBI_RVAE1, handle_tlbi_el1),
3038+
SYS_INSN(TLBI_RVAAE1, handle_tlbi_el1),
3039+
SYS_INSN(TLBI_RVALE1, handle_tlbi_el1),
3040+
SYS_INSN(TLBI_RVAALE1, handle_tlbi_el1),
3041+
29753042
SYS_INSN(TLBI_VMALLE1, handle_tlbi_el1),
29763043
SYS_INSN(TLBI_VAE1, handle_tlbi_el1),
29773044
SYS_INSN(TLBI_ASIDE1, handle_tlbi_el1),
@@ -2980,20 +3047,33 @@ static struct sys_reg_desc sys_insn_descs[] = {
29803047
SYS_INSN(TLBI_VAALE1, handle_tlbi_el1),
29813048

29823049
SYS_INSN(TLBI_IPAS2E1IS, handle_ipas2e1is),
3050+
SYS_INSN(TLBI_RIPAS2E1IS, handle_ripas2e1is),
29833051
SYS_INSN(TLBI_IPAS2LE1IS, handle_ipas2e1is),
3052+
SYS_INSN(TLBI_RIPAS2LE1IS, handle_ripas2e1is),
29843053

29853054
SYS_INSN(TLBI_ALLE2OS, trap_undef),
29863055
SYS_INSN(TLBI_VAE2OS, trap_undef),
29873056
SYS_INSN(TLBI_ALLE1OS, handle_alle1is),
29883057
SYS_INSN(TLBI_VALE2OS, trap_undef),
29893058
SYS_INSN(TLBI_VMALLS12E1OS, handle_vmalls12e1is),
29903059

3060+
SYS_INSN(TLBI_RVAE2IS, trap_undef),
3061+
SYS_INSN(TLBI_RVALE2IS, trap_undef),
3062+
29913063
SYS_INSN(TLBI_ALLE1IS, handle_alle1is),
29923064
SYS_INSN(TLBI_VMALLS12E1IS, handle_vmalls12e1is),
29933065
SYS_INSN(TLBI_IPAS2E1OS, handle_ipas2e1is),
29943066
SYS_INSN(TLBI_IPAS2E1, handle_ipas2e1is),
3067+
SYS_INSN(TLBI_RIPAS2E1, handle_ripas2e1is),
3068+
SYS_INSN(TLBI_RIPAS2E1OS, handle_ripas2e1is),
29953069
SYS_INSN(TLBI_IPAS2LE1OS, handle_ipas2e1is),
29963070
SYS_INSN(TLBI_IPAS2LE1, handle_ipas2e1is),
3071+
SYS_INSN(TLBI_RIPAS2LE1, handle_ripas2e1is),
3072+
SYS_INSN(TLBI_RIPAS2LE1OS, handle_ripas2e1is),
3073+
SYS_INSN(TLBI_RVAE2OS, trap_undef),
3074+
SYS_INSN(TLBI_RVALE2OS, trap_undef),
3075+
SYS_INSN(TLBI_RVAE2, trap_undef),
3076+
SYS_INSN(TLBI_RVALE2, trap_undef),
29973077
SYS_INSN(TLBI_ALLE1, handle_alle1is),
29983078
SYS_INSN(TLBI_VMALLS12E1, handle_vmalls12e1is),
29993079
};

0 commit comments

Comments
 (0)