/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Perform Frame Management Function (pfmf) tests
 *
 * Copyright (c) 2018 IBM
 *
 * Authors:
 *  Janosch Frank <frankja@linux.vnet.ibm.com>
 */
#include <libcflat.h>
#include <asm/asm-offsets.h>
#include <asm/interrupt.h>
#include <asm/page.h>
#include <asm/facility.h>
#include <asm/mem.h>

static uint8_t pagebuf[PAGE_SIZE * 256] __attribute__((aligned(PAGE_SIZE * 256)));

static void test_priv(void)
{
	report_prefix_push("privileged");
	expect_pgm_int();
	enter_pstate();
	pfmf(0, pagebuf);
	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
	report_prefix_pop();
}

static void test_4k_key(void)
{
	union pfmf_r1 r1 = {
		.reg.sk = 1,
		.reg.fsc = PFMF_FSC_4K,
		.reg.key = 0x30,
	};
	union skey skey;

	report_prefix_push("4K");
	if (test_facility(169)) {
		report_skip("storage key removal facility is active");
		goto out;
	}
	pfmf(r1.val, pagebuf);
	skey.val = get_storage_key(pagebuf);
	skey.val &= SKEY_ACC | SKEY_FP;
	report(skey.val == 0x30, "set storage keys");
out:
	report_prefix_pop();
}

static void test_1m_key(void)
{
	int i;
	bool rp = true;
	union skey skey;
	union pfmf_r1 r1 = {
		.reg.fsc = PFMF_FSC_1M,
		.reg.key = 0x30,
		.reg.sk = 1,
	};

	report_prefix_push("1M");
	if (test_facility(169)) {
		report_skip("storage key removal facility is active");
		goto out;
	}

	pfmf(r1.val, pagebuf);
	for (i = 0; i < 256; i++) {
		skey.val = get_storage_key(pagebuf + i * PAGE_SIZE);
		skey.val &= SKEY_ACC | SKEY_FP;
		if (skey.val != 0x30) {
			rp = false;
			break;
		}
	}
	report(rp, "set storage keys");
out:
	report_prefix_pop();
}

static void test_4k_clear(void)
{
	union pfmf_r1 r1 = {
		.reg.cf = 1,
		.reg.fsc = PFMF_FSC_4K,
	};

	report_prefix_push("4K");
	memset(pagebuf, 42, PAGE_SIZE);
	pfmf(r1.val, pagebuf);
	report(!memcmp(pagebuf, pagebuf + PAGE_SIZE, PAGE_SIZE),
	       "clear memory");
	report_prefix_pop();
}

static void test_1m_clear(void)
{
	int i;
	union pfmf_r1 r1 = {
		.reg.cf = 1,
		.reg.fsc = PFMF_FSC_1M,
	};
	unsigned long sum = 0;

	report_prefix_push("1M");
	memset(pagebuf, 42, PAGE_SIZE * 256);
	pfmf(r1.val, pagebuf);
	for (i = 0; i < PAGE_SIZE * 256; i++)
		sum |= pagebuf[i];
	report(!sum, "clear memory");
	report_prefix_pop();
}

static void test_low_addr_prot(void)
{
	union pfmf_r1 r1 = {
		.reg.cf = 1,
		.reg.fsc = PFMF_FSC_4K
	};

	report_prefix_push("low-address protection");

	report_prefix_push("0x1000");
	expect_pgm_int();
	low_prot_enable();
	pfmf(r1.val, (void *)0x1000);
	low_prot_disable();
	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
	report_prefix_pop();

	report_prefix_push("0x0");
	expect_pgm_int();
	low_prot_enable();
	pfmf(r1.val, 0);
	low_prot_disable();
	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
	report_prefix_pop();

	report_prefix_pop();
}

int main(void)
{
	bool has_edat = test_facility(8);

	report_prefix_push("pfmf");
	if (!has_edat) {
		report_skip("PFMF is not available");
		goto done;
	}

	test_priv();
	test_low_addr_prot();
	/* Force the buffer pages in */
	memset(pagebuf, 0, PAGE_SIZE * 256);

	test_4k_key();
	test_4k_clear();
	test_1m_key();
	test_1m_clear();

done:
	report_prefix_pop();
	return report_summary();
}
