Commit 07676c04 authored by Sean Christopherson's avatar Sean Christopherson
Browse files

KVM: selftests: Move TDP mapping functions outside of vmx.c



Now that the functions are no longer VMX-specific, move them to
processor.c. Do a minor comment tweak replacing 'EPT' with 'TDP'.

No functional change intended.

Signed-off-by: default avatarYosry Ahmed <yosry.ahmed@linux.dev>
Link: https://patch.msgid.link/20251230230150.4150236-15-seanjc@google.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 508d1cc3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1479,6 +1479,10 @@ void __virt_pg_map(struct kvm_vm *vm, struct kvm_mmu *mmu, uint64_t vaddr,
void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
		    uint64_t nr_bytes, int level);

void tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr, uint64_t size);
void tdp_identity_map_default_memslots(struct kvm_vm *vm);
void tdp_identity_map_1g(struct kvm_vm *vm,  uint64_t addr, uint64_t size);

/*
 * Basic CPU control in CR0
 */
+0 −3
Original line number Diff line number Diff line
@@ -557,9 +557,6 @@ bool load_vmcs(struct vmx_pages *vmx);

bool ept_1g_pages_supported(void);

void tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr, uint64_t size);
void tdp_identity_map_default_memslots(struct kvm_vm *vm);
void tdp_identity_map_1g(struct kvm_vm *vm,  uint64_t addr, uint64_t size);
bool kvm_cpu_has_ept(void);
void vm_enable_ept(struct kvm_vm *vm);
void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm);
+53 −0
Original line number Diff line number Diff line
@@ -472,6 +472,59 @@ void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
	}
}

void __tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr,
	       uint64_t size, int level)
{
	size_t page_size = PG_LEVEL_SIZE(level);
	size_t npages = size / page_size;

	TEST_ASSERT(nested_paddr + size > nested_paddr, "Vaddr overflow");
	TEST_ASSERT(paddr + size > paddr, "Paddr overflow");

	while (npages--) {
		__virt_pg_map(vm, &vm->stage2_mmu, nested_paddr, paddr, level);
		nested_paddr += page_size;
		paddr += page_size;
	}
}

void tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr,
	     uint64_t size)
{
	__tdp_map(vm, nested_paddr, paddr, size, PG_LEVEL_4K);
}

/* Prepare an identity extended page table that maps all the
 * physical pages in VM.
 */
void tdp_identity_map_default_memslots(struct kvm_vm *vm)
{
	uint32_t s, memslot = 0;
	sparsebit_idx_t i, last;
	struct userspace_mem_region *region = memslot2region(vm, memslot);

	/* Only memslot 0 is mapped here, ensure it's the only one being used */
	for (s = 0; s < NR_MEM_REGIONS; s++)
		TEST_ASSERT_EQ(vm->memslots[s], 0);

	i = (region->region.guest_phys_addr >> vm->page_shift) - 1;
	last = i + (region->region.memory_size >> vm->page_shift);
	for (;;) {
		i = sparsebit_next_clear(region->unused_phy_pages, i);
		if (i > last)
			break;

		tdp_map(vm, (uint64_t)i << vm->page_shift,
			(uint64_t)i << vm->page_shift, 1 << vm->page_shift);
	}
}

/* Identity map a region with 1GiB Pages. */
void tdp_identity_map_1g(struct kvm_vm *vm, uint64_t addr, uint64_t size)
{
	__tdp_map(vm, addr, addr, size, PG_LEVEL_1G);
}

/*
 * Set Unusable Segment
 *
+0 −71
Original line number Diff line number Diff line
@@ -373,77 +373,6 @@ void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp)
	init_vmcs_guest_state(guest_rip, guest_rsp);
}

/*
 * Map a range of EPT guest physical addresses to the VM's physical address
 *
 * Input Args:
 *   vm - Virtual Machine
 *   nested_paddr - Nested guest physical address to map
 *   paddr - VM Physical Address
 *   size - The size of the range to map
 *   level - The level at which to map the range
 *
 * Output Args: None
 *
 * Return: None
 *
 * Within the VM given by vm, creates a nested guest translation for the
 * page range starting at nested_paddr to the page range starting at paddr.
 */
void __tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr,
	       uint64_t size, int level)
{
	struct kvm_mmu *mmu = &vm->stage2_mmu;
	size_t page_size = PG_LEVEL_SIZE(level);
	size_t npages = size / page_size;

	TEST_ASSERT(nested_paddr + size > nested_paddr, "Vaddr overflow");
	TEST_ASSERT(paddr + size > paddr, "Paddr overflow");

	while (npages--) {
		__virt_pg_map(vm, mmu, nested_paddr, paddr, level);
		nested_paddr += page_size;
		paddr += page_size;
	}
}

void tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr,
	     uint64_t size)
{
	__tdp_map(vm, nested_paddr, paddr, size, PG_LEVEL_4K);
}

/* Prepare an identity extended page table that maps all the
 * physical pages in VM.
 */
void tdp_identity_map_default_memslots(struct kvm_vm *vm)
{
	uint32_t s, memslot = 0;
	sparsebit_idx_t i, last;
	struct userspace_mem_region *region = memslot2region(vm, memslot);

	/* Only memslot 0 is mapped here, ensure it's the only one being used */
	for (s = 0; s < NR_MEM_REGIONS; s++)
		TEST_ASSERT_EQ(vm->memslots[s], 0);

	i = (region->region.guest_phys_addr >> vm->page_shift) - 1;
	last = i + (region->region.memory_size >> vm->page_shift);
	for (;;) {
		i = sparsebit_next_clear(region->unused_phy_pages, i);
		if (i > last)
			break;

		tdp_map(vm, (uint64_t)i << vm->page_shift,
			(uint64_t)i << vm->page_shift, 1 << vm->page_shift);
	}
}

/* Identity map a region with 1GiB Pages. */
void tdp_identity_map_1g(struct kvm_vm *vm, uint64_t addr, uint64_t size)
{
	__tdp_map(vm, addr, addr, size, PG_LEVEL_1G);
}

bool kvm_cpu_has_ept(void)
{
	uint64_t ctrl;