xref: /kvm-unit-tests/x86/realmode.c (revision 96b9ca1ebddc6360a42aba3a70c97ee82e55b253)
17d36db35SAvi Kivity asm(".code16gcc");
27d36db35SAvi Kivity 
37d36db35SAvi Kivity typedef unsigned char u8;
47d36db35SAvi Kivity typedef unsigned short u16;
57d36db35SAvi Kivity typedef unsigned u32;
67d36db35SAvi Kivity typedef unsigned long long u64;
77d36db35SAvi Kivity 
87d36db35SAvi Kivity void test_function(void);
97d36db35SAvi Kivity 
107d36db35SAvi Kivity asm(
117d36db35SAvi Kivity 	"test_function: \n\t"
127d36db35SAvi Kivity 	"mov $0x1234, %eax \n\t"
137d36db35SAvi Kivity 	"ret"
147d36db35SAvi Kivity    );
157d36db35SAvi Kivity 
167d36db35SAvi Kivity static int strlen(const char *str)
177d36db35SAvi Kivity {
187d36db35SAvi Kivity 	int n;
197d36db35SAvi Kivity 
207d36db35SAvi Kivity 	for (n = 0; *str; ++str)
217d36db35SAvi Kivity 		++n;
227d36db35SAvi Kivity 	return n;
237d36db35SAvi Kivity }
247d36db35SAvi Kivity 
257d36db35SAvi Kivity static void print_serial(const char *buf)
267d36db35SAvi Kivity {
277d36db35SAvi Kivity 	unsigned long len = strlen(buf);
287d36db35SAvi Kivity 
297d36db35SAvi Kivity 	asm volatile ("cld; addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
307d36db35SAvi Kivity }
317d36db35SAvi Kivity 
327d36db35SAvi Kivity static void exit(int code)
337d36db35SAvi Kivity {
347d36db35SAvi Kivity         asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4));
357d36db35SAvi Kivity }
367d36db35SAvi Kivity 
377d36db35SAvi Kivity struct regs {
387d36db35SAvi Kivity 	u32 eax, ebx, ecx, edx;
397d36db35SAvi Kivity 	u32 esi, edi, esp, ebp;
407d36db35SAvi Kivity 	u32 eip, eflags;
417d36db35SAvi Kivity };
427d36db35SAvi Kivity 
437d36db35SAvi Kivity static u64 gdt[] = {
447d36db35SAvi Kivity 	0,
457d36db35SAvi Kivity 	0x00cf9b000000ffffull, // flat 32-bit code segment
467d36db35SAvi Kivity 	0x00cf93000000ffffull, // flat 32-bit data segment
477d36db35SAvi Kivity };
487d36db35SAvi Kivity 
497d36db35SAvi Kivity static struct {
507d36db35SAvi Kivity 	u16 limit;
517d36db35SAvi Kivity 	void *base;
527d36db35SAvi Kivity } __attribute__((packed)) gdt_descr = {
537d36db35SAvi Kivity 	sizeof(gdt) - 1,
547d36db35SAvi Kivity 	gdt,
557d36db35SAvi Kivity };
567d36db35SAvi Kivity 
577d36db35SAvi Kivity static void exec_in_big_real_mode(const struct regs *inregs,
587d36db35SAvi Kivity 				  struct regs *outregs,
597d36db35SAvi Kivity 				  const u8 *insn, int insn_len)
607d36db35SAvi Kivity {
617d36db35SAvi Kivity 	unsigned long tmp;
627d36db35SAvi Kivity 	static struct regs save;
637d36db35SAvi Kivity 	int i;
647d36db35SAvi Kivity 	extern u8 test_insn[], test_insn_end[];
657d36db35SAvi Kivity 
667d36db35SAvi Kivity 	for (i = 0; i < insn_len; ++i)
677d36db35SAvi Kivity 		test_insn[i] = insn[i];
687d36db35SAvi Kivity 	for (; i < test_insn_end - test_insn; ++i)
697d36db35SAvi Kivity 		test_insn[i] = 0x90; // nop
707d36db35SAvi Kivity 
717d36db35SAvi Kivity 	save = *inregs;
727d36db35SAvi Kivity 	asm volatile(
737d36db35SAvi Kivity 		"lgdtl %[gdt_descr] \n\t"
747d36db35SAvi Kivity 		"mov %%cr0, %[tmp] \n\t"
757d36db35SAvi Kivity 		"or $1, %[tmp] \n\t"
767d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
777d36db35SAvi Kivity 		"mov %[bigseg], %%gs \n\t"
787d36db35SAvi Kivity 		"and $-2, %[tmp] \n\t"
797d36db35SAvi Kivity 		"mov %[tmp], %%cr0 \n\t"
807d36db35SAvi Kivity 
817d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
827d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
837d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
847d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
857d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
867d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
877d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
887d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
897d36db35SAvi Kivity 
907d36db35SAvi Kivity 		"test_insn: . = . + 32\n\t"
917d36db35SAvi Kivity 		"test_insn_end: \n\t"
927d36db35SAvi Kivity 
937d36db35SAvi Kivity 		"xchg %%eax, %[save]+0 \n\t"
947d36db35SAvi Kivity 		"xchg %%ebx, %[save]+4 \n\t"
957d36db35SAvi Kivity 		"xchg %%ecx, %[save]+8 \n\t"
967d36db35SAvi Kivity 		"xchg %%edx, %[save]+12 \n\t"
977d36db35SAvi Kivity 		"xchg %%esi, %[save]+16 \n\t"
987d36db35SAvi Kivity 		"xchg %%edi, %[save]+20 \n\t"
997d36db35SAvi Kivity 		"xchg %%esp, %[save]+24 \n\t"
1007d36db35SAvi Kivity 		"xchg %%ebp, %[save]+28 \n\t"
1017d36db35SAvi Kivity 
1027d36db35SAvi Kivity 		/* Save EFLAGS in outregs*/
1037d36db35SAvi Kivity 		"pushfl \n\t"
1047d36db35SAvi Kivity 		"popl %[save]+36 \n\t"
1057d36db35SAvi Kivity 
1067d36db35SAvi Kivity 		"xor %[tmp], %[tmp] \n\t"
1077d36db35SAvi Kivity 		"mov %[tmp], %%gs \n\t"
1087d36db35SAvi Kivity 		: [tmp]"=&r"(tmp), [save]"+m"(save)
1097d36db35SAvi Kivity 		: [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
1107d36db35SAvi Kivity 		: "cc", "memory"
1117d36db35SAvi Kivity 		);
1127d36db35SAvi Kivity 	*outregs = save;
1137d36db35SAvi Kivity }
1147d36db35SAvi Kivity 
1157d36db35SAvi Kivity #define R_AX 1
1167d36db35SAvi Kivity #define R_BX 2
1177d36db35SAvi Kivity #define R_CX 4
1187d36db35SAvi Kivity #define R_DX 8
1197d36db35SAvi Kivity #define R_SI 16
1207d36db35SAvi Kivity #define R_DI 32
1217d36db35SAvi Kivity #define R_SP 64
1227d36db35SAvi Kivity #define R_BP 128
1237d36db35SAvi Kivity 
1247d36db35SAvi Kivity int regs_equal(const struct regs *r1, const struct regs *r2, int ignore)
1257d36db35SAvi Kivity {
1267d36db35SAvi Kivity 	const u32 *p1 = &r1->eax, *p2 = &r2->eax;  // yuck
1277d36db35SAvi Kivity 	int i;
1287d36db35SAvi Kivity 
1297d36db35SAvi Kivity 	for (i = 0; i < 8; ++i)
1307d36db35SAvi Kivity 		if (!(ignore & (1 << i)) && p1[i] != p2[i])
1317d36db35SAvi Kivity 			return 0;
1327d36db35SAvi Kivity 	return 1;
1337d36db35SAvi Kivity }
1347d36db35SAvi Kivity 
1357d36db35SAvi Kivity #define MK_INSN(name, str)                         \
1367d36db35SAvi Kivity 	asm (				           \
1377d36db35SAvi Kivity 		".text 1\n\t"                      \
1387d36db35SAvi Kivity 		"insn_" #name ": " str " \n\t"	   \
1397d36db35SAvi Kivity 		"insn_" #name "_end: \n\t"	   \
1407d36db35SAvi Kivity 		".text\n\t"                        \
1417d36db35SAvi Kivity 		);				   \
1427d36db35SAvi Kivity 	extern u8 insn_##name[], insn_##name##_end[]
1437d36db35SAvi Kivity 
1447d36db35SAvi Kivity void test_xchg(void)
1457d36db35SAvi Kivity {
1467d36db35SAvi Kivity 	struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}, outregs;
1477d36db35SAvi Kivity 
1487d36db35SAvi Kivity 	MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
1497d36db35SAvi Kivity 	MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
1507d36db35SAvi Kivity 	MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
1517d36db35SAvi Kivity 	MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
1527d36db35SAvi Kivity 	MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
1537d36db35SAvi Kivity 	MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
1547d36db35SAvi Kivity 	MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
1557d36db35SAvi Kivity 	MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
1567d36db35SAvi Kivity 
1577d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
1587d36db35SAvi Kivity 			      insn_xchg_test1,
1597d36db35SAvi Kivity                               insn_xchg_test1_end - insn_xchg_test1);
1607d36db35SAvi Kivity 
1617d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
1627d36db35SAvi Kivity 		print_serial("xchg test 1: FAIL\n");
1637d36db35SAvi Kivity 	else
1647d36db35SAvi Kivity 		print_serial("xchg test 1: PASS\n");
1657d36db35SAvi Kivity 
1667d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
1677d36db35SAvi Kivity 			      insn_xchg_test2,
1687d36db35SAvi Kivity                               insn_xchg_test2_end - insn_xchg_test2);
1697d36db35SAvi Kivity 
1707d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_BX) ||
1717d36db35SAvi Kivity             outregs.eax != inregs.ebx ||
1727d36db35SAvi Kivity             outregs.ebx != inregs.eax)
1737d36db35SAvi Kivity 		print_serial("xchg test 2: FAIL\n");
1747d36db35SAvi Kivity 	else
1757d36db35SAvi Kivity 		print_serial("xchg test 2: PASS\n");
1767d36db35SAvi Kivity 
1777d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
1787d36db35SAvi Kivity 			      insn_xchg_test3,
1797d36db35SAvi Kivity                               insn_xchg_test3_end - insn_xchg_test3);
1807d36db35SAvi Kivity 
1817d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_CX) ||
1827d36db35SAvi Kivity             outregs.eax != inregs.ecx ||
1837d36db35SAvi Kivity             outregs.ecx != inregs.eax)
1847d36db35SAvi Kivity 		print_serial("xchg test 3: FAIL\n");
1857d36db35SAvi Kivity 	else
1867d36db35SAvi Kivity 		print_serial("xchg test 3: PASS\n");
1877d36db35SAvi Kivity 
1887d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
1897d36db35SAvi Kivity 			      insn_xchg_test4,
1907d36db35SAvi Kivity                               insn_xchg_test4_end - insn_xchg_test4);
1917d36db35SAvi Kivity 
1927d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_DX) ||
1937d36db35SAvi Kivity             outregs.eax != inregs.edx ||
1947d36db35SAvi Kivity             outregs.edx != inregs.eax)
1957d36db35SAvi Kivity 		print_serial("xchg test 4: FAIL\n");
1967d36db35SAvi Kivity 	else
1977d36db35SAvi Kivity 		print_serial("xchg test 4: PASS\n");
1987d36db35SAvi Kivity 
1997d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2007d36db35SAvi Kivity 			      insn_xchg_test5,
2017d36db35SAvi Kivity                               insn_xchg_test5_end - insn_xchg_test5);
2027d36db35SAvi Kivity 
2037d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_SI) ||
2047d36db35SAvi Kivity             outregs.eax != inregs.esi ||
2057d36db35SAvi Kivity             outregs.esi != inregs.eax)
2067d36db35SAvi Kivity 		print_serial("xchg test 5: FAIL\n");
2077d36db35SAvi Kivity 	else
2087d36db35SAvi Kivity 		print_serial("xchg test 5: PASS\n");
2097d36db35SAvi Kivity 
2107d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2117d36db35SAvi Kivity 			      insn_xchg_test6,
2127d36db35SAvi Kivity                               insn_xchg_test6_end - insn_xchg_test6);
2137d36db35SAvi Kivity 
2147d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_DI) ||
2157d36db35SAvi Kivity             outregs.eax != inregs.edi ||
2167d36db35SAvi Kivity             outregs.edi != inregs.eax)
2177d36db35SAvi Kivity 		print_serial("xchg test 6: FAIL\n");
2187d36db35SAvi Kivity 	else
2197d36db35SAvi Kivity 		print_serial("xchg test 6: PASS\n");
2207d36db35SAvi Kivity 
2217d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2227d36db35SAvi Kivity 			      insn_xchg_test7,
2237d36db35SAvi Kivity                               insn_xchg_test7_end - insn_xchg_test7);
2247d36db35SAvi Kivity 
2257d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_BP) ||
2267d36db35SAvi Kivity             outregs.eax != inregs.ebp ||
2277d36db35SAvi Kivity             outregs.ebp != inregs.eax)
2287d36db35SAvi Kivity 		print_serial("xchg test 7: FAIL\n");
2297d36db35SAvi Kivity 	else
2307d36db35SAvi Kivity 		print_serial("xchg test 7: PASS\n");
2317d36db35SAvi Kivity 
2327d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2337d36db35SAvi Kivity 			      insn_xchg_test8,
2347d36db35SAvi Kivity                               insn_xchg_test8_end - insn_xchg_test8);
2357d36db35SAvi Kivity 
2367d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX | R_SP) ||
2377d36db35SAvi Kivity             outregs.eax != inregs.esp ||
2387d36db35SAvi Kivity             outregs.esp != inregs.eax)
2397d36db35SAvi Kivity 		print_serial("xchg test 8: FAIL\n");
2407d36db35SAvi Kivity 	else
2417d36db35SAvi Kivity 		print_serial("xchg test 8: PASS\n");
2427d36db35SAvi Kivity }
2437d36db35SAvi Kivity 
2447d36db35SAvi Kivity void test_shld(void)
2457d36db35SAvi Kivity {
2467d36db35SAvi Kivity 	struct regs inregs = { .eax = 0xbe, .edx = 0xef000000 }, outregs;
2477d36db35SAvi Kivity 	MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
2487d36db35SAvi Kivity 
2497d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2507d36db35SAvi Kivity 			      insn_shld_test,
2517d36db35SAvi Kivity 			      insn_shld_test_end - insn_shld_test);
2527d36db35SAvi Kivity 	if (outregs.eax != 0xbeef)
2537d36db35SAvi Kivity 		print_serial("shld: FAIL\n");
2547d36db35SAvi Kivity 	else
2557d36db35SAvi Kivity 		print_serial("shld: PASS\n");
2567d36db35SAvi Kivity }
2577d36db35SAvi Kivity 
2587d36db35SAvi Kivity void test_mov_imm(void)
2597d36db35SAvi Kivity {
2607d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
2617d36db35SAvi Kivity 	MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
2627d36db35SAvi Kivity 	MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
2637d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
2647d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
2657d36db35SAvi Kivity 	MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
2667d36db35SAvi Kivity 
2677d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2687d36db35SAvi Kivity 			      insn_mov_r16_imm_1,
2697d36db35SAvi Kivity 			      insn_mov_r16_imm_1_end - insn_mov_r16_imm_1);
2707d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234)
2717d36db35SAvi Kivity 		print_serial("mov test 1: FAIL\n");
2727d36db35SAvi Kivity 	else
2737d36db35SAvi Kivity 		print_serial("mov test 1: PASS\n");
2747d36db35SAvi Kivity 
2757d36db35SAvi Kivity 	/* test mov $imm, %eax */
2767d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2777d36db35SAvi Kivity 			      insn_mov_r32_imm_1,
2787d36db35SAvi Kivity 			      insn_mov_r32_imm_1_end - insn_mov_r32_imm_1);
2797d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567890)
2807d36db35SAvi Kivity 		print_serial("mov test 2: FAIL\n");
2817d36db35SAvi Kivity 	else
2827d36db35SAvi Kivity 		print_serial("mov test 2: PASS\n");
2837d36db35SAvi Kivity 
2847d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
2857d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2867d36db35SAvi Kivity 			      insn_mov_r8_imm_1,
2877d36db35SAvi Kivity 			      insn_mov_r8_imm_1_end - insn_mov_r8_imm_1);
2887d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1200)
2897d36db35SAvi Kivity 		print_serial("mov test 3: FAIL\n");
2907d36db35SAvi Kivity 	else
2917d36db35SAvi Kivity 		print_serial("mov test 3: PASS\n");
2927d36db35SAvi Kivity 
2937d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
2947d36db35SAvi Kivity 			      insn_mov_r8_imm_2,
2957d36db35SAvi Kivity 			      insn_mov_r8_imm_2_end - insn_mov_r8_imm_2);
2967d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x34)
2977d36db35SAvi Kivity 		print_serial("mov test 4: FAIL\n");
2987d36db35SAvi Kivity 	else
2997d36db35SAvi Kivity 		print_serial("mov test 4: PASS\n");
3007d36db35SAvi Kivity 
3017d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3027d36db35SAvi Kivity 			      insn_mov_r8_imm_3,
3037d36db35SAvi Kivity 			      insn_mov_r8_imm_3_end - insn_mov_r8_imm_3);
3047d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
3057d36db35SAvi Kivity 		print_serial("mov test 5: FAIL\n");
3067d36db35SAvi Kivity 	else
3077d36db35SAvi Kivity 		print_serial("mov test 5: PASS\n");
3087d36db35SAvi Kivity }
3097d36db35SAvi Kivity 
3107d36db35SAvi Kivity void test_sub_imm(void)
3117d36db35SAvi Kivity {
3127d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
3137d36db35SAvi Kivity 	MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
3147d36db35SAvi Kivity 	MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
3157d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
3167d36db35SAvi Kivity 	MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
3177d36db35SAvi Kivity 
3187d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3197d36db35SAvi Kivity 			      insn_sub_r16_imm_1,
3207d36db35SAvi Kivity 			      insn_sub_r16_imm_1_end - insn_sub_r16_imm_1);
3217d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1224)
3227d36db35SAvi Kivity 		print_serial("sub test 1: FAIL\n");
3237d36db35SAvi Kivity 	else
3247d36db35SAvi Kivity 		print_serial("sub test 1: PASS\n");
3257d36db35SAvi Kivity 
3267d36db35SAvi Kivity 	/* test mov $imm, %eax */
3277d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3287d36db35SAvi Kivity 			      insn_sub_r32_imm_1,
3297d36db35SAvi Kivity 			      insn_sub_r32_imm_1_end - insn_sub_r32_imm_1);
3307d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 1234567880)
3317d36db35SAvi Kivity 		print_serial("sub test 2: FAIL\n");
3327d36db35SAvi Kivity 	else
3337d36db35SAvi Kivity 		print_serial("sub test 2: PASS\n");
3347d36db35SAvi Kivity 
3357d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
3367d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3377d36db35SAvi Kivity 			      insn_sub_r8_imm_1,
3387d36db35SAvi Kivity 			      insn_sub_r8_imm_1_end - insn_sub_r8_imm_1);
3397d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x0200)
3407d36db35SAvi Kivity 		print_serial("sub test 3: FAIL\n");
3417d36db35SAvi Kivity 	else
3427d36db35SAvi Kivity 		print_serial("sub test 3: PASS\n");
3437d36db35SAvi Kivity 
3447d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3457d36db35SAvi Kivity 			      insn_sub_r8_imm_2,
3467d36db35SAvi Kivity 			      insn_sub_r8_imm_2_end - insn_sub_r8_imm_2);
3477d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x24)
3487d36db35SAvi Kivity 		print_serial("sub test 4: FAIL\n");
3497d36db35SAvi Kivity 	else
3507d36db35SAvi Kivity 		print_serial("sub test 4: PASS\n");
3517d36db35SAvi Kivity }
3527d36db35SAvi Kivity 
3537d36db35SAvi Kivity 
3547d36db35SAvi Kivity void test_xor_imm(void)
3557d36db35SAvi Kivity {
3567d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
3577d36db35SAvi Kivity 	MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
3587d36db35SAvi Kivity 	MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
3597d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
3607d36db35SAvi Kivity 	MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
3617d36db35SAvi Kivity 
3627d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3637d36db35SAvi Kivity 			      insn_xor_r16_imm_1,
3647d36db35SAvi Kivity 			      insn_xor_r16_imm_1_end - insn_xor_r16_imm_1);
3657d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3667d36db35SAvi Kivity 		print_serial("xor test 1: FAIL\n");
3677d36db35SAvi Kivity 	else
3687d36db35SAvi Kivity 		print_serial("xor test 1: PASS\n");
3697d36db35SAvi Kivity 
3707d36db35SAvi Kivity 	/* test mov $imm, %eax */
3717d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3727d36db35SAvi Kivity 			      insn_xor_r32_imm_1,
3737d36db35SAvi Kivity 			      insn_xor_r32_imm_1_end - insn_xor_r32_imm_1);
3747d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3757d36db35SAvi Kivity 		print_serial("xor test 2: FAIL\n");
3767d36db35SAvi Kivity 	else
3777d36db35SAvi Kivity 		print_serial("xor test 2: PASS\n");
3787d36db35SAvi Kivity 
3797d36db35SAvi Kivity 	/* test mov $imm, %al/%ah */
3807d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3817d36db35SAvi Kivity 			      insn_xor_r8_imm_1,
3827d36db35SAvi Kivity 			      insn_xor_r8_imm_1_end - insn_xor_r8_imm_1);
3837d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3847d36db35SAvi Kivity 		print_serial("xor test 3: FAIL\n");
3857d36db35SAvi Kivity 	else
3867d36db35SAvi Kivity 		print_serial("xor test 3: PASS\n");
3877d36db35SAvi Kivity 
3887d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
3897d36db35SAvi Kivity 			      insn_xor_r8_imm_2,
3907d36db35SAvi Kivity 			      insn_xor_r8_imm_2_end - insn_xor_r8_imm_2);
3917d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0)
3927d36db35SAvi Kivity 		print_serial("xor test 4: FAIL\n");
3937d36db35SAvi Kivity 	else
3947d36db35SAvi Kivity 		print_serial("xor test 4: PASS\n");
3957d36db35SAvi Kivity }
3967d36db35SAvi Kivity 
3977d36db35SAvi Kivity void test_cmp_imm(void)
3987d36db35SAvi Kivity {
3997d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
4007d36db35SAvi Kivity 	MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
4017d36db35SAvi Kivity 			   "cmp $0x34, %al\n\t");
4027d36db35SAvi Kivity 	MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
4037d36db35SAvi Kivity 			   "cmp $0x39, %al\n\t");
4047d36db35SAvi Kivity 	MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
4057d36db35SAvi Kivity 			   "cmp $0x24, %al\n\t");
4067d36db35SAvi Kivity 
4077d36db35SAvi Kivity 	/* test cmp imm8 with AL */
4087d36db35SAvi Kivity 	/* ZF: (bit 6) Zero Flag becomes 1 if an operation results
4097d36db35SAvi Kivity 	 * in a 0 writeback, or 0 register
4107d36db35SAvi Kivity 	 */
4117d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4127d36db35SAvi Kivity 			      insn_cmp_test1,
4137d36db35SAvi Kivity 			      insn_cmp_test1_end - insn_cmp_test1);
4147d36db35SAvi Kivity 	if ((outregs.eflags & (1<<6)) != (1<<6))
4157d36db35SAvi Kivity 		print_serial("cmp test 1: FAIL\n");
4167d36db35SAvi Kivity 	else
4177d36db35SAvi Kivity 		print_serial("cmp test 1: PASS\n");
4187d36db35SAvi Kivity 
4197d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4207d36db35SAvi Kivity 			      insn_cmp_test2,
4217d36db35SAvi Kivity 			      insn_cmp_test2_end - insn_cmp_test2);
4227d36db35SAvi Kivity 	if ((outregs.eflags & (1<<6)) != 0)
4237d36db35SAvi Kivity 		print_serial("cmp test 2: FAIL\n");
4247d36db35SAvi Kivity 	else
4257d36db35SAvi Kivity 		print_serial("cmp test 2: PASS\n");
4267d36db35SAvi Kivity 
4277d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4287d36db35SAvi Kivity 			      insn_cmp_test3,
4297d36db35SAvi Kivity 			      insn_cmp_test3_end - insn_cmp_test3);
4307d36db35SAvi Kivity 	if ((outregs.eflags & (1<<6)) != 0)
4317d36db35SAvi Kivity 		print_serial("cmp test 3: FAIL\n");
4327d36db35SAvi Kivity 	else
4337d36db35SAvi Kivity 		print_serial("cmp test 3: PASS\n");
4347d36db35SAvi Kivity }
4357d36db35SAvi Kivity 
4367d36db35SAvi Kivity void test_add_imm(void)
4377d36db35SAvi Kivity {
4387d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
4397d36db35SAvi Kivity 	MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
4407d36db35SAvi Kivity 			   "add $0x12344321, %eax \n\t");
4417d36db35SAvi Kivity 	MK_INSN(add_test2, "mov $0x12, %eax \n\t"
4427d36db35SAvi Kivity 			   "add $0x21, %al\n\t");
4437d36db35SAvi Kivity 
4447d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4457d36db35SAvi Kivity 			      insn_add_test1,
4467d36db35SAvi Kivity 			      insn_add_test1_end - insn_add_test1);
4477d36db35SAvi Kivity 	if (outregs.eax != 0x55555555)
4487d36db35SAvi Kivity 		print_serial("add test 1: FAIL\n");
4497d36db35SAvi Kivity 	else
4507d36db35SAvi Kivity 		print_serial("add test 1: PASS\n");
4517d36db35SAvi Kivity 
4527d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4537d36db35SAvi Kivity 			      insn_add_test2,
4547d36db35SAvi Kivity 			      insn_add_test2_end - insn_add_test2);
4557d36db35SAvi Kivity 	if (outregs.eax != 0x33)
4567d36db35SAvi Kivity 		print_serial("add test 2: FAIL\n");
4577d36db35SAvi Kivity 	else
4587d36db35SAvi Kivity 		print_serial("add test 2: PASS\n");
4597d36db35SAvi Kivity }
4607d36db35SAvi Kivity 
4617d36db35SAvi Kivity void test_eflags_insn(void)
4627d36db35SAvi Kivity {
4637d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
4647d36db35SAvi Kivity 	MK_INSN(clc, "clc");
4657d36db35SAvi Kivity 	MK_INSN(cli, "cli");
4667d36db35SAvi Kivity 	MK_INSN(sti, "sti");
4677d36db35SAvi Kivity 	MK_INSN(cld, "cld");
4687d36db35SAvi Kivity 	MK_INSN(std, "std");
4697d36db35SAvi Kivity 
4707d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4717d36db35SAvi Kivity 			      insn_clc,
4727d36db35SAvi Kivity 			      insn_clc_end - insn_clc);
4737d36db35SAvi Kivity 	if (outregs.eflags & 1)
4747d36db35SAvi Kivity 		print_serial("clc test: FAIL\n");
4757d36db35SAvi Kivity 	else
4767d36db35SAvi Kivity 		print_serial("clc test: PASS\n");
4777d36db35SAvi Kivity 
4787d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4797d36db35SAvi Kivity 			      insn_cli,
4807d36db35SAvi Kivity 			      insn_cli_end - insn_cli);
4817d36db35SAvi Kivity 	if (outregs.eflags & (1 << 9))
4827d36db35SAvi Kivity 		print_serial("cli test: FAIL\n");
4837d36db35SAvi Kivity 	else
4847d36db35SAvi Kivity 		print_serial("cli test: PASS\n");
4857d36db35SAvi Kivity 
4867d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4877d36db35SAvi Kivity 			      insn_sti,
4887d36db35SAvi Kivity 			      insn_sti_end - insn_sti);
4897d36db35SAvi Kivity 	if (!(outregs.eflags & (1 << 9)))
4907d36db35SAvi Kivity 		print_serial("sti test: FAIL\n");
4917d36db35SAvi Kivity 	else
4927d36db35SAvi Kivity 		print_serial("sti test: PASS\n");
4937d36db35SAvi Kivity 
4947d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
4957d36db35SAvi Kivity 			      insn_cld,
4967d36db35SAvi Kivity 			      insn_cld_end - insn_cld);
4977d36db35SAvi Kivity 	if (outregs.eflags & (1 << 10))
4987d36db35SAvi Kivity 		print_serial("cld test: FAIL\n");
4997d36db35SAvi Kivity 	else
5007d36db35SAvi Kivity 		print_serial("cld test: PASS\n");
5017d36db35SAvi Kivity 
5027d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5037d36db35SAvi Kivity 			      insn_std,
5047d36db35SAvi Kivity 			      insn_std_end - insn_std);
5057d36db35SAvi Kivity 	if (!(outregs.eflags & (1 << 10)))
5067d36db35SAvi Kivity 		print_serial("std test: FAIL\n");
5077d36db35SAvi Kivity 	else
5087d36db35SAvi Kivity 		print_serial("std test: PASS\n");
5097d36db35SAvi Kivity }
5107d36db35SAvi Kivity 
5117d36db35SAvi Kivity void test_io(void)
5127d36db35SAvi Kivity {
5137d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
5147d36db35SAvi Kivity 	MK_INSN(io_test1, "mov $0xff, %al \n\t"
5157d36db35SAvi Kivity 		          "out %al, $0xe0 \n\t"
5167d36db35SAvi Kivity 		          "mov $0x00, %al \n\t"
5177d36db35SAvi Kivity 			  "in $0xe0, %al \n\t");
5187d36db35SAvi Kivity 	MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
5197d36db35SAvi Kivity 			  "out %ax, $0xe0 \n\t"
5207d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
5217d36db35SAvi Kivity 			  "in $0xe0, %ax \n\t");
5227d36db35SAvi Kivity 	MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
5237d36db35SAvi Kivity 			  "out %eax, $0xe0 \n\t"
5247d36db35SAvi Kivity 			  "mov $0x000000, %eax \n\t"
5257d36db35SAvi Kivity 			  "in $0xe0, %eax \n\t");
5267d36db35SAvi Kivity 	MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
5277d36db35SAvi Kivity 			  "mov $0xff, %al \n\t"
5287d36db35SAvi Kivity 			  "out %al, %dx \n\t"
5297d36db35SAvi Kivity 			  "mov $0x00, %al \n\t"
5307d36db35SAvi Kivity 			  "in %dx, %al \n\t");
5317d36db35SAvi Kivity 	MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
5327d36db35SAvi Kivity 			  "mov $0xffff, %ax \n\t"
5337d36db35SAvi Kivity 			  "out %ax, %dx \n\t"
5347d36db35SAvi Kivity 			  "mov $0x0000, %ax \n\t"
5357d36db35SAvi Kivity 			  "in %dx, %ax \n\t");
5367d36db35SAvi Kivity 	MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
5377d36db35SAvi Kivity 			  "mov $0xffffffff, %eax \n\t"
5387d36db35SAvi Kivity 			  "out %eax, %dx \n\t"
5397d36db35SAvi Kivity 			  "mov $0x00000000, %eax \n\t"
5407d36db35SAvi Kivity 			  "in %dx, %eax \n\t");
5417d36db35SAvi Kivity 
5427d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5437d36db35SAvi Kivity 			      insn_io_test1,
5447d36db35SAvi Kivity 			      insn_io_test1_end - insn_io_test1);
5457d36db35SAvi Kivity 
5467d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xff)
5477d36db35SAvi Kivity 		print_serial("I/O test 1: FAIL\n");
5487d36db35SAvi Kivity 	else
5497d36db35SAvi Kivity 		print_serial("I/O test 1: PASS\n");
5507d36db35SAvi Kivity 
5517d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5527d36db35SAvi Kivity 			      insn_io_test2,
5537d36db35SAvi Kivity 			      insn_io_test2_end - insn_io_test2);
5547d36db35SAvi Kivity 
5557d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffff)
5567d36db35SAvi Kivity 		print_serial("I/O test 2: FAIL\n");
5577d36db35SAvi Kivity 	else
5587d36db35SAvi Kivity 		print_serial("I/O test 2: PASS\n");
5597d36db35SAvi Kivity 
5607d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5617d36db35SAvi Kivity 			      insn_io_test3,
5627d36db35SAvi Kivity 			      insn_io_test3_end - insn_io_test3);
5637d36db35SAvi Kivity 
5647d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0xffffffff)
5657d36db35SAvi Kivity 		print_serial("I/O test 3: FAIL\n");
5667d36db35SAvi Kivity 	else
5677d36db35SAvi Kivity 		print_serial("I/O test 3: PASS\n");
5687d36db35SAvi Kivity 
5697d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5707d36db35SAvi Kivity 			      insn_io_test4,
5717d36db35SAvi Kivity 			      insn_io_test4_end - insn_io_test4);
5727d36db35SAvi Kivity 
5737d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xff)
5747d36db35SAvi Kivity 		print_serial("I/O test 4: FAIL\n");
5757d36db35SAvi Kivity 	else
5767d36db35SAvi Kivity 		print_serial("I/O test 4: PASS\n");
5777d36db35SAvi Kivity 
5787d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5797d36db35SAvi Kivity 			      insn_io_test5,
5807d36db35SAvi Kivity 			      insn_io_test5_end - insn_io_test5);
5817d36db35SAvi Kivity 
5827d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffff)
5837d36db35SAvi Kivity 		print_serial("I/O test 5: FAIL\n");
5847d36db35SAvi Kivity 	else
5857d36db35SAvi Kivity 		print_serial("I/O test 5: PASS\n");
5867d36db35SAvi Kivity 
5877d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
5887d36db35SAvi Kivity 			      insn_io_test6,
5897d36db35SAvi Kivity 			      insn_io_test6_end - insn_io_test6);
5907d36db35SAvi Kivity 
5917d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_DX) || outregs.eax != 0xffffffff)
5927d36db35SAvi Kivity 		print_serial("I/O test 6: FAIL\n");
5937d36db35SAvi Kivity 	else
5947d36db35SAvi Kivity 		print_serial("I/O test 6: PASS\n");
5957d36db35SAvi Kivity }
5967d36db35SAvi Kivity 
5977d36db35SAvi Kivity void test_call(void)
5987d36db35SAvi Kivity {
5997d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
6007d36db35SAvi Kivity 	u32 esp[16];
6017d36db35SAvi Kivity 
6027d36db35SAvi Kivity 	inregs.esp = (u32)esp;
6037d36db35SAvi Kivity 
6047d36db35SAvi Kivity 	MK_INSN(call1, "mov $test_function, %eax \n\t"
6057d36db35SAvi Kivity 		       "call *%eax\n\t");
6067d36db35SAvi Kivity 	MK_INSN(call_near1, "jmp 2f\n\t"
6077d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
6087d36db35SAvi Kivity 			    "ret\n\t"
6097d36db35SAvi Kivity 			    "2: call 1b\t");
6107d36db35SAvi Kivity 	MK_INSN(call_near2, "call 1f\n\t"
6117d36db35SAvi Kivity 			    "jmp 2f\n\t"
6127d36db35SAvi Kivity 			    "1: mov $0x1234, %eax\n\t"
6137d36db35SAvi Kivity 			    "ret\n\t"
6147d36db35SAvi Kivity 			    "2:\t");
6157d36db35SAvi Kivity 
6167d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6177d36db35SAvi Kivity 			      insn_call1,
6187d36db35SAvi Kivity 			      insn_call1_end - insn_call1);
6197d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
6207d36db35SAvi Kivity 		print_serial("Call Test 1: FAIL\n");
6217d36db35SAvi Kivity 	else
6227d36db35SAvi Kivity 		print_serial("Call Test 1: PASS\n");
6237d36db35SAvi Kivity 
6247d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6257d36db35SAvi Kivity 			insn_call_near1, insn_call_near1_end - insn_call_near1);
6267d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
6277d36db35SAvi Kivity 		print_serial("Call near Test 1: FAIL\n");
6287d36db35SAvi Kivity 	else
6297d36db35SAvi Kivity 		print_serial("Call near Test 1: PASS\n");
6307d36db35SAvi Kivity 
6317d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6327d36db35SAvi Kivity 			insn_call_near2, insn_call_near2_end - insn_call_near2);
6337d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
6347d36db35SAvi Kivity 		print_serial("Call near Test 2: FAIL\n");
6357d36db35SAvi Kivity 	else
6367d36db35SAvi Kivity 		print_serial("Call near Test 2: PASS\n");
6377d36db35SAvi Kivity }
6387d36db35SAvi Kivity 
6397d36db35SAvi Kivity void test_jcc_short(void)
6407d36db35SAvi Kivity {
6417d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
6427d36db35SAvi Kivity 	MK_INSN(jnz_short1, "jnz 1f\n\t"
6437d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
6447d36db35SAvi Kivity 		            "1:\n\t");
6457d36db35SAvi Kivity 	MK_INSN(jnz_short2, "1:\n\t"
6467d36db35SAvi Kivity 			    "cmp $0x1234, %eax\n\t"
6477d36db35SAvi Kivity 			    "mov $0x1234, %eax\n\t"
6487d36db35SAvi Kivity 		            "jnz 1b\n\t");
6497d36db35SAvi Kivity 	MK_INSN(jmp_short1, "jmp 1f\n\t"
6507d36db35SAvi Kivity 		      "mov $0x1234, %eax\n\t"
6517d36db35SAvi Kivity 		      "1:\n\t");
6527d36db35SAvi Kivity 
6537d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6547d36db35SAvi Kivity 			insn_jnz_short1, insn_jnz_short1_end - insn_jnz_short1);
6557d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6567d36db35SAvi Kivity 		print_serial("JNZ short Test 1: FAIL\n");
6577d36db35SAvi Kivity 	else
6587d36db35SAvi Kivity 		print_serial("JNZ short Test 1: PASS\n");
6597d36db35SAvi Kivity 
6607d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6617d36db35SAvi Kivity 			insn_jnz_short2, insn_jnz_short2_end - insn_jnz_short2);
6627d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6)))
6637d36db35SAvi Kivity 		print_serial("JNZ short Test 2: FAIL\n");
6647d36db35SAvi Kivity 	else
6657d36db35SAvi Kivity 		print_serial("JNZ short Test 2: PASS\n");
6667d36db35SAvi Kivity 
6677d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6687d36db35SAvi Kivity 			insn_jmp_short1, insn_jmp_short1_end - insn_jmp_short1);
6697d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6707d36db35SAvi Kivity 		print_serial("JMP short Test 1: FAIL\n");
6717d36db35SAvi Kivity 	else
6727d36db35SAvi Kivity 		print_serial("JMP short Test 1: PASS\n");
6737d36db35SAvi Kivity }
6747d36db35SAvi Kivity 
6757d36db35SAvi Kivity void test_jcc_near(void)
6767d36db35SAvi Kivity {
6777d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
6787d36db35SAvi Kivity 	/* encode near jmp manually. gas will not do it if offsets < 127 byte */
6797d36db35SAvi Kivity 	MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
6807d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6817d36db35SAvi Kivity 	MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
6827d36db35SAvi Kivity 			   "mov $0x1234, %eax\n\t"
6837d36db35SAvi Kivity 		           ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
6847d36db35SAvi Kivity 	MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
6857d36db35SAvi Kivity 		           "mov $0x1234, %eax\n\t");
6867d36db35SAvi Kivity 
6877d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6887d36db35SAvi Kivity 			insn_jnz_near1, insn_jnz_near1_end - insn_jnz_near1);
6897d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
6907d36db35SAvi Kivity 		print_serial("JNZ near Test 1: FAIL\n");
6917d36db35SAvi Kivity 	else
6927d36db35SAvi Kivity 		print_serial("JNZ near Test 1: PASS\n");
6937d36db35SAvi Kivity 
6947d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
6957d36db35SAvi Kivity 			insn_jnz_near2, insn_jnz_near2_end - insn_jnz_near2);
6967d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || !(outregs.eflags & (1 << 6)))
6977d36db35SAvi Kivity 		print_serial("JNZ near Test 2: FAIL\n");
6987d36db35SAvi Kivity 	else
6997d36db35SAvi Kivity 		print_serial("JNZ near Test 2: PASS\n");
7007d36db35SAvi Kivity 
7017d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7027d36db35SAvi Kivity 			insn_jmp_near1, insn_jmp_near1_end - insn_jmp_near1);
7037d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, 0))
7047d36db35SAvi Kivity 		print_serial("JMP near Test 1: FAIL\n");
7057d36db35SAvi Kivity 	else
7067d36db35SAvi Kivity 		print_serial("JMP near Test 1: PASS\n");
7077d36db35SAvi Kivity }
7087d36db35SAvi Kivity 
7097d36db35SAvi Kivity void test_long_jmp()
7107d36db35SAvi Kivity {
7117d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
7127d36db35SAvi Kivity 	u32 esp[16];
7137d36db35SAvi Kivity 
7147d36db35SAvi Kivity 	inregs.esp = (u32)esp;
7157d36db35SAvi Kivity 	MK_INSN(long_jmp, "call 1f\n\t"
7167d36db35SAvi Kivity 			  "jmp 2f\n\t"
7177d36db35SAvi Kivity 			  "1: jmp $0, $test_function\n\t"
7187d36db35SAvi Kivity 		          "2:\n\t");
7197d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7207d36db35SAvi Kivity 			      insn_long_jmp,
7217d36db35SAvi Kivity 			      insn_long_jmp_end - insn_long_jmp);
7227d36db35SAvi Kivity 	if(!regs_equal(&inregs, &outregs, R_AX) || outregs.eax != 0x1234)
7237d36db35SAvi Kivity 		print_serial("Long JMP Test: FAIL\n");
7247d36db35SAvi Kivity 	else
7257d36db35SAvi Kivity 		print_serial("Long JMP Test: PASS\n");
7267d36db35SAvi Kivity }
7277d36db35SAvi Kivity void test_push_pop()
7287d36db35SAvi Kivity {
7297d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
7307d36db35SAvi Kivity 	MK_INSN(push32, "mov $0x12345678, %eax\n\t"
7317d36db35SAvi Kivity 			"push %eax\n\t"
7327d36db35SAvi Kivity 			"pop %ebx\n\t");
7337d36db35SAvi Kivity 	MK_INSN(push16, "mov $0x1234, %ax\n\t"
7347d36db35SAvi Kivity 			"push %ax\n\t"
7357d36db35SAvi Kivity 			"pop %bx\n\t");
7367d36db35SAvi Kivity 
7377d36db35SAvi Kivity 	MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
7387d36db35SAvi Kivity 			 "mov $0x123, %ax\n\t"
7397d36db35SAvi Kivity 			 "mov %ax, %es\n\t"
7407d36db35SAvi Kivity 			 "push %es\n\t"
7417d36db35SAvi Kivity 			 "pop %bx \n\t"
7427d36db35SAvi Kivity 			 );
7437d36db35SAvi Kivity 	MK_INSN(pop_es, "push %ax\n\t"
7447d36db35SAvi Kivity 			"pop %es\n\t"
7457d36db35SAvi Kivity 			"mov %es, %bx\n\t"
7467d36db35SAvi Kivity 			);
7477d36db35SAvi Kivity 	MK_INSN(push_pop_ss, "push %ss\n\t"
7487d36db35SAvi Kivity 			     "pushw %ax\n\t"
7497d36db35SAvi Kivity 			     "popw %ss\n\t"
7507d36db35SAvi Kivity 			     "mov %ss, %bx\n\t"
7517d36db35SAvi Kivity 			     "pop %ss\n\t"
7527d36db35SAvi Kivity 			);
7537d36db35SAvi Kivity 	MK_INSN(push_pop_fs, "push %fs\n\t"
7547d36db35SAvi Kivity 			     "pushl %eax\n\t"
7557d36db35SAvi Kivity 			     "popl %fs\n\t"
7567d36db35SAvi Kivity 			     "mov %fs, %ebx\n\t"
7577d36db35SAvi Kivity 			     "pop %fs\n\t"
7587d36db35SAvi Kivity 			);
7597d36db35SAvi Kivity 
7607d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7617d36db35SAvi Kivity 			      insn_push32,
7627d36db35SAvi Kivity 			      insn_push32_end - insn_push32);
7637d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x12345678)
7647d36db35SAvi Kivity 		print_serial("Push/Pop Test 1: FAIL\n");
7657d36db35SAvi Kivity 	else
7667d36db35SAvi Kivity 		print_serial("Push/Pop Test 1: PASS\n");
7677d36db35SAvi Kivity 
7687d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7697d36db35SAvi Kivity 			      insn_push16,
7707d36db35SAvi Kivity 			      insn_push16_end - insn_push16);
7717d36db35SAvi Kivity 
7727d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.eax != outregs.ebx || outregs.eax != 0x1234)
7737d36db35SAvi Kivity 		print_serial("Push/Pop Test 2: FAIL\n");
7747d36db35SAvi Kivity 	else
7757d36db35SAvi Kivity 		print_serial("Push/Pop Test 2: PASS\n");
7767d36db35SAvi Kivity 
7777d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7787d36db35SAvi Kivity 			      insn_push_es,
7797d36db35SAvi Kivity 			      insn_push_es_end - insn_push_es);
7807d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) ||  outregs.ebx != outregs.eax || outregs.eax != 0x123)
7817d36db35SAvi Kivity 		print_serial("Push/Pop Test 3: FAIL\n");
7827d36db35SAvi Kivity 	else
7837d36db35SAvi Kivity 		print_serial("Push/Pop Test 3: PASS\n");
7847d36db35SAvi Kivity 
7857d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7867d36db35SAvi Kivity 			      insn_pop_es,
7877d36db35SAvi Kivity 			      insn_pop_es_end - insn_pop_es);
7887d36db35SAvi Kivity 
7897d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
7907d36db35SAvi Kivity 		print_serial("Push/Pop Test 4: FAIL\n");
7917d36db35SAvi Kivity 	else
7927d36db35SAvi Kivity 		print_serial("Push/Pop Test 4: PASS\n");
7937d36db35SAvi Kivity 
7947d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
7957d36db35SAvi Kivity 			      insn_push_pop_ss,
7967d36db35SAvi Kivity 			      insn_push_pop_ss_end - insn_push_pop_ss);
7977d36db35SAvi Kivity 
7987d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
7997d36db35SAvi Kivity 		print_serial("Push/Pop Test 5: FAIL\n");
8007d36db35SAvi Kivity 	else
8017d36db35SAvi Kivity 		print_serial("Push/Pop Test 5: PASS\n");
8027d36db35SAvi Kivity 
8037d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
8047d36db35SAvi Kivity 			      insn_push_pop_fs,
8057d36db35SAvi Kivity 			      insn_push_pop_fs_end - insn_push_pop_fs);
8067d36db35SAvi Kivity 
8077d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX|R_BX) || outregs.ebx != outregs.eax)
8087d36db35SAvi Kivity 		print_serial("Push/Pop Test 6: FAIL\n");
8097d36db35SAvi Kivity 	else
8107d36db35SAvi Kivity 		print_serial("Push/Pop Test 6: PASS\n");
8117d36db35SAvi Kivity }
8127d36db35SAvi Kivity 
8137d36db35SAvi Kivity void test_null(void)
8147d36db35SAvi Kivity {
8157d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
8167d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs, 0, 0);
8177d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
8187d36db35SAvi Kivity 		print_serial("null test: FAIL\n");
8197d36db35SAvi Kivity 	else
8207d36db35SAvi Kivity 		print_serial("null test: PASS\n");
8217d36db35SAvi Kivity }
8227d36db35SAvi Kivity 
8237d36db35SAvi Kivity struct {
8247d36db35SAvi Kivity     char stack[500];
8257d36db35SAvi Kivity     char top[];
8267d36db35SAvi Kivity } tmp_stack;
8277d36db35SAvi Kivity 
8287d36db35SAvi Kivity void test_pusha_popa()
8297d36db35SAvi Kivity {
8307d36db35SAvi Kivity 	struct regs inregs = { .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }, outregs;
8317d36db35SAvi Kivity 
8327d36db35SAvi Kivity 	MK_INSN(pusha, "pusha\n\t"
8337d36db35SAvi Kivity 		       "pop %edi\n\t"
8347d36db35SAvi Kivity 		       "pop %esi\n\t"
8357d36db35SAvi Kivity 		       "pop %ebp\n\t"
8367d36db35SAvi Kivity 		       "add $4, %esp\n\t"
8377d36db35SAvi Kivity 		       "pop %ebx\n\t"
8387d36db35SAvi Kivity 		       "pop %edx\n\t"
8397d36db35SAvi Kivity 		       "pop %ecx\n\t"
8407d36db35SAvi Kivity 		       "pop %eax\n\t"
8417d36db35SAvi Kivity 		       );
8427d36db35SAvi Kivity 
8437d36db35SAvi Kivity 	MK_INSN(popa, "push %eax\n\t"
8447d36db35SAvi Kivity 		      "push %ecx\n\t"
8457d36db35SAvi Kivity 		      "push %edx\n\t"
8467d36db35SAvi Kivity 		      "push %ebx\n\t"
8477d36db35SAvi Kivity 		      "push %esp\n\t"
8487d36db35SAvi Kivity 		      "push %ebp\n\t"
8497d36db35SAvi Kivity 		      "push %esi\n\t"
8507d36db35SAvi Kivity 		      "push %edi\n\t"
8517d36db35SAvi Kivity 		      "popa\n\t"
8527d36db35SAvi Kivity 		      );
8537d36db35SAvi Kivity 
8547d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
8557d36db35SAvi Kivity 			      insn_pusha,
8567d36db35SAvi Kivity 			      insn_pusha_end - insn_pusha);
8577d36db35SAvi Kivity 
8587d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
8597d36db35SAvi Kivity 		print_serial("Pusha/Popa Test1: FAIL\n");
8607d36db35SAvi Kivity 	else
8617d36db35SAvi Kivity 		print_serial("Pusha/Popa Test1: PASS\n");
8627d36db35SAvi Kivity 
8637d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
8647d36db35SAvi Kivity 			      insn_popa,
8657d36db35SAvi Kivity 			      insn_popa_end - insn_popa);
8667d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
8677d36db35SAvi Kivity 		print_serial("Pusha/Popa Test2: FAIL\n");
8687d36db35SAvi Kivity 	else
8697d36db35SAvi Kivity 		print_serial("Pusha/Popa Test2: PASS\n");
8707d36db35SAvi Kivity }
8717d36db35SAvi Kivity 
8727d36db35SAvi Kivity void test_iret()
8737d36db35SAvi Kivity {
8747d36db35SAvi Kivity 	struct regs inregs = { 0 }, outregs;
8757d36db35SAvi Kivity 
8767d36db35SAvi Kivity 	MK_INSN(iret32, "pushf\n\t"
8777d36db35SAvi Kivity 			"pushl %cs\n\t"
8787d36db35SAvi Kivity 			"call 1f\n\t" /* a near call will push eip onto the stack */
8797d36db35SAvi Kivity 			"jmp 2f\n\t"
8807d36db35SAvi Kivity 			"1: iret\n\t"
8817d36db35SAvi Kivity 			"2:\n\t"
8827d36db35SAvi Kivity 		     );
8837d36db35SAvi Kivity 
8847d36db35SAvi Kivity 	MK_INSN(iret16, "pushfw\n\t"
8857d36db35SAvi Kivity 			"pushw %cs\n\t"
8867d36db35SAvi Kivity 			"callw 1f\n\t"
8877d36db35SAvi Kivity 			"jmp 2f\n\t"
8887d36db35SAvi Kivity 			"1: iretw\n\t"
8897d36db35SAvi Kivity 			"2:\n\t");
8907d36db35SAvi Kivity 
8917d36db35SAvi Kivity 	MK_INSN(iret_flags32, "pushfl\n\t"
8927d36db35SAvi Kivity 			      "popl %eax\n\t"
8937d36db35SAvi Kivity 			      "andl $~0x2, %eax\n\t"
8947d36db35SAvi Kivity 			      "orl $0xffc08028, %eax\n\t"
8957d36db35SAvi Kivity 			      "pushl %eax\n\t"
8967d36db35SAvi Kivity 			      "pushl %cs\n\t"
8977d36db35SAvi Kivity 			      "call 1f\n\t"
8987d36db35SAvi Kivity 			      "jmp 2f\n\t"
8997d36db35SAvi Kivity 			      "1: iret\n\t"
9007d36db35SAvi Kivity 			      "2:\n\t");
9017d36db35SAvi Kivity 
9027d36db35SAvi Kivity 	MK_INSN(iret_flags16, "pushfw\n\t"
9037d36db35SAvi Kivity 			      "popw %ax\n\t"
9047d36db35SAvi Kivity 			      "and $~0x2, %ax\n\t"
9057d36db35SAvi Kivity 			      "or $0x8028, %ax\n\t"
9067d36db35SAvi Kivity 			      "pushw %ax\n\t"
9077d36db35SAvi Kivity 			      "pushw %cs\n\t"
9087d36db35SAvi Kivity 			      "callw 1f\n\t"
9097d36db35SAvi Kivity 			      "jmp 2f\n\t"
9107d36db35SAvi Kivity 			      "1: iretw\n\t"
9117d36db35SAvi Kivity 			      "2:\n\t");
9127d36db35SAvi Kivity 
9137d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
9147d36db35SAvi Kivity 			      insn_iret32,
9157d36db35SAvi Kivity 			      insn_iret32_end - insn_iret32);
9167d36db35SAvi Kivity 
9177d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
9187d36db35SAvi Kivity 		print_serial("iret Test 1: FAIL\n");
9197d36db35SAvi Kivity 	else
9207d36db35SAvi Kivity 		print_serial("iret Test 1: PASS\n");
9217d36db35SAvi Kivity 
9227d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
9237d36db35SAvi Kivity 			      insn_iret16,
9247d36db35SAvi Kivity 			      insn_iret16_end - insn_iret16);
9257d36db35SAvi Kivity 
9267d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, 0))
9277d36db35SAvi Kivity 		print_serial("iret Test 2: FAIL\n");
9287d36db35SAvi Kivity 	else
9297d36db35SAvi Kivity 		print_serial("iret Test 2: PASS\n");
9307d36db35SAvi Kivity 
9317d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
9327d36db35SAvi Kivity 			      insn_iret_flags32,
9337d36db35SAvi Kivity 			      insn_iret_flags32_end - insn_iret_flags32);
9347d36db35SAvi Kivity 
9357d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX))
9367d36db35SAvi Kivity 		print_serial("iret Test 3: FAIL\n");
9377d36db35SAvi Kivity 	else
9387d36db35SAvi Kivity 		print_serial("iret Test 3: PASS\n");
9397d36db35SAvi Kivity 
9407d36db35SAvi Kivity 	exec_in_big_real_mode(&inregs, &outregs,
9417d36db35SAvi Kivity 			      insn_iret_flags16,
9427d36db35SAvi Kivity 			      insn_iret_flags16_end - insn_iret_flags16);
9437d36db35SAvi Kivity 
9447d36db35SAvi Kivity 	if (!regs_equal(&inregs, &outregs, R_AX))
9457d36db35SAvi Kivity 		print_serial("iret Test 4: FAIL\n");
9467d36db35SAvi Kivity 	else
9477d36db35SAvi Kivity 		print_serial("iret Test 4: PASS\n");
9487d36db35SAvi Kivity }
9497d36db35SAvi Kivity 
950*96b9ca1eSMohammed Gamal void test_int()
951*96b9ca1eSMohammed Gamal {
952*96b9ca1eSMohammed Gamal 	struct regs inregs = { 0 }, outregs;
953*96b9ca1eSMohammed Gamal 
954*96b9ca1eSMohammed Gamal 	*(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
955*96b9ca1eSMohammed Gamal 	*(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
956*96b9ca1eSMohammed Gamal 
957*96b9ca1eSMohammed Gamal 	MK_INSN(int11, "int $0x11\n\t");
958*96b9ca1eSMohammed Gamal 
959*96b9ca1eSMohammed Gamal 	exec_in_big_real_mode(&inregs, &outregs,
960*96b9ca1eSMohammed Gamal 			      insn_int11,
961*96b9ca1eSMohammed Gamal 			      insn_int11_end - insn_int11);
962*96b9ca1eSMohammed Gamal 
963*96b9ca1eSMohammed Gamal 	if (!regs_equal(&inregs, &outregs, 0))
964*96b9ca1eSMohammed Gamal 		print_serial("int Test 1: FAIL\n");
965*96b9ca1eSMohammed Gamal 	else
966*96b9ca1eSMohammed Gamal 		print_serial("int Test 1: PASS\n");
967*96b9ca1eSMohammed Gamal }
968*96b9ca1eSMohammed Gamal 
9697d36db35SAvi Kivity void realmode_start(void)
9707d36db35SAvi Kivity {
9717d36db35SAvi Kivity 	test_null();
9727d36db35SAvi Kivity 
9737d36db35SAvi Kivity 	test_shld();
9747d36db35SAvi Kivity 	test_push_pop();
9757d36db35SAvi Kivity 	test_pusha_popa();
9767d36db35SAvi Kivity 	test_mov_imm();
9777d36db35SAvi Kivity 	test_cmp_imm();
9787d36db35SAvi Kivity 	test_add_imm();
9797d36db35SAvi Kivity 	test_sub_imm();
9807d36db35SAvi Kivity 	test_xor_imm();
9817d36db35SAvi Kivity 	test_io();
9827d36db35SAvi Kivity 	test_eflags_insn();
9837d36db35SAvi Kivity 	test_jcc_short();
9847d36db35SAvi Kivity 	test_jcc_near();
9857d36db35SAvi Kivity 	/* test_call() uses short jump so call it after testing jcc */
9867d36db35SAvi Kivity 	test_call();
9877d36db35SAvi Kivity 	/* long jmp test uses call near so test it after testing call */
9887d36db35SAvi Kivity 	test_long_jmp();
9897d36db35SAvi Kivity 	test_xchg();
9907d36db35SAvi Kivity 	test_iret();
991*96b9ca1eSMohammed Gamal 	test_int();
9927d36db35SAvi Kivity 
9937d36db35SAvi Kivity 	exit(0);
9947d36db35SAvi Kivity }
9957d36db35SAvi Kivity 
9967d36db35SAvi Kivity unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
9977d36db35SAvi Kivity 
9987d36db35SAvi Kivity struct __attribute__((packed)) {
9997d36db35SAvi Kivity 	unsigned short limit;
10007d36db35SAvi Kivity 	void *base;
10017d36db35SAvi Kivity } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
10027d36db35SAvi Kivity 
10037d36db35SAvi Kivity asm(
10047d36db35SAvi Kivity 	".section .init \n\t"
10057d36db35SAvi Kivity 
10067d36db35SAvi Kivity 	".code32 \n\t"
10077d36db35SAvi Kivity 
10087d36db35SAvi Kivity 	"mb_magic = 0x1BADB002 \n\t"
10097d36db35SAvi Kivity 	"mb_flags = 0x0 \n\t"
10107d36db35SAvi Kivity 
10117d36db35SAvi Kivity 	"# multiboot header \n\t"
10127d36db35SAvi Kivity 	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
10137d36db35SAvi Kivity 
10147d36db35SAvi Kivity 	".globl start \n\t"
10157d36db35SAvi Kivity 	".data \n\t"
10167d36db35SAvi Kivity 	". = . + 4096 \n\t"
10177d36db35SAvi Kivity 	"stacktop: \n\t"
10187d36db35SAvi Kivity 
10197d36db35SAvi Kivity 	".text \n\t"
10207d36db35SAvi Kivity 	"start: \n\t"
10217d36db35SAvi Kivity 	"lgdt r_gdt_descr \n\t"
10227d36db35SAvi Kivity 	"ljmp $8, $1f; 1: \n\t"
10237d36db35SAvi Kivity 	".code16gcc \n\t"
10247d36db35SAvi Kivity 	"mov $16, %eax \n\t"
10257d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
10267d36db35SAvi Kivity 	"mov %ax, %es \n\t"
10277d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
10287d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
10297d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
10307d36db35SAvi Kivity 	"mov %cr0, %eax \n\t"
10317d36db35SAvi Kivity 	"btc $0, %eax \n\t"
10327d36db35SAvi Kivity 	"mov %eax, %cr0 \n\t"
10337d36db35SAvi Kivity 	"ljmp $0, $realmode_entry \n\t"
10347d36db35SAvi Kivity 
10357d36db35SAvi Kivity 	"realmode_entry: \n\t"
10367d36db35SAvi Kivity 
10377d36db35SAvi Kivity 	"xor %ax, %ax \n\t"
10387d36db35SAvi Kivity 	"mov %ax, %ds \n\t"
10397d36db35SAvi Kivity 	"mov %ax, %es \n\t"
10407d36db35SAvi Kivity 	"mov %ax, %ss \n\t"
10417d36db35SAvi Kivity 	"mov %ax, %fs \n\t"
10427d36db35SAvi Kivity 	"mov %ax, %gs \n\t"
10437d36db35SAvi Kivity 	"mov $stacktop, %esp\n\t"
10447d36db35SAvi Kivity 	"ljmp $0, $realmode_start \n\t"
10457d36db35SAvi Kivity 
10467d36db35SAvi Kivity 	".code16gcc \n\t"
10477d36db35SAvi Kivity 	);
1048