From 268d74c73af1c767169539f7643faf5c5dab0b7e Mon Sep 17 00:00:00 2001 From: neel Date: Tue, 14 Oct 2014 21:02:33 +0000 Subject: Emulate "POP r/m". This is needed to boot OpenBSD/i386 MP kernel in bhyve. Reported by: grehan MFC after: 1 week --- sys/amd64/vmm/vmm_instruction_emul.c | 97 ++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 20 deletions(-) (limited to 'sys/amd64/vmm') diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index 0d48895..c6ba01e 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -69,6 +69,7 @@ enum { VIE_OP_TYPE_TWO_BYTE, VIE_OP_TYPE_PUSH, VIE_OP_TYPE_CMP, + VIE_OP_TYPE_POP, VIE_OP_TYPE_LAST }; @@ -159,6 +160,11 @@ static const struct vie_op one_byte_opcodes[256] = { .op_type = VIE_OP_TYPE_OR, .op_flags = VIE_OP_F_IMM8, }, + [0x8F] = { + /* XXX Group 1A extended opcode - not just POP */ + .op_byte = 0x8F, + .op_type = VIE_OP_TYPE_POP, + }, [0xFF] = { /* XXX Group 5 extended opcode - not just PUSH */ .op_byte = 0xFF, @@ -821,7 +827,7 @@ emulate_sub(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, } static int -emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, +emulate_stack_op(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, struct vm_guest_paging *paging, mem_region_read_t memread, mem_region_write_t memwrite, void *arg) { @@ -832,18 +838,12 @@ emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, #endif struct seg_desc ss_desc; uint64_t cr0, rflags, rsp, stack_gla, val; - int error, size, stackaddrsize; - - /* - * Table A-6, "Opcode Extensions", Intel SDM, Vol 2. - * - * PUSH is part of the group 5 extended opcodes and is identified - * by ModRM:reg = b110. - */ - if ((vie->reg & 7) != 6) - return (EINVAL); + int error, size, stackaddrsize, pushop; + val = 0; size = vie->opsize; + pushop = (vie->op.op_type == VIE_OP_TYPE_PUSH) ? 1 : 0; + /* * From "Address-Size Attributes for Stack Accesses", Intel SDL, Vol 1 */ @@ -882,10 +882,13 @@ emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RSP, &rsp); KASSERT(error == 0, ("%s: error %d getting rsp", __func__, error)); + if (pushop) { + rsp -= size; + } - rsp -= size; if (vie_calculate_gla(paging->cpu_mode, VM_REG_GUEST_SS, &ss_desc, - rsp, size, stackaddrsize, PROT_WRITE, &stack_gla)) { + rsp, size, stackaddrsize, pushop ? PROT_WRITE : PROT_READ, + &stack_gla)) { vm_inject_ss(vm, vcpuid, 0); return (0); } @@ -900,8 +903,8 @@ emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, return (0); } - error = vm_copy_setup(vm, vcpuid, paging, stack_gla, size, PROT_WRITE, - copyinfo, nitems(copyinfo)); + error = vm_copy_setup(vm, vcpuid, paging, stack_gla, size, + pushop ? PROT_WRITE : PROT_READ, copyinfo, nitems(copyinfo)); if (error == -1) { /* * XXX cannot return a negative error value here because it @@ -914,16 +917,66 @@ emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, return (0); } - error = memread(vm, vcpuid, mmio_gpa, &val, size, arg); + if (pushop) { + error = memread(vm, vcpuid, mmio_gpa, &val, size, arg); + if (error == 0) + vm_copyout(vm, vcpuid, &val, copyinfo, size); + } else { + vm_copyin(vm, vcpuid, copyinfo, &val, size); + error = memwrite(vm, vcpuid, mmio_gpa, val, size, arg); + rsp += size; + } +#ifdef _KERNEL + vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); +#endif + if (error == 0) { - vm_copyout(vm, vcpuid, &val, copyinfo, size); error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RSP, rsp, stackaddrsize); KASSERT(error == 0, ("error %d updating rsp", error)); } -#ifdef _KERNEL - vm_copy_teardown(vm, vcpuid, copyinfo, nitems(copyinfo)); -#endif + return (error); +} + +static int +emulate_push(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, + struct vm_guest_paging *paging, mem_region_read_t memread, + mem_region_write_t memwrite, void *arg) +{ + int error; + + /* + * Table A-6, "Opcode Extensions", Intel SDM, Vol 2. + * + * PUSH is part of the group 5 extended opcodes and is identified + * by ModRM:reg = b110. + */ + if ((vie->reg & 7) != 6) + return (EINVAL); + + error = emulate_stack_op(vm, vcpuid, mmio_gpa, vie, paging, memread, + memwrite, arg); + return (error); +} + +static int +emulate_pop(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, + struct vm_guest_paging *paging, mem_region_read_t memread, + mem_region_write_t memwrite, void *arg) +{ + int error; + + /* + * Table A-6, "Opcode Extensions", Intel SDM, Vol 2. + * + * POP is part of the group 1A extended opcodes and is identified + * by ModRM:reg = b000. + */ + if ((vie->reg & 7) != 0) + return (EINVAL); + + error = emulate_stack_op(vm, vcpuid, mmio_gpa, vie, paging, memread, + memwrite, arg); return (error); } @@ -938,6 +991,10 @@ vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, return (EINVAL); switch (vie->op.op_type) { + case VIE_OP_TYPE_POP: + error = emulate_pop(vm, vcpuid, gpa, vie, paging, memread, + memwrite, memarg); + break; case VIE_OP_TYPE_PUSH: error = emulate_push(vm, vcpuid, gpa, vie, paging, memread, memwrite, memarg); -- cgit v1.1 From e88bd26b3f101e3aad82304315f731daa60cc6de Mon Sep 17 00:00:00 2001 From: davide Date: Thu, 16 Oct 2014 18:04:43 +0000 Subject: Follow up to r225617. In order to maximize the re-usability of kernel code in userland rename in-kernel getenv()/setenv() to kern_setenv()/kern_getenv(). This fixes a namespace collision with libc symbols. Submitted by: kmacy Tested by: make universe --- sys/amd64/vmm/vmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/amd64/vmm') diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 8f987b7..dd0829c 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -1934,7 +1934,7 @@ vmm_is_pptdev(int bus, int slot, int func) /* set pptdevs="1/2/3 4/5/6 7/8/9 10/11/12" */ found = 0; for (i = 0; names[i] != NULL && !found; i++) { - cp = val = getenv(names[i]); + cp = val = kern_getenv(names[i]); while (cp != NULL && *cp != '\0') { if ((cp2 = strchr(cp, ' ')) != NULL) *cp2 = '\0'; -- cgit v1.1