#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";
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;
}
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;
}
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;
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;
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;
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;
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;
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;
// 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 */
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;
}
/* 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;
}
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) */
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;
}
(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
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;
}
{
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;
}
{
// 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;
}
* 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;
}
//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;
}
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;
}
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;
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;
}
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;
}
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;
}
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))) {
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;
}
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;
}
{
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);
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;
}
{
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;
// 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;
}
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;
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;
}
}
+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
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;
}
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;
}
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;
/* 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;
}
{
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));
/* 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;
}
/* 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;
}
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;
}
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;
}
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;
}
}
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)++;
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;
}
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;
}
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;
}
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;
}
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)++;
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;
}
}
+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,
*priv_data = tms;
tm_global_state = tms;
+ tm_prepare_cpuid(vm);
+
return 0;
out_err1:
{
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;
}
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;
}
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;
}
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! */
*/
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) {
}
// Handle the exit
- v3_handle_trans_abort(core);
+ v3_handle_trans_abort(core, TM_ABORT_XABORT, reason);
return 0;
}
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;
+ }
+
+ // 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;
}
- rdtscll(tm->entry_time);
- tm->entry_exits = core->num_exits;
+ /* 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);
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;
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;
}
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;
}
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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;
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();
}
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;
}
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);
}
}
(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;
}
(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;
}
}
return 0;
}
+