/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Emulator tests - for s390x CPU instructions that are usually interpreted
 *                  by the hardware
 *
 * Copyright (c) 2017 Red Hat Inc
 *
 * Authors:
 *  David Hildenbrand <david@redhat.com>
 */
#include <libcflat.h>
#include <asm/cpacf.h>
#include <asm/interrupt.h>
#include <asm/float.h>
#include <asm/mem.h>
#include <linux/compiler.h>

static inline void __test_spm_ipm(uint8_t cc, uint8_t key)
{
	uint64_t in = (cc << 28) | (key << 24);
	uint64_t out = ~0ULL;

	report_prefix_pushf("cc=%d,key=%x", cc, key);

	asm volatile ("spm %1\n"
		      "ipm %0\n"
		      : "+r"(out) : "r"(in) : "cc");

	report(!(out & 0xc0000000UL), "bit 32 and 33 set to zero");
	report((out & ~0xff000000ULL) == ~0xff000000ULL,
	       "bit 0-31, 40-63 unchanged");
	report(!((in ^ out) & 0x3f000000UL), "cc and key applied");

	report_prefix_pop();
}

/* Test the SET PROGRAM PARAMETER and INSERT PROGRAM PARAMETER instruction */
static void test_spm_ipm(void)
{
	__test_spm_ipm(0, 0xf);
	__test_spm_ipm(1, 0x9);
	__test_spm_ipm(2, 0x5);
	__test_spm_ipm(3, 0x3);
	__test_spm_ipm(0, 0);
}

static __always_inline void __test_cpacf(unsigned int opcode, unsigned long func,
				unsigned int r1, unsigned int r2,
				unsigned int r3)
{
	register unsigned long gr0 asm("0") = func;
	cpacf_mask_t mask;
	register unsigned long gr1 asm("1") = (unsigned long)&mask;

	asm volatile(".insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],0\n"
		     : : "d" (gr0), "d" (gr1), [opc] "i" (opcode),
		         [r1] "i" (r1), [r2] "i" (r2), [r3] "i" (r3));
}

