// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018, Red Hat, Inc.
 *
 * Tests for SMM.
 */
#define _GNU_SOURCE /* for program_invocation_short_name */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>

#include "test_util.h"

#include "kvm_util.h"

#include "vmx.h"
#include "svm_util.h"

#define SMRAM_SIZE 65536
#define SMRAM_MEMSLOT ((1 << 16) | 1)
#define SMRAM_PAGES (SMRAM_SIZE / PAGE_SIZE)
#define SMRAM_GPA 0x1000000
#define SMRAM_STAGE 0xfe

#define STR(x) #x
#define XSTR(s) STR(s)

#define SYNC_PORT 0xe
#define DONE 0xff

/*
 * This is compiled as normal 64-bit code, however, SMI handler is executed
 * in real-address mode. To stay simple we're limiting ourselves to a mode
 * independent subset of asm here.
 * SMI handler always report back fixed stage SMRAM_STAGE.
 */
uint8_t smi_handler[] = {
	0xb0, SMRAM_STAGE,    /* mov $SMRAM_STAGE, %al */
	0xe4, SYNC_PORT,      /* in $SYNC_PORT, %al */
	0x0f, 0xaa,           /* rsm */
};

static inline void sync_with_host(uint64_t phase)
{
	asm volatile("in $" XSTR(SYNC_PORT)", %%al \n"
		     : "+a" (phase));
}

static void self_smi(void)
{
	x2apic_write_reg(APIC_ICR,
			 APIC_DEST_SELF | APIC_INT_ASSERT | APIC_DM_SMI);
}

static void l2_guest_code(void)
{
	sync_with_host(8);

	sync_with_host(10);

	vmcall();
}

static void guest_code(void *arg)
{
	#define L2_GUEST_STACK_SIZE 64
	unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
	uint64_t apicbase = rdmsr(MSR_IA32_APICBASE);
	struct svm_test_data *svm = arg;
	struct vmx_pages *vmx_pages = arg;

	sync_with_host(1);

	wrmsr(MSR_IA32_APICBASE, apicbase | X2APIC_ENABLE);

	sync_with_host(2);

	self_smi();

	sync_with_host(4);

	if (arg) {
		if (this_cpu_has(X86_FEATURE_SVM)) {
			generic_svm_setup(svm, l2_guest_code,
					  &l2_guest_stack[L2_GUEST_STACK_SIZE]);
		} else {
			GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
			GUEST_ASSERT(load_vmcs(vmx_pages));
			prepare_vmcs(vmx_pages, l2_guest_code,
				     &l2_guest_stack[L2_GUEST_STACK_SIZE]);
		}

		sync_with_host(5);

		self_smi();

		sync_with_host(7);

		if (this_cpu_has(X86_FEATURE_SVM)) {
			run_guest(svm->vmcb, svm->vmcb_gpa);
			run_guest(svm->vmcb, svm->vmcb_gpa);
		} else {
			vmlaunch();
			vmresume();
		}

		/* Stages 8-11 are eaten by SMM (SMRAM_STAGE reported instead) */
		sync_with_host(12);
	}

	sync_with_host(DONE);
}

void inject_smi(struct kvm_vcpu *vcpu)
{
	struct kvm_vcpu_events events;

	vcpu_events_get(vcpu, &events);

	events.smi.pending = 1;
	events.flags |= KVM_VCPUEVENT_VALID_SMM;

	vcpu_events_set(vcpu, &events);
}

int main(int argc, char *argv[])
{
	vm_vaddr_t nested_gva = 0;

	struct kvm_vcpu *vcpu;
	struct kvm_regs regs;
	struct kvm_vm *vm;
	struct kvm_run *run;
	struct kvm_x86_state *state;
	int stage, stage_reported;

	TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_SMM));

	/* Create VM */
	vm = vm_create_with_one_vcpu(&vcpu, guest_code);

	run = vcpu->run;

	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, SMRAM_GPA,
				    SMRAM_MEMSLOT, SMRAM_PAGES, 0);
	TEST_ASSERT(vm_phy_pages_alloc(vm, SMRAM_PAGES, SMRAM_GPA, SMRAM_MEMSLOT)
		    == SMRAM_GPA, "could not allocate guest physical addresses?");

	memset(addr_gpa2hva(vm, SMRAM_GPA), 0x0, SMRAM_SIZE);
	memcpy(addr_gpa2hva(vm, SMRAM_GPA) + 0x8000, smi_handler,
	       sizeof(smi_handler));

	vcpu_set_msr(vcpu, MSR_IA32_SMBASE, SMRAM_GPA);

	if (kvm_has_cap(KVM_CAP_NESTED_STATE)) {
		if (kvm_cpu_has(X86_FEATURE_SVM))
			vcpu_alloc_svm(vm, &nested_gva);
		else if (kvm_cpu_has(X86_FEATURE_VMX))
			vcpu_alloc_vmx(vm, &nested_gva);
	}

	if (!nested_gva)
		pr_info("will skip SMM test with VMX enabled\n");

	vcpu_args_set(vcpu, 1, nested_gva);

	for (stage = 1;; stage++) {
		vcpu_run(vcpu);
		TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
			    "Stage %d: unexpected exit reason: %u (%s),\n",
			    stage, run->exit_reason,
			    exit_reason_str(run->exit_reason));

		memset(&regs, 0, sizeof(regs));
		vcpu_regs_get(vcpu, &regs);

		stage_reported = regs.rax & 0xff;

		if (stage_reported == DONE)
			goto done;

		TEST_ASSERT(stage_reported == stage ||
			    stage_reported == SMRAM_STAGE,
			    "Unexpected stage: #%x, got %x",
			    stage, stage_reported);

		/*
		 * Enter SMM during L2 execution and check that we correctly
		 * return from it. Do not perform save/restore while in SMM yet.
		 */
		if (stage == 8) {
			inject_smi(vcpu);
			continue;
		}

		/*
		 * Perform save/restore while the guest is in SMM triggered
		 * during L2 execution.
		 */
		if (stage == 10)
			inject_smi(vcpu);

		state = vcpu_save_state(vcpu);
		kvm_vm_release(vm);

		vcpu = vm_recreate_with_one_vcpu(vm);
		vcpu_load_state(vcpu, state);
		run = vcpu->run;
		kvm_x86_state_cleanup(state);
	}

done:
	kvm_vm_free(vm);
}
