// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2021, Red Hat Inc.
 *
 * Generic tests for KVM CPUID set/get ioctls
 */
#include <asm/kvm_para.h>
#include <linux/kvm_para.h>
#include <stdint.h>

#include "test_util.h"
#include "kvm_util.h"
#include "processor.h"

/* CPUIDs known to differ */
struct {
	u32 function;
	u32 index;
} mangled_cpuids[] = {
	/*
	 * These entries depend on the vCPU's XCR0 register and IA32_XSS MSR,
	 * which are not controlled for by this test.
	 */
	{.function = 0xd, .index = 0},
	{.function = 0xd, .index = 1},
};

static void test_guest_cpuids(struct kvm_cpuid2 *guest_cpuid)
{
	int i;
	u32 eax, ebx, ecx, edx;

	for (i = 0; i < guest_cpuid->nent; i++) {
		__cpuid(guest_cpuid->entries[i].function,
			guest_cpuid->entries[i].index,
			&eax, &ebx, &ecx, &edx);

		GUEST_ASSERT_EQ(eax, guest_cpuid->entries[i].eax);
		GUEST_ASSERT_EQ(ebx, guest_cpuid->entries[i].ebx);
		GUEST_ASSERT_EQ(ecx, guest_cpuid->entries[i].ecx);
		GUEST_ASSERT_EQ(edx, guest_cpuid->entries[i].edx);
	}

}

static void guest_main(struct kvm_cpuid2 *guest_cpuid)
{
	GUEST_SYNC(1);

	test_guest_cpuids(guest_cpuid);

	GUEST_SYNC(2);

	GUEST_ASSERT_EQ(this_cpu_property(X86_PROPERTY_MAX_KVM_LEAF), 0x40000001);

	GUEST_DONE();
}

static bool is_cpuid_mangled(const struct kvm_cpuid_entry2 *entrie)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(mangled_cpuids); i++) {
		if (mangled_cpuids[i].function == entrie->function &&
		    mangled_cpuids[i].index == entrie->index)
			return true;
	}

	return false;
}

static void compare_cpuids(const struct kvm_cpuid2 *cpuid1,
			   const struct kvm_cpuid2 *cpuid2)
{
	const struct kvm_cpuid_entry2 *e1, *e2;
	int i;

	TEST_ASSERT(cpuid1->nent == cpuid2->nent,
		    "CPUID nent mismatch: %d vs. %d", cpuid1->nent, cpuid2->nent);

	for (i = 0; i < cpuid1->nent; i++) {
		e1 = &cpuid1->entries[i];
		e2 = &cpuid2->entries[i];

		TEST_ASSERT(e1->function == e2->function &&
			    e1->index == e2->index && e1->flags == e2->flags,
			    "CPUID entries[%d] mismtach: 0x%x.%d.%x vs. 0x%x.%d.%x",
			    i, e1->function, e1->index, e1->flags,
			    e2->function, e2->index, e2->flags);

		if (is_cpuid_mangled(e1))
			continue;

		TEST_ASSERT(e1->eax == e2->eax && e1->ebx == e2->ebx &&
			    e1->ecx == e2->ecx && e1->edx == e2->edx,
			    "CPUID 0x%x.%x differ: 0x%x:0x%x:0x%x:0x%x vs 0x%x:0x%x:0x%x:0x%x",
			    e1->function, e1->index,
			    e1->eax, e1->ebx, e1->ecx, e1->edx,
			    e2->eax, e2->ebx, e2->ecx, e2->edx);
	}
}

static void run_vcpu(struct kvm_vcpu *vcpu, int stage)
{
	struct ucall uc;

	vcpu_run(vcpu);

	switch (get_ucall(vcpu, &uc)) {
	case UCALL_SYNC:
		TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
			    uc.args[1] == stage + 1,
			    "Stage %d: Unexpected register values vmexit, got %lx",
			    stage + 1, (ulong)uc.args[1]);
		return;
	case UCALL_DONE:
		return;
	case UCALL_ABORT:
		REPORT_GUEST_ASSERT(uc);
	default:
		TEST_ASSERT(false, "Unexpected exit: %s",
			    exit_reason_str(vcpu->run->exit_reason));
	}
}

struct kvm_cpuid2 *vcpu_alloc_cpuid(struct kvm_vm *vm, vm_vaddr_t *p_gva, struct kvm_cpuid2 *cpuid)
{
	int size = sizeof(*cpuid) + cpuid->nent * sizeof(cpuid->entries[0]);
	vm_vaddr_t gva = vm_vaddr_alloc(vm, size, KVM_UTIL_MIN_VADDR);
	struct kvm_cpuid2 *guest_cpuids = addr_gva2hva(vm, gva);

	memcpy(guest_cpuids, cpuid, size);

	*p_gva = gva;
	return guest_cpuids;
}

static void set_cpuid_after_run(struct kvm_vcpu *vcpu)
{
	struct kvm_cpuid_entry2 *ent;
	int rc;
	u32 eax, ebx, x;

	/* Setting unmodified CPUID is allowed */
	rc = __vcpu_set_cpuid(vcpu);
	TEST_ASSERT(!rc, "Setting unmodified CPUID after KVM_RUN failed: %d", rc);

	/* Changing CPU features is forbidden */
	ent = vcpu_get_cpuid_entry(vcpu, 0x7);
	ebx = ent->ebx;
	ent->ebx--;
	rc = __vcpu_set_cpuid(vcpu);
	TEST_ASSERT(rc, "Changing CPU features should fail");
	ent->ebx = ebx;

	/* Changing MAXPHYADDR is forbidden */
	ent = vcpu_get_cpuid_entry(vcpu, 0x80000008);
	eax = ent->eax;
	x = eax & 0xff;
	ent->eax = (eax & ~0xffu) | (x - 1);
	rc = __vcpu_set_cpuid(vcpu);
	TEST_ASSERT(rc, "Changing MAXPHYADDR should fail");
	ent->eax = eax;
}

static void test_get_cpuid2(struct kvm_vcpu *vcpu)
{
	struct kvm_cpuid2 *cpuid = allocate_kvm_cpuid2(vcpu->cpuid->nent + 1);
	int i, r;

	vcpu_ioctl(vcpu, KVM_GET_CPUID2, cpuid);
	TEST_ASSERT(cpuid->nent == vcpu->cpuid->nent,
		    "KVM didn't update nent on success, wanted %u, got %u",
		    vcpu->cpuid->nent, cpuid->nent);

	for (i = 0; i < vcpu->cpuid->nent; i++) {
		cpuid->nent = i;
		r = __vcpu_ioctl(vcpu, KVM_GET_CPUID2, cpuid);
		TEST_ASSERT(r && errno == E2BIG, KVM_IOCTL_ERROR(KVM_GET_CPUID2, r));
		TEST_ASSERT(cpuid->nent == i, "KVM modified nent on failure");
	}
	free(cpuid);
}

int main(void)
{
	struct kvm_vcpu *vcpu;
	vm_vaddr_t cpuid_gva;
	struct kvm_vm *vm;
	int stage;

	vm = vm_create_with_one_vcpu(&vcpu, guest_main);

	compare_cpuids(kvm_get_supported_cpuid(), vcpu->cpuid);

	vcpu_alloc_cpuid(vm, &cpuid_gva, vcpu->cpuid);

	vcpu_args_set(vcpu, 1, cpuid_gva);

	for (stage = 0; stage < 3; stage++)
		run_vcpu(vcpu, stage);

	set_cpuid_after_run(vcpu);

	test_get_cpuid2(vcpu);

	kvm_vm_free(vm);
}
