// SPDX-License-Identifier: GPL-2.0-only
/*
 * smccc_filter - Tests for the SMCCC filter UAPI.
 *
 * Copyright (c) 2023 Google LLC
 *
 * This test includes:
 *  - Tests that the UAPI constraints are upheld by KVM. For example, userspace
 *    is prevented from filtering the architecture range of SMCCC calls.
 *  - Test that the filter actions (DENIED, FWD_TO_USER) work as intended.
 */

#include <linux/arm-smccc.h>
#include <linux/psci.h>
#include <stdint.h>

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

enum smccc_conduit {
	HVC_INSN,
	SMC_INSN,
};

#define for_each_conduit(conduit)					\
	for (conduit = HVC_INSN; conduit <= SMC_INSN; conduit++)

static void guest_main(uint32_t func_id, enum smccc_conduit conduit)
{
	struct arm_smccc_res res;

	if (conduit == SMC_INSN)
		smccc_smc(func_id, 0, 0, 0, 0, 0, 0, 0, &res);
	else
		smccc_hvc(func_id, 0, 0, 0, 0, 0, 0, 0, &res);

	GUEST_SYNC(res.a0);
}

static int __set_smccc_filter(struct kvm_vm *vm, uint32_t start, uint32_t nr_functions,
			      enum kvm_smccc_filter_action action)
{
	struct kvm_smccc_filter filter = {
		.base		= start,
		.nr_functions	= nr_functions,
		.action		= action,
	};

	return __kvm_device_attr_set(vm->fd, KVM_ARM_VM_SMCCC_CTRL,
				     KVM_ARM_VM_SMCCC_FILTER, &filter);
}

static void set_smccc_filter(struct kvm_vm *vm, uint32_t start, uint32_t nr_functions,
			     enum kvm_smccc_filter_action action)
{
	int ret = __set_smccc_filter(vm, start, nr_functions, action);

	TEST_ASSERT(!ret, "failed to configure SMCCC filter: %d", ret);
}

static struct kvm_vm *setup_vm(struct kvm_vcpu **vcpu)
{
	struct kvm_vcpu_init init;
	struct kvm_vm *vm;

	vm = vm_create(1);
	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);

	/*
	 * Enable in-kernel emulation of PSCI to ensure that calls are denied
	 * due to the SMCCC filter, not because of KVM.
	 */
	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);

	*vcpu = aarch64_vcpu_add(vm, 0, &init, guest_main);
	return vm;
}

static void test_pad_must_be_zero(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm = setup_vm(&vcpu);
	struct kvm_smccc_filter filter = {
		.base		= PSCI_0_2_FN_PSCI_VERSION,
		.nr_functions	= 1,
		.action		= KVM_SMCCC_FILTER_DENY,
		.pad		= { -1 },
	};
	int r;

	r = __kvm_device_attr_set(vm->fd, KVM_ARM_VM_SMCCC_CTRL,
				  KVM_ARM_VM_SMCCC_FILTER, &filter);
	TEST_ASSERT(r < 0 && errno == EINVAL,
		    "Setting filter with nonzero padding should return EINVAL");
}

/* Ensure that userspace cannot filter the Arm Architecture SMCCC range */
static void test_filter_reserved_range(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm = setup_vm(&vcpu);
	uint32_t smc64_fn;
	int r;

	r = __set_smccc_filter(vm, ARM_SMCCC_ARCH_WORKAROUND_1,
			       1, KVM_SMCCC_FILTER_DENY);
	TEST_ASSERT(r < 0 && errno == EEXIST,
		    "Attempt to filter reserved range should return EEXIST");

	smc64_fn = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
				      0, 0);

	r = __set_smccc_filter(vm, smc64_fn, 1, KVM_SMCCC_FILTER_DENY);
	TEST_ASSERT(r < 0 && errno == EEXIST,
		    "Attempt to filter reserved range should return EEXIST");

	kvm_vm_free(vm);
}

static void test_invalid_nr_functions(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm = setup_vm(&vcpu);
	int r;

	r = __set_smccc_filter(vm, PSCI_0_2_FN64_CPU_ON, 0, KVM_SMCCC_FILTER_DENY);
	TEST_ASSERT(r < 0 && errno == EINVAL,
		    "Attempt to filter 0 functions should return EINVAL");

	kvm_vm_free(vm);
}

