Skip to content

Commit 0abc1b1

Browse files
ryanhrobMarc Zyngier
authored andcommitted
KVM: arm64: Support up to 5 levels of translation in kvm_pgtable
FEAT_LPA2 increases the maximum levels of translation from 4 to 5 for the 4KB page case, when IA is >48 bits. While we can still use 4 levels for stage2 translation in this case (due to stage2 allowing concatenated page tables for first level lookup), the same kvm_pgtable library is used for the hyp stage1 page tables and stage1 does not support concatenation. Therefore, modify the library to support up to 5 levels. Previous patches already laid the groundwork for this by refactoring code to work in terms of KVM_PGTABLE_FIRST_LEVEL and KVM_PGTABLE_LAST_LEVEL. So we just need to change these macros. The hardware sometimes encodes the new level differently from the others: One such place is when reading the level from the FSC field in the ESR_EL2 register. We never expect to see the lowest level (-1) here since the stage 2 page tables always use concatenated tables for first level lookup and therefore only use 4 levels of lookup. So we get away with just adding a comment to explain why we are not being careful about decoding level -1. For stage2 VTCR_EL2.SL2 is introduced to encode the new start level. However, since we always use concatenated page tables for first level look up at stage2 (and therefore we will never need the new extra level) we never touch this new field. Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20231127111737.1897081-10-ryan.roberts@arm.com
1 parent 419edf4 commit 0abc1b1

3 files changed

Lines changed: 20 additions & 1 deletion

File tree

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,16 @@ static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vc
411411

412412
static __always_inline s8 kvm_vcpu_trap_get_fault_level(const struct kvm_vcpu *vcpu)
413413
{
414+
/*
415+
* Note: With the introduction of FEAT_LPA2 an extra level of
416+
* translation (level -1) is added. This level (obviously) doesn't
417+
* follow the previous convention of encoding the 4 levels in the 2 LSBs
418+
* of the FSC so this function breaks if the fault is for level -1.
419+
*
420+
* However, stage2 tables always use concatenated tables for first level
421+
* lookup and therefore it is guaranteed that the level will be between
422+
* 0 and 3, and this function continues to work.
423+
*/
414424
return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC_LEVEL;
415425
}
416426

arch/arm64/include/asm/kvm_pgtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <linux/kvm_host.h>
1212
#include <linux/types.h>
1313

14-
#define KVM_PGTABLE_FIRST_LEVEL 0
14+
#define KVM_PGTABLE_FIRST_LEVEL -1
1515
#define KVM_PGTABLE_LAST_LEVEL 3
1616

1717
/*

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,15 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
645645
lvls = stage2_pgtable_levels(phys_shift);
646646
if (lvls < 2)
647647
lvls = 2;
648+
649+
/*
650+
* When LPA2 is enabled, the HW supports an extra level of translation
651+
* (for 5 in total) when using 4K pages. It also introduces VTCR_EL2.SL2
652+
* to as an addition to SL0 to enable encoding this extra start level.
653+
* However, since we always use concatenated pages for the first level
654+
* lookup, we will never need this extra level and therefore do not need
655+
* to touch SL2.
656+
*/
648657
vtcr |= VTCR_EL2_LVLS_TO_SL0(lvls);
649658

650659
#ifdef CONFIG_ARM64_HW_AFDBM

0 commit comments

Comments
 (0)