Author: neel
Date: Thu Jul 24 23:01:53 2014
New Revision: 269080
URL: http://svnweb.freebsd.org/changeset/base/269080

Log:
  Fix a couple of issues in the PUSH emulation:
  
  It is not possible to PUSH a 32-bit operand on the stack in 64-bit mode. The
  default operand size for PUSH is 64-bits and the operand size override prefix
  changes that to 16-bits.
  
  vm_copy_setup() can return '1' if it encounters a fault when walking the
  guest page tables. This is a guest issue and is now handled properly by
  resuming the guest to handle the fault.

Modified:
  head/sys/amd64/vmm/vmm_instruction_emul.c

Modified: head/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- head/sys/amd64/vmm/vmm_instruction_emul.c   Thu Jul 24 20:44:30 2014        
(r269079)
+++ head/sys/amd64/vmm/vmm_instruction_emul.c   Thu Jul 24 23:01:53 2014        
(r269080)
@@ -726,11 +726,19 @@ emulate_push(void *vm, int vcpuid, uint6
        /*
         * From "Address-Size Attributes for Stack Accesses", Intel SDL, Vol 1
         */
-       if (paging->cpu_mode == CPU_MODE_REAL)
+       if (paging->cpu_mode == CPU_MODE_REAL) {
                stackaddrsize = 2;
-       else if (paging->cpu_mode == CPU_MODE_64BIT)
+       } else if (paging->cpu_mode == CPU_MODE_64BIT) {
+               /*
+                * "Stack Manipulation Instructions in 64-bit Mode", SDM, Vol 3
+                * - Stack pointer size is always 64-bits.
+                * - PUSH/POP of 32-bit values is not possible in 64-bit mode.
+                * - 16-bit PUSH/POP is supported by using the operand size
+                *   override prefix (66H).
+                */
                stackaddrsize = 8;
-       else {
+               size = vie->opsize_override ? 2 : 8;
+       } else {
                /*
                 * In protected or compability mode the 'B' flag in the
                 * stack-segment descriptor determines the size of the
@@ -773,8 +781,10 @@ emulate_push(void *vm, int vcpuid, uint6
 
        error = vm_copy_setup(vm, vcpuid, paging, stack_gla, size, PROT_WRITE,
            copyinfo, nitems(copyinfo));
-       if (error)
-               return (error);
+       if (error == -1)
+               return (-1);    /* Unrecoverable error */
+       else if (error == 1)
+               return (0);     /* Return to guest to handle page fault */
 
        error = memread(vm, vcpuid, mmio_gpa, &val, size, arg);
        if (error == 0) {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to