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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/xapic_state_test.c
Extension
.c
Size
6991 bytes
Lines
263
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 xapic_vcpu {
	struct kvm_vcpu *vcpu;
	bool is_x2apic;
	bool has_xavic_errata;
};

static void xapic_guest_code(void)
{
	cli();

	xapic_enable();

	while (1) {
		u64 val = (u64)xapic_read_reg(APIC_IRR) |
			       (u64)xapic_read_reg(APIC_IRR + 0x10) << 32;

		xapic_write_reg(APIC_ICR2, val >> 32);
		xapic_write_reg(APIC_ICR, val);
		GUEST_SYNC(val);
	}
}

#define X2APIC_RSVD_BITS_MASK  (GENMASK_ULL(31, 20) | \
				GENMASK_ULL(17, 16) | \
				GENMASK_ULL(13, 13))

static void x2apic_guest_code(void)
{
	cli();

	x2apic_enable();

	do {
		u64 val = x2apic_read_reg(APIC_IRR) |
			       x2apic_read_reg(APIC_IRR + 0x10) << 32;

		if (val & X2APIC_RSVD_BITS_MASK) {
			x2apic_write_reg_fault(APIC_ICR, val);
		} else {
			x2apic_write_reg(APIC_ICR, val);
			GUEST_ASSERT_EQ(x2apic_read_reg(APIC_ICR), val);
		}
		GUEST_SYNC(val);
	} while (1);
}

static void ____test_icr(struct xapic_vcpu *x, u64 val)
{
	struct kvm_vcpu *vcpu = x->vcpu;
	struct kvm_lapic_state xapic;
	struct ucall uc;
	u64 icr;

	/*
	 * Tell the guest what ICR value to write.  Use the IRR to pass info,
	 * all bits are valid and should not be modified by KVM (ignoring the
	 * fact that vectors 0-15 are technically illegal).
	 */
	vcpu_ioctl(vcpu, KVM_GET_LAPIC, &xapic);
	*((u32 *)&xapic.regs[APIC_IRR]) = val;
	*((u32 *)&xapic.regs[APIC_IRR + 0x10]) = val >> 32;
	vcpu_ioctl(vcpu, KVM_SET_LAPIC, &xapic);

	vcpu_run(vcpu);
	TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC);
	TEST_ASSERT_EQ(uc.args[1], val);

	vcpu_ioctl(vcpu, KVM_GET_LAPIC, &xapic);
	icr = (u64)(*((u32 *)&xapic.regs[APIC_ICR])) |
	      (u64)(*((u32 *)&xapic.regs[APIC_ICR2])) << 32;
	if (!x->is_x2apic) {
		if (!x->has_xavic_errata)
			val &= (-1u | (0xffull << (32 + 24)));
	} else if (val & X2APIC_RSVD_BITS_MASK) {
		return;
	}

	if (x->has_xavic_errata)
		TEST_ASSERT_EQ(icr & ~APIC_ICR_BUSY, val & ~APIC_ICR_BUSY);
	else
		TEST_ASSERT_EQ(icr, val & ~APIC_ICR_BUSY);
}

static void __test_icr(struct xapic_vcpu *x, u64 val)
{
	/*
	 * The BUSY bit is reserved on both AMD and Intel, but only AMD treats
	 * it is as _must_ be zero.  Intel simply ignores the bit.  Don't test
	 * the BUSY bit for x2APIC, as there is no single correct behavior.
	 */

Annotation

Implementation Notes