KVM: selftests: Set the user bit on nested NPT PTEs

According to the APM, NPT walks are treated as user accesses. In
preparation for supporting NPT mappings, set the 'user' bit on NPTs by
adding a mask of bits to always be set on PTEs in kvm_mmu.

Signed-off-by: Yosry Ahmed <yosry.ahmed@linux.dev>
Link: https://patch.msgid.link/20251230230150.4150236-18-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
Yosry Ahmed 2025-12-30 15:01:46 -08:00 committed by Sean Christopherson
parent 753c0d5a50
commit 251e4849a7
4 changed files with 9 additions and 2 deletions

View File

@ -22,6 +22,8 @@ struct pte_masks {
uint64_t nx;
uint64_t c;
uint64_t s;
uint64_t always_set;
};
struct kvm_mmu_arch {

View File

@ -1452,6 +1452,7 @@ enum pg_level {
#define PTE_NX_MASK(mmu) ((mmu)->arch.pte_masks.nx)
#define PTE_C_BIT_MASK(mmu) ((mmu)->arch.pte_masks.c)
#define PTE_S_BIT_MASK(mmu) ((mmu)->arch.pte_masks.s)
#define PTE_ALWAYS_SET_MASK(mmu) ((mmu)->arch.pte_masks.always_set)
/*
* For PTEs without a PRESENT bit (i.e. EPT entries), treat the PTE as present

View File

@ -231,7 +231,8 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *vm,
if (!is_present_pte(mmu, pte)) {
*pte = PTE_PRESENT_MASK(mmu) | PTE_READABLE_MASK(mmu) |
PTE_WRITABLE_MASK(mmu) | PTE_EXECUTABLE_MASK(mmu);
PTE_WRITABLE_MASK(mmu) | PTE_EXECUTABLE_MASK(mmu) |
PTE_ALWAYS_SET_MASK(mmu);
if (current_level == target_level)
*pte |= PTE_HUGE_MASK(mmu) | (paddr & PHYSICAL_PAGE_MASK);
else
@ -299,7 +300,7 @@ void __virt_pg_map(struct kvm_vm *vm, struct kvm_mmu *mmu, uint64_t vaddr,
"PTE already present for 4k page at vaddr: 0x%lx", vaddr);
*pte = PTE_PRESENT_MASK(mmu) | PTE_READABLE_MASK(mmu) |
PTE_WRITABLE_MASK(mmu) | PTE_EXECUTABLE_MASK(mmu) |
(paddr & PHYSICAL_PAGE_MASK);
PTE_ALWAYS_SET_MASK(mmu) | (paddr & PHYSICAL_PAGE_MASK);
/*
* Neither SEV nor TDX supports shared page tables, so only the final

View File

@ -75,6 +75,9 @@ void vm_enable_npt(struct kvm_vm *vm)
pte_masks = vm->mmu.arch.pte_masks;
pte_masks.c = 0;
/* NPT walks are treated as user accesses, so set the 'user' bit. */
pte_masks.always_set = pte_masks.user;
tdp_mmu_init(vm, vm->mmu.pgtable_levels, &pte_masks);
}