xref: /kvm-unit-tests/powerpc/emulator.c (revision 8260a1561239fe48391227a86db5928d33dbf518)
1be9b007bSLaurent Vivier /*
2be9b007bSLaurent Vivier  * Test some powerpc instructions
3be9b007bSLaurent Vivier  */
4be9b007bSLaurent Vivier 
5be9b007bSLaurent Vivier #include <libcflat.h>
6be9b007bSLaurent Vivier #include <asm/processor.h>
7be9b007bSLaurent Vivier 
8be9b007bSLaurent Vivier static int verbose;
9be9b007bSLaurent Vivier static int volatile is_invalid;
10be9b007bSLaurent Vivier 
11be9b007bSLaurent Vivier static void program_check_handler(struct pt_regs *regs, void *opaque)
12be9b007bSLaurent Vivier {
13be9b007bSLaurent Vivier 	int *data = opaque;
14be9b007bSLaurent Vivier 
15be9b007bSLaurent Vivier 	if (verbose) {
16be9b007bSLaurent Vivier 		printf("Detected invalid instruction 0x%016lx: %08x\n",
17be9b007bSLaurent Vivier 		       regs->nip, *(uint32_t*)regs->nip);
18be9b007bSLaurent Vivier 	}
19be9b007bSLaurent Vivier 
20be9b007bSLaurent Vivier 	/* the result is bit 16 to 19 of SRR1
21be9b007bSLaurent Vivier 	 * bit 0: SRR0 contains the address of the next instruction
22be9b007bSLaurent Vivier 	 * bit 1: Trap
23be9b007bSLaurent Vivier 	 * bit 2: Privileged instruction
24be9b007bSLaurent Vivier 	 * bit 3: Illegal instruction
25be9b007bSLaurent Vivier 	 * bit 4: FP enabled exception type
26be9b007bSLaurent Vivier 	 */
27be9b007bSLaurent Vivier 
28be9b007bSLaurent Vivier 	*data = regs->msr >> 16;
29be9b007bSLaurent Vivier 
30be9b007bSLaurent Vivier 	regs->nip += 4;
31be9b007bSLaurent Vivier }
32be9b007bSLaurent Vivier 
33be9b007bSLaurent Vivier static void test_illegal(void)
34be9b007bSLaurent Vivier {
35be9b007bSLaurent Vivier 	report_prefix_push("invalid");
36be9b007bSLaurent Vivier 
37be9b007bSLaurent Vivier 	is_invalid = 0;
38be9b007bSLaurent Vivier 
39be9b007bSLaurent Vivier 	asm volatile (".long 0");
40be9b007bSLaurent Vivier 
41be9b007bSLaurent Vivier 	report("exception", is_invalid == 8); /* illegal instruction */
42be9b007bSLaurent Vivier 
43be9b007bSLaurent Vivier 	report_prefix_pop();
44be9b007bSLaurent Vivier }
45be9b007bSLaurent Vivier 
46*8260a156SLaurent Vivier static void test_64bit(void)
47*8260a156SLaurent Vivier {
48*8260a156SLaurent Vivier 	uint64_t msr;
49*8260a156SLaurent Vivier 
50*8260a156SLaurent Vivier 	report_prefix_push("64bit");
51*8260a156SLaurent Vivier 
52*8260a156SLaurent Vivier 	asm("mfmsr %[msr]": [msr] "=r" (msr));
53*8260a156SLaurent Vivier 
54*8260a156SLaurent Vivier 	report("detected", msr & 0x8000000000000000UL);
55*8260a156SLaurent Vivier 
56*8260a156SLaurent Vivier 	report_prefix_pop();
57*8260a156SLaurent Vivier }
58*8260a156SLaurent Vivier 
59be9b007bSLaurent Vivier int main(int argc, char **argv)
60be9b007bSLaurent Vivier {
61be9b007bSLaurent Vivier 	int i;
62be9b007bSLaurent Vivier 
63be9b007bSLaurent Vivier 	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
64be9b007bSLaurent Vivier 
65be9b007bSLaurent Vivier 	for (i = 0; i < argc; i++) {
66be9b007bSLaurent Vivier 		if (strcmp(argv[i], "-v") == 0) {
67be9b007bSLaurent Vivier 			verbose = 1;
68be9b007bSLaurent Vivier 		}
69be9b007bSLaurent Vivier 	}
70be9b007bSLaurent Vivier 
71be9b007bSLaurent Vivier 	report_prefix_push("emulator");
72be9b007bSLaurent Vivier 
73*8260a156SLaurent Vivier 	test_64bit();
74be9b007bSLaurent Vivier 	test_illegal();
75be9b007bSLaurent Vivier 
76be9b007bSLaurent Vivier 	report_prefix_pop();
77be9b007bSLaurent Vivier 
78be9b007bSLaurent Vivier 	return report_summary();
79be9b007bSLaurent Vivier }
80