* [kvm-unit-tests PATCH v3 0/2] Save/Restore clobbered register and struct initialization @ 2019-11-01 20:33 Bill Wendling 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es Bill Wendling 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 2/2] x86: realmode: initialize inregs with a stack Bill Wendling 0 siblings, 2 replies; 7+ messages in thread From: Bill Wendling @ 2019-11-01 20:33 UTC (permalink / raw) To: kvm, pbonzini, jmattson; +Cc: thuth, alexandru.elisei, Bill Wendling - Some tests may clobber the %es register, causing problems later on. - Many tests require a stack, but it's easy to forget to allocate one. Use an initialization function to set it automagically. Bill Wendling (2): x86: realmode: save and restore %es x86: realmode: initialize inregs with a stack x86/realmode.c | 149 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 44 deletions(-) -- 2.24.0.rc1.363.gb1bccd3e3d-goog ^ permalink raw reply [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es 2019-11-01 20:33 [kvm-unit-tests PATCH v3 0/2] Save/Restore clobbered register and struct initialization Bill Wendling @ 2019-11-01 20:33 ` Bill Wendling 2019-11-04 12:08 ` Paolo Bonzini 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 2/2] x86: realmode: initialize inregs with a stack Bill Wendling 1 sibling, 1 reply; 7+ messages in thread From: Bill Wendling @ 2019-11-01 20:33 UTC (permalink / raw) To: kvm, pbonzini, jmattson; +Cc: thuth, alexandru.elisei, Bill Wendling Some of the code test sequences (e.g. push_es) clobber ES. That causes trouble for future rep string instructions. So save and restore ES around the test code sequence in exec_in_big_real_mode. Signed-off-by: Bill Wendling <morbo@google.com> --- x86/realmode.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/x86/realmode.c b/x86/realmode.c index 5dbc2aa..629a221 100644 --- a/x86/realmode.c +++ b/x86/realmode.c @@ -164,7 +164,10 @@ static void exec_in_big_real_mode(struct insn_desc *insn) "and $-2, %[tmp] \n\t" "mov %[tmp], %%cr0 \n\t" - "pushw %[save]+36; popfw \n\t" + /* Save ES, because it is clobbered by some tests. */ + "pushw %%es \n\t" + + "pushw %[save]+36; popfw \n\t" "xchg %%eax, %[save]+0 \n\t" "xchg %%ebx, %[save]+4 \n\t" "xchg %%ecx, %[save]+8 \n\t" @@ -190,6 +193,9 @@ static void exec_in_big_real_mode(struct insn_desc *insn) "pushfl \n\t" "popl %[save]+36 \n\t" + /* Restore ES for future rep string operations. */ + "popw %%es \n\t" + /* Restore DF for the harness code */ "cld\n\t" "xor %[tmp], %[tmp] \n\t" @@ -1312,10 +1318,8 @@ static void test_lds_lss(void) outregs.eax == (unsigned long)desc.address && outregs.ebx == desc.sel); - MK_INSN(les, "push %es\n\t" - "les (%ebx), %eax\n\t" - "mov %es, %ebx\n\t" - "pop %es\n\t"); + MK_INSN(les, "les (%ebx), %eax\n\t" + "mov %es, %ebx\n\t"); exec_in_big_real_mode(&insn_les); report("les", R_AX | R_BX, outregs.eax == (unsigned long)desc.address && -- 2.24.0.rc1.363.gb1bccd3e3d-goog ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es Bill Wendling @ 2019-11-04 12:08 ` Paolo Bonzini 2019-11-05 18:07 ` Jim Mattson 0 siblings, 1 reply; 7+ messages in thread From: Paolo Bonzini @ 2019-11-04 12:08 UTC (permalink / raw) To: Bill Wendling, kvm, jmattson; +Cc: thuth, alexandru.elisei On 01/11/19 21:33, Bill Wendling wrote: > Some of the code test sequences (e.g. push_es) clobber ES. That causes > trouble for future rep string instructions. So save and restore ES > around the test code sequence in exec_in_big_real_mode. You mean pop_es. Applied with that change. Paolo ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es 2019-11-04 12:08 ` Paolo Bonzini @ 2019-11-05 18:07 ` Jim Mattson 2019-11-05 22:26 ` Paolo Bonzini 0 siblings, 1 reply; 7+ messages in thread From: Jim Mattson @ 2019-11-05 18:07 UTC (permalink / raw) To: Paolo Bonzini; +Cc: Bill Wendling, kvm list, thuth, alexandru.elisei On Mon, Nov 4, 2019 at 4:08 AM Paolo Bonzini <pbonzini@redhat.com> wrote: > > On 01/11/19 21:33, Bill Wendling wrote: > > Some of the code test sequences (e.g. push_es) clobber ES. That causes > > trouble for future rep string instructions. So save and restore ES > > around the test code sequence in exec_in_big_real_mode. > > You mean pop_es. Applied with that change. I think push_es and pop_es are both guilty of clobbering %es: MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten "mov $0x123, %ax\n\t" "mov %ax, %es\n\t" <======= Here "push %es\n\t" "pop %bx \n\t" ); MK_INSN(pop_es, "push %ax\n\t" "pop %es\n\t" <======== Here "mov %es, %bx\n\t" ); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es 2019-11-05 18:07 ` Jim Mattson @ 2019-11-05 22:26 ` Paolo Bonzini 0 siblings, 0 replies; 7+ messages in thread From: Paolo Bonzini @ 2019-11-05 22:26 UTC (permalink / raw) To: Jim Mattson; +Cc: Bill Wendling, kvm list, thuth, alexandru.elisei On 05/11/19 19:07, Jim Mattson wrote: > On Mon, Nov 4, 2019 at 4:08 AM Paolo Bonzini <pbonzini@redhat.com> wrote: >> >> On 01/11/19 21:33, Bill Wendling wrote: >>> Some of the code test sequences (e.g. push_es) clobber ES. That causes >>> trouble for future rep string instructions. So save and restore ES >>> around the test code sequence in exec_in_big_real_mode. >> >> You mean pop_es. Applied with that change. > > I think push_es and pop_es are both guilty of clobbering %es: > > MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to > see if it gets overwritten > "mov $0x123, %ax\n\t" > "mov %ax, %es\n\t" <======= Here > "push %es\n\t" > "pop %bx \n\t" > ); > > MK_INSN(pop_es, "push %ax\n\t" > "pop %es\n\t" <======== Here > "mov %es, %bx\n\t" > ); Intel vs AT&T always gets me... Paolo ^ permalink raw reply [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v3 2/2] x86: realmode: initialize inregs with a stack 2019-11-01 20:33 [kvm-unit-tests PATCH v3 0/2] Save/Restore clobbered register and struct initialization Bill Wendling 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es Bill Wendling @ 2019-11-01 20:33 ` Bill Wendling 2019-11-04 12:09 ` Paolo Bonzini 1 sibling, 1 reply; 7+ messages in thread From: Bill Wendling @ 2019-11-01 20:33 UTC (permalink / raw) To: kvm, pbonzini, jmattson; +Cc: thuth, alexandru.elisei, Bill Wendling Tests may use the stack during execution. It's easy to miss allocating one, so automatically point %esp to the stack when initializing "inregs". Also remove the initialization of ".esp" in "test_movzx_movsx" as it doesn't appear to be required. Signed-off-by: Bill Wendling <morbo@google.com> --- x86/realmode.c | 158 +++++++++++++++++++++++++++++-------------------- 1 file changed, 95 insertions(+), 63 deletions(-) diff --git a/x86/realmode.c b/x86/realmode.c index 629a221..f5967ef 100644 --- a/x86/realmode.c +++ b/x86/realmode.c @@ -11,6 +11,10 @@ typedef unsigned short u16; typedef unsigned u32; typedef unsigned long long u64; +#ifndef NULL +#define NULL ((void*)0) +#endif + void realmode_start(void); void test_function(void); @@ -140,8 +144,22 @@ struct insn_desc { u16 len; }; +struct { + u32 stack[128]; + char top[]; +} tmp_stack; + static struct regs inregs, outregs; +static inline void init_inregs(struct regs *regs) +{ + inregs = (struct regs){ 0 }; + if (regs) + inregs = *regs; + if (!inregs.esp) + inregs.esp = (unsigned long)&tmp_stack.top; +} + static void exec_in_big_real_mode(struct insn_desc *insn) { unsigned long tmp; @@ -302,7 +320,8 @@ static void test_shld(void) { MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); - inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; + init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 }); + exec_in_big_real_mode(&insn_shld_test); report("shld", ~0, outregs.eax == 0xbeef); } @@ -315,7 +334,7 @@ static void test_mov_imm(void) MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_mov_r16_imm_1); report("mov 1", R_AX, outregs.eax == 1234); @@ -342,7 +361,7 @@ static void test_sub_imm(void) MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_sub_r16_imm_1); report("sub 1", R_AX, outregs.eax == 1224); @@ -366,7 +385,7 @@ static void test_xor_imm(void) MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_xor_r16_imm_1); report("xor 1", R_AX, outregs.eax == 0); @@ -392,7 +411,7 @@ static void test_cmp_imm(void) MK_INSN(cmp_test3, "mov $0x34, %al\n\t" "cmp $0x24, %al\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); /* test cmp imm8 with AL */ /* ZF: (bit 6) Zero Flag becomes 1 if an operation results @@ -415,7 +434,7 @@ static void test_add_imm(void) MK_INSN(add_test2, "mov $0x12, %eax \n\t" "add $0x21, %al\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_add_test1); report("add 1", ~0, outregs.eax == 0x55555555); @@ -433,7 +452,7 @@ static void test_eflags_insn(void) MK_INSN(cld, "cld"); MK_INSN(std, "std"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_clc); report("clc", ~0, (outregs.eflags & 1) == 0); @@ -484,7 +503,7 @@ static void test_io(void) "mov $0x00000000, %eax \n\t" "in %dx, %eax \n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_io_test1); report("pio 1", R_AX, outregs.eax == 0xff); @@ -513,12 +532,8 @@ extern void retf_imm(void); static void test_call(void) { - u32 esp[16]; u32 addr; - inregs = (struct regs){ 0 }; - inregs.esp = (u32)&esp[ARRAY_SIZE(esp)]; - MK_INSN(call1, "mov $test_function, %eax \n\t" "call *%eax\n\t"); MK_INSN(call_near1, "jmp 2f\n\t" @@ -535,6 +550,8 @@ static void test_call(void) MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); + init_inregs(NULL); + exec_in_big_real_mode(&insn_call1); report("call 1", R_AX, outregs.eax == 0x1234); @@ -572,7 +589,7 @@ static void test_jcc_short(void) "mov $0x1234, %eax\n\t" "1:\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_jnz_short1); report("jnz short 1", ~0, 1); @@ -595,7 +612,7 @@ static void test_jcc_near(void) MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" "mov $0x1234, %eax\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_jnz_near1); report("jnz near 1", 0, 1); @@ -609,14 +626,13 @@ static void test_jcc_near(void) static void test_long_jmp(void) { - u32 esp[16]; - - inregs = (struct regs){ 0 }; - inregs.esp = (u32)&esp[ARRAY_SIZE(esp)]; MK_INSN(long_jmp, "call 1f\n\t" "jmp 2f\n\t" "1: jmp $0, $test_function\n\t" "2:\n\t"); + + init_inregs(NULL); + exec_in_big_real_mode(&insn_long_jmp); report("jmp far 1", R_AX, outregs.eax == 0x1234); } @@ -658,7 +674,7 @@ static void test_push_pop(void) "xor $0x12340000, %esp \n\t" "pop %bx"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_push32); report("push/pop 1", R_AX|R_BX, @@ -691,17 +707,12 @@ static void test_null(void) { MK_INSN(null, ""); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_null); report("null", 0, 1); } -struct { - char stack[500]; - char top[]; -} tmp_stack; - static void test_pusha_popa(void) { MK_INSN(pusha, "pusha\n\t" @@ -726,7 +737,7 @@ static void test_pusha_popa(void) "popa\n\t" ); - inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; + init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 }); exec_in_big_real_mode(&insn_pusha); report("pusha/popa 1", 0, 1); @@ -774,7 +785,7 @@ static void test_iret(void) "1: iretw\n\t" "2:\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_iret32); report("iret 1", 0, 1); @@ -792,7 +803,7 @@ static void test_iret(void) static void test_int(void) { - inregs = (struct regs){ 0 }; + init_inregs(NULL); *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ @@ -829,7 +840,7 @@ static void test_imul(void) "mov $4, %ecx\n\t" "imul %ecx\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_imul8_1); report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); @@ -866,7 +877,7 @@ static void test_mul(void) "mov $4, %ecx\n\t" "imul %ecx\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_mul8); report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); @@ -892,7 +903,7 @@ static void test_div(void) "mov $5, %ecx\n\t" "div %ecx\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_div8); report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); @@ -920,7 +931,7 @@ static void test_idiv(void) "mov $-2, %ecx\n\t" "idiv %ecx\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_idiv8); report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); @@ -939,7 +950,7 @@ static void test_cbw(void) MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" "cwde\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_cbw); report("cbq 1", ~0, outregs.eax == 0xFFFE); @@ -964,7 +975,7 @@ static void test_loopcc(void) "1: dec %eax\n\t" "loopne 1b\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_loop); report("LOOPcc short 1", R_AX, outregs.eax == 10); @@ -1243,7 +1254,7 @@ static void test_das(void) MK_INSN(das, "das"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); for (i = 0; i < 1024; ++i) { unsigned tmp = test_cases[i]; @@ -1278,7 +1289,7 @@ static void test_cwd_cdq(void) MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" "cdq\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_cwd_1); report("cwd 1", R_AX | R_DX, @@ -1307,7 +1318,7 @@ static struct { static void test_lds_lss(void) { - inregs = (struct regs){ .ebx = (unsigned long)&desc }; + init_inregs(&(struct regs){ .ebx = (unsigned long)&desc }); MK_INSN(lds, "push %ds\n\t" "lds (%ebx), %eax\n\t" @@ -1376,7 +1387,7 @@ static void test_jcxz(void) "mov $0, %ecx\n\t" "1:\n\t"); - inregs = (struct regs){ 0 }; + init_inregs(NULL); exec_in_big_real_mode(&insn_jcxz1); report("jcxz short 1", 0, 1); @@ -1400,8 +1411,10 @@ static void test_cpuid(void) unsigned function = 0x1234; unsigned eax, ebx, ecx, edx; - inregs.eax = eax = function; - inregs.ecx = ecx = 0; + init_inregs(&(struct regs){ .eax = function }); + + eax = inregs.eax; + ecx = inregs.ecx; asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx)); exec_in_big_real_mode(&insn_cpuid); report("cpuid", R_AX|R_BX|R_CX|R_DX, @@ -1415,10 +1428,11 @@ static void test_ss_base_for_esp_ebp(void) MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; - inregs.ebx = 1; - inregs.ebp = (unsigned)array; + init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array }); + exec_in_big_real_mode(&insn_ssrel1); report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); + inregs.ebx = 1; inregs.ebp = (unsigned)array; inregs.edi = 0; @@ -1434,7 +1448,8 @@ static void test_sgdt_sidt(void) MK_INSN(sidt, "sidtw (%eax)"); struct table_descr x, y; - inregs.eax = (unsigned)&y; + init_inregs(&(struct regs){ .eax = (unsigned)&y }); + asm volatile("sgdtw %0" : "=m"(x)); exec_in_big_real_mode(&insn_sgdt); report("sgdt", 0, x.limit == y.limit && x.base == y.base); @@ -1449,7 +1464,8 @@ static void test_sahf(void) { MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); - inregs.eax = 0xfd00; + init_inregs(&(struct regs){ .eax = 0xfd00 }); + exec_in_big_real_mode(&insn_sahf); report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); } @@ -1458,7 +1474,8 @@ static void test_lahf(void) { MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); - inregs.eax = 0xc7; + init_inregs(&(struct regs){ .eax = 0xc7 }); + exec_in_big_real_mode(&insn_lahf); report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); } @@ -1470,8 +1487,8 @@ static void test_movzx_movsx(void) MK_INSN(movzsah, "movsx %ah, %ebx"); MK_INSN(movzxah, "movzx %ah, %ebx"); - inregs.eax = 0x1234569c; - inregs.esp = 0xffff; + init_inregs(&(struct regs){ .eax = 0x1234569c }); + exec_in_big_real_mode(&insn_movsx); report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); exec_in_big_real_mode(&insn_movzx); @@ -1486,7 +1503,8 @@ static void test_bswap(void) { MK_INSN(bswap, "bswap %ecx"); - inregs.ecx = 0x12345678; + init_inregs(&(struct regs){ .ecx = 0x12345678 }); + exec_in_big_real_mode(&insn_bswap); report("bswap", R_CX, outregs.ecx == 0x78563412); } @@ -1495,7 +1513,8 @@ static void test_aad(void) { MK_INSN(aad, "aad"); - inregs.eax = 0x12345678; + init_inregs(&(struct regs){ .eax = 0x12345678 }); + exec_in_big_real_mode(&insn_aad); report("aad", R_AX, outregs.eax == 0x123400d4); } @@ -1504,7 +1523,8 @@ static void test_aam(void) { MK_INSN(aam, "aam"); - inregs.eax = 0x76543210; + init_inregs(&(struct regs){ .eax = 0x76543210 }); + exec_in_big_real_mode(&insn_aam); report("aam", R_AX, outregs.eax == 0x76540106); } @@ -1519,8 +1539,8 @@ static void test_xlat(void) table[i] = i + 1; } - inregs.eax = 0x89abcdef; - inregs.ebx = (u32)table; + init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table }); + exec_in_big_real_mode(&insn_xlat); report("xlat", R_AX, outregs.eax == 0x89abcdf0); } @@ -1530,7 +1550,8 @@ static void test_salc(void) MK_INSN(clc_salc, "clc; .byte 0xd6"); MK_INSN(stc_salc, "stc; .byte 0xd6"); - inregs.eax = 0x12345678; + init_inregs(&(struct regs){ .eax = 0x12345678 }); + exec_in_big_real_mode(&insn_clc_salc); report("salc (1)", R_AX, outregs.eax == 0x12345600); exec_in_big_real_mode(&insn_stc_salc); @@ -1542,8 +1563,7 @@ static void test_fninit(void) u16 fcw = -1, fsw = -1; MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); - inregs.eax = (u32)&fsw; - inregs.ebx = (u32)&fcw; + init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw }); exec_in_big_real_mode(&insn_fninit); report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); @@ -1576,7 +1596,8 @@ static u32 cycles_in_big_real_mode(struct insn_desc *insn) { u64 start, end; - inregs.ecx = PERF_COUNT; + init_inregs(&(struct regs){ .ecx = PERF_COUNT }); + exec_in_big_real_mode(insn); start = ((u64)outregs.esi << 32) | outregs.ebx; end = ((u64)outregs.edx << 32) | outregs.eax; @@ -1624,7 +1645,9 @@ static void test_perf_memory_load(void) u32 cyc, tmp; MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)"); - inregs.edi = (u32)&tmp; + + init_inregs(&(struct regs){ .edi = (u32)&tmp }); + cyc = cycles_in_big_real_mode(&insn_perf_memory_load); print_serial_u32((cyc - perf_baseline) / PERF_COUNT); print_serial(" cycles/emulated memory load instruction\n"); @@ -1635,7 +1658,9 @@ static void test_perf_memory_store(void) u32 cyc, tmp; MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)"); - inregs.edi = (u32)&tmp; + + init_inregs(&(struct regs){ .edi = (u32)&tmp }); + cyc = cycles_in_big_real_mode(&insn_perf_memory_store); print_serial_u32((cyc - perf_baseline) / PERF_COUNT); print_serial(" cycles/emulated memory store instruction\n"); @@ -1646,7 +1671,9 @@ static void test_perf_memory_rmw(void) u32 cyc, tmp; MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)"); - inregs.edi = (u32)&tmp; + + init_inregs(&(struct regs){ .edi = (u32)&tmp }); + cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw); print_serial_u32((cyc - perf_baseline) / PERF_COUNT); print_serial(" cycles/emulated memory RMW instruction\n"); @@ -1656,8 +1683,9 @@ static void test_dr_mod(void) { MK_INSN(drmod, "movl %ebx, %dr0\n\t" ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t"); - inregs.eax = 0xdead; - inregs.ebx = 0xaced; + + init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced }); + exec_in_big_real_mode(&insn_drmod); report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced); } @@ -1670,7 +1698,9 @@ static void test_smsw(void) "movl %ebx, %cr0\n\t" "smswl %eax\n\t" "movl %ecx, %cr0\n\t"); - inregs.eax = 0x12345678; + + init_inregs(&(struct regs){ .eax = 0x12345678 }); + exec_in_big_real_mode(&insn_smsw); report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx); } @@ -1678,7 +1708,9 @@ static void test_smsw(void) static void test_xadd(void) { MK_INSN(xadd, "xaddl %eax, %eax\n\t"); - inregs.eax = 0x12345678; + + init_inregs(&(struct regs){ .eax = 0x12345678 }); + exec_in_big_real_mode(&insn_xadd); report("xadd", R_AX, outregs.eax == inregs.eax * 2); } -- 2.24.0.rc1.363.gb1bccd3e3d-goog ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [kvm-unit-tests PATCH v3 2/2] x86: realmode: initialize inregs with a stack 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 2/2] x86: realmode: initialize inregs with a stack Bill Wendling @ 2019-11-04 12:09 ` Paolo Bonzini 0 siblings, 0 replies; 7+ messages in thread From: Paolo Bonzini @ 2019-11-04 12:09 UTC (permalink / raw) To: Bill Wendling, kvm, jmattson; +Cc: thuth, alexandru.elisei On 01/11/19 21:33, Bill Wendling wrote: > Tests may use the stack during execution. It's easy to miss allocating > one, so automatically point %esp to the stack when initializing > "inregs". Also remove the initialization of ".esp" in "test_movzx_movsx" > as it doesn't appear to be required. > > Signed-off-by: Bill Wendling <morbo@google.com> > --- > x86/realmode.c | 158 +++++++++++++++++++++++++++++-------------------- > 1 file changed, 95 insertions(+), 63 deletions(-) > > diff --git a/x86/realmode.c b/x86/realmode.c > index 629a221..f5967ef 100644 > --- a/x86/realmode.c > +++ b/x86/realmode.c > @@ -11,6 +11,10 @@ typedef unsigned short u16; > typedef unsigned u32; > typedef unsigned long long u64; > > +#ifndef NULL > +#define NULL ((void*)0) > +#endif > + > void realmode_start(void); > void test_function(void); > > @@ -140,8 +144,22 @@ struct insn_desc { > u16 len; > }; > > +struct { > + u32 stack[128]; > + char top[]; > +} tmp_stack; > + > static struct regs inregs, outregs; > > +static inline void init_inregs(struct regs *regs) > +{ > + inregs = (struct regs){ 0 }; > + if (regs) > + inregs = *regs; > + if (!inregs.esp) > + inregs.esp = (unsigned long)&tmp_stack.top; > +} > + > static void exec_in_big_real_mode(struct insn_desc *insn) > { > unsigned long tmp; > @@ -302,7 +320,8 @@ static void test_shld(void) > { > MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); > > - inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; > + init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 }); > + > exec_in_big_real_mode(&insn_shld_test); > report("shld", ~0, outregs.eax == 0xbeef); > } > @@ -315,7 +334,7 @@ static void test_mov_imm(void) > MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); > MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_mov_r16_imm_1); > report("mov 1", R_AX, outregs.eax == 1234); > @@ -342,7 +361,7 @@ static void test_sub_imm(void) > MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); > MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_sub_r16_imm_1); > report("sub 1", R_AX, outregs.eax == 1224); > @@ -366,7 +385,7 @@ static void test_xor_imm(void) > MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); > MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_xor_r16_imm_1); > report("xor 1", R_AX, outregs.eax == 0); > @@ -392,7 +411,7 @@ static void test_cmp_imm(void) > MK_INSN(cmp_test3, "mov $0x34, %al\n\t" > "cmp $0x24, %al\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > /* test cmp imm8 with AL */ > /* ZF: (bit 6) Zero Flag becomes 1 if an operation results > @@ -415,7 +434,7 @@ static void test_add_imm(void) > MK_INSN(add_test2, "mov $0x12, %eax \n\t" > "add $0x21, %al\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_add_test1); > report("add 1", ~0, outregs.eax == 0x55555555); > @@ -433,7 +452,7 @@ static void test_eflags_insn(void) > MK_INSN(cld, "cld"); > MK_INSN(std, "std"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_clc); > report("clc", ~0, (outregs.eflags & 1) == 0); > @@ -484,7 +503,7 @@ static void test_io(void) > "mov $0x00000000, %eax \n\t" > "in %dx, %eax \n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_io_test1); > report("pio 1", R_AX, outregs.eax == 0xff); > @@ -513,12 +532,8 @@ extern void retf_imm(void); > > static void test_call(void) > { > - u32 esp[16]; > u32 addr; > > - inregs = (struct regs){ 0 }; > - inregs.esp = (u32)&esp[ARRAY_SIZE(esp)]; > - > MK_INSN(call1, "mov $test_function, %eax \n\t" > "call *%eax\n\t"); > MK_INSN(call_near1, "jmp 2f\n\t" > @@ -535,6 +550,8 @@ static void test_call(void) > MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); > MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); > > + init_inregs(NULL); > + > exec_in_big_real_mode(&insn_call1); > report("call 1", R_AX, outregs.eax == 0x1234); > > @@ -572,7 +589,7 @@ static void test_jcc_short(void) > "mov $0x1234, %eax\n\t" > "1:\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_jnz_short1); > report("jnz short 1", ~0, 1); > @@ -595,7 +612,7 @@ static void test_jcc_near(void) > MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" > "mov $0x1234, %eax\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_jnz_near1); > report("jnz near 1", 0, 1); > @@ -609,14 +626,13 @@ static void test_jcc_near(void) > > static void test_long_jmp(void) > { > - u32 esp[16]; > - > - inregs = (struct regs){ 0 }; > - inregs.esp = (u32)&esp[ARRAY_SIZE(esp)]; > MK_INSN(long_jmp, "call 1f\n\t" > "jmp 2f\n\t" > "1: jmp $0, $test_function\n\t" > "2:\n\t"); > + > + init_inregs(NULL); > + > exec_in_big_real_mode(&insn_long_jmp); > report("jmp far 1", R_AX, outregs.eax == 0x1234); > } > @@ -658,7 +674,7 @@ static void test_push_pop(void) > "xor $0x12340000, %esp \n\t" > "pop %bx"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_push32); > report("push/pop 1", R_AX|R_BX, > @@ -691,17 +707,12 @@ static void test_null(void) > { > MK_INSN(null, ""); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_null); > report("null", 0, 1); > } > > -struct { > - char stack[500]; > - char top[]; > -} tmp_stack; > - > static void test_pusha_popa(void) > { > MK_INSN(pusha, "pusha\n\t" > @@ -726,7 +737,7 @@ static void test_pusha_popa(void) > "popa\n\t" > ); > > - inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; > + init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 }); > > exec_in_big_real_mode(&insn_pusha); > report("pusha/popa 1", 0, 1); > @@ -774,7 +785,7 @@ static void test_iret(void) > "1: iretw\n\t" > "2:\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_iret32); > report("iret 1", 0, 1); > @@ -792,7 +803,7 @@ static void test_iret(void) > > static void test_int(void) > { > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ > *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ > @@ -829,7 +840,7 @@ static void test_imul(void) > "mov $4, %ecx\n\t" > "imul %ecx\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_imul8_1); > report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); > @@ -866,7 +877,7 @@ static void test_mul(void) > "mov $4, %ecx\n\t" > "imul %ecx\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_mul8); > report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); > @@ -892,7 +903,7 @@ static void test_div(void) > "mov $5, %ecx\n\t" > "div %ecx\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_div8); > report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); > @@ -920,7 +931,7 @@ static void test_idiv(void) > "mov $-2, %ecx\n\t" > "idiv %ecx\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_idiv8); > report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); > @@ -939,7 +950,7 @@ static void test_cbw(void) > MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" > "cwde\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_cbw); > report("cbq 1", ~0, outregs.eax == 0xFFFE); > @@ -964,7 +975,7 @@ static void test_loopcc(void) > "1: dec %eax\n\t" > "loopne 1b\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_loop); > report("LOOPcc short 1", R_AX, outregs.eax == 10); > @@ -1243,7 +1254,7 @@ static void test_das(void) > > MK_INSN(das, "das"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > for (i = 0; i < 1024; ++i) { > unsigned tmp = test_cases[i]; > @@ -1278,7 +1289,7 @@ static void test_cwd_cdq(void) > MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" > "cdq\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_cwd_1); > report("cwd 1", R_AX | R_DX, > @@ -1307,7 +1318,7 @@ static struct { > > static void test_lds_lss(void) > { > - inregs = (struct regs){ .ebx = (unsigned long)&desc }; > + init_inregs(&(struct regs){ .ebx = (unsigned long)&desc }); > > MK_INSN(lds, "push %ds\n\t" > "lds (%ebx), %eax\n\t" > @@ -1376,7 +1387,7 @@ static void test_jcxz(void) > "mov $0, %ecx\n\t" > "1:\n\t"); > > - inregs = (struct regs){ 0 }; > + init_inregs(NULL); > > exec_in_big_real_mode(&insn_jcxz1); > report("jcxz short 1", 0, 1); > @@ -1400,8 +1411,10 @@ static void test_cpuid(void) > unsigned function = 0x1234; > unsigned eax, ebx, ecx, edx; > > - inregs.eax = eax = function; > - inregs.ecx = ecx = 0; > + init_inregs(&(struct regs){ .eax = function }); > + > + eax = inregs.eax; > + ecx = inregs.ecx; > asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx)); > exec_in_big_real_mode(&insn_cpuid); > report("cpuid", R_AX|R_BX|R_CX|R_DX, > @@ -1415,10 +1428,11 @@ static void test_ss_base_for_esp_ebp(void) > MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); > static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; > > - inregs.ebx = 1; > - inregs.ebp = (unsigned)array; > + init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array }); > + > exec_in_big_real_mode(&insn_ssrel1); > report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); > + > inregs.ebx = 1; > inregs.ebp = (unsigned)array; > inregs.edi = 0; > @@ -1434,7 +1448,8 @@ static void test_sgdt_sidt(void) > MK_INSN(sidt, "sidtw (%eax)"); > struct table_descr x, y; > > - inregs.eax = (unsigned)&y; > + init_inregs(&(struct regs){ .eax = (unsigned)&y }); > + > asm volatile("sgdtw %0" : "=m"(x)); > exec_in_big_real_mode(&insn_sgdt); > report("sgdt", 0, x.limit == y.limit && x.base == y.base); > @@ -1449,7 +1464,8 @@ static void test_sahf(void) > { > MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); > > - inregs.eax = 0xfd00; > + init_inregs(&(struct regs){ .eax = 0xfd00 }); > + > exec_in_big_real_mode(&insn_sahf); > report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); > } > @@ -1458,7 +1474,8 @@ static void test_lahf(void) > { > MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); > > - inregs.eax = 0xc7; > + init_inregs(&(struct regs){ .eax = 0xc7 }); > + > exec_in_big_real_mode(&insn_lahf); > report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); > } > @@ -1470,8 +1487,8 @@ static void test_movzx_movsx(void) > MK_INSN(movzsah, "movsx %ah, %ebx"); > MK_INSN(movzxah, "movzx %ah, %ebx"); > > - inregs.eax = 0x1234569c; > - inregs.esp = 0xffff; > + init_inregs(&(struct regs){ .eax = 0x1234569c }); > + > exec_in_big_real_mode(&insn_movsx); > report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); > exec_in_big_real_mode(&insn_movzx); > @@ -1486,7 +1503,8 @@ static void test_bswap(void) > { > MK_INSN(bswap, "bswap %ecx"); > > - inregs.ecx = 0x12345678; > + init_inregs(&(struct regs){ .ecx = 0x12345678 }); > + > exec_in_big_real_mode(&insn_bswap); > report("bswap", R_CX, outregs.ecx == 0x78563412); > } > @@ -1495,7 +1513,8 @@ static void test_aad(void) > { > MK_INSN(aad, "aad"); > > - inregs.eax = 0x12345678; > + init_inregs(&(struct regs){ .eax = 0x12345678 }); > + > exec_in_big_real_mode(&insn_aad); > report("aad", R_AX, outregs.eax == 0x123400d4); > } > @@ -1504,7 +1523,8 @@ static void test_aam(void) > { > MK_INSN(aam, "aam"); > > - inregs.eax = 0x76543210; > + init_inregs(&(struct regs){ .eax = 0x76543210 }); > + > exec_in_big_real_mode(&insn_aam); > report("aam", R_AX, outregs.eax == 0x76540106); > } > @@ -1519,8 +1539,8 @@ static void test_xlat(void) > table[i] = i + 1; > } > > - inregs.eax = 0x89abcdef; > - inregs.ebx = (u32)table; > + init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table }); > + > exec_in_big_real_mode(&insn_xlat); > report("xlat", R_AX, outregs.eax == 0x89abcdf0); > } > @@ -1530,7 +1550,8 @@ static void test_salc(void) > MK_INSN(clc_salc, "clc; .byte 0xd6"); > MK_INSN(stc_salc, "stc; .byte 0xd6"); > > - inregs.eax = 0x12345678; > + init_inregs(&(struct regs){ .eax = 0x12345678 }); > + > exec_in_big_real_mode(&insn_clc_salc); > report("salc (1)", R_AX, outregs.eax == 0x12345600); > exec_in_big_real_mode(&insn_stc_salc); > @@ -1542,8 +1563,7 @@ static void test_fninit(void) > u16 fcw = -1, fsw = -1; > MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); > > - inregs.eax = (u32)&fsw; > - inregs.ebx = (u32)&fcw; > + init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw }); > > exec_in_big_real_mode(&insn_fninit); > report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); > @@ -1576,7 +1596,8 @@ static u32 cycles_in_big_real_mode(struct insn_desc *insn) > { > u64 start, end; > > - inregs.ecx = PERF_COUNT; > + init_inregs(&(struct regs){ .ecx = PERF_COUNT }); > + > exec_in_big_real_mode(insn); > start = ((u64)outregs.esi << 32) | outregs.ebx; > end = ((u64)outregs.edx << 32) | outregs.eax; > @@ -1624,7 +1645,9 @@ static void test_perf_memory_load(void) > u32 cyc, tmp; > > MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)"); > - inregs.edi = (u32)&tmp; > + > + init_inregs(&(struct regs){ .edi = (u32)&tmp }); > + > cyc = cycles_in_big_real_mode(&insn_perf_memory_load); > print_serial_u32((cyc - perf_baseline) / PERF_COUNT); > print_serial(" cycles/emulated memory load instruction\n"); > @@ -1635,7 +1658,9 @@ static void test_perf_memory_store(void) > u32 cyc, tmp; > > MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)"); > - inregs.edi = (u32)&tmp; > + > + init_inregs(&(struct regs){ .edi = (u32)&tmp }); > + > cyc = cycles_in_big_real_mode(&insn_perf_memory_store); > print_serial_u32((cyc - perf_baseline) / PERF_COUNT); > print_serial(" cycles/emulated memory store instruction\n"); > @@ -1646,7 +1671,9 @@ static void test_perf_memory_rmw(void) > u32 cyc, tmp; > > MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)"); > - inregs.edi = (u32)&tmp; > + > + init_inregs(&(struct regs){ .edi = (u32)&tmp }); > + > cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw); > print_serial_u32((cyc - perf_baseline) / PERF_COUNT); > print_serial(" cycles/emulated memory RMW instruction\n"); > @@ -1656,8 +1683,9 @@ static void test_dr_mod(void) > { > MK_INSN(drmod, "movl %ebx, %dr0\n\t" > ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t"); > - inregs.eax = 0xdead; > - inregs.ebx = 0xaced; > + > + init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced }); > + > exec_in_big_real_mode(&insn_drmod); > report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced); > } > @@ -1670,7 +1698,9 @@ static void test_smsw(void) > "movl %ebx, %cr0\n\t" > "smswl %eax\n\t" > "movl %ecx, %cr0\n\t"); > - inregs.eax = 0x12345678; > + > + init_inregs(&(struct regs){ .eax = 0x12345678 }); > + > exec_in_big_real_mode(&insn_smsw); > report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx); > } > @@ -1678,7 +1708,9 @@ static void test_smsw(void) > static void test_xadd(void) > { > MK_INSN(xadd, "xaddl %eax, %eax\n\t"); > - inregs.eax = 0x12345678; > + > + init_inregs(&(struct regs){ .eax = 0x12345678 }); > + > exec_in_big_real_mode(&insn_xadd); > report("xadd", R_AX, outregs.eax == inregs.eax * 2); > } > Applied, thanks. Paolo ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2019-11-05 22:26 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-11-01 20:33 [kvm-unit-tests PATCH v3 0/2] Save/Restore clobbered register and struct initialization Bill Wendling 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 1/2] x86: realmode: save and restore %es Bill Wendling 2019-11-04 12:08 ` Paolo Bonzini 2019-11-05 18:07 ` Jim Mattson 2019-11-05 22:26 ` Paolo Bonzini 2019-11-01 20:33 ` [kvm-unit-tests PATCH v3 2/2] x86: realmode: initialize inregs with a stack Bill Wendling 2019-11-04 12:09 ` Paolo Bonzini
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).