diff options
author | neel <neel@FreeBSD.org> | 2014-07-24 23:01:53 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-07-24 23:01:53 +0000 |
commit | 563faffd70680046c3f7fa9006056290ed2d712b (patch) | |
tree | aa4138c30e09c29823f382de0479612c95183612 /sys/amd64/vmm | |
parent | c6ab5d746c37cac49f50a1579f5d9147ad4c176d (diff) | |
download | FreeBSD-src-563faffd70680046c3f7fa9006056290ed2d712b.zip FreeBSD-src-563faffd70680046c3f7fa9006056290ed2d712b.tar.gz |
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.
Diffstat (limited to 'sys/amd64/vmm')
-rw-r--r-- | sys/amd64/vmm/vmm_instruction_emul.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index e8a5f7b..b145f69 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -726,11 +726,19 @@ emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, /* * 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, uint64_t mmio_gpa, struct vie *vie, 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) { |