Commit dec79eab authored by Sean Christopherson's avatar Sean Christopherson
Browse files

KVM: selftests: Rework platform_info_test to actually verify #GP

Rework platform_info_test to actually handle and verify the expected #GP
on RDMSR when the associated KVM capability is disabled.  Currently, the
test _deliberately_ doesn't handle the #GP, and instead lets it escalated
to a triple fault shutdown.

In addition to verifying that KVM generates the correct fault, handling
the #GP will be necessary (without even more shenanigans) when a future
change to the core KVM selftests library configures the IDT and exception
handlers by default (the test subtly relies on the IDT limit being '0').

Link: https://lore.kernel.org/r/20240314232637.2538648-7-seanjc@google.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 53635ec2
Loading
Loading
Loading
Loading
+33 −33
Original line number Diff line number Diff line
@@ -24,27 +24,48 @@
static void guest_code(void)
{
	uint64_t msr_platform_info;
	uint8_t vector;

	for (;;) {
	GUEST_SYNC(true);
	msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
	GUEST_ASSERT_EQ(msr_platform_info & MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
			MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
		GUEST_SYNC(0);
		asm volatile ("inc %r11");
	}

	GUEST_SYNC(false);
	vector = rdmsr_safe(MSR_PLATFORM_INFO, &msr_platform_info);
	GUEST_ASSERT_EQ(vector, GP_VECTOR);

	GUEST_DONE();
}

static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu)
int main(int argc, char *argv[])
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;
	uint64_t msr_platform_info;
	struct ucall uc;

	vm_enable_cap(vcpu->vm, KVM_CAP_MSR_PLATFORM_INFO, true);
	TEST_REQUIRE(kvm_has_cap(KVM_CAP_MSR_PLATFORM_INFO));

	vm = vm_create_with_one_vcpu(&vcpu, guest_code);

	vm_init_descriptor_tables(vm);
	vcpu_init_descriptor_tables(vcpu);

	msr_platform_info = vcpu_get_msr(vcpu, MSR_PLATFORM_INFO);
	vcpu_set_msr(vcpu, MSR_PLATFORM_INFO,
		     msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);

	for (;;) {
		vcpu_run(vcpu);
		TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);

		switch (get_ucall(vcpu, &uc)) {
		case UCALL_SYNC:
			vm_enable_cap(vm, KVM_CAP_MSR_PLATFORM_INFO, uc.args[1]);
			break;
		case UCALL_DONE:
			goto done;
		case UCALL_ABORT:
			REPORT_GUEST_ASSERT(uc);
		default:
@@ -53,28 +74,7 @@ static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu)
		}
	}

static void test_msr_platform_info_disabled(struct kvm_vcpu *vcpu)
{
	vm_enable_cap(vcpu->vm, KVM_CAP_MSR_PLATFORM_INFO, false);
	vcpu_run(vcpu);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN);
}

int main(int argc, char *argv[])
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;
	uint64_t msr_platform_info;

	TEST_REQUIRE(kvm_has_cap(KVM_CAP_MSR_PLATFORM_INFO));

	vm = vm_create_with_one_vcpu(&vcpu, guest_code);

	msr_platform_info = vcpu_get_msr(vcpu, MSR_PLATFORM_INFO);
	vcpu_set_msr(vcpu, MSR_PLATFORM_INFO,
		     msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
	test_msr_platform_info_enabled(vcpu);
	test_msr_platform_info_disabled(vcpu);
done:
	vcpu_set_msr(vcpu, MSR_PLATFORM_INFO, msr_platform_info);

	kvm_vm_free(vm);