xref: /kvm-unit-tests/s390x/emulator.c (revision 9cab58249f98adc451933530fd7e618e1856eb94)
1fa624cc2SJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
2559eaa1eSDavid Hildenbrand /*
3559eaa1eSDavid Hildenbrand  * Emulator tests - for s390x CPU instructions that are usually interpreted
4559eaa1eSDavid Hildenbrand  *                  by the hardware
5559eaa1eSDavid Hildenbrand  *
6559eaa1eSDavid Hildenbrand  * Copyright (c) 2017 Red Hat Inc
7559eaa1eSDavid Hildenbrand  *
8559eaa1eSDavid Hildenbrand  * Authors:
9559eaa1eSDavid Hildenbrand  *  David Hildenbrand <david@redhat.com>
10559eaa1eSDavid Hildenbrand  */
11559eaa1eSDavid Hildenbrand #include <libcflat.h>
1240c8f4ceSDavid Hildenbrand #include <asm/cpacf.h>
1340c8f4ceSDavid Hildenbrand #include <asm/interrupt.h>
142d0d5f41SDavid Hildenbrand #include <asm/float.h>
155af83aa8SJanis Schoetterl-Glausch #include <asm/mem.h>
16c2f4799aSClaudio Imbrenda #include <linux/compiler.h>
172d0d5f41SDavid Hildenbrand 
__test_spm_ipm(uint8_t cc,uint8_t key)18559eaa1eSDavid Hildenbrand static inline void __test_spm_ipm(uint8_t cc, uint8_t key)
19559eaa1eSDavid Hildenbrand {
20559eaa1eSDavid Hildenbrand 	uint64_t in = (cc << 28) | (key << 24);
21559eaa1eSDavid Hildenbrand 	uint64_t out = ~0ULL;
22559eaa1eSDavid Hildenbrand 
23559eaa1eSDavid Hildenbrand 	report_prefix_pushf("cc=%d,key=%x", cc, key);
24559eaa1eSDavid Hildenbrand 
25559eaa1eSDavid Hildenbrand 	asm volatile ("spm %1\n"
26559eaa1eSDavid Hildenbrand 		      "ipm %0\n"
27559eaa1eSDavid Hildenbrand 		      : "+r"(out) : "r"(in) : "cc");
28559eaa1eSDavid Hildenbrand 
29a299895bSThomas Huth 	report(!(out & 0xc0000000UL), "bit 32 and 33 set to zero");
30a299895bSThomas Huth 	report((out & ~0xff000000ULL) == ~0xff000000ULL,
31a299895bSThomas Huth 	       "bit 0-31, 40-63 unchanged");
32a299895bSThomas Huth 	report(!((in ^ out) & 0x3f000000UL), "cc and key applied");
33559eaa1eSDavid Hildenbrand 
34559eaa1eSDavid Hildenbrand 	report_prefix_pop();
35559eaa1eSDavid Hildenbrand }
36559eaa1eSDavid Hildenbrand 
37559eaa1eSDavid Hildenbrand /* Test the SET PROGRAM PARAMETER and INSERT PROGRAM PARAMETER instruction */
test_spm_ipm(void)38559eaa1eSDavid Hildenbrand static void test_spm_ipm(void)
39559eaa1eSDavid Hildenbrand {
40559eaa1eSDavid Hildenbrand 	__test_spm_ipm(0, 0xf);
41559eaa1eSDavid Hildenbrand 	__test_spm_ipm(1, 0x9);
42559eaa1eSDavid Hildenbrand 	__test_spm_ipm(2, 0x5);
43559eaa1eSDavid Hildenbrand 	__test_spm_ipm(3, 0x3);
44559eaa1eSDavid Hildenbrand 	__test_spm_ipm(0, 0);
45559eaa1eSDavid Hildenbrand }
46559eaa1eSDavid Hildenbrand 
__test_cpacf(unsigned int opcode,unsigned long func,unsigned int r1,unsigned int r2,unsigned int r3)47c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf(unsigned int opcode, unsigned long func,
4840c8f4ceSDavid Hildenbrand 				unsigned int r1, unsigned int r2,
4940c8f4ceSDavid Hildenbrand 				unsigned int r3)
5040c8f4ceSDavid Hildenbrand {
5140c8f4ceSDavid Hildenbrand 	register unsigned long gr0 asm("0") = func;
5240c8f4ceSDavid Hildenbrand 	cpacf_mask_t mask;
5340c8f4ceSDavid Hildenbrand 	register unsigned long gr1 asm("1") = (unsigned long)&mask;
5440c8f4ceSDavid Hildenbrand 
5540c8f4ceSDavid Hildenbrand 	asm volatile(".insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],0\n"
5640c8f4ceSDavid Hildenbrand 		     : : "d" (gr0), "d" (gr1), [opc] "i" (opcode),
5740c8f4ceSDavid Hildenbrand 		         [r1] "i" (r1), [r2] "i" (r2), [r3] "i" (r3));
5840c8f4ceSDavid Hildenbrand }
5940c8f4ceSDavid Hildenbrand 
__test_cpacf_r1_odd(unsigned int opcode)60c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_r1_odd(unsigned int opcode)
6140c8f4ceSDavid Hildenbrand {
6240c8f4ceSDavid Hildenbrand 	report_prefix_push("r1 odd");
6340c8f4ceSDavid Hildenbrand 	expect_pgm_int();
6440c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, 0, 1, 4, 6);
6540c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
6640c8f4ceSDavid Hildenbrand 	report_prefix_pop();
6740c8f4ceSDavid Hildenbrand }
6840c8f4ceSDavid Hildenbrand 
__test_cpacf_r1_null(unsigned int opcode)69c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_r1_null(unsigned int opcode)
7040c8f4ceSDavid Hildenbrand {
7140c8f4ceSDavid Hildenbrand 	report_prefix_push("r1 null");
7240c8f4ceSDavid Hildenbrand 	expect_pgm_int();
7340c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, 0, 0, 4, 6);
7440c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
7540c8f4ceSDavid Hildenbrand 	report_prefix_pop();
7640c8f4ceSDavid Hildenbrand }
7740c8f4ceSDavid Hildenbrand 
__test_cpacf_r2_odd(unsigned int opcode)78c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_r2_odd(unsigned int opcode)
7940c8f4ceSDavid Hildenbrand {
8040c8f4ceSDavid Hildenbrand 	report_prefix_push("r2 odd");
8140c8f4ceSDavid Hildenbrand 	expect_pgm_int();
8240c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, 0, 2, 3, 6);
8340c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
8440c8f4ceSDavid Hildenbrand 	report_prefix_pop();
8540c8f4ceSDavid Hildenbrand }
8640c8f4ceSDavid Hildenbrand 
__test_cpacf_r2_null(unsigned int opcode)87c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_r2_null(unsigned int opcode)
8840c8f4ceSDavid Hildenbrand {
8940c8f4ceSDavid Hildenbrand 	report_prefix_push("r2 null");
9040c8f4ceSDavid Hildenbrand 	expect_pgm_int();
9140c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, 0, 2, 0, 6);
9240c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
9340c8f4ceSDavid Hildenbrand 	report_prefix_pop();
9440c8f4ceSDavid Hildenbrand }
9540c8f4ceSDavid Hildenbrand 
__test_cpacf_r3_odd(unsigned int opcode)96c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_r3_odd(unsigned int opcode)
9740c8f4ceSDavid Hildenbrand {
9840c8f4ceSDavid Hildenbrand 	report_prefix_push("r3 odd");
9940c8f4ceSDavid Hildenbrand 	expect_pgm_int();
10040c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, 0, 2, 4, 5);
10140c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
10240c8f4ceSDavid Hildenbrand 	report_prefix_pop();
10340c8f4ceSDavid Hildenbrand }
10440c8f4ceSDavid Hildenbrand 
__test_cpacf_r3_null(unsigned int opcode)105c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_r3_null(unsigned int opcode)
10640c8f4ceSDavid Hildenbrand {
10740c8f4ceSDavid Hildenbrand 	report_prefix_push("r3 null");
10840c8f4ceSDavid Hildenbrand 	expect_pgm_int();
10940c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, 0, 2, 4, 0);
11040c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
11140c8f4ceSDavid Hildenbrand 	report_prefix_pop();
11240c8f4ceSDavid Hildenbrand }
11340c8f4ceSDavid Hildenbrand 
__test_cpacf_mod_bit(unsigned int opcode)114c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_mod_bit(unsigned int opcode)
11540c8f4ceSDavid Hildenbrand {
11640c8f4ceSDavid Hildenbrand 	report_prefix_push("mod bit");
11740c8f4ceSDavid Hildenbrand 	expect_pgm_int();
11840c8f4ceSDavid Hildenbrand 	__test_cpacf(opcode, CPACF_DECRYPT, 2, 4, 6);
11940c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
12040c8f4ceSDavid Hildenbrand 	report_prefix_pop();
12140c8f4ceSDavid Hildenbrand }
12240c8f4ceSDavid Hildenbrand 
__test_cpacf_invalid_func(unsigned int opcode)123c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_invalid_func(unsigned int opcode)
12440c8f4ceSDavid Hildenbrand {
12540c8f4ceSDavid Hildenbrand 	report_prefix_push("invalid subfunction");
12640c8f4ceSDavid Hildenbrand 	expect_pgm_int();
12740c8f4ceSDavid Hildenbrand 	/* 127 is unassigned for now. We don't simply use any, as HW
12840c8f4ceSDavid Hildenbrand 	 * might simply mask valid codes in query but they might still work */
12940c8f4ceSDavid Hildenbrand 	if (cpacf_query_func(opcode, 127)) {
13040c8f4ceSDavid Hildenbrand 		report_skip("127 not invalid");
13140c8f4ceSDavid Hildenbrand 	} else {
13240c8f4ceSDavid Hildenbrand 		__test_cpacf(opcode, 127, 2, 4, 6);
13340c8f4ceSDavid Hildenbrand 		check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
134*950bc1d6SChristian Borntraeger 	}
13540c8f4ceSDavid Hildenbrand 	report_prefix_pop();
13640c8f4ceSDavid Hildenbrand }
13740c8f4ceSDavid Hildenbrand 
__test_cpacf_invalid_parm(unsigned int opcode)138c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_invalid_parm(unsigned int opcode)
13940c8f4ceSDavid Hildenbrand {
14040c8f4ceSDavid Hildenbrand 	report_prefix_push("invalid parm address");
14140c8f4ceSDavid Hildenbrand 	expect_pgm_int();
1425af83aa8SJanis Schoetterl-Glausch 	__cpacf_query(opcode, OPAQUE_PTR(-1));
14340c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
14440c8f4ceSDavid Hildenbrand 	report_prefix_pop();
14540c8f4ceSDavid Hildenbrand }
14640c8f4ceSDavid Hildenbrand 
__test_cpacf_protected_parm(unsigned int opcode)147c2f4799aSClaudio Imbrenda static __always_inline void __test_cpacf_protected_parm(unsigned int opcode)
14840c8f4ceSDavid Hildenbrand {
14940c8f4ceSDavid Hildenbrand 	report_prefix_push("protected parm address");
15040c8f4ceSDavid Hildenbrand 	expect_pgm_int();
15140c8f4ceSDavid Hildenbrand 	low_prot_enable();
1525af83aa8SJanis Schoetterl-Glausch 	__cpacf_query(opcode, OPAQUE_PTR(8));
15340c8f4ceSDavid Hildenbrand 	low_prot_disable();
15440c8f4ceSDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
15540c8f4ceSDavid Hildenbrand 	report_prefix_pop();
15640c8f4ceSDavid Hildenbrand }
15740c8f4ceSDavid Hildenbrand 
__test_basic_cpacf_opcode(unsigned int opcode)158c2f4799aSClaudio Imbrenda static __always_inline void __test_basic_cpacf_opcode(unsigned int opcode)
15940c8f4ceSDavid Hildenbrand {
16040c8f4ceSDavid Hildenbrand 	bool mod_bit_allowed = false;
16140c8f4ceSDavid Hildenbrand 
16240c8f4ceSDavid Hildenbrand 	if (!__cpacf_check_opcode(opcode)) {
16340c8f4ceSDavid Hildenbrand 		report_skip("not available");
16440c8f4ceSDavid Hildenbrand 		return;
16540c8f4ceSDavid Hildenbrand 	}
166a299895bSThomas Huth 	report(cpacf_query_func(opcode, 0), "query indicated in query");
16740c8f4ceSDavid Hildenbrand 
16840c8f4ceSDavid Hildenbrand 	switch (opcode) {
16940c8f4ceSDavid Hildenbrand 	case CPACF_KMCTR:
17040c8f4ceSDavid Hildenbrand 		__test_cpacf_r3_odd(opcode);
17140c8f4ceSDavid Hildenbrand 		__test_cpacf_r3_null(opcode);
17240c8f4ceSDavid Hildenbrand 		/* FALL THROUGH */
17340c8f4ceSDavid Hildenbrand 	case CPACF_PRNO:
17440c8f4ceSDavid Hildenbrand 	case CPACF_KMF:
17540c8f4ceSDavid Hildenbrand 	case CPACF_KMC:
17640c8f4ceSDavid Hildenbrand 	case CPACF_KMO:
17740c8f4ceSDavid Hildenbrand 	case CPACF_KM:
17840c8f4ceSDavid Hildenbrand 		__test_cpacf_r1_odd(opcode);
17940c8f4ceSDavid Hildenbrand 		__test_cpacf_r1_null(opcode);
18040c8f4ceSDavid Hildenbrand 		mod_bit_allowed = true;
18140c8f4ceSDavid Hildenbrand 		/* FALL THROUGH */
18240c8f4ceSDavid Hildenbrand 	case CPACF_KMAC:
18340c8f4ceSDavid Hildenbrand 	case CPACF_KIMD:
18440c8f4ceSDavid Hildenbrand 	case CPACF_KLMD:
18540c8f4ceSDavid Hildenbrand 		__test_cpacf_r2_odd(opcode);
18640c8f4ceSDavid Hildenbrand 		__test_cpacf_r2_null(opcode);
18740c8f4ceSDavid Hildenbrand 	        break;
18840c8f4ceSDavid Hildenbrand 	}
18940c8f4ceSDavid Hildenbrand 	if (!mod_bit_allowed)
19040c8f4ceSDavid Hildenbrand 		__test_cpacf_mod_bit(opcode);
19140c8f4ceSDavid Hildenbrand 	__test_cpacf_invalid_func(opcode);
19240c8f4ceSDavid Hildenbrand 	__test_cpacf_invalid_parm(opcode);
19340c8f4ceSDavid Hildenbrand 	__test_cpacf_protected_parm(opcode);
19440c8f4ceSDavid Hildenbrand }
19540c8f4ceSDavid Hildenbrand 
19640c8f4ceSDavid Hildenbrand /* COMPUTE MESSAGE AUTHENTICATION CODE */
test_kmac(void)19740c8f4ceSDavid Hildenbrand static void test_kmac(void)
19840c8f4ceSDavid Hildenbrand {
19940c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KMAC);
20040c8f4ceSDavid Hildenbrand }
20140c8f4ceSDavid Hildenbrand 
20240c8f4ceSDavid Hildenbrand /* CIPHER MESSAGE */
test_km(void)20340c8f4ceSDavid Hildenbrand static void test_km(void)
20440c8f4ceSDavid Hildenbrand {
20540c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KM);
20640c8f4ceSDavid Hildenbrand }
20740c8f4ceSDavid Hildenbrand /* CIPHER MESSAGE WITH CHAINING */
test_kmc(void)20840c8f4ceSDavid Hildenbrand static void test_kmc(void)
20940c8f4ceSDavid Hildenbrand {
21040c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KMC);
21140c8f4ceSDavid Hildenbrand }
21240c8f4ceSDavid Hildenbrand 
21340c8f4ceSDavid Hildenbrand /* COMPUTE INTERMEDIATE MESSAGE DIGEST */
test_kimd(void)21440c8f4ceSDavid Hildenbrand static void test_kimd(void)
21540c8f4ceSDavid Hildenbrand {
21640c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KIMD);
21740c8f4ceSDavid Hildenbrand }
21840c8f4ceSDavid Hildenbrand 
21940c8f4ceSDavid Hildenbrand /* COMPUTE LAST MESSAGE DIGEST */
test_klmd(void)22040c8f4ceSDavid Hildenbrand static void test_klmd(void)
22140c8f4ceSDavid Hildenbrand {
22240c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KLMD);
22340c8f4ceSDavid Hildenbrand }
22440c8f4ceSDavid Hildenbrand 
22540c8f4ceSDavid Hildenbrand /* PERFORM CRYPTOGRAPHIC KEY MANAGEMENT OPERATION */
test_pckmo(void)22640c8f4ceSDavid Hildenbrand static void test_pckmo(void)
22740c8f4ceSDavid Hildenbrand {
22840c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_PCKMO);
22940c8f4ceSDavid Hildenbrand }
23040c8f4ceSDavid Hildenbrand 
23140c8f4ceSDavid Hildenbrand /* CIPHER MESSAGE WITH CIPHER FEEDBACK */
test_kmf(void)23240c8f4ceSDavid Hildenbrand static void test_kmf(void)
23340c8f4ceSDavid Hildenbrand {
23440c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KMF);
23540c8f4ceSDavid Hildenbrand }
23640c8f4ceSDavid Hildenbrand 
23740c8f4ceSDavid Hildenbrand /* PERFORM CRYPTOGRAPHIC KEY MANAGEMENT OPERATION */
test_kmo(void)23840c8f4ceSDavid Hildenbrand static void test_kmo(void)
23940c8f4ceSDavid Hildenbrand {
24040c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KMO);
24140c8f4ceSDavid Hildenbrand }
24240c8f4ceSDavid Hildenbrand 
24340c8f4ceSDavid Hildenbrand /* PERFORM CRYPTOGRAPHIC COMPUTATION */
test_pcc(void)24440c8f4ceSDavid Hildenbrand static void test_pcc(void)
24540c8f4ceSDavid Hildenbrand {
24640c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_PCC);
24740c8f4ceSDavid Hildenbrand }
24840c8f4ceSDavid Hildenbrand 
24940c8f4ceSDavid Hildenbrand /* CIPHER MESSAGE WITH COUNTER */
test_kmctr(void)25040c8f4ceSDavid Hildenbrand static void test_kmctr(void)
25140c8f4ceSDavid Hildenbrand {
25240c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_KMCTR);
25340c8f4ceSDavid Hildenbrand }
25440c8f4ceSDavid Hildenbrand 
25540c8f4ceSDavid Hildenbrand /* PERFORM RANDOM NUMBER OPERATION (formerly PPNO) */
test_prno(void)25640c8f4ceSDavid Hildenbrand static void test_prno(void)
25740c8f4ceSDavid Hildenbrand {
25840c8f4ceSDavid Hildenbrand 	__test_basic_cpacf_opcode(CPACF_PRNO);
25940c8f4ceSDavid Hildenbrand }
26040c8f4ceSDavid Hildenbrand 
test_dxc(void)2612d0d5f41SDavid Hildenbrand static void test_dxc(void)
2622d0d5f41SDavid Hildenbrand {
2632d0d5f41SDavid Hildenbrand 	/* DXC (0xff) is to be stored in LC and FPC on a trap (CRT) with AFP */
264cd719531SJanis Schoetterl-Glausch 	lowcore.dxc_vxc = 0x12345678;
2652d0d5f41SDavid Hildenbrand 	set_fpc_dxc(0);
2662d0d5f41SDavid Hildenbrand 
26799ee877dSJanosch Frank 	report_prefix_push("afp");
2682d0d5f41SDavid Hildenbrand 	expect_pgm_int();
2692d0d5f41SDavid Hildenbrand 	asm volatile("	.insn	rrf,0xb9600000,%0,%0,8,0\n"
2702d0d5f41SDavid Hildenbrand 		     : : "r"(0) : "memory");
2712d0d5f41SDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_DATA);
2722d0d5f41SDavid Hildenbrand 
273cd719531SJanis Schoetterl-Glausch 	report(lowcore.dxc_vxc == 0xff, "dxc in LC");
274a299895bSThomas Huth 	report(get_fpc_dxc() == 0xff, "dxc in FPC");
27599ee877dSJanosch Frank 	report_prefix_pop();
2762d0d5f41SDavid Hildenbrand 
2772d0d5f41SDavid Hildenbrand 	/* DXC (0xff) is to be stored in LC only on a trap (CRT) without AFP */
278cd719531SJanis Schoetterl-Glausch 	lowcore.dxc_vxc = 0x12345678;
2792d0d5f41SDavid Hildenbrand 	set_fpc_dxc(0);
2802d0d5f41SDavid Hildenbrand 
28199ee877dSJanosch Frank 	report_prefix_push("no-afp");
2822d0d5f41SDavid Hildenbrand 	expect_pgm_int();
2832d0d5f41SDavid Hildenbrand 	/* temporarily disable AFP */
2842d0d5f41SDavid Hildenbrand 	afp_disable();
2852d0d5f41SDavid Hildenbrand 	asm volatile("	.insn	rrf,0xb9600000,%0,%0,8,0\n"
2862d0d5f41SDavid Hildenbrand 		     : : "r"(0) : "memory");
2872d0d5f41SDavid Hildenbrand 	afp_enable();
2882d0d5f41SDavid Hildenbrand 	check_pgm_int_code(PGM_INT_CODE_DATA);
2892d0d5f41SDavid Hildenbrand 
290cd719531SJanis Schoetterl-Glausch 	report(lowcore.dxc_vxc == 0xff, "dxc in LC");
291a299895bSThomas Huth 	report(get_fpc_dxc() == 0, "dxc not in FPC");
29299ee877dSJanosch Frank 	report_prefix_pop();
2932d0d5f41SDavid Hildenbrand }
2942d0d5f41SDavid Hildenbrand 
295559eaa1eSDavid Hildenbrand static struct {
296559eaa1eSDavid Hildenbrand 	const char *name;
297559eaa1eSDavid Hildenbrand 	void (*func)(void);
298559eaa1eSDavid Hildenbrand } tests[] = {
299559eaa1eSDavid Hildenbrand 	{ "spm/ipm", test_spm_ipm },
30040c8f4ceSDavid Hildenbrand 	{ "kmac", test_kmac },
30140c8f4ceSDavid Hildenbrand 	{ "km", test_km },
30240c8f4ceSDavid Hildenbrand 	{ "kmc", test_kmc },
30340c8f4ceSDavid Hildenbrand 	{ "kimd", test_kimd },
30440c8f4ceSDavid Hildenbrand 	{ "klmd", test_klmd },
30540c8f4ceSDavid Hildenbrand 	{ "pckmo", test_pckmo },
30640c8f4ceSDavid Hildenbrand 	{ "kmf", test_kmf },
30740c8f4ceSDavid Hildenbrand 	{ "kmo", test_kmo },
30840c8f4ceSDavid Hildenbrand 	{ "pcc", test_pcc },
30940c8f4ceSDavid Hildenbrand 	{ "kmctr", test_kmctr },
31040c8f4ceSDavid Hildenbrand 	{ "prno", test_prno },
3112d0d5f41SDavid Hildenbrand 	{ "dxc", test_dxc },
312559eaa1eSDavid Hildenbrand 	{ NULL, NULL }
313559eaa1eSDavid Hildenbrand };
314559eaa1eSDavid Hildenbrand 
main(int argc,char ** argv)315559eaa1eSDavid Hildenbrand int main(int argc, char**argv)
316559eaa1eSDavid Hildenbrand {
317559eaa1eSDavid Hildenbrand 	int i;
318559eaa1eSDavid Hildenbrand 
319559eaa1eSDavid Hildenbrand 	report_prefix_push("emulator");
320559eaa1eSDavid Hildenbrand 	for (i = 0; tests[i].name; i++) {
321559eaa1eSDavid Hildenbrand 		report_prefix_push(tests[i].name);
322559eaa1eSDavid Hildenbrand 		tests[i].func();
323559eaa1eSDavid Hildenbrand 		report_prefix_pop();
324559eaa1eSDavid Hildenbrand 	}
325559eaa1eSDavid Hildenbrand 	report_prefix_pop();
326559eaa1eSDavid Hildenbrand 
327559eaa1eSDavid Hildenbrand 	return report_summary();
328559eaa1eSDavid Hildenbrand }
329