/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Move Page instruction tests
 *
 * Copyright (c) 2021 IBM Corp
 *
 * Authors:
 *  Claudio Imbrenda <imbrenda@linux.ibm.com>
 */
#include <libcflat.h>
#include <asm/asm-offsets.h>
#include <asm/interrupt.h>
#include <asm/pgtable.h>
#include <mmu.h>
#include <asm/page.h>
#include <asm/facility.h>
#include <asm/mem.h>
#include <alloc_page.h>
#include <bitops.h>
#include <hardware.h>

/* Used to build the appropriate test values for register 0 */
#define KFC(x) ((x) << 10)
#define CCO 0x100

/* How much memory to allocate for the test */
#define MEM_ORDER 12
/* How many iterations to perform in the loops */
#define ITER 8

/* Used to generate the simple pattern */
#define MAGIC 42

static uint8_t source[PAGE_SIZE]  __attribute__((aligned(PAGE_SIZE)));
static uint8_t buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));

/* Keep track of fresh memory */
static uint8_t *fresh;

static inline int mvpg(unsigned long r0, void *dest, void *src)
{
	register unsigned long reg0 asm ("0") = r0;
	uint64_t bogus_cc = 3;
	int cc;

	asm volatile("	tmll	%[bogus_cc],3\n"
		     "	mvpg    %1,%2\n"
		     "	ipm     %0\n"
		     "	srl     %0,28"
		: "=&d" (cc) : "a" (dest), "a" (src), "d" (reg0), [bogus_cc] "d" (bogus_cc)
		: "memory", "cc");
	return cc;
}

/*
 * Initialize a page with a simple pattern
 */
static void init_page(uint8_t *p)
{
	int i;

	for (i = 0; i < PAGE_SIZE; i++)
		p[i] = i + MAGIC;
}

/*
 * Check if the given page contains the simple pattern
 */
static int page_ok(const uint8_t *p)
{
	int i;

	for (i = 0; i < PAGE_SIZE; i++)
		if (p[i] != (uint8_t)(i + MAGIC))
			return 0;
	return 1;
}

/*
 * Check that the Operand Access Identification matches with the values of
 * the r1 and r2 fields in the instruction format. The r1 and r2 fields are
 * in the last byte of the instruction, and the Program Old PSW will point
 * to the beginning of the instruction after the one that caused the fault
 * (the fixup code in the interrupt handler takes care of that for
 * nullifying instructions). Therefore it is enough to compare the byte
 * before the one contained in the Program Old PSW with the value of the
 * Operand Access Identification.
 */
static inline bool check_oai(void)
{
	return *(uint8_t *)(lowcore.pgm_old_psw.addr - 1) == lowcore.op_acc_id;
}

static void test_exceptions(void)
{
	int i, expected;

	report_prefix_push("exceptions");

	/*
	 * Key Function Control values 4 and 5 are allowed only in supervisor
	 * state, and even then, only if the move-page-and-set-key facility
	 * is present (STFLE bit 149)
	 */
	report_prefix_push("privileged");
	if (test_facility(149)) {
		expected = PGM_INT_CODE_PRIVILEGED_OPERATION;
		for (i = 4; i < 6; i++) {
			expect_pgm_int();
			enter_pstate();
			mvpg(KFC(i), buffer, source);
			report(clear_pgm_int() == expected, "Key Function Control value %d", i);
		}
	} else {
		report_skip("Key Function Control value %d", 4);
		report_skip("Key Function Control value %d", 5);
		i = 4;
	}
	report_prefix_pop();

	/*
	 * Invalid values of the Key Function Control, or setting the
	 * reserved bits, should result in a specification exception
	 */
	report_prefix_push("specification");
	expected = PGM_INT_CODE_SPECIFICATION;
	expect_pgm_int();
	mvpg(KFC(3), buffer, source);
	report(clear_pgm_int() == expected, "Key Function Control value 3");
	for (; i < 32; i++) {
		expect_pgm_int();
		mvpg(KFC(i), buffer, source);
		report(clear_pgm_int() == expected, "Key Function Control value %d", i);
	}
	report_prefix_pop();

	/* Operands outside memory result in addressing exceptions, as usual */
	report_prefix_push("addressing");
	expected = PGM_INT_CODE_ADDRESSING;
	expect_pgm_int();
	mvpg(0, buffer, (void *)PAGE_MASK);
	report(clear_pgm_int() == expected, "Second operand outside memory");

	expect_pgm_int();
	mvpg(0, (void *)PAGE_MASK, source);
	report(clear_pgm_int() == expected, "First operand outside memory");
	report_prefix_pop();

	report_prefix_pop();
}

