svn commit: r269080 - head/sys/amd64/vmm

Neel Natu neel at FreeBSD.org
Thu Jul 24 23:01:54 UTC 2014


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) {


More information about the svn-src-head mailing list