Skip to content

Commit d1de157

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: nv: Handle FEAT_TTL hinted TLB operations
Support guest-provided information information to size the range of required invalidation. This helps with reducing over-invalidation, provided that the guest actually provides accurate information. Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 70109bc commit d1de157

File tree

3 files changed

+92
-23
lines changed

3 files changed

+92
-23
lines changed

arch/arm64/include/asm/kvm_nested.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ extern void kvm_nested_s2_wp(struct kvm *kvm);
124124
extern void kvm_nested_s2_unmap(struct kvm *kvm);
125125
extern void kvm_nested_s2_flush(struct kvm *kvm);
126126

127+
unsigned long compute_tlb_inval_range(struct kvm_s2_mmu *mmu, u64 val);
128+
127129
static inline bool kvm_supported_tlbi_s1e1_op(struct kvm_vcpu *vpcu, u32 instr)
128130
{
129131
struct kvm *kvm = vpcu->kvm;

arch/arm64/kvm/nested.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,95 @@ int kvm_walk_nested_s2(struct kvm_vcpu *vcpu, phys_addr_t gipa,
364364
return ret;
365365
}
366366

367+
static unsigned int ttl_to_size(u8 ttl)
368+
{
369+
int level = ttl & 3;
370+
int gran = (ttl >> 2) & 3;
371+
unsigned int max_size = 0;
372+
373+
switch (gran) {
374+
case TLBI_TTL_TG_4K:
375+
switch (level) {
376+
case 0:
377+
break;
378+
case 1:
379+
max_size = SZ_1G;
380+
break;
381+
case 2:
382+
max_size = SZ_2M;
383+
break;
384+
case 3:
385+
max_size = SZ_4K;
386+
break;
387+
}
388+
break;
389+
case TLBI_TTL_TG_16K:
390+
switch (level) {
391+
case 0:
392+
case 1:
393+
break;
394+
case 2:
395+
max_size = SZ_32M;
396+
break;
397+
case 3:
398+
max_size = SZ_16K;
399+
break;
400+
}
401+
break;
402+
case TLBI_TTL_TG_64K:
403+
switch (level) {
404+
case 0:
405+
case 1:
406+
/* No 52bit IPA support */
407+
break;
408+
case 2:
409+
max_size = SZ_512M;
410+
break;
411+
case 3:
412+
max_size = SZ_64K;
413+
break;
414+
}
415+
break;
416+
default: /* No size information */
417+
break;
418+
}
419+
420+
return max_size;
421+
}
422+
423+
unsigned long compute_tlb_inval_range(struct kvm_s2_mmu *mmu, u64 val)
424+
{
425+
unsigned long max_size;
426+
u8 ttl;
427+
428+
ttl = FIELD_GET(GENMASK_ULL(47, 44), val);
429+
430+
max_size = ttl_to_size(ttl);
431+
432+
if (!max_size) {
433+
/* Compute the maximum extent of the invalidation */
434+
switch (mmu->tlb_vtcr & VTCR_EL2_TG0_MASK) {
435+
case VTCR_EL2_TG0_4K:
436+
max_size = SZ_1G;
437+
break;
438+
case VTCR_EL2_TG0_16K:
439+
max_size = SZ_32M;
440+
break;
441+
case VTCR_EL2_TG0_64K:
442+
default: /* IMPDEF: treat any other value as 64k */
443+
/*
444+
* No, we do not support 52bit IPA in nested yet. Once
445+
* we do, this should be 4TB.
446+
*/
447+
max_size = SZ_512M;
448+
break;
449+
}
450+
}
451+
452+
WARN_ON(!max_size);
453+
return max_size;
454+
}
455+
367456
/*
368457
* We can have multiple *different* MMU contexts with the same VMID:
369458
*

arch/arm64/kvm/sys_regs.c

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2865,34 +2865,12 @@ static void s2_mmu_unmap_ipa(struct kvm_s2_mmu *mmu,
28652865
*
28662866
* - NS bit: we're non-secure only.
28672867
*
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-
*
28722868
* - IPA[51:48]: We don't support 52bit IPA just yet...
28732869
*
28742870
* And of course, adjust the IPA to be on an actual address.
28752871
*/
28762872
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-
2873+
max_size = compute_tlb_inval_range(mmu, info->ipa.addr);
28962874
base_addr &= ~(max_size - 1);
28972875

28982876
kvm_stage2_unmap_range(mmu, base_addr, max_size);

0 commit comments

Comments
 (0)