static __always_inline void __test_cpacf_r1_odd(unsigned int opcode)
{
	report_prefix_push("r1 odd");
	expect_pgm_int();
	__test_cpacf(opcode, 0, 1, 4, 6);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_r1_null(unsigned int opcode)
{
	report_prefix_push("r1 null");
	expect_pgm_int();
	__test_cpacf(opcode, 0, 0, 4, 6);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_r2_odd(unsigned int opcode)
{
	report_prefix_push("r2 odd");
	expect_pgm_int();
	__test_cpacf(opcode, 0, 2, 3, 6);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_r2_null(unsigned int opcode)
{
	report_prefix_push("r2 null");
	expect_pgm_int();
	__test_cpacf(opcode, 0, 2, 0, 6);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_r3_odd(unsigned int opcode)
{
	report_prefix_push("r3 odd");
	expect_pgm_int();
	__test_cpacf(opcode, 0, 2, 4, 5);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_r3_null(unsigned int opcode)
{
	report_prefix_push("r3 null");
	expect_pgm_int();
	__test_cpacf(opcode, 0, 2, 4, 0);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_mod_bit(unsigned int opcode)
{
	report_prefix_push("mod bit");
	expect_pgm_int();
	__test_cpacf(opcode, CPACF_DECRYPT, 2, 4, 6);
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_invalid_func(unsigned int opcode)
{
	report_prefix_push("invalid subfunction");
	expect_pgm_int();
	/* 127 is unassigned for now. We don't simply use any, as HW
	 * might simply mask valid codes in query but they might still work */
	if (cpacf_query_func(opcode, 127)) {
		report_skip("127 not invalid");
	} else {
		__test_cpacf(opcode, 127, 2, 4, 6);
	}
	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_invalid_parm(unsigned int opcode)
{
	report_prefix_push("invalid parm address");
	expect_pgm_int();
	__cpacf_query(opcode, OPAQUE_PTR(-1));
	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
	report_prefix_pop();
}

static __always_inline void __test_cpacf_protected_parm(unsigned int opcode)
{
	report_prefix_push("protected parm address");
	expect_pgm_int();
	low_prot_enable();
	__cpacf_query(opcode, OPAQUE_PTR(8));
	low_prot_disable();
	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
	report_prefix_pop();
}

static __always_inline void __test_basic_cpacf_opcode(unsigned int opcode)
{
	bool mod_bit_allowed = false;

	if (!__cpacf_check_opcode(opcode)) {
		report_skip("not available");
		return;
	}
	report(cpacf_query_func(opcode, 0), "query indicated in query");

	switch (opcode) {
	case CPACF_KMCTR:
		__test_cpacf_r3_odd(opcode);
		__test_cpacf_r3_null(opcode);
		/* FALL THROUGH */
	case CPACF_PRNO:
	case CPACF_KMF:
	case CPACF_KMC:
	case CPACF_KMO:
	case CPACF_KM:
		__test_cpacf_r1_odd(opcode);
		__test_cpacf_r1_null(opcode);
		mod_bit_allowed = true;
		/* FALL THROUGH */
	case CPACF_KMAC:
	case CPACF_KIMD:
	case CPACF_KLMD:
		__test_cpacf_r2_odd(opcode);
		__test_cpacf_r2_null(opcode);
	        break;
	}
	if (!mod_bit_allowed)
		__test_cpacf_mod_bit(opcode);
	__test_cpacf_invalid_func(opcode);
	__test_cpacf_invalid_parm(opcode);
	__test_cpacf_protected_parm(opcode);
}

/* COMPUTE MESSAGE AUTHENTICATION CODE */
static void test_kmac(void)
{
	__test_basic_cpacf_opcode(CPACF_KMAC);
}

/* CIPHER MESSAGE */
static void test_km(void)
{
	__test_basic_cpacf_opcode(CPACF_KM);
}
/* CIPHER MESSAGE WITH CHAINING */
static void test_kmc(void)
{
	__test_basic_cpacf_opcode(CPACF_KMC);
}

/* COMPUTE INTERMEDIATE MESSAGE DIGEST */
static void test_kimd(void)
{
	__test_basic_cpacf_opcode(CPACF_KIMD);
}

/* COMPUTE LAST MESSAGE DIGEST */
static void test_klmd(void)
{
	__test_basic_cpacf_opcode(CPACF_KLMD);
}

/* PERFORM CRYPTOGRAPHIC KEY MANAGEMENT OPERATION */
static void test_pckmo(void)
{
	__test_basic_cpacf_opcode(CPACF_PCKMO);
}

/* CIPHER MESSAGE WITH CIPHER FEEDBACK */
static void test_kmf(void)
{
	__test_basic_cpacf_opcode(CPACF_KMF);
}

/* PERFORM CRYPTOGRAPHIC KEY MANAGEMENT OPERATION */
static void test_kmo(void)
{
	__test_basic_cpacf_opcode(CPACF_KMO);
}

/* PERFORM CRYPTOGRAPHIC COMPUTATION */
static void test_pcc(void)
{
	__test_basic_cpacf_opcode(CPACF_PCC);
}

/* CIPHER MESSAGE WITH COUNTER */
static void test_kmctr(void)
{
	__test_basic_cpacf_opcode(CPACF_KMCTR);
}

/* PERFORM RANDOM NUMBER OPERATION (formerly PPNO) */
static void test_prno(void)
{
	__test_basic_cpacf_opcode(CPACF_PRNO);
}

static void test_dxc(void)
{
	/* DXC (0xff) is to be stored in LC and FPC on a trap (CRT) with AFP */
	lowcore.dxc_vxc = 0x12345678;
	set_fpc_dxc(0);

	report_prefix_push("afp");
	expect_pgm_int();
	asm volatile("	.insn	rrf,0xb9600000,%0,%0,8,0\n"
		     : : "r"(0) : "memory");
	check_pgm_int_code(PGM_INT_CODE_DATA);

	report(lowcore.dxc_vxc == 0xff, "dxc in LC");
	report(get_fpc_dxc() == 0xff, "dxc in FPC");
	report_prefix_pop();

	/* DXC (0xff) is to be stored in LC only on a trap (CRT) without AFP */
	lowcore.dxc_vxc = 0x12345678;
	set_fpc_dxc(0);

	report_prefix_push("no-afp");
	expect_pgm_int();
	/* temporarily disable AFP */
	afp_disable();
	asm volatile("	.insn	rrf,0xb9600000,%0,%0,8,0\n"
		     : : "r"(0) : "memory");
	afp_enable();
	check_pgm_int_code(PGM_INT_CODE_DATA);

	report(lowcore.dxc_vxc == 0xff, "dxc in LC");
	report(get_fpc_dxc() == 0, "dxc not in FPC");
	report_prefix_pop();
}

static struct {
	const char *name;
	void (*func)(void);
} tests[] = {
	{ "spm/ipm", test_spm_ipm },
	{ "kmac", test_kmac },
	{ "km", test_km },
	{ "kmc", test_kmc },
	{ "kimd", test_kimd },
	{ "klmd", test_klmd },
	{ "pckmo", test_pckmo },
	{ "kmf", test_kmf },
	{ "kmo", test_kmo },
	{ "pcc", test_pcc },
	{ "kmctr", test_kmctr },
	{ "prno", test_prno },
	{ "dxc", test_dxc },
	{ NULL, NULL }
};

int main(int argc, char**argv)
{
	int i;

	report_prefix_push("emulator");
	for (i = 0; tests[i].name; i++) {
		report_prefix_push(tests[i].name);
		tests[i].func();
		report_prefix_pop();
	}
	report_prefix_pop();

	return report_summary();
}
