/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Guest Ultravisor Call tests
 *
 * Copyright IBM Corp. 2020, 2022
 *
 * Authors:
 *  Janosch Frank <frankja@linux.ibm.com>
 */

#include <libcflat.h>
#include <alloc_page.h>
#include <asm/page.h>
#include <asm/asm-offsets.h>
#include <asm/interrupt.h>
#include <asm/facility.h>
#include <asm/uv.h>
#include <sclp.h>
#include <uv.h>

static unsigned long page;

static void test_priv(void)
{
	struct uv_cb_header uvcb = {};

	report_prefix_push("privileged");

	report_prefix_push("query");
	uvcb.cmd = UVC_CMD_QUI;
	uvcb.len = sizeof(struct uv_cb_qui);
	expect_pgm_int();
	enter_pstate();
	uv_call_once(0, (u64)&uvcb);
	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
	report_prefix_pop();

	report_prefix_push("share");
	uvcb.cmd = UVC_CMD_SET_SHARED_ACCESS;
	uvcb.len = sizeof(struct uv_cb_share);
	expect_pgm_int();
	enter_pstate();
	uv_call_once(0, (u64)&uvcb);
	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
	report_prefix_pop();

	report_prefix_push("unshare");
	uvcb.cmd = UVC_CMD_REMOVE_SHARED_ACCESS;
	uvcb.len = sizeof(struct uv_cb_share);
	expect_pgm_int();
	enter_pstate();
	uv_call_once(0, (u64)&uvcb);
	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
	report_prefix_pop();

	report_prefix_push("attest");
	uvcb.cmd = UVC_CMD_ATTESTATION;
	uvcb.len = sizeof(struct uv_cb_attest);
	expect_pgm_int();
	enter_pstate();
	uv_call_once(0, (uint64_t)&uvcb);
	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
	report_prefix_pop();

	report_prefix_pop();
}

static void test_query(void)
{
	struct uv_cb_qui uvcb = {
		.header.cmd = UVC_CMD_QUI,
		/* A dword below the minimum length */
		.header.len = 0xa0,
	};
	int cc;

	report_prefix_push("query");
	cc = uv_call(0, (u64)&uvcb);
	report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length");

	/*
	 * BIT_UVC_CMD_QUI, BIT_UVC_CMD_SET_SHARED_ACCESS and
	 * BIT_UVC_CMD_REMOVE_SHARED_ACCESS are always present as they
	 * have been introduced with the first Ultravisor version.
	 * However, we only need to check for QUI as
	 * SET/REMOVE SHARED are used to fence this test to be only
	 * executed by protected guests.
	 */
	report(uv_query_test_call(BIT_UVC_CMD_QUI), "query indicated");
	report_prefix_pop();
}

static void test_sharing(void)
{
	struct uv_cb_share uvcb = {
		.header.cmd = UVC_CMD_SET_SHARED_ACCESS,
		.header.len = sizeof(uvcb) - 8,
		.paddr = page,
	};
	int cc;

	report_prefix_push("share");
	cc = uv_call(0, (u64)&uvcb);
	report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length");
	uvcb.header.len = sizeof(uvcb);
	cc = uv_call(0, (u64)&uvcb);
	report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "share");
	uvcb.paddr = get_ram_size() + PAGE_SIZE;
	cc = uv_call(0, (u64)&uvcb);
	report(cc == 1 && uvcb.header.rc == 0x101, "invalid memory");
	uvcb.paddr = page;
	report_prefix_pop();

	report_prefix_push("unshare");
	uvcb.header.cmd = UVC_CMD_REMOVE_SHARED_ACCESS;
	uvcb.header.len -= 8;
	cc = uv_call(0, (u64)&uvcb);
	report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length");
	uvcb.header.len = sizeof(uvcb);
	cc = uv_call(0, (u64)&uvcb);
	report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "unshare");
	report_prefix_pop();
}

static struct {
	const char *name;
	uint16_t cmd;
	uint16_t len;
	int call_bit;
} invalid_cmds[] = {
	{ "bogus", 0x4242, sizeof(struct uv_cb_header), -1 },
	{ "init", UVC_CMD_INIT_UV, sizeof(struct uv_cb_init), BIT_UVC_CMD_INIT_UV },
	{ "create conf", UVC_CMD_CREATE_SEC_CONF, sizeof(struct uv_cb_cgc), BIT_UVC_CMD_CREATE_SEC_CONF },
	{ "destroy conf", UVC_CMD_DESTROY_SEC_CONF, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CONF },
	{ "create cpu", UVC_CMD_CREATE_SEC_CPU, sizeof(struct uv_cb_csc), BIT_UVC_CMD_CREATE_SEC_CPU },
	{ "destroy cpu", UVC_CMD_DESTROY_SEC_CPU, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CPU },
	{ "conv to", UVC_CMD_CONV_TO_SEC_STOR, sizeof(struct uv_cb_cts), BIT_UVC_CMD_CONV_TO_SEC_STOR },
	{ "conv from", UVC_CMD_CONV_FROM_SEC_STOR, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_CONV_FROM_SEC_STOR },
	{ "set sec conf", UVC_CMD_SET_SEC_CONF_PARAMS, sizeof(struct uv_cb_ssc), BIT_UVC_CMD_SET_SEC_PARMS },
	{ "unpack", UVC_CMD_UNPACK_IMG, sizeof(struct uv_cb_unp), BIT_UVC_CMD_UNPACK_IMG },
	{ "verify", UVC_CMD_VERIFY_IMG, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_VERIFY_IMG },
	{ "cpu reset", UVC_CMD_CPU_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET },
	{ "cpu initial reset", UVC_CMD_CPU_RESET_INITIAL, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET_INITIAL },
	{ "prepare clear reset", UVC_CMD_PREPARE_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_PREPARE_RESET },
	{ "cpu clear reset", UVC_CMD_CPU_RESET_CLEAR, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET },
	{ "cpu set state", UVC_CMD_CPU_SET_STATE, sizeof(struct uv_cb_cpu_set_state), BIT_UVC_CMD_CPU_SET_STATE },
	{ "pin shared", UVC_CMD_PIN_PAGE_SHARED, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_PIN_PAGE_SHARED },
	{ "unpin shared", UVC_CMD_UNPIN_PAGE_SHARED, sizeof(struct uv_cb_cts), BIT_UVC_CMD_UNPIN_PAGE_SHARED },
	{ NULL, 0, 0 },
};

static void test_invalid(void)
{
	struct uv_cb_header *hdr = (void *)page;
	int cc, i;

	report_prefix_push("invalid");
	for (i = 0; invalid_cmds[i].name; i++) {
		hdr->cmd = invalid_cmds[i].cmd;
		hdr->len = invalid_cmds[i].len;
		cc = uv_call(0, (u64)hdr);
		report(cc == 1 && hdr->rc == UVC_RC_INV_CMD &&
		       (invalid_cmds[i].call_bit == -1 || !uv_query_test_call(invalid_cmds[i].call_bit)),
		       "%s", invalid_cmds[i].name);
	}
	report_prefix_pop();
}

static void test_share_bits(void)
{
	bool unshare = uv_query_test_call(BIT_UVC_CMD_REMOVE_SHARED_ACCESS);
	bool share = uv_query_test_call(BIT_UVC_CMD_SET_SHARED_ACCESS);

	report_prefix_push("query");
	report(!(share ^ unshare), "share bits are identical");
	report_prefix_pop();
}

int main(void)
{
	bool has_uvc = test_facility(158);

	report_prefix_push("uvc");
	if (!has_uvc) {
		report_skip("Ultravisor call facility is not available");
		goto done;
	}

	/*
	 * Needs to be done before the guest-fence,
	 * as the fence tests if both shared bits are present
	 */
	test_share_bits();

	if (!uv_os_is_guest()) {
		report_skip("Not a protected guest");
		goto done;
	}

	page = (unsigned long)alloc_page();
	test_priv();
	test_invalid();
	test_query();
	test_sharing();
	free_page((void *)page);
done:
	report_prefix_pop();
	return report_summary();
}