static void test_overflow_nr_functions(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm = setup_vm(&vcpu);
	int r;

	r = __set_smccc_filter(vm, ~0, ~0, KVM_SMCCC_FILTER_DENY);
	TEST_ASSERT(r < 0 && errno == EINVAL,
		    "Attempt to overflow filter range should return EINVAL");

	kvm_vm_free(vm);
}

static void test_reserved_action(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm = setup_vm(&vcpu);
	int r;

	r = __set_smccc_filter(vm, PSCI_0_2_FN64_CPU_ON, 1, -1);
	TEST_ASSERT(r < 0 && errno == EINVAL,
		    "Attempt to use reserved filter action should return EINVAL");

	kvm_vm_free(vm);
}


/* Test that overlapping configurations of the SMCCC filter are rejected */
static void test_filter_overlap(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm = setup_vm(&vcpu);
	int r;

	set_smccc_filter(vm, PSCI_0_2_FN64_CPU_ON, 1, KVM_SMCCC_FILTER_DENY);

	r = __set_smccc_filter(vm, PSCI_0_2_FN64_CPU_ON, 1, KVM_SMCCC_FILTER_DENY);
	TEST_ASSERT(r < 0 && errno == EEXIST,
		    "Attempt to filter already configured range should return EEXIST");

	kvm_vm_free(vm);
}

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

	if (get_ucall(vcpu, &uc) != UCALL_SYNC)
		TEST_FAIL("Unexpected ucall: %lu\n", uc.cmd);

	TEST_ASSERT(uc.args[1] == SMCCC_RET_NOT_SUPPORTED,
		    "Unexpected SMCCC return code: %lu", uc.args[1]);
}

/* Denied SMCCC calls have a return code of SMCCC_RET_NOT_SUPPORTED */
static void test_filter_denied(void)
{
	enum smccc_conduit conduit;
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;

	for_each_conduit(conduit) {
		vm = setup_vm(&vcpu);

		set_smccc_filter(vm, PSCI_0_2_FN_PSCI_VERSION, 1, KVM_SMCCC_FILTER_DENY);
		vcpu_args_set(vcpu, 2, PSCI_0_2_FN_PSCI_VERSION, conduit);

		vcpu_run(vcpu);
		expect_call_denied(vcpu);

		kvm_vm_free(vm);
	}
}

static void expect_call_fwd_to_user(struct kvm_vcpu *vcpu, uint32_t func_id,
				    enum smccc_conduit conduit)
{
	struct kvm_run *run = vcpu->run;

	TEST_ASSERT(run->exit_reason == KVM_EXIT_HYPERCALL,
		    "Unexpected exit reason: %u", run->exit_reason);
	TEST_ASSERT(run->hypercall.nr == func_id,
		    "Unexpected SMCCC function: %llu", run->hypercall.nr);

	if (conduit == SMC_INSN)
		TEST_ASSERT(run->hypercall.flags & KVM_HYPERCALL_EXIT_SMC,
			    "KVM_HYPERCALL_EXIT_SMC is not set");
	else
		TEST_ASSERT(!(run->hypercall.flags & KVM_HYPERCALL_EXIT_SMC),
			    "KVM_HYPERCALL_EXIT_SMC is set");
}

/* SMCCC calls forwarded to userspace cause KVM_EXIT_HYPERCALL exits */
static void test_filter_fwd_to_user(void)
{
	enum smccc_conduit conduit;
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;

	for_each_conduit(conduit) {
		vm = setup_vm(&vcpu);

		set_smccc_filter(vm, PSCI_0_2_FN_PSCI_VERSION, 1, KVM_SMCCC_FILTER_FWD_TO_USER);
		vcpu_args_set(vcpu, 2, PSCI_0_2_FN_PSCI_VERSION, conduit);

		vcpu_run(vcpu);
		expect_call_fwd_to_user(vcpu, PSCI_0_2_FN_PSCI_VERSION, conduit);

		kvm_vm_free(vm);
	}
}

static bool kvm_supports_smccc_filter(void)
{
	struct kvm_vm *vm = vm_create_barebones();
	int r;

	r = __kvm_has_device_attr(vm->fd, KVM_ARM_VM_SMCCC_CTRL, KVM_ARM_VM_SMCCC_FILTER);

	kvm_vm_free(vm);
	return !r;
}

int main(void)
{
	TEST_REQUIRE(kvm_supports_smccc_filter());

	test_pad_must_be_zero();
	test_invalid_nr_functions();
	test_overflow_nr_functions();
	test_reserved_action();
	test_filter_reserved_range();
	test_filter_overlap();
	test_filter_denied();
	test_filter_fwd_to_user();
}