static void test_success(void)
{
	int cc;

	report_prefix_push("success");
	/* Test successful scenarios, both in supervisor and problem state */
	cc = mvpg(0, buffer, source);
	report(page_ok(buffer) && !cc, "Supervisor state MVPG successful");
	memset(buffer, 0xff, PAGE_SIZE);

	enter_pstate();
	cc = mvpg(0, buffer, source);
	leave_pstate();
	report(page_ok(buffer) && !cc, "Problem state MVPG successful");

	report_prefix_pop();
}

static void test_small_loop(const void *string)
{
	uint8_t *dest;
	int i, cc;

	/* Looping over cold and warm pages helps catch VSIE bugs */
	report_prefix_push(string);
	dest = fresh;
	for (i = 0; i < ITER; i++) {
		cc = mvpg(0, fresh, source);
		report(page_ok(fresh) && !cc, "cold: %p, %p", source, fresh);
		fresh += PAGE_SIZE;
	}

	for (i = 0; i < ITER; i++) {
		memset(dest, 0, PAGE_SIZE);
		cc = mvpg(0, dest, source);
		report(page_ok(dest) && !cc, "warm: %p, %p", source, dest);
		dest += PAGE_SIZE;
	}
	report_prefix_pop();
}

static void test_mmu_prot(void)
{
	int cc;

	report_prefix_push("protection");
	report_prefix_push("cco=0");

	/* MVPG should still succeed when the source is read-only */
	protect_page(source, PAGE_ENTRY_P);
	cc = mvpg(0, fresh, source);
	report(page_ok(fresh) && !cc, "source read only");
	unprotect_page(source, PAGE_ENTRY_P);
	fresh += PAGE_SIZE;

	/*
	 * When the source or destination are invalid, a page translation
	 * exception should be raised; when the destination is read-only,
	 * a protection exception should be raised.
	 */
	protect_page(fresh, PAGE_ENTRY_P);
	expect_pgm_int();
	mvpg(0, fresh, source);
	report(clear_pgm_int() == PGM_INT_CODE_PROTECTION, "destination read only");
	fresh += PAGE_SIZE;

	report_prefix_push("source invalid");
	protect_page(source, PAGE_ENTRY_I);
	lowcore.op_acc_id = 0;
	expect_pgm_int();
	mvpg(0, fresh, source);
	report(clear_pgm_int() == PGM_INT_CODE_PAGE_TRANSLATION, "exception");
	unprotect_page(source, PAGE_ENTRY_I);
	report(check_oai(), "operand access ident");
	report_prefix_pop();
	fresh += PAGE_SIZE;

	report_prefix_push("destination invalid");
	protect_page(fresh, PAGE_ENTRY_I);
	lowcore.op_acc_id = 0;
	expect_pgm_int();
	mvpg(0, fresh, source);
	report(clear_pgm_int() == PGM_INT_CODE_PAGE_TRANSLATION, "exception");
	report(check_oai(), "operand access ident");
	report_prefix_pop();
	fresh += PAGE_SIZE;

	report_prefix_pop();
	report_prefix_push("cco=1");
	/*
	 * Setting the CCO bit should suppress page translation exceptions,
	 * but not protection exceptions.
	 */
	protect_page(fresh, PAGE_ENTRY_P);
	expect_pgm_int();
	mvpg(CCO, fresh, source);
	report(clear_pgm_int() == PGM_INT_CODE_PROTECTION, "destination read only");
	fresh += PAGE_SIZE;

	/* Known issue in TCG: CCO flag is not honoured */
	if (host_is_tcg()) {
		report_prefix_push("TCG");
		report_skip("destination invalid");
		report_skip("source invalid");
		report_skip("source and destination invalid");
		report_prefix_pop();
	} else {
		protect_page(fresh, PAGE_ENTRY_I);
		cc = mvpg(CCO, fresh, source);
		report(cc == 1, "destination invalid");
		fresh += PAGE_SIZE;

		protect_page(source, PAGE_ENTRY_I);
		cc = mvpg(CCO, fresh, source);
		report(cc == 2, "source invalid");
		fresh += PAGE_SIZE;

		protect_page(fresh, PAGE_ENTRY_I);
		cc = mvpg(CCO, fresh, source);
		report(cc == 2, "source and destination invalid");
		fresh += PAGE_SIZE;
	}

	unprotect_page(source, PAGE_ENTRY_I);
	report_prefix_pop();
	report_prefix_pop();
}

int main(void)
{
	report_prefix_push("mvpg");

	init_page(source);
	fresh = alloc_pages_flags(MEM_ORDER, FLAG_DONTZERO | FLAG_FRESH);
	assert(fresh);

	test_exceptions();
	test_success();
	test_small_loop("nommu");

	setup_vm();

	test_small_loop("mmu");
	test_mmu_prot();

	report_prefix_pop();
	return report_summary();
}
