/* this will attempt to abort all the remote cores */
if (tm_handle_decode_fail(core) == -1) {
TM_ERR(core,Error,"Could not handle failed decode\n");
- return -1;
+ return ERR_STORE_FAIL;
}
/* we need to trigger a local abort */
return ERR_TRANS_FAULT_FAIL;
} else if (sto == ERR_STORE_MUST_ABORT) {
TM_DBG(core,EXIT,"aborting for some reason\n");
- v3_handle_trans_abort(core);
+ v3_handle_trans_abort(core, TM_ABORT_UNSPECIFIED, 0);
return TRANS_FAULT_OK;
}
} else if (sto == ERR_STORE_MUST_ABORT) {
TM_ERR(core,IFETCH,"decode failed, going out of single stepping\n");
- v3_handle_trans_abort(core);
+ v3_handle_trans_abort(core, TM_ABORT_UNSPECIFIED, 0);
return TRANS_FAULT_OK;
}
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);
TM_DBG(core,EXIT,"RIP after abort: %p\n", ((void*)(core->rip)));
} else if (conflict == CHECK_IS_CONFLICT) {
TM_DBG(core,EXIT,"we have a conflict, aborting\n");
- v3_handle_trans_abort(core);
+ v3_handle_trans_abort(core, TM_ABORT_CONFLICT, 0);
return CHECK_MUST_ABORT;
}
}
+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;
+ 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");
v3_tm_inc_tnum(tm);
}
-
+ tm_set_abort_status(core, cause, xabort_reason);
+
// time to garbage collect
if (tm_hash_gc(tm) == -1) {
TM_ERR(core,GC,"could not gc!\n");
}
+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:
*/
static int
tm_handle_xabort (struct guest_info * core,
- struct v3_trans_mem * tm)
+ struct v3_trans_mem * tm,
+ uchar_t * instr)
{
+ uint8_t reason;
+
+ // we must reflect the immediate back into EAX 31:24
+ reason = *(uint8_t*)(instr+2);
+
/* TODO: this probably needs to move somewhere else */
rdtscll(tm->exit_time);
}
// Handle the exit
- v3_handle_trans_abort(core);
+ v3_handle_trans_abort(core, TM_ABORT_XABORT, reason);
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;
}
}
else {
TM_DBG(info,EXCP,"aborting due to DE exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP1:
}
else {
TM_DBG(info,EXCP,"aborting due to DB exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP3:
}
else {
TM_DBG(info,EXCP,"aborting due to BP exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP4:
}
else {
TM_DBG(info,EXCP,"aborting due to OF exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP5:
}
else {
TM_DBG(info,EXCP,"aborting due to BR exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP7:
}
else {
TM_DBG(info,EXCP,"aborting due to NM exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP10:
}
else {
TM_DBG(info,EXCP,"aborting due to TS exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP11:
}
else {
TM_DBG(info,EXCP,"aborting due to NP exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP12:
}
else {
TM_DBG(info,EXCP,"aborting due to SS exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP13:
}
else {
TM_DBG(info,EXCP,"aborting due to GPF exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP16:
}
else {
TM_DBG(info,EXCP,"aborting due to MF exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP17:
}
else {
TM_DBG(info,EXCP,"aborting due to AC exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
case SVM_EXIT_EXCP19:
}
else {
TM_DBG(info,EXCP,"aborting due to XF exception\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
}
break;
v3_stgi();
TM_DBG(info,INTR,"we have a pending interrupt!\n");
- v3_handle_trans_abort(info);
+ v3_handle_trans_abort(info, TM_ABORT_UNSPECIFIED, 0);
// Copy new RIP state into arch dependent structure
guest_state->rip = info->rip;
TM_DBG(info,INTR,"currently guest state rip is %llx\n",(uint64_t)guest_state->rip);
return 0;
}
+