|
@@ -95,6 +95,10 @@ asm (
|
|
"int3\n\t"
|
|
"int3\n\t"
|
|
"vmcode_int80:\n\t"
|
|
"vmcode_int80:\n\t"
|
|
"int $0x80\n\t"
|
|
"int $0x80\n\t"
|
|
|
|
+ "vmcode_popf_hlt:\n\t"
|
|
|
|
+ "push %ax\n\t"
|
|
|
|
+ "popf\n\t"
|
|
|
|
+ "hlt\n\t"
|
|
"vmcode_umip:\n\t"
|
|
"vmcode_umip:\n\t"
|
|
/* addressing via displacements */
|
|
/* addressing via displacements */
|
|
"smsw (2052)\n\t"
|
|
"smsw (2052)\n\t"
|
|
@@ -124,8 +128,8 @@ asm (
|
|
|
|
|
|
extern unsigned char vmcode[], end_vmcode[];
|
|
extern unsigned char vmcode[], end_vmcode[];
|
|
extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
|
|
extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
|
|
- vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[],
|
|
|
|
- vmcode_umip_str[], vmcode_umip_sldt[];
|
|
|
|
|
|
+ vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_popf_hlt[],
|
|
|
|
+ vmcode_umip[], vmcode_umip_str[], vmcode_umip_sldt[];
|
|
|
|
|
|
/* Returns false if the test was skipped. */
|
|
/* Returns false if the test was skipped. */
|
|
static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
|
|
static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
|
|
@@ -175,7 +179,7 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
|
|
(VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) {
|
|
(VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) {
|
|
printf("[OK]\tReturned correctly\n");
|
|
printf("[OK]\tReturned correctly\n");
|
|
} else {
|
|
} else {
|
|
- printf("[FAIL]\tIncorrect return reason\n");
|
|
|
|
|
|
+ printf("[FAIL]\tIncorrect return reason (started at eip = 0x%lx, ended at eip = 0x%lx)\n", eip, v86->regs.eip);
|
|
nerrs++;
|
|
nerrs++;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -264,6 +268,9 @@ int main(void)
|
|
v86.regs.ds = load_addr / 16;
|
|
v86.regs.ds = load_addr / 16;
|
|
v86.regs.es = load_addr / 16;
|
|
v86.regs.es = load_addr / 16;
|
|
|
|
|
|
|
|
+ /* Use the end of the page as our stack. */
|
|
|
|
+ v86.regs.esp = 4096;
|
|
|
|
+
|
|
assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
|
|
assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
|
|
|
|
|
|
/* #BR -- should deliver SIG??? */
|
|
/* #BR -- should deliver SIG??? */
|
|
@@ -295,6 +302,23 @@ int main(void)
|
|
v86.regs.eflags &= ~X86_EFLAGS_IF;
|
|
v86.regs.eflags &= ~X86_EFLAGS_IF;
|
|
do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set");
|
|
do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set");
|
|
|
|
|
|
|
|
+ /* POPF with VIP set but IF clear: should not trap */
|
|
|
|
+ v86.regs.eflags = X86_EFLAGS_VIP;
|
|
|
|
+ v86.regs.eax = 0;
|
|
|
|
+ do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP set and IF clear");
|
|
|
|
+
|
|
|
|
+ /* POPF with VIP set and IF set: should trap */
|
|
|
|
+ v86.regs.eflags = X86_EFLAGS_VIP;
|
|
|
|
+ v86.regs.eax = X86_EFLAGS_IF;
|
|
|
|
+ do_test(&v86, vmcode_popf_hlt - vmcode, VM86_STI, 0, "POPF with VIP and IF set");
|
|
|
|
+
|
|
|
|
+ /* POPF with VIP clear and IF set: should not trap */
|
|
|
|
+ v86.regs.eflags = 0;
|
|
|
|
+ v86.regs.eax = X86_EFLAGS_IF;
|
|
|
|
+ do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP clear and IF set");
|
|
|
|
+
|
|
|
|
+ v86.regs.eflags = 0;
|
|
|
|
+
|
|
/* INT3 -- should cause #BP */
|
|
/* INT3 -- should cause #BP */
|
|
do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3");
|
|
do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3");
|
|
|
|
|
|
@@ -318,7 +342,7 @@ int main(void)
|
|
clearhandler(SIGSEGV);
|
|
clearhandler(SIGSEGV);
|
|
|
|
|
|
/* Make sure nothing explodes if we fork. */
|
|
/* Make sure nothing explodes if we fork. */
|
|
- if (fork() > 0)
|
|
|
|
|
|
+ if (fork() == 0)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
return (nerrs == 0 ? 0 : 1);
|
|
return (nerrs == 0 ? 0 : 1);
|