From 0d4297c58706a4609ec1540da73e1420b1d80a2b Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Mon, 3 Jul 2017 22:31:19 -0400 Subject: [PATCH] clean up caller-saved register saving in load store thunks --- src/guest/maple/maple.c | 2 +- src/jit/backend/x64/x64_backend.cc | 88 +++++++++++++++++------------- 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/src/guest/maple/maple.c b/src/guest/maple/maple.c index 5c69b55e..df069ff6 100644 --- a/src/guest/maple/maple.c +++ b/src/guest/maple/maple.c @@ -91,7 +91,7 @@ int maple_handle_command(struct maple *mp, struct maple_frame *frame, } if (!dev->frame(dev, frame, res)) { - LOG_INFO("Unhandled maple cmd %d for port %d, unit %d", + LOG_INFO("unhandled maple cmd %d for port %d, unit %d", frame->header.command, p, u); return 0; } diff --git a/src/jit/backend/x64/x64_backend.cc b/src/jit/backend/x64/x64_backend.cc index 9879cbd2..de92aae4 100644 --- a/src/jit/backend/x64/x64_backend.cc +++ b/src/jit/backend/x64/x64_backend.cc @@ -126,8 +126,7 @@ const Xbyak::Xmm x64_backend_xmm(struct x64_backend *backend, int i = v->reg; CHECK_NE(i, NO_REGISTER); - const Xbyak::Xmm &xmm = - *reinterpret_cast(x64_registers[i].data); + const Xbyak::Xmm &xmm = *(const Xbyak::Xmm *)x64_registers[i].data; CHECK(xmm.isXMM()); return xmm; } @@ -393,11 +392,21 @@ static void x64_backend_emit_thunks(struct x64_backend *backend) { backend->load_thunk[i] = e.getCurr(); +/* save caller-saved registers */ +#if PLATFORM_WINDOWS + e.push(e.rsi); + e.push(e.rdi); +#else + e.push(e.r8); + e.push(e.r9); +#endif + e.push(e.r10); + e.push(e.r11); + /* call the mmio handler */ e.call(e.rax); /* restore caller-saved registers */ - e.add(e.rsp, X64_STACK_SHADOW_SPACE + 8); e.pop(e.r11); e.pop(e.r10); #if PLATFORM_WINDOWS @@ -412,6 +421,7 @@ static void x64_backend_emit_thunks(struct x64_backend *backend) { e.mov(dst, e.rax); /* return to jit code */ + e.add(e.rsp, X64_STACK_SHADOW_SPACE + 8); e.ret(); } } @@ -421,11 +431,21 @@ static void x64_backend_emit_thunks(struct x64_backend *backend) { backend->store_thunk = e.getCurr(); +/* save caller-saved registers */ +#if PLATFORM_WINDOWS + e.push(e.rsi); + e.push(e.rdi); +#else + e.push(e.r8); + e.push(e.r9); +#endif + e.push(e.r10); + e.push(e.r11); + /* call the mmio handler */ e.call(e.rax); /* restore caller-saved registers */ - e.add(e.rsp, X64_STACK_SHADOW_SPACE + 8); e.pop(e.r11); e.pop(e.r10); #if PLATFORM_WINDOWS @@ -437,6 +457,7 @@ static void x64_backend_emit_thunks(struct x64_backend *backend) { #endif /* return to jit code */ + e.add(e.rsp, X64_STACK_SHADOW_SPACE + 8); e.ret(); } } @@ -474,13 +495,12 @@ static int x64_backend_handle_exception(struct jit_backend *base, struct x64_backend *backend = container_of(base, struct x64_backend, base); struct jit_guest *guest = backend->base.jit->guest; - const uint8_t *data = reinterpret_cast(ex->thread_state.rip); + const uint8_t *data = (const uint8_t *)ex->thread_state.rip; /* figure out the guest address that was being accessed */ - const uint8_t *fault_addr = reinterpret_cast(ex->fault_addr); - const uint8_t *protected_start = - reinterpret_cast(ex->thread_state.r15); - uint32_t guest_addr = static_cast(fault_addr - protected_start); + const uint8_t *fault_addr = (const uint8_t *)ex->fault_addr; + const uint8_t *protected_start = (const uint8_t *)ex->thread_state.r15; + uint32_t guest_addr = (uint32_t)(fault_addr - protected_start); /* ensure it was an mmio address that caused the exception */ void *ptr; @@ -502,72 +522,62 @@ static int x64_backend_handle_exception(struct jit_backend *base, from any restrictions imposed by an exception handler, and also prevents a possible recursive exception - push all of the caller saved registers used by the jit, as well as the - return address (the next instruction after the current mov) to the stack. - add an extra 8 bytes to keep the stack aligned */ - *(uint64_t *)(ex->thread_state.rsp - 40) = ex->thread_state.r11; - *(uint64_t *)(ex->thread_state.rsp - 32) = ex->thread_state.r10; -#if PLATFORM_WINDOWS - *(uint64_t *)(ex->thread_state.rsp - 24) = ex->thread_state.rdi; - *(uint64_t *)(ex->thread_state.rsp - 16) = ex->thread_state.rsi; -#else - *(uint64_t *)(ex->thread_state.rsp - 24) = ex->thread_state.r9; - *(uint64_t *)(ex->thread_state.rsp - 16) = ex->thread_state.r8; -#endif + push the return address (the next instruction after the current mov) to + the stack. also, adjust the stack for the return address, with an extra + 8 bytes to keep it aligned */ *(uint64_t *)(ex->thread_state.rsp - 8) = ex->thread_state.rip + mov.length; - ex->thread_state.rsp -= X64_STACK_SHADOW_SPACE + 40 + 8; + ex->thread_state.rsp -= X64_STACK_SHADOW_SPACE + 8 + 8; CHECK(ex->thread_state.rsp % 16 == 0); if (mov.is_load) { /* prep argument registers (memory object, guest_addr) for read function */ - ex->thread_state.r[x64_arg0_idx] = reinterpret_cast(guest->space); - ex->thread_state.r[x64_arg1_idx] = static_cast(guest_addr); + ex->thread_state.r[x64_arg0_idx] = (uint64_t)guest->space; + ex->thread_state.r[x64_arg1_idx] = (uint64_t)guest_addr; /* prep function call address for thunk */ switch (mov.operand_size) { case 1: - ex->thread_state.rax = reinterpret_cast(guest->r8); + ex->thread_state.rax = (uint64_t)guest->r8; break; case 2: - ex->thread_state.rax = reinterpret_cast(guest->r16); + ex->thread_state.rax = (uint64_t)guest->r16; break; case 4: - ex->thread_state.rax = reinterpret_cast(guest->r32); + ex->thread_state.rax = (uint64_t)guest->r32; break; case 8: - ex->thread_state.rax = reinterpret_cast(guest->r64); + ex->thread_state.rax = (uint64_t)guest->r64; break; } /* resume execution in the thunk once the exception handler exits */ - ex->thread_state.rip = - reinterpret_cast(backend->load_thunk[mov.reg]); + ex->thread_state.rip = (uint64_t)backend->load_thunk[mov.reg]; } else { /* prep argument registers (memory object, guest_addr, value) for write function */ - ex->thread_state.r[x64_arg0_idx] = reinterpret_cast(guest->space); - ex->thread_state.r[x64_arg1_idx] = static_cast(guest_addr); + ex->thread_state.r[x64_arg0_idx] = (uint64_t)guest->space; + ex->thread_state.r[x64_arg1_idx] = (uint64_t)guest_addr; ex->thread_state.r[x64_arg2_idx] = mov.has_imm ? mov.imm : ex->thread_state.r[mov.reg]; /* prep function call address for thunk */ switch (mov.operand_size) { case 1: - ex->thread_state.rax = reinterpret_cast(guest->w8); + ex->thread_state.rax = (uint64_t)guest->w8; break; case 2: - ex->thread_state.rax = reinterpret_cast(guest->w16); + ex->thread_state.rax = (uint64_t)guest->w16; break; case 4: - ex->thread_state.rax = reinterpret_cast(guest->w32); + ex->thread_state.rax = (uint64_t)guest->w32; break; case 8: - ex->thread_state.rax = reinterpret_cast(guest->w64); + ex->thread_state.rax = (uint64_t)guest->w64; break; } /* resume execution in the thunk once the exception handler exits */ - ex->thread_state.rip = reinterpret_cast(backend->store_thunk); + ex->thread_state.rip = (uint64_t)backend->store_thunk; } return 1; @@ -648,8 +658,8 @@ static void x64_backend_init(struct jit_backend *base) { } struct jit_backend *x64_backend_create(void *code, int code_size) { - struct x64_backend *backend = reinterpret_cast( - calloc(1, sizeof(struct x64_backend))); + struct x64_backend *backend = + (struct x64_backend *)calloc(1, sizeof(struct x64_backend)); Xbyak::util::Cpu cpu; int r = protect_pages(code, code_size, ACC_READWRITEEXEC);