tools/testing/selftests/kvm/x86/ucna_injection_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/x86/ucna_injection_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/ucna_injection_test.c
Extension
.c
Size
8424 bytes
Lines
297
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 thread_params {
	struct kvm_vcpu *vcpu;
	u64 *p_i_ucna_rcvd;
	u64 *p_i_ucna_addr;
	u64 *p_ucna_addr;
	u64 *p_ucna_addr2;
};

static void verify_apic_base_addr(void)
{
	u64 msr = rdmsr(MSR_IA32_APICBASE);
	u64 base = GET_APIC_BASE(msr);

	GUEST_ASSERT(base == APIC_DEFAULT_GPA);
}

static void ucna_injection_guest_code(void)
{
	u64 ctl2;
	verify_apic_base_addr();
	xapic_enable();

	/* Sets up the interrupt vector and enables per-bank CMCI sigaling. */
	xapic_write_reg(APIC_LVTCMCI, CMCI_VECTOR | APIC_DM_FIXED);
	ctl2 = rdmsr(MSR_IA32_MCx_CTL2(UCNA_BANK));
	wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 | MCI_CTL2_CMCI_EN);

	/* Enables interrupt in guest. */
	sti();

	/* Let user space inject the first UCNA */
	GUEST_SYNC(SYNC_FIRST_UCNA);

	ucna_addr = rdmsr(MSR_IA32_MCx_ADDR(UCNA_BANK));

	/* Disables the per-bank CMCI signaling. */
	ctl2 = rdmsr(MSR_IA32_MCx_CTL2(UCNA_BANK));
	wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 & ~MCI_CTL2_CMCI_EN);

	/* Let the user space inject the second UCNA */
	GUEST_SYNC(SYNC_SECOND_UCNA);

	ucna_addr2 = rdmsr(MSR_IA32_MCx_ADDR(UCNA_BANK));
	GUEST_DONE();
}

static void cmci_disabled_guest_code(void)
{
	u64 ctl2 = rdmsr(MSR_IA32_MCx_CTL2(UCNA_BANK));
	wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 | MCI_CTL2_CMCI_EN);

	GUEST_DONE();
}

static void cmci_enabled_guest_code(void)
{
	u64 ctl2 = rdmsr(MSR_IA32_MCx_CTL2(UCNA_BANK));
	wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 | MCI_CTL2_RESERVED_BIT);

	GUEST_DONE();
}

static void guest_cmci_handler(struct ex_regs *regs)
{
	i_ucna_rcvd++;
	i_ucna_addr = rdmsr(MSR_IA32_MCx_ADDR(UCNA_BANK));
	xapic_write_reg(APIC_EOI, 0);
}

static void guest_gp_handler(struct ex_regs *regs)
{
	GUEST_SYNC(SYNC_GP);
}

static void run_vcpu_expect_gp(struct kvm_vcpu *vcpu)
{
	struct ucall uc;

	vcpu_run(vcpu);

	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
	TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC,
		    "Expect UCALL_SYNC");
	TEST_ASSERT(uc.args[1] == SYNC_GP, "#GP is expected.");
	printf("vCPU received GP in guest.\n");
}

static void inject_ucna(struct kvm_vcpu *vcpu, u64 addr)
{
	/*

Annotation

Implementation Notes