Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cleanup based on cppcheck pass (Devices and Extensions)
[palacios.git] / palacios / src / extensions / ext_trans_mem.c
index 4b417e1..7fb8164 100644 (file)
 #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;
 }
 
+