tools/testing/selftests/kvm/arm64/page_fault_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/arm64/page_fault_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/arm64/page_fault_test.c
Extension
.c
Size
34310 bytes
Lines
1136
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct test_desc {
	const char *name;
	u64 mem_mark_cmd;
	/* Skip the test if any prepare function returns false */
	bool (*guest_prepare[PREPARE_FN_NR])(void);
	void (*guest_test)(void);
	void (*guest_test_check[CHECK_FN_NR])(void);
	uffd_handler_t uffd_pt_handler;
	uffd_handler_t uffd_data_handler;
	void (*dabt_handler)(struct ex_regs *regs);
	void (*iabt_handler)(struct ex_regs *regs);
	void (*mmio_handler)(struct kvm_vm *vm, struct kvm_run *run);
	void (*fail_vcpu_run_handler)(int ret);
	u32 pt_memslot_flags;
	u32 data_memslot_flags;
	bool skip;
	struct event_cnt expected_events;
};

struct test_params {
	enum vm_mem_backing_src_type src_type;
	struct test_desc *test_desc;
};

static inline void flush_tlb_page(gva_t gva)
{
	gva_t page = gva >> 12;

	dsb(ishst);
	asm volatile("tlbi vaae1is, %0" :: "r" (page));
	dsb(ish);
	isb();
}

static void guest_write64(void)
{
	u64 val;

	WRITE_ONCE(*guest_test_memory, TEST_DATA);
	val = READ_ONCE(*guest_test_memory);
	GUEST_ASSERT_EQ(val, TEST_DATA);
}

/* Check the system for atomic instructions. */
static bool guest_check_lse(void)
{
	u64 isar0 = read_sysreg(id_aa64isar0_el1);
	u64 atomic;

	atomic = FIELD_GET(ID_AA64ISAR0_EL1_ATOMIC, isar0);
	return atomic >= 2;
}

static bool guest_check_dc_zva(void)
{
	u64 dczid = read_sysreg(dczid_el0);
	u64 dzp = FIELD_GET(DCZID_EL0_DZP, dczid);

	return dzp == 0;
}

/* Compare and swap instruction. */
static void guest_cas(void)
{
	u64 val;

	GUEST_ASSERT(guest_check_lse());
	asm volatile(".arch_extension lse\n"
		     "casal %0, %1, [%2]\n"
		     :: "r" (0ul), "r" (TEST_DATA), "r" (guest_test_memory));
	val = READ_ONCE(*guest_test_memory);
	GUEST_ASSERT_EQ(val, TEST_DATA);
}

static void guest_read64(void)
{
	u64 val;

	val = READ_ONCE(*guest_test_memory);
	GUEST_ASSERT_EQ(val, 0);
}

/* Address translation instruction */
static void guest_at(void)
{
	u64 par;

	asm volatile("at s1e1r, %0" :: "r" (guest_test_memory));
	isb();
	par = read_sysreg(par_el1);

Annotation

Implementation Notes