Commit 8972a991 authored by Will Deacon's avatar Will Deacon Committed by Marc Zyngier
Browse files

KVM: arm64: Register 'selftest_vm' in the VM table



In preparation for extending the pKVM page ownership selftests to cover
forceful reclaim of donated pages, rework the creation of the
'selftest_vm' so that it is registered in the VM table while the tests
are running.

Tested-by: default avatarFuad Tabba <tabba@google.com>
Tested-by: default avatarMostafa Saleh <smostafa@google.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
Link: https://patch.msgid.link/20260330144841.26181-35-will@kernel.org


Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent c290df52
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ static __always_inline void __load_host_stage2(void)

#ifdef CONFIG_NVHE_EL2_DEBUG
void pkvm_ownership_selftest(void *base);
struct pkvm_hyp_vcpu *init_selftest_vm(void *virt);
void teardown_selftest_vm(void);
#else
static inline void pkvm_ownership_selftest(void *base) { }
#endif
+10 −43
Original line number Diff line number Diff line
@@ -1648,53 +1648,18 @@ struct pkvm_expected_state {

static struct pkvm_expected_state selftest_state;
static struct hyp_page *selftest_page;

static struct pkvm_hyp_vm selftest_vm = {
	.kvm = {
		.arch = {
			.mmu = {
				.arch = &selftest_vm.kvm.arch,
				.pgt = &selftest_vm.pgt,
			},
		},
	},
};

static struct pkvm_hyp_vcpu selftest_vcpu = {
	.vcpu = {
		.arch = {
			.hw_mmu = &selftest_vm.kvm.arch.mmu,
		},
		.kvm = &selftest_vm.kvm,
	},
};

static void init_selftest_vm(void *virt)
{
	struct hyp_page *p = hyp_virt_to_page(virt);
	int i;

	selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
	WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));

	for (i = 0; i < pkvm_selftest_pages(); i++) {
		if (p[i].refcount)
			continue;
		p[i].refcount = 1;
		hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
	}
}
static struct pkvm_hyp_vcpu *selftest_vcpu;

static u64 selftest_ipa(void)
{
	return BIT(selftest_vm.pgt.ia_bits - 1);
	return BIT(selftest_vcpu->vcpu.arch.hw_mmu->pgt->ia_bits - 1);
}

static void assert_page_state(void)
{
	void *virt = hyp_page_to_virt(selftest_page);
	u64 size = PAGE_SIZE << selftest_page->order;
	struct pkvm_hyp_vcpu *vcpu = &selftest_vcpu;
	struct pkvm_hyp_vcpu *vcpu = selftest_vcpu;
	u64 phys = hyp_virt_to_phys(virt);
	u64 ipa[2] = { selftest_ipa(), selftest_ipa() + PAGE_SIZE };
	struct pkvm_hyp_vm *vm;
@@ -1709,10 +1674,10 @@ static void assert_page_state(void)
	WARN_ON(__hyp_check_page_state_range(phys, size, selftest_state.hyp));
	hyp_unlock_component();

	guest_lock_component(&selftest_vm);
	guest_lock_component(vm);
	WARN_ON(__guest_check_page_state_range(vm, ipa[0], size, selftest_state.guest[0]));
	WARN_ON(__guest_check_page_state_range(vm, ipa[1], size, selftest_state.guest[1]));
	guest_unlock_component(&selftest_vm);
	guest_unlock_component(vm);
}

#define assert_transition_res(res, fn, ...)		\
@@ -1725,14 +1690,15 @@ void pkvm_ownership_selftest(void *base)
{
	enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_RWX;
	void *virt = hyp_alloc_pages(&host_s2_pool, 0);
	struct pkvm_hyp_vcpu *vcpu = &selftest_vcpu;
	struct pkvm_hyp_vm *vm = &selftest_vm;
	struct pkvm_hyp_vcpu *vcpu;
	u64 phys, size, pfn, gfn;
	struct pkvm_hyp_vm *vm;

	WARN_ON(!virt);
	selftest_page = hyp_virt_to_page(virt);
	selftest_page->refcount = 0;
	init_selftest_vm(base);
	selftest_vcpu = vcpu = init_selftest_vm(base);
	vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);

	size = PAGE_SIZE << selftest_page->order;
	phys = hyp_virt_to_phys(virt);
@@ -1856,6 +1822,7 @@ void pkvm_ownership_selftest(void *base)
	selftest_state.hyp = PKVM_PAGE_OWNED;
	assert_transition_res(0,	__pkvm_host_donate_hyp, pfn, 1);

	teardown_selftest_vm();
	selftest_page->refcount = 1;
	hyp_put_page(&host_s2_pool, virt);
}
+49 −0
Original line number Diff line number Diff line
@@ -733,6 +733,55 @@ void __pkvm_unreserve_vm(pkvm_handle_t handle)
	hyp_spin_unlock(&vm_table_lock);
}

#ifdef CONFIG_NVHE_EL2_DEBUG
static struct pkvm_hyp_vm selftest_vm = {
	.kvm = {
		.arch = {
			.mmu = {
				.arch = &selftest_vm.kvm.arch,
				.pgt = &selftest_vm.pgt,
			},
		},
	},
};

static struct pkvm_hyp_vcpu selftest_vcpu = {
	.vcpu = {
		.arch = {
			.hw_mmu = &selftest_vm.kvm.arch.mmu,
		},
		.kvm = &selftest_vm.kvm,
	},
};

struct pkvm_hyp_vcpu *init_selftest_vm(void *virt)
{
	struct hyp_page *p = hyp_virt_to_page(virt);
	int i;

	selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
	WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));

	for (i = 0; i < pkvm_selftest_pages(); i++) {
		if (p[i].refcount)
			continue;
		p[i].refcount = 1;
		hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
	}

	selftest_vm.kvm.arch.pkvm.handle = __pkvm_reserve_vm();
	insert_vm_table_entry(selftest_vm.kvm.arch.pkvm.handle, &selftest_vm);
	return &selftest_vcpu;
}

void teardown_selftest_vm(void)
{
	hyp_spin_lock(&vm_table_lock);
	remove_vm_table_entry(selftest_vm.kvm.arch.pkvm.handle);
	hyp_spin_unlock(&vm_table_lock);
}
#endif /* CONFIG_NVHE_EL2_DEBUG */

/*
 * Initialize the hypervisor copy of the VM state using host-donated memory.
 *