/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Ultravisor related functionality
 *
 * Copyright 2020 IBM Corp.
 *
 * Authors:
 *    Janosch Frank <frankja@linux.ibm.com>
 */
#include <libcflat.h>
#include <bitops.h>
#include <alloc.h>
#include <alloc_page.h>
#include <asm/page.h>
#include <asm/arch_def.h>

#include <asm/facility.h>
#include <asm/uv.h>
#include <uv.h>
#include <sie.h>
#include <snippet.h>

static struct uv_cb_qui uvcb_qui = {
	.header.cmd = UVC_CMD_QUI,
	.header.len = sizeof(uvcb_qui),
};
static uint64_t uv_init_mem;


bool uv_os_is_guest(void)
{
	return test_facility(158) &&
		uv_query_test_call(BIT_UVC_CMD_SET_SHARED_ACCESS) &&
		uv_query_test_call(BIT_UVC_CMD_REMOVE_SHARED_ACCESS);
}

bool uv_os_is_host(void)
{
	return test_facility(158) && uv_query_test_call(BIT_UVC_CMD_INIT_UV);
}

bool uv_host_requirement_checks(void)
{
	if (!test_facility(158)) {
		report_skip("UV Call facility unavailable");
		return false;
	}
	if (!sclp_facilities.has_sief2) {
		report_skip("SIEF2 facility unavailable");
		return false;
	}
	if (get_ram_size() < SNIPPET_PV_MIN_MEM_SIZE) {
		report_skip("Not enough memory. This test needs about %ld MB of memory",
			    SNIPPET_PV_MIN_MEM_SIZE / SZ_1M);
		return false;
	}

	return true;
}

bool uv_query_test_call(unsigned int nr)
{
	/* Query needs to be called first */
	assert(uvcb_qui.header.rc);
	assert(nr < BITS_PER_LONG * ARRAY_SIZE(uvcb_qui.inst_calls_list));

	return test_bit_inv(nr, uvcb_qui.inst_calls_list);
}

const struct uv_cb_qui *uv_get_query_data(void)
{
	/* Query needs to be called first */
	assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100);

	return &uvcb_qui;
}

int uv_setup(void)
{
	if (!test_facility(158))
		return 0;

	uv_call(0, (u64)&uvcb_qui);

	assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100);
	return 1;
}

void uv_init(void)
{
	struct uv_cb_init uvcb_init = {
		.header.len = sizeof(uvcb_init),
		.header.cmd = UVC_CMD_INIT_UV,
	};
	static bool initialized;
	int cc;

	/* Let's not do this twice */
	if (initialized)
		return;
	/* Query is done on initialization but let's check anyway */
	assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100);

	/* Donated storage needs to be over 2GB aligned to 1MB */
	uv_init_mem = (uint64_t)memalign_pages_flags(HPAGE_SIZE, uvcb_qui.uv_base_stor_len, AREA_NORMAL);
	uvcb_init.stor_origin = uv_init_mem;
	uvcb_init.stor_len = uvcb_qui.uv_base_stor_len;

	cc = uv_call(0, (uint64_t)&uvcb_init);
	assert(cc == 0);
	initialized = true;
}

/*
 * Create a new ASCE for the UV config because they can't be shared
 * for security reasons. We just simply copy the top most table into a
 * fresh set of allocated pages and use those pages as the asce.
 */
static uint64_t create_asce(void)
{
	void *pgd_new, *pgd_old;
	uint64_t asce = stctg(1);

	pgd_new = memalign_pages(PAGE_SIZE, PAGE_SIZE * 4);
	pgd_old = (void *)(asce & PAGE_MASK);

	memcpy(pgd_new, pgd_old, PAGE_SIZE * 4);

	asce = __pa(pgd_new) | ASCE_P | (asce & (ASCE_DT | ASCE_TL));
	return asce;
}

void uv_create_guest(struct vm *vm)
{
	struct uv_cb_cgc uvcb_cgc = {
		.header.cmd = UVC_CMD_CREATE_SEC_CONF,
		.header.len = sizeof(uvcb_cgc),
	};
	struct uv_cb_csc uvcb_csc = {
		.header.len = sizeof(uvcb_csc),
		.header.cmd = UVC_CMD_CREATE_SEC_CPU,
		.state_origin = (uint64_t)vm->sblk,
		.num = 0,
	};
	unsigned long vsize;
	int cc;

	uvcb_cgc.guest_stor_origin = vm->sblk->mso;
	uvcb_cgc.guest_stor_len = vm->sblk->msl - vm->sblk->mso + SZ_1M;

	/* Config allocation */
	vsize = uvcb_qui.conf_base_virt_stor_len +
		((uvcb_cgc.guest_stor_len / HPAGE_SIZE) * uvcb_qui.conf_virt_var_stor_len);

	vm->uv.conf_base_stor = memalign_pages_flags(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len, 0);
	/*
	 * This allocation needs to be below the max guest storage
	 * address so let's simply put it into the physical memory
	 */
	vm->uv.conf_var_stor = memalign_pages_flags(PAGE_SIZE, vsize,0);
	uvcb_cgc.conf_base_stor_origin = (uint64_t)vm->uv.conf_base_stor;
	uvcb_cgc.conf_var_stor_origin = (uint64_t)vm->uv.conf_var_stor;

	/* CPU allocation */
	vm->uv.cpu_stor = memalign_pages_flags(PAGE_SIZE, uvcb_qui.cpu_stor_len, 0);
	uvcb_csc.stor_origin = (uint64_t)vm->uv.cpu_stor;

	uvcb_cgc.guest_asce = create_asce();
	vm->save_area.guest.asce = uvcb_cgc.guest_asce;
	uvcb_cgc.guest_sca = (uint64_t)vm->sca;

	cc = uv_call(0, (uint64_t)&uvcb_cgc);
	assert(!cc);

	vm->uv.vm_handle = uvcb_cgc.guest_handle;
	uvcb_csc.guest_handle = uvcb_cgc.guest_handle;
	cc = uv_call(0, (uint64_t)&uvcb_csc);
	vm->uv.vcpu_handle = uvcb_csc.cpu_handle;
	assert(!cc);

	/*
	 * Convert guest to format 4:
	 *
	 *  - Set format 4
	 *  - Write UV handles into sblk
	 *  - Allocate and set SIDA
	 */
	vm->sblk->sdf = 2;
	vm->sblk->sidad = (uint64_t)alloc_page();
	vm->sblk->pv_handle_cpu = uvcb_csc.cpu_handle;
	vm->sblk->pv_handle_config = uvcb_cgc.guest_handle;
}

void uv_destroy_guest(struct vm *vm)
{
	int cc;
	u16 rc, rrc;

	cc = uv_cmd_nodata(vm->sblk->pv_handle_cpu,
			   UVC_CMD_DESTROY_SEC_CPU, &rc, &rrc);
	assert(cc == 0);
	free_page((void *)vm->sblk->sidad);
	free_pages(vm->uv.cpu_stor);

	cc = uv_cmd_nodata(vm->sblk->pv_handle_config,
			   UVC_CMD_DESTROY_SEC_CONF, &rc, &rrc);
	assert(cc == 0);
	free_pages(vm->uv.conf_base_stor);
	free_pages(vm->uv.conf_var_stor);

	free_pages((void *)(vm->uv.asce & PAGE_MASK));
	memset(&vm->uv, 0, sizeof(vm->uv));

	/* Convert the sblk back to non-PV */
	vm->save_area.guest.asce = stctg(1);
	vm->sblk->sdf = 0;
	vm->sblk->sidad = 0;
	vm->sblk->pv_handle_cpu = 0;
	vm->sblk->pv_handle_config = 0;
}

int uv_unpack(struct vm *vm, uint64_t addr, uint64_t len, uint64_t tweak)
{
	int i, cc;

	for (i = 0; i < len / PAGE_SIZE; i++) {
		cc = uv_unp_page(vm->uv.vm_handle, addr, tweak, i * PAGE_SIZE);
		assert(!cc);
		addr += PAGE_SIZE;
	}
	return cc;
}

void uv_verify_load(struct vm *vm)
{
	uint16_t rc, rrc;
	int cc;

	cc = uv_cmd_nodata(vm->uv.vm_handle, UVC_CMD_VERIFY_IMG, &rc, &rrc);
	assert(!cc);
	cc = uv_set_cpu_state(vm->uv.vcpu_handle, PV_CPU_STATE_OPR_LOAD);
	assert(!cc);
}
