X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fextensions%2Fext_trans_mem.c;h=7fb816409eea055ea61984320d46cd65d52089c6;hb=2282a040e60b24d3fb7c48bb197c5bff6636df67;hp=4b417e13b6001c663ef205c3ee7b2b9ea8c01bb3;hpb=1675f10b6a5173570788c4fc5e013925c0189fea;p=palacios.git diff --git a/palacios/src/extensions/ext_trans_mem.c b/palacios/src/extensions/ext_trans_mem.c index 4b417e1..7fb8164 100644 --- a/palacios/src/extensions/ext_trans_mem.c +++ b/palacios/src/extensions/ext_trans_mem.c @@ -44,11 +44,6 @@ #define PrintDebug(fmt, args...) #endif -/* TODO LIST: - * - save/restore register state on XBEGIN/XABORT - * - put status codes in RAX - * - Implement proper exceptions for failed XBEGINS etc. - */ /* this includes a mov to rax */ static const char * vmmcall_bytes = "\x48\xc7\xc0\x37\x13\x00\x00\x0f\x01\xd9"; @@ -118,7 +113,7 @@ tm_handle_decode_fail (struct guest_info * core) remote_tm = v3_get_ext_core_state(&(core->vm_info->cores[core_num]), "trans_mem"); if (!remote_tm) { - PrintError(core->vm_info, core,"++ TM DECODE ++ couldnt get remote_tm\n"); + TM_ERR(core,DECODE,"couldnt get remote_tm\n"); return -1; } @@ -127,7 +122,7 @@ tm_handle_decode_fail (struct guest_info * core) continue; } - PrintDebug(core->vm_info, core,"++ TM DECODE ++ setting abort for core %d due to decoding error\n", core_num); + TM_DBG(core,DECODE,"setting abort for core %d due to decoding error\n", core_num); remote_tm->TM_ABORT = 1; } @@ -154,7 +149,7 @@ tm_handle_ctrl_flow (struct guest_info * core, switch (struct_instr->op_type) { case V3_OP_JLE: - PrintDebug(core->vm_info, core, "!!++ JLE\n"); + TM_DBG(core,DECODE, "!!++ JLE\n"); to_jmp = (flags->zf || flags->sf != flags->of); offset = struct_instr->dst_operand.operand; @@ -163,7 +158,7 @@ tm_handle_ctrl_flow (struct guest_info * core, tm->to_branch = to_jmp; break; case V3_OP_JAE: - PrintDebug(core->vm_info, core,"!!++ JAE\n"); + TM_DBG(core,DECODE,"!!++ JAE\n"); to_jmp = (flags->cf == 0); offset = struct_instr->dst_operand.operand; @@ -172,7 +167,7 @@ tm_handle_ctrl_flow (struct guest_info * core, tm->to_branch = to_jmp; break; case V3_OP_JMP: - PrintDebug(core->vm_info, core,"!!++ JMP\n"); + TM_DBG(core,DECODE,"!!++ JMP\n"); to_jmp = 1; offset = struct_instr->dst_operand.operand; @@ -181,7 +176,7 @@ tm_handle_ctrl_flow (struct guest_info * core, tm->to_branch = to_jmp; break; case V3_OP_JNZ: - PrintDebug(core->vm_info, core,"!!++ JNZ\n"); + TM_DBG(core,DECODE,"!!++ JNZ\n"); to_jmp = (flags->zf == 0); offset = struct_instr->dst_operand.operand; @@ -190,7 +185,7 @@ tm_handle_ctrl_flow (struct guest_info * core, tm->to_branch = to_jmp; break; case V3_OP_JL: - PrintDebug(core->vm_info, core,"!!++ JL\n"); + TM_DBG(core,DECODE,"!!++ JL\n"); to_jmp = (flags->sf != flags->of); offset = struct_instr->dst_operand.operand; @@ -199,7 +194,7 @@ tm_handle_ctrl_flow (struct guest_info * core, tm->to_branch = to_jmp; break; case V3_OP_JNS: - PrintDebug(core->vm_info, core,"!!++ JNS\n"); + TM_DBG(core,DECODE,"!!++ JNS\n"); to_jmp = (flags->sf == 0); offset = struct_instr->dst_operand.operand; @@ -231,17 +226,17 @@ v3_store_next_instr (struct guest_info * core, struct v3_trans_mem * tm) // Fetch the current instruction tm_read_instr(core, core->rip, cur_instr, INSTR_BUF_SZ); - PrintDebug(core->vm_info, core,"-- TM STORE -- storing next instruction, current rip: %llx\n", (uint64_t)core->rip); + TM_DBG(core,STORE,"storing next instruction, current rip: %llx\n", (uint64_t)core->rip); /* Attempt to decode current instruction to determine its length */ if (v3_decode(core, (addr_t)cur_instr, &struct_instr) == ERR_DECODE_FAIL) { - PrintError(core->vm_info, core,"++ TM Error ++ Could not decode currrent instruction (at %llx)\n", (uint64_t)core->rip); + TM_ERR(core,Error,"Could not decode currrent instruction (at %llx)\n", (uint64_t)core->rip); /* this will attempt to abort all the remote cores */ if (tm_handle_decode_fail(core) == -1) { - PrintError(core->vm_info, core, "++ TM Error ++ Could not handle failed decode\n"); - return -1; + TM_ERR(core,Error,"Could not handle failed decode\n"); + return ERR_STORE_FAIL; } /* we need to trigger a local abort */ @@ -257,7 +252,7 @@ v3_store_next_instr (struct guest_info * core, struct v3_trans_mem * tm) struct_instr.prefixes.repe || struct_instr.prefixes.repz)) { - PrintError(core->vm_info, core,"Encountered REP prefix, aborting\n"); + TM_ERR(core,DECODE,"Encountered REP prefix, aborting\n"); return ERR_STORE_MUST_ABORT; } @@ -288,14 +283,14 @@ v3_overwrite_next_instr (struct guest_info * core, struct v3_trans_mem * tm) /* we can't currently handle instructions that span page boundaries */ if ((ptr + tm->cur_instr_len) % PAGE_SIZE_4KB < (ptr % PAGE_SIZE_4KB)) { - PrintError(core->vm_info, core,"++ TM OVERWRITE ++ emulated instr straddling page boundary\n"); + TM_ERR(core,OVERWRITE,"emulated instr straddling page boundary\n"); return -1; } ptr = core->rip + tm->cur_instr_len + (tm->to_branch ? tm->offset : 0); if ((ptr + INSTR_INJECT_LEN) % PAGE_SIZE_4KB < (ptr % PAGE_SIZE_4KB)) { - PrintError(core->vm_info, core,"++ TM OVERWRITE ++ injected instr straddling page boundary\n"); + TM_ERR(core,OVERWRITE,"injected instr straddling page boundary\n"); return -1; } @@ -303,11 +298,11 @@ v3_overwrite_next_instr (struct guest_info * core, struct v3_trans_mem * tm) get_addr_linear(core, ptr, &(core->segments.cs)), &ptr) == -1) { - PrintError(core->vm_info, core,"++ TM Error ++ Calculating next rip hva failed\n"); + TM_ERR(core,Error,"Calculating next rip hva failed\n"); return -1; } - PrintDebug(core->vm_info, core,"-- TM REPLACE -- Replacing next instruction at addr %llx with vmm hyper call, len=%d\n", + TM_DBG(core,REPLACE,"Replacing next instruction at addr %llx with vmm hyper call, len=%d\n", core->rip + tm->cur_instr_len + (tm->to_branch ? tm->offset : 0), (int)tm->cur_instr_len ); /* Copy VMM call into the memory address of beginning of next instruction (ptr) */ @@ -333,11 +328,11 @@ v3_restore_dirty_instr (struct guest_info * core) struct v3_trans_mem * tm = (struct v3_trans_mem *)v3_get_ext_core_state(core, "trans_mem"); /* Restore next instruction, transition to IFETCH state */ - PrintDebug(core->vm_info, core,"-- TM RESTORE -- Restoring next instruction.\n"); + TM_DBG(core,RESTORE,"Restoring next instruction.\n"); /* check if we've actually done an instruction overwrite */ if (!(tm->dirty_instr_flag)) { - PrintDebug(core->vm_info, core,"++ TM RESTORE ++ nothing to restore here...\n"); + TM_DBG(core,RESTORE,"nothing to restore here...\n"); return 0; } @@ -348,7 +343,7 @@ v3_restore_dirty_instr (struct guest_info * core) (core->vm_regs).rax = tm->clobbered_rax; // Scoot rip back up - PrintDebug(core->vm_info, core,"-- TM RESTORE -- RIP in vmmcall: %llx\n", core->rip); + TM_DBG(core,RESTORE,"RIP in vmmcall: %llx\n", core->rip); core->rip = tm->dirty_gva; // clean up @@ -357,7 +352,7 @@ v3_restore_dirty_instr (struct guest_info * core) tm->dirty_hva = 0; memset(tm->dirty_instr, 0, 15); - PrintDebug(core->vm_info, core,"-- TM RESTORE -- RIP after scooting it back up: %llx\n", core->rip); + TM_DBG(core,RESTORE,"RIP after scooting it back up: %llx\n", core->rip); return 0; } @@ -369,21 +364,21 @@ tm_handle_fault_ifetch (struct guest_info * core, { int sto; - PrintDebug(core->vm_info, core,"-- TM IFETCH -- Page fault caused by IFETCH: rip is the same as faulting address, we must be at an ifetch.\n"); + TM_DBG(core,IFETCH,"Page fault caused by IFETCH: rip is the same as faulting address, we must be at an ifetch.\n"); sto = v3_store_next_instr(core, tm); if (sto == ERR_STORE_FAIL) { - PrintError(core->vm_info, core,"++ TM EXIT ++ Could not store next instruction in transaction\n"); + TM_ERR(core,EXIT,"Could not store next instruction in transaction\n"); return ERR_TRANS_FAULT_FAIL; } else if (sto == ERR_STORE_MUST_ABORT) { - PrintDebug(core->vm_info, core,"-- TM EXIT -- aborting for some reason\n"); - v3_handle_trans_abort(core); + TM_DBG(core,EXIT,"aborting for some reason\n"); + v3_handle_trans_abort(core, TM_ABORT_UNSPECIFIED, 0); return TRANS_FAULT_OK; } if (v3_overwrite_next_instr(core, tm) == -1) { - PrintError(core->vm_info, core,"++ TM PF ++ problem overwriting instruction\n"); + TM_ERR(core,PF,"problem overwriting instruction\n"); return ERR_TRANS_FAULT_FAIL; } @@ -401,16 +396,16 @@ tm_handle_fault_read (struct guest_info * core, { // This page fault was caused by a read to memory in the current instruction for a core in TM mode - PrintDebug(core->vm_info, core,"-- TM DATA -- Page fault caused by read.\n"); - PrintDebug(core->vm_info, core,"-- TM PF -- Adding %p to read list and hash\n", (void*)fault_addr); + TM_DBG(core,DATA,"Page fault caused by read.\n"); + TM_DBG(core,PF,"Adding %p to read list and hash\n", (void*)fault_addr); if (add_mem_op_to_list(&(tm->trans_r_list), fault_addr) == -1) { - PrintError(core->vm_info, core,"++ TM PF ++ problem adding to list\n"); + TM_ERR(core,PF,"problem adding to list\n"); return ERR_TRANS_FAULT_FAIL; } if (tm_record_access(tm, error.write, fault_addr) == -1) { - PrintError(core->vm_info, core,"++ TM PF ++ problem recording access\n"); + TM_ERR(core,PF,"problem recording access\n"); return ERR_TRANS_FAULT_FAIL; } @@ -418,11 +413,11 @@ tm_handle_fault_read (struct guest_info * core, * staging page and map it in */ if (list_contains_guest_addr(&(tm->trans_w_list), fault_addr)) { - PrintDebug(core->vm_info, core,"-- TM PF -- Saw a read from something in the write list\n"); + TM_DBG(core,PF,"Saw a read from something in the write list\n"); /* write the value from linked list to staging page */ if (stage_entry(tm, &(tm->trans_w_list), fault_addr) == -1) { - PrintError(core->vm_info, core, "could not stage entry!\n"); + TM_ERR(core,PF, "could not stage entry!\n"); return ERR_TRANS_FAULT_FAIL; } @@ -434,10 +429,10 @@ tm_handle_fault_read (struct guest_info * core, //Add it to the read set addr_t shadow_addr = 0; - PrintDebug(core->vm_info, core,"-- TM PF -- Saw a read from a fresh address\n"); + TM_DBG(core,PF,"Saw a read from a fresh address\n"); if (v3_gva_to_hva(core, (uint64_t)fault_addr, &shadow_addr) == -1) { - PrintError(core->vm_info, core,"Could not translate gva to hva for transaction read\n"); + TM_ERR(core,PF,"Could not translate gva to hva for transaction read\n"); return ERR_TRANS_FAULT_FAIL; } @@ -457,21 +452,21 @@ tm_handle_fault_write (struct guest_info * core, addr_t virt_data_loc; addr_t shadow_addr = 0; - PrintDebug(core->vm_info, core,"-- TM DATA -- Page fault cause by write\n"); - PrintDebug(core->vm_info, core,"-- TM PF -- Adding %p to write list and hash\n", (void*)fault_addr); + TM_DBG(core,DATA,"Page fault cause by write\n"); + TM_DBG(core,PF,"Adding %p to write list and hash\n", (void*)fault_addr); if (add_mem_op_to_list(&(tm->trans_w_list), fault_addr) == -1) { - PrintError(core->vm_info, core,"could not add to list!\n"); + TM_ERR(core,WRITE,"could not add to list!\n"); return ERR_TRANS_FAULT_FAIL; } if (tm_record_access(tm, error.write, fault_addr) == -1) { - PrintError(core->vm_info, core,"could not record access!\n"); + TM_ERR(core,WRITE,"could not record access!\n"); return ERR_TRANS_FAULT_FAIL; } if (v3_gva_to_hva(core, (uint64_t)fault_addr, &shadow_addr) == -1) { - PrintError(core->vm_info, core,"could not translate gva to hva for transaction read\n"); + TM_ERR(core,WRITE,"could not translate gva to hva for transaction read\n"); return ERR_TRANS_FAULT_FAIL; } @@ -481,11 +476,11 @@ tm_handle_fault_write (struct guest_info * core, data_loc = (void*)((addr_t)(tm->staging_page) + (shadow_addr % PAGE_SIZE_4KB)); if (v3_hpa_to_hva((addr_t)(data_loc), &virt_data_loc) == -1) { - PrintError(core->vm_info, core,"Could not convert address on staging page to virt addr\n"); + TM_ERR(core,WRITE,"Could not convert address on staging page to virt addr\n"); return ERR_TRANS_FAULT_FAIL; } - PrintDebug(core->vm_info, core,"\tValue being copied (core %d): %p\n", core->vcpu_id, *((void**)(virt_data_loc))); + TM_DBG(core,WRITE,"\tValue being copied (core %d): %p\n", core->vcpu_id, *((void**)(virt_data_loc))); //memcpy((void*)virt_data_loc, (void*)shadow_addr, sizeof(uint64_t)); *(uint64_t*)virt_data_loc = *(uint64_t*)shadow_addr; @@ -502,29 +497,29 @@ tm_handle_fault_extern_ifetch (struct guest_info * core, int sto; // system is in tm state, record the access - PrintDebug(core->vm_info, core,"-- TM IFETCH -- Page fault caused by IFETCH: we are not in TM, recording.\n"); + TM_DBG(core,IFETCH,"Page fault caused by IFETCH: we are not in TM, recording.\n"); sto = v3_store_next_instr(core,tm); if (sto == ERR_STORE_FAIL) { - PrintError(core->vm_info, core,"++ TM Error ++ Could not store next instruction in transaction\n"); + TM_ERR(core,Error,"Could not store next instruction in transaction\n"); return ERR_TRANS_FAULT_FAIL; } else if (sto == ERR_STORE_MUST_ABORT) { - PrintError(core->vm_info, core,"++ TM IFETCH ++ decode failed, going out of single stepping\n"); - v3_handle_trans_abort(core); + TM_ERR(core,IFETCH,"decode failed, going out of single stepping\n"); + v3_handle_trans_abort(core, TM_ABORT_UNSPECIFIED, 0); return TRANS_FAULT_OK; } if (v3_overwrite_next_instr(core, tm) == -1) { - PrintError(core->vm_info, core,"could not overwrite next instr!\n"); + TM_ERR(core,IFETCH,"could not overwrite next instr!\n"); return ERR_TRANS_FAULT_FAIL; } tm->TM_STATE = TM_EXEC; if (tm_record_access(tm, error.write, fault_addr) == -1) { - PrintError(core->vm_info, core,"could not record access!\n"); + TM_ERR(core,IFETCH,"could not record access!\n"); return ERR_TRANS_FAULT_FAIL; } @@ -538,9 +533,9 @@ tm_handle_fault_extern_access (struct guest_info * core, addr_t fault_addr, pf_error_t error) { - PrintDebug(core->vm_info, core,"-- TM PF HANDLE -- recording access\n"); + TM_DBG(core,PF_HANDLE,"recording access\n"); if (tm_record_access(tm, error.write, fault_addr) == -1) { - PrintError(core->vm_info, core,"could not record access!\n"); + TM_ERR(core,PF_HANDLE,"could not record access!\n"); return ERR_TRANS_FAULT_FAIL; } @@ -551,10 +546,10 @@ tm_handle_fault_extern_access (struct guest_info * core, static addr_t tm_handle_fault_tmoff (struct guest_info * core) { - PrintDebug(core->vm_info, core, "-- TM PF HANDLE -- in pf handler but noone is in tm mode anymore (core %d), i should try to eliminate hypercalls\n", core->vcpu_id); + TM_DBG(core,PF_HANDLE, "in pf handler but noone is in tm mode anymore (core %d), i should try to eliminate hypercalls\n", core->vcpu_id); if (v3_restore_dirty_instr(core) == -1) { - PrintError(core->vm_info, core,"could not restore dirty instr!\n"); + TM_ERR(core,PF_HANDLE,"could not restore dirty instr!\n"); return ERR_TRANS_FAULT_FAIL; } @@ -585,16 +580,16 @@ v3_handle_trans_mem_fault (struct guest_info * core, struct v3_tm_state * tms = (struct v3_tm_state *)v3_get_extension_state(core->vm_info, "trans_mem"); if (!tm) { - PrintError(core->vm_info, core, "+++ TM ERROR +++ : coudln't get core state\n"); + TM_ERR(core,ERROR,": coudln't get core state\n"); return ERR_TRANS_FAULT_FAIL; } if (!tms) { - PrintError(core->vm_info, core, "+++ TM ERROR +++ : couldn't get vm trans_mem state\n"); + TM_ERR(core,ERROR,": couldn't get vm trans_mem state\n"); return ERR_TRANS_FAULT_FAIL; } - PrintDebug(core->vm_info, core,"++ TM PF ++ PF handler core->mode : %d, system->mode : %d\n", tm->TM_MODE, tms->TM_MODE); + TM_DBG(core,PF,"PF handler core->mode : %d, system->mode : %d\n", tm->TM_MODE, tms->TM_MODE); if ((tm->TM_MODE == TM_ON) && ((void *)fault_addr == (void *)(core->rip))) { @@ -637,15 +632,15 @@ static int tm_handle_hcall_tmoff (struct guest_info * core, struct v3_trans_mem * tm) { if (tm->TM_MODE == TM_ON) { - PrintError(core->vm_info, core,"++ TM EXIT ++ we are in tm mode but system is not!\n"); + TM_ERR(core,EXIT,"we are in tm mode but system is not!\n"); return TRANS_HCALL_FAIL; } // we got to an exit when things were off! - PrintDebug(core->vm_info, core,"-- TM EXIT -- system is off, restore the instruction and go away\n"); + TM_DBG(core,EXIT,"system is off, restore the instruction and go away\n"); if (v3_restore_dirty_instr(core) == -1) { - PrintError(core->vm_info, core,"could not restore dirty instr!\n"); + TM_ERR(core,HCALL,"could not restore dirty instr!\n"); return TRANS_HCALL_FAIL; } @@ -660,12 +655,12 @@ tm_handle_hcall_dec_abort (struct guest_info * core, struct v3_trans_mem * tm) { // only ever get here from TM DECODE - PrintDebug(core->vm_info, core,"-- TM EXIT -- we are in ABORT, call the abort handler\n"); + TM_DBG(core,EXIT,"we are in ABORT, call the abort handler\n"); tm->TM_ABORT = 0; - v3_handle_trans_abort(core); + v3_handle_trans_abort(core, TM_ABORT_UNSPECIFIED, 0); - PrintDebug(core->vm_info, core,"-- TM EXIT -- RIP after abort: %p\n", ((void*)(core->rip))); + TM_DBG(core,EXIT,"RIP after abort: %p\n", ((void*)(core->rip))); return TRANS_HCALL_OK; } @@ -677,7 +672,7 @@ tm_handle_hcall_ifetch_start (struct guest_info * core, { tm->TM_STATE = TM_IFETCH; - PrintDebug(core->vm_info, core,"-- TM EXIT -- VMEXIT after TM_EXEC, blast away VTLB and go into TM_IFETCH\n"); + TM_DBG(core,EXIT,"VMEXIT after TM_EXEC, blast away VTLB and go into TM_IFETCH\n"); // Finally, invalidate the shadow page table v3_invalidate_shadow_pts(core); @@ -702,13 +697,13 @@ tm_check_list_conflict (struct guest_info * core, if (conflict == ERR_CHECK_FAIL) { - PrintError(core->vm_info, core,"++ TM EXIT ++ error checking for conflicts\n"); + TM_ERR(core,EXIT,"error checking for conflicts\n"); return TRANS_HCALL_FAIL; } else if (conflict == CHECK_IS_CONFLICT) { - PrintDebug(core->vm_info, core,"-- TM EXIT -- we have a conflict, aborting\n"); - v3_handle_trans_abort(core); + TM_DBG(core,EXIT,"we have a conflict, aborting\n"); + v3_handle_trans_abort(core, TM_ABORT_CONFLICT, 0); return CHECK_MUST_ABORT; } @@ -725,8 +720,8 @@ tm_handle_hcall_check_conflicts (struct guest_info * core, { int ret; - PrintDebug(core->vm_info, core,"-- TM EXIT -- still TM_ON\n"); - PrintDebug(core->vm_info, core,"-- TM EXIT -- checking for conflicts\n"); + TM_DBG(core,EXIT,"still TM_ON\n"); + TM_DBG(core,EXIT,"checking for conflicts\n"); if ((ret = tm_check_list_conflict(core, tm, &(tm->trans_w_list), OP_TYPE_WRITE)) == TRANS_HCALL_FAIL) { return TRANS_HCALL_FAIL; @@ -773,15 +768,15 @@ tm_handle_hcall (struct guest_info * core, // Previous instruction has finished, copy staging page back into linked list! if (update_list(tm, &(tm->trans_w_list)) == -1) { - PrintError(core->vm_info, core,"could not update_list!\n"); + TM_ERR(core,HCALL,"could not update_list!\n"); return TRANS_HCALL_FAIL; } // Done handling previous instruction, must put back the next instruction, reset %rip and go back to IFETCH state - PrintDebug(core->vm_info, core,"-- TM EXIT -- saw VMEXIT, need to restore previous state and proceed\n"); + TM_DBG(core,EXIT,"saw VMEXIT, need to restore previous state and proceed\n"); if (v3_restore_dirty_instr(core) == -1) { - PrintError(core->vm_info, core,"could not restore dirty instr!\n"); + TM_ERR(core,HCALL,"could not restore dirty instr!\n"); return TRANS_HCALL_FAIL; } @@ -802,7 +797,7 @@ tm_handle_hcall (struct guest_info * core, return tm_handle_hcall_check_conflicts(core, tm); } else if (tm->TM_MODE == TM_OFF) { - PrintDebug(core->vm_info, core,"-- TM EXIT -- we are in TM_OFF\n"); + TM_DBG(core,EXIT,"we are in TM_OFF\n"); } return TRANS_HCALL_OK; @@ -825,11 +820,11 @@ v3_tm_inc_tnum (struct v3_trans_mem * tm) tm->t_num++; /* - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"-- TM INC TNUM -- global state is |%d|%d|, my tnum is %d\n", (int)lt[0], + TM_DBG(tm->ginfo,INC TNUM,"global state is |%d|%d|, my tnum is %d\n", (int)lt[0], (int)lt[1], (int)tm->t_num); */ if (new_ctxt != tm->t_num) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM INC TNUM ++ misaligned global and local context value\n"); + TM_ERR(tm->ginfo,TM_INC_TNUM,"misaligned global and local context value\n"); return -1; } @@ -837,30 +832,65 @@ v3_tm_inc_tnum (struct v3_trans_mem * tm) } +static void +tm_set_abort_status (struct guest_info * core, + tm_abrt_cause_t cause, + uint8_t xabort_reason) +{ + core->vm_regs.rax = 0; + + switch (cause) { + case TM_ABORT_XABORT: + // we put the xabort immediate in eax 31:24 + // cause is zero + core->vm_regs.rax |= (xabort_reason << 24); + break; + case TM_ABORT_CONFLICT: + // if this was a conflict from another core, it may work + // if we try again + core->vm_regs.rax |= (1 << ABORT_CONFLICT) | (1 << ABORT_RETRY); + break; + case TM_ABORT_INTERNAL: + case TM_ABORT_BKPT: + core->vm_regs.rax |= (1 << cause); + break; + case TM_ABORT_UNSPECIFIED: + // just return 0 in EAX + break; + default: + TM_ERR(core, ABORT, "invalid abort cause\n"); + break; + } +} + + +// xabort_reason is only used for XABORT instruction int -v3_handle_trans_abort (struct guest_info * core) +v3_handle_trans_abort (struct guest_info * core, + tm_abrt_cause_t cause, + uint8_t xabort_reason) { struct v3_trans_mem * tm = (struct v3_trans_mem *)v3_get_ext_core_state(core, "trans_mem"); // Free the staging page if (v3_free_staging_page(tm) == -1) { - PrintError(core->vm_info, core,"++ TM ABORT ++ problem freeing staging page\n"); + TM_ERR(core,ABORT,"problem freeing staging page\n"); return -1; } // Clear the VTLB which still has our staging page in it if (v3_clr_vtlb(core) == -1) { - PrintError(core->vm_info, core,"++ TM ABORT ++ problem clearing vtlb\n"); + TM_ERR(core,ABORT,"problem clearing vtlb\n"); return -1; } // Free the lists v3_clear_tm_lists(tm); - PrintDebug(core->vm_info, core,"-- TM ABORT -- handler - TM_MODE: %d | RIP: %llx | XABORT RIP: %llx\n", tm->TM_MODE, (uint64_t)core->rip, (uint64_t)tm->fail_call); + TM_DBG(core,ABORT -- handler,"TM_MODE: %d | RIP: %llx | XABORT RIP: %llx\n", tm->TM_MODE, (uint64_t)core->rip, (uint64_t)tm->fail_call); if (tm->TM_MODE == TM_ON) { - PrintDebug(core->vm_info, core,"-- TM ABORT -- Setting RIP to %llx\n", (uint64_t)tm->fail_call); + TM_DBG(core,ABORT,"Setting RIP to %llx\n", (uint64_t)tm->fail_call); core->rip = tm->fail_call; // Turn TM off @@ -870,10 +900,11 @@ v3_handle_trans_abort (struct guest_info * core) v3_tm_inc_tnum(tm); } - + tm_set_abort_status(core, cause, xabort_reason); + // time to garbage collect if (tm_hash_gc(tm) == -1) { - PrintError(core->vm_info, core,"could not gc!\n"); + TM_ERR(core,GC,"could not gc!\n"); return -1; } @@ -1108,33 +1139,25 @@ static int tm_collect_context (struct v3_trans_mem * tm, struct hashtable_iter * ctxt_iter, struct hash_chain * curr, - uint64_t * begin_time, - uint64_t * end_time, addr_t gva) { uint64_t i; for (i = 0; i < tm->ginfo->vm_info->num_cores; i++) { - void * buf[3]; + struct v3_ctxt_tuple tup; struct v3_tm_access_type * type; addr_t key; - rdtscll(*end_time); - if ((*end_time - *begin_time) > 100000000) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ GC ++ time threshhold exceeded, exiting!!!\n"); - return -1; - } - - buf[0] = (void *)gva; - buf[1] = (void *)i; - buf[2] = (void *)curr->curr_lt[i]; + tup.gva = (void *)gva; + tup.core_id = (void *)i; + tup.core_lt = (void *)curr->curr_lt[i]; - key = v3_hash_buffer((uchar_t*)buf, sizeof(void*)*3); + key = v3_hash_buffer((uchar_t*)&tup, sizeof(struct v3_ctxt_tuple)); type = (struct v3_tm_access_type *)v3_htable_search(tm->access_type, key); if (!type) { // something has gone terribly wrong - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM GC ++ could not find accesstype entry to gc, THIS! IS! WRONG!\n"); + TM_ERR(tm->ginfo,GC,"could not find accesstype entry to gc, THIS! IS! WRONG!\n"); return -1; } @@ -1153,9 +1176,7 @@ static int tm_collect_all_contexts (struct v3_trans_mem * tm, struct hashtable_iter * ctxt_iter, uint64_t tmoff, - uint64_t * lt_copy, - uint64_t * begin_time, - uint64_t * end_time) + uint64_t * lt_copy) { struct hash_chain * tmp; struct hash_chain * curr; @@ -1176,15 +1197,15 @@ tm_collect_all_contexts (struct v3_trans_mem * tm, /* not garbage, go on to the next context in the list */ if (!to_gc) { - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"-- TM GC -- not garbage collecting entries for address %llx\n", (uint64_t)gva); + TM_DBG(tm->ginfo,GC,"not garbage collecting entries for address %llx\n", (uint64_t)gva); continue; } - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"-- TM GC -- garbage collecting entries for address %llx\n", (uint64_t)gva); + TM_DBG(tm->ginfo,GC,"garbage collecting entries for address %llx\n", (uint64_t)gva); /* found one, delete corresponding entries in access_type */ - if (tm_collect_context(tm, ctxt_iter, curr, begin_time, end_time, gva) == -1) { - PrintError(tm->ginfo->vm_info, tm->ginfo, "++ TM GC ++ ERROR collecting context\n"); + if (tm_collect_context(tm, ctxt_iter, curr, gva) == -1) { + TM_ERR(tm->ginfo,GC,"ERROR collecting context\n"); return -1; } @@ -1210,33 +1231,31 @@ tm_hash_gc (struct v3_trans_mem * tm) { addr_t irqstate, irqstate2; int rc = 0; - uint64_t begin_time, end_time, tmoff; + uint64_t tmoff; uint64_t * lt_copy; struct v3_tm_state * tms = NULL; struct hashtable_iter * ctxt_iter = NULL; tms = (struct v3_tm_state *)v3_get_extension_state(tm->ginfo->vm_info, "trans_mem"); if (!tms) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ %d : TM GC ++ could not alloc tms\n", tm->ginfo->vcpu_id); + TM_ERR(tm->ginfo,GC,"could not alloc tms\n"); return -1; } - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"-- TM GC -- beginning garbage collection\n"); - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"\t %d entries in addr_ctxt (pre)\n", (int)v3_htable_count(tm->addr_ctxt)); - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"\t %d entries in access_type (pre)\n", (int)v3_htable_count(tm->access_type)); + TM_DBG(tm->ginfo,GC,"beginning garbage collection\n"); + TM_DBG(tm->ginfo,GC,"\t %d entries in addr_ctxt (pre)\n", (int)v3_htable_count(tm->addr_ctxt)); + TM_DBG(tm->ginfo,GC,"\t %d entries in access_type (pre)\n", (int)v3_htable_count(tm->access_type)); tmoff = (tms->cores_active == 0); lt_copy = V3_Malloc(sizeof(uint64_t)*(tm->ginfo->vm_info->num_cores)); if (!lt_copy) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM GC ++ Could not allocate space for lt_copy\n"); + TM_ERR(tm->ginfo,GC,"Could not allocate space for lt_copy\n"); return -1; } memset(lt_copy, 0, sizeof(uint64_t)*(tm->ginfo->vm_info->num_cores)); - rdtscll(begin_time); - /* lt_copy holds the last transaction number for each core */ irqstate = v3_lock_irqsave(tm_global_state->lock); memcpy(lt_copy, tm_global_state->last_trans, sizeof(uint64_t)*(tm->ginfo->vm_info->num_cores)); @@ -1249,7 +1268,7 @@ tm_hash_gc (struct v3_trans_mem * tm) /* loop over hash entries in addr_ctxt */ ctxt_iter = v3_create_htable_iter(tm->addr_ctxt); if (!ctxt_iter) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM GC ++ could not create htable iterator\n"); + TM_ERR(tm->ginfo,GC,"could not create htable iterator\n"); rc = -1; goto out; } @@ -1257,7 +1276,7 @@ tm_hash_gc (struct v3_trans_mem * tm) /* we check each address stored in the hash */ while (ctxt_iter->entry) { /* NOTE: this call advances the hash iterator */ - if (tm_collect_all_contexts(tm, ctxt_iter, tmoff, lt_copy, &begin_time, &end_time) == -1) { + if (tm_collect_all_contexts(tm, ctxt_iter, tmoff, lt_copy) == -1) { rc = -1; goto out1; } @@ -1270,16 +1289,14 @@ out: v3_unlock_irqrestore(tm->access_type_lock, irqstate); v3_unlock_irqrestore(tm->addr_ctxt_lock, irqstate2); - rdtscll(end_time); - if (rc == -1) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM GC ++ garbage collection failed, time spent: %d cycles\n", (int)(end_time - begin_time)); + TM_ERR(tm->ginfo,GC,"garbage collection failed\n"); } else { - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"++ TM GC ++ ended garbage collection succesfuly, time spent: %d cycles\n", (int)(end_time - begin_time)); + TM_DBG(tm->ginfo,GC,"ended garbage collection succesfuly\n"); } - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"\t %d entries in addr_ctxt (post)\n", (int)v3_htable_count(tm->addr_ctxt)); - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"\t %d entries in access_type (post)\n", (int)v3_htable_count(tm->access_type)); + TM_DBG(tm->ginfo,GC,"\t %d entries in addr_ctxt (post)\n", (int)v3_htable_count(tm->addr_ctxt)); + TM_DBG(tm->ginfo,GC,"\t %d entries in access_type (post)\n", (int)v3_htable_count(tm->access_type)); return rc; } @@ -1322,7 +1339,7 @@ tm_update_ctxt_list (struct v3_trans_mem * tm, struct hash_chain * new_l = V3_Malloc(sizeof(struct hash_chain)); if (!new_l) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ %d : TM HASH ++ Could not allocate new list\n", tm->ginfo->vcpu_id); + TM_ERR(tm->ginfo,HASH,"Could not allocate new list\n"); return -1; } @@ -1353,7 +1370,7 @@ tm_update_ctxt_list (struct v3_trans_mem * tm, type = V3_Malloc(sizeof(struct v3_tm_access_type)); if (!type) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"could not allocate type access struct\n"); + TM_ERR(tm->ginfo,HASH,"could not allocate type access struct\n"); return -1; } } @@ -1366,7 +1383,7 @@ tm_update_ctxt_list (struct v3_trans_mem * tm, if (new_e) { if (HTABLE_INSERT(tm->access_type, key, type) == 0) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"TM: problem inserting new mem access in htable\n"); + TM_ERR(tm->ginfo,HASH,"problem inserting new mem access in htable\n"); return -1; } (tm->access_type_entries)++; @@ -1391,7 +1408,7 @@ tm_create_ctxt_key (struct v3_trans_mem * tm, hash_list = (struct list_head *)V3_Malloc(sizeof(struct list_head)); if (!hash_list) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM HASH ++ Problem allocating hash_list\n"); + TM_ERR(tm->ginfo,HASH,"Problem allocating hash_list\n"); return -1; } @@ -1400,7 +1417,7 @@ tm_create_ctxt_key (struct v3_trans_mem * tm, new_l = V3_Malloc(sizeof(struct hash_chain)); if (!new_l) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM HASH ++ Problem allocating hash_chain\n"); + TM_ERR(tm->ginfo,HASH,"Problem allocating hash_chain\n"); goto out_err; } @@ -1412,7 +1429,7 @@ tm_create_ctxt_key (struct v3_trans_mem * tm, list_add_tail(&(new_l->lt_node), hash_list); if (!(HTABLE_INSERT(tm->addr_ctxt, gva, hash_list))) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"++ TM HASH CHAIN ++ problem inserting new chain into hash\n"); + TM_ERR(tm->ginfo,HASH CHAIN,"problem inserting new chain into hash\n"); goto out_err1; } @@ -1431,7 +1448,7 @@ tm_create_ctxt_key (struct v3_trans_mem * tm, type = V3_Malloc(sizeof(struct v3_tm_access_type)); if (!type) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"could not allocate access type struct\n"); + TM_ERR(tm->ginfo,HASH,"could not allocate access type struct\n"); goto out_err1; } @@ -1444,7 +1461,7 @@ tm_create_ctxt_key (struct v3_trans_mem * tm, key = v3_hash_buffer((uchar_t*)&tup, sizeof(struct v3_ctxt_tuple)); if (HTABLE_INSERT(tm->access_type, key, type) == 0) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"TM: problem inserting new mem access in htable\n"); + TM_ERR(tm->ginfo,HASH,"TM: problem inserting new mem access in htable\n"); goto out_err1; } (tm->access_type_entries)++; @@ -1479,13 +1496,13 @@ tm_record_access (struct v3_trans_mem * tm, num_cores = tm->ginfo->vm_info->num_cores; - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"-- TM REC -- recording addr %llx, addr-ctxt.cnt = %d, access-type.cnt = %d\n", (uint64_t)gva, + TM_DBG(tm->ginfo,REC,"recording addr %llx, addr-ctxt.cnt = %d, access-type.cnt = %d\n", (uint64_t)gva, (int)v3_htable_count(tm->addr_ctxt), (int)v3_htable_count(tm->access_type)); - PrintDebug(tm->ginfo->vm_info, tm->ginfo,"\tWe think that addr-ctxt.cnt = %d, access-type.cnt = %d\n",(int)tm->addr_ctxt_entries,(int)tm->access_type_entries); + //PrintDebug(tm->ginfo->vm_info, tm->ginfo,"\tWe think that addr-ctxt.cnt = %d, access-type.cnt = %d\n",(int)tm->addr_ctxt_entries,(int)tm->access_type_entries); lt_copy = V3_Malloc(sizeof(uint64_t)*num_cores); if (!lt_copy) { - PrintError(tm->ginfo->vm_info, tm->ginfo,"Allocating array failed\n"); + TM_ERR(tm->ginfo,REC,"Allocating array failed\n"); return -1; } @@ -1508,6 +1525,34 @@ tm_record_access (struct v3_trans_mem * tm, } +static void +tm_prepare_cpuid (struct v3_vm_info * vm) +{ + + V3_Print(vm, VCORE_NONE, "TM INIT | enabling RTM cap in CPUID\n"); + + /* increase max CPUID function to 7 (extended feature flags enumeration) */ + v3_cpuid_add_fields(vm,0x0, + 0xf, 0x7, + 0, 0, + 0, 0, + 0, 0); + + + /* do the same for AMD */ + v3_cpuid_add_fields(vm,0x80000000, + 0xffffffff, 0x80000007, + 0, 0, + 0, 0, + 0, 0); + + + /* enable RTM (CPUID.07H.EBX.RTM = 1) */ + v3_cpuid_add_fields(vm, 0x07, 0, 0, (1<<11), 0, 0, 0, 0, 0); + v3_cpuid_add_fields(vm, 0x80000007, 0, 0, (1<<11), 0, 0, 0, 0, 0); +} + + static int init_trans_mem (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, @@ -1553,6 +1598,8 @@ init_trans_mem (struct v3_vm_info * vm, *priv_data = tms; tm_global_state = tms; + tm_prepare_cpuid(vm); + return 0; out_err1: @@ -1571,10 +1618,10 @@ init_trans_mem_core (struct guest_info * core, { struct v3_trans_mem * tm = V3_Malloc(sizeof(struct v3_trans_mem)); - PrintDebug(core->vm_info, core, "Trans Mem. Core Init\n"); + TM_DBG(core,INIT, "Trans Mem. Core Init\n"); if (!tm) { - PrintError(core->vm_info, core, "Problem allocating TM state\n"); + TM_ERR(core,INIT, "Problem allocating TM state\n"); return -1; } @@ -1585,13 +1632,13 @@ init_trans_mem_core (struct guest_info * core, tm->addr_ctxt = v3_create_htable(0, tm_hash_fn, tm_eq_fn); if (!(tm->addr_ctxt)) { - PrintError(core->vm_info, core,"++ TM INIT ++ problem creating addr_ctxt\n"); + TM_ERR(core,INIT,"problem creating addr_ctxt\n"); goto out_err; } tm->access_type = v3_create_htable(0, tm_hash_buf_fn, tm_eq_buf_fn); if (!(tm->access_type)) { - PrintError(core->vm_info, core,"++ TM INIT ++ problem creating access_type\n"); + TM_ERR(core,INIT,"problem creating access_type\n"); goto out_err1; } @@ -1657,12 +1704,12 @@ deinit_trans_mem_core (struct guest_info * core, v3_clear_tm_lists(tm); if (tm->staging_page) { - PrintError(core->vm_info, core,"++ TM DEINIT CORE ++ WARNING: staging page not freed!\n"); + TM_ERR(core,DEINIT CORE,"WARNING: staging page not freed!\n"); } ctxt_iter = v3_create_htable_iter(tm->addr_ctxt); if (!ctxt_iter) { - PrintError(core->vm_info, core, "++ TM DEINIT CORE ++ could not create htable iterator\n"); + TM_DBG(core,DEINIT_CORE,"could not create htable iterator\n"); return -1; } @@ -1695,9 +1742,7 @@ deinit_trans_mem_core (struct guest_info * core, v3_lock_deinit(&(tm->addr_ctxt_lock)); v3_lock_deinit(&(tm->access_type_lock)); - if (tm) { - V3_Free(tm); - } + V3_Free(tm); return 0; } @@ -1725,16 +1770,14 @@ static int tm_handle_xend (struct guest_info * core, struct v3_trans_mem * tm) { - rdtscll(tm->exit_time); - // Error checking! make sure that we have gotten here in a legitimate manner + /* XEND should raise a GPF when RTM mode is not on */ if (tm->TM_MODE != TM_ON) { TM_ERR(core, UD, "Encountered XEND while not in a transactional region\n"); - v3_free_staging_page(tm); - v3_clr_vtlb(core); - v3_clear_tm_lists(tm); - v3_raise_exception(core, UD_EXCEPTION); + + v3_raise_exception(core, GPF_EXCEPTION); return 0; + } /* Our transaction finished! */ @@ -1786,10 +1829,13 @@ tm_handle_xend (struct guest_info * core, */ static int tm_handle_xabort (struct guest_info * core, - struct v3_trans_mem * tm) + struct v3_trans_mem * tm, + uchar_t * instr) { - /* TODO: this probably needs to move somewhere else */ - rdtscll(tm->exit_time); + uint8_t reason; + + // we must reflect the immediate back into EAX 31:24 + reason = *(uint8_t*)(instr+2); // Error checking! make sure that we have gotten here in a legitimate manner if (tm->TM_MODE != TM_ON) { @@ -1804,7 +1850,7 @@ tm_handle_xabort (struct guest_info * core, } // Handle the exit - v3_handle_trans_abort(core); + v3_handle_trans_abort(core, TM_ABORT_XABORT, reason); return 0; } @@ -1820,22 +1866,38 @@ tm_handle_xbegin (struct guest_info * core, uchar_t * instr) { sint32_t rel_addr = 0; + uint8_t out_of_bounds = 0; + uint8_t in_compat_no_long = 0; if (tm->TM_MODE == TM_ON) { - TM_ERR(core,UD,"We got here while already in a transactional region!"); + /* TODO: this is actually an indication of nesting, we'll fix this later */ + TM_ERR(core,UD,"We don't support nested transactions yet!\n"); v3_raise_exception(core, UD_EXCEPTION); + return -1; } - rdtscll(tm->entry_time); - tm->entry_exits = core->num_exits; + // Save the fail_call address (first 2 bytes = opcode, last 4 = fail call addr) + rel_addr = *(sint32_t*)(instr+2); + + /* raise a GPF if we're trying to set a fail call outside of code segment */ + in_compat_no_long = (core->cpu_mode == LONG_32_COMPAT) || ((struct efer_64*)&(core->ctrl_regs.efer))->lma == 0; + out_of_bounds = (core->rip + rel_addr > core->segments.cs.base + core->segments.cs.limit || + core->rip + rel_addr < core->segments.cs.base); + + if (in_compat_no_long && out_of_bounds) { + v3_raise_exception(core, GPF_EXCEPTION); + return 0; + } + + /* TODO: also raise GPF if we're in long mode and failcall isn't canonical */ + /* set the tm_mode for this core */ v3_set_tm(tm); TM_DBG(core,UD,"Set the system in TM Mode, save fallback address"); - // Save the fail_call address (first 2 bytes = opcode, last 4 = fail call addr) - rel_addr = *(sint32_t*)(instr+2); + tm->fail_call = core->rip + XBEGIN_INSTR_LEN + rel_addr; TM_DBG(core,UD,"we set fail_call to %llx, rip is %llx, rel_addr is %x", (uint64_t)tm->fail_call,(uint64_t)core->rip,rel_addr); @@ -1859,13 +1921,21 @@ static int tm_handle_xtest (struct guest_info * core, struct v3_trans_mem * tm) { + struct rflags * rf = (struct rflags*)&(core->ctrl_regs.rflags); + // if we are in tm mode, set zf to 0, otherwise 1 if (tm->TM_MODE == TM_ON) { - core->ctrl_regs.rflags &= ~(1ULL << 6); + rf->zf = 0; } else { - core->ctrl_regs.rflags |= (1ULL << 6); + rf->zf = 1; } + rf->cf = 0; + rf->of = 0; + rf->sf = 0; + rf->pf = 0; + rf->af = 0; + core->rip += XTEST_INSTR_LEN; return 0; @@ -1904,7 +1974,7 @@ tm_handle_ud (struct guest_info * core) TM_DBG(core, UD, "Encountered Haswell-specific XABORT %x %x %d at %llx\n", byte1, byte2, byte3, (uint64_t)core->rip); - if (tm_handle_xabort(core, tm) == -1) { + if (tm_handle_xabort(core, tm, instr) == -1) { TM_ERR(core, UD, "Problem handling XABORT\n"); return -1; } @@ -1946,7 +2016,7 @@ v3_tm_handle_exception (struct guest_info * info, struct v3_trans_mem * tm = (struct v3_trans_mem *)v3_get_ext_core_state(info, "trans_mem"); if (!tm) { - PrintError(info->vm_info, info, "++ TM ERR ++ TM extension state not found\n"); + TM_ERR(info,ERR,"TM extension state not found\n"); return -1; } @@ -1962,8 +2032,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, DE_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to DE exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to DE exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP1: @@ -1971,8 +2041,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, DB_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to DB exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to DB exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP3: @@ -1980,8 +2050,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, BP_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to BP exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to BP exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP4: @@ -1989,8 +2059,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, OF_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to OF exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to OF exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP5: @@ -1998,8 +2068,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, BR_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to BR exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to BR exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP7: @@ -2007,8 +2077,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, NM_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to NM exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to NM exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP10: @@ -2016,8 +2086,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, TS_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to TS exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to TS exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP11: @@ -2025,8 +2095,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, NP_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to NP exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to NP exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP12: @@ -2034,8 +2104,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, SS_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to SS exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to SS exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP13: @@ -2043,8 +2113,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, GPF_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to GPF exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to GPF exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP16: @@ -2052,8 +2122,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, MF_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to MF exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to MF exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP17: @@ -2061,8 +2131,8 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, AC_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to AC exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to AC exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; case SVM_EXIT_EXCP19: @@ -2070,12 +2140,12 @@ v3_tm_handle_exception (struct guest_info * info, v3_raise_exception(info, XF_EXCEPTION); } else { - PrintDebug(info->vm_info, info,"-- TM EXCP -- aborting due to XF exception\n"); - v3_handle_trans_abort(info); + TM_DBG(info,EXCP,"aborting due to XF exception\n"); + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); } break; - PrintDebug(info->vm_info, info,"-- TM EXCP -- exception # %d\n", (int)exit_code - 0x40); + TM_DBG(info,EXCP,"exception # %d\n", (int)exit_code - 0x40); } return 0; @@ -2118,29 +2188,27 @@ v3_tm_check_intr_state (struct guest_info * info, struct v3_trans_mem * tm = (struct v3_trans_mem *)v3_get_ext_core_state(info, "trans_mem"); if (!tm) { - PrintError(info->vm_info, info,"++ : SVM ++ TM extension state not found\n"); - v3_stgi(); + TM_ERR(info,INTR,"TM extension state not found\n"); return; } - /* TODO: work this in */ - if (0 && (tm->TM_MODE == TM_ON) && - (tm->TM_ABORT != 1)) { + if ((tm->TM_MODE == TM_ON) && + (tm->TM_ABORT != 1)) { if (guest_ctrl->guest_ctrl.V_IRQ || guest_ctrl->EVENTINJ.valid) { - rdtscll(tm->exit_time); - PrintDebug(info->vm_info, info,"+=+ TM INTR DEBUG +=+ %lld exits happened, time delta is %lld",(info->num_exits - tm->entry_exits),(tm->entry_time - tm->exit_time)); - // We do indeed have pending interrupts v3_stgi(); - PrintDebug(info->vm_info, info,"-- ITR -- we have a pending interrupt!\n"); - v3_handle_trans_abort(info); + TM_DBG(info,INTR,"we have a pending interrupt\n"); + + v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0); + // Copy new RIP state into arch dependent structure guest_state->rip = info->rip; - PrintDebug(info->vm_info, info,"currently guest state rip is %llx\n",(uint64_t)guest_state->rip); + + //TM_DBG(info,INTR,"currently guest state rip is %llx\n",(uint64_t)guest_state->rip); v3_clgi(); } @@ -2159,24 +2227,24 @@ v3_tm_handle_pf_64 (struct guest_info * info, struct v3_tm_state * tms = (struct v3_tm_state *)v3_get_extension_state(info->vm_info, "trans_mem"); if (!tm) { - PrintError(info->vm_info, info, "+++ TM +++ ERROR: couldn't get tm core state\n"); + TM_ERR(info,HANDLE_PF, "couldn't get tm core state\n"); return -1; } if (!tms) { - PrintError(info->vm_info, info, "+++ TM +++ ERROR: couldn't get tm global state\n"); + TM_ERR(info,HANDLE_PF, "couldn't get tm global state\n"); return -1; } if ((tms->TM_MODE == TM_ON) && (error_code.user == 1)) { - PrintDebug(info->vm_info, info,"++ TM #PF ++ Core reporting in, got a #PF (tms->mode is %d)\n", tms->TM_MODE); + TM_DBG(info,PF,"Core reporting in, got a #PF (tms->mode is %d)\n", tms->TM_MODE); *page_to_use = v3_handle_trans_mem_fault(info, fault_addr, error_code); if (*page_to_use == ERR_TRANS_FAULT_FAIL){ - PrintError(info->vm_info, info, "could not handle transaction page fault\n"); + TM_ERR(info,HANDLE_PF, "could not handle transaction page fault\n"); return -1; } @@ -2186,11 +2254,11 @@ v3_tm_handle_pf_64 (struct guest_info * info, tm->staging_page = V3_AllocPages(1); if (!(tm->staging_page)) { - PrintError(info->vm_info, info,"++ TM MMU ++ Problem allocating staging page\n"); + TM_ERR(info,MMU,"Problem allocating staging page\n"); return -1; } - PrintDebug(info->vm_info, info,"-- TM MMU -- Created staging page at %p\n", (void *)tm->staging_page); + TM_DBG(info,MMU,"Created staging page at %p\n", (void *)tm->staging_page); } } @@ -2211,7 +2279,7 @@ v3_tm_handle_usr_tlb_miss (struct guest_info * info, (error_code.user == 1)) { if (page_to_use > TRANS_FAULT_OK) { - PrintDebug(info->vm_info, info, "-- TM MMU -- Using alternate page at: %llx\n", (uint64_t)page_to_use); + TM_DBG(info,MMU, "Using alternate page at: %llx\n", (uint64_t)page_to_use); *shadow_pa = page_to_use; } @@ -2234,7 +2302,7 @@ v3_tm_handle_read_fault (struct guest_info * info, (error_code.write == 0) && (error_code.user == 1)) { - PrintDebug(info->vm_info, info, "-- TM MMU -- Flagging the page read only\n"); + TM_DBG(info,MMU, "Flagging the page read only\n"); shadow_pte->writable = 0; } } @@ -2283,3 +2351,4 @@ v3_tm_decode_rtm_instrs (struct guest_info * info, return 0; } +