|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 12/13] test_x86_emulator.c: Add tests for #GP usage
On 02/24/15 10:38, Jan Beulich wrote:
>>>> On 17.02.15 at 00:05, <dslutz@xxxxxxxxxxx> wrote:
>> Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
>
> There's a whole lot of stuff being added here, and I easily can't see
> where delivery of a #GP would actually be tested.
Clearly I need more comments. Short form is that j=1
is the #GP tests.
+ regs.edx = 0x5658 + j;
...
+ if ( rc != X86EMUL_OKAY )
+ {
+ if ( j == 0 )
+ goto fail;
+ }
And the use in the real #GP handler:
+ if ( rc != X86EMUL_OKAY && rc != X86EMUL_RETRY )
+ hvm_inject_hw_exception(TRAP_gp_fault, vmcb->exitinfo1);
Since the test code and x86_emulate.c do not return
X86EMUL_RETRY it was good enough a test for me.
> Please explain
> here what the tests are supposed to test and why emulops_gp
> needs all the function pointers you're adding functions for.
Ok. Here it is as text:
I added 2 testing "modes", j=0 and j=1. Testing 4 instructions (all the
basic PIO) in both modes.
In j=0, there should not be an error returned.
In j=1, there should be an error returned.
For IN, eax should change. For OUT eax should not change.
All 4 PIO instructions are 1 byte long, so eip should only change by 1.
The same as a diff with comments (and v10 code that does more checking):
+ /*
+ * Test out special #GP handling for the VMware port 0x5658.
+ * This is done in two "modes", j=0 and j=1. Testing 4
+ * instructions (all the basic PIO) in both modes.
+ *
+ * The port used is based on j.
+ *
+ * For IN, eax should change. For OUT eax should not change.
+ *
+ * All 4 PIO instructions are 1 byte long, so eip should only
+ * change by 1.
+ */
+ for ( j = 0; j <= 1; j++ )
+ {
+ regs.eflags = 0x20002;
+ regs.edx = 0x5658 + j;
+ printf("Testing %s dx=%x ... ", "in (%dx),%eax",
(int)regs.edx);
+ instr[0] = 0xed; /* in (%dx),%eax or in (%dx),%ax */
+ regs.eip = (unsigned long)&instr[0];
+ regs.eax = 0x12345678;
+ regs.ebx = 0;
+ regs.ecx = 0;
+ regs.esi = 0;
+ rc = x86_emulate(&ctxt, &emulops_gp);
+ /*
+ * In j=0, there should not be an error returned.
+ * In j=1, there should be an error returned.
+ */
+ if ( rc != X86EMUL_OKAY )
+ {
+ if ( j == 0 )
+ goto fail;
+ }
+ else if ( j == 1 )
+ goto fail;
+ /* Check for only 1 byte used or 0 if #GP. */
+ if ( regs.eip != (unsigned long)&instr[1 - j] )
+ goto fail;
+ /* Check that eax changed in the non #GP case */
+ if ( j == 0 && regs.eax == 0x12345678 )
+ goto fail;
+ /* Check that ebx has the correct value */
+ if ( regs.ebx == j )
+ goto fail;
+ /* Check that ecx has the correct value */
+ if ( regs.ecx == j )
+ goto fail;
+ /* Check that esi has the correct value */
+ if ( regs.esi == j )
+ goto fail;
+ printf("okay\n");
+
+ printf("Testing %s dx=%x ... ", "in (%dx),%al",
(int)regs.edx);
+ instr[0] = 0xec; /* in (%dx),%al */
+ regs.eip = (unsigned long)&instr[0];
+ regs.eax = 0x12345678;
+ regs.ebx = 0;
+ regs.ecx = 0;
+ regs.esi = 0;
+ rc = x86_emulate(&ctxt, &emulops_gp);
+ /*
+ * In j=0, there should not be an error returned.
+ * In j=1, there should be an error returned.
+ */
+ if ( rc != X86EMUL_OKAY )
+ {
+ if ( j == 0 )
+ goto fail;
+ }
+ else if ( j == 1 )
+ goto fail;
+ /* Check for only 1 byte used or 0 if #GP. */
+ if ( regs.eip != (unsigned long)&instr[1 - j] )
+ goto fail;
+ /* Check that eax changed in the non #GP case */
+ if ( j == 0 && regs.eax == 0x12345678 )
+ goto fail;
+ /* Check that ebx has the correct value */
+ if ( regs.ebx == j )
+ goto fail;
+ /* Check that ecx has the correct value */
+ if ( regs.ecx == j )
+ goto fail;
+ /* Check that esi has the correct value */
+ if ( regs.esi == j )
+ goto fail;
+ printf("okay\n");
+
+ printf("Testing %s dx=%x ... ", "out %eax,(%dx)",
(int)regs.edx);
+ instr[0] = 0xef; /* out %eax,(%dx) or out %ax,(%dx) */
+ regs.eip = (unsigned long)&instr[0];
+ regs.eax = 0x12345678;
+ regs.ebx = 0;
+ regs.ecx = 0;
+ regs.esi = 0;
+ rc = x86_emulate(&ctxt, &emulops_gp);
+ /*
+ * In j=0, there should not be an error returned.
+ * In j=1, there should be an error returned.
+ */
+ if ( rc != X86EMUL_OKAY )
+ {
+ if ( j == 0 )
+ goto fail;
+ }
+ else if ( j == 1 )
+ goto fail;
+ /* Check for only 1 byte used or 0 if #GP. */
+ if ( regs.eip != (unsigned long)&instr[1 - j] )
+ goto fail;
+ /* Check that eax did not change */
+ if ( regs.eax != 0x12345678 )
+ goto fail;
+ /* Check that ebx has the correct value */
+ if ( regs.ebx == j )
+ goto fail;
+ /* Check that ecx has the correct value */
+ if ( regs.ecx == j )
+ goto fail;
+ /* Check that esi has the correct value */
+ if ( regs.esi == j )
+ goto fail;
+ printf("okay\n");
+
+ printf("Testing %s dx=%x ... ", "out %al,(%dx)",
(int)regs.edx);
+ instr[0] = 0xee; /* out %al,(%dx) */
+ regs.eip = (unsigned long)&instr[0];
+ regs.eax = 0x12345678;
+ regs.ebx = 0;
+ regs.ecx = 0;
+ regs.esi = 0;
+ rc = x86_emulate(&ctxt, &emulops_gp);
+ /*
+ * In j=0, there should not be an error returned.
+ * In j=1, there should be an error returned.
+ */
+ if ( rc != X86EMUL_OKAY )
+ {
+ if ( j == 0 )
+ goto fail;
+ }
+ else if ( j == 1 )
+ goto fail;
+ /* Check for only 1 byte used or 0 if #GP. */
+ if ( regs.eip != (unsigned long)&instr[1 - j] )
+ goto fail;
+ /* Check that eax did not change */
+ if ( regs.eax != 0x12345678 )
+ goto fail;
+ /* Check that ebx has the correct value */
+ if ( regs.ebx == j )
+ goto fail;
+ /* Check that ecx has the correct value */
+ if ( regs.ecx == j )
+ goto fail;
+ /* Check that esi has the correct value */
+ if ( regs.esi == j )
+ goto fail;
+ printf("okay\n");
+ }
+
Since it looks to me that with many cpus, it would be possible to pass
all opcodes to hvm_emulate_one_gp() by chaning memory at just the right
time. So for emulops_gp, I had an attempt at running all the blowfish
code (32 and 64) through the #GP mode code, but it was not working and
so I dropped it after 2 days of poking.
Looks like I did not drop the no longer needed ops for the simple tests
I did add.
So I have checked and read, write_gp, cmpxchg_gp, read_segment,
and inject_hw_exception are not needed. So that leaves:
static struct x86_emulate_ops emulops_gp = {
.insn_fetch = fetch,
.read_io = read_io,
.write_io = write_io,
.vmport_check = vmport_check,
};
-Don Slutz
>
> Jan
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |