time handling on SVM.
help
This turns on debugging for the interrupt system
-
+config DEBUG_TIME
+ bool "Timing"
+ default n
+ depends on DEBUG_ON
+ help
+ This turns on debugging of system time virtualization
config DEBUG_IO
bool "IO"
int v3_svm_enter(struct guest_info * info) {
vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
- ullong_t tmp_tsc;
addr_t exit_code = 0, exit_info1 = 0, exit_info2 = 0;
// Conditionally yield the CPU if the timeslice has expired
#endif
- rdtscll(tmp_tsc);
- v3_update_timers(info, (tmp_tsc - info->time_state.cached_host_tsc));
- rdtscll(info->time_state.cached_host_tsc);
- // guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
+ v3_update_timers(info);
+ v3_resume_time(info);
+ guest_ctrl->TSC_OFFSET = info->time_state.host_offset;
//V3_Print("Calling v3_svm_launch\n");
-
v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->cpu_id]);
-
- //V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip);
+ v3_pause_time(info);
+#ifdef OPTION_TIME_MASK_OVERHEAD
+ v3_offset_time(info, -SVM_ENTRY_OVERHEAD);
+#endif
- v3_last_exit = (uint32_t)(guest_ctrl->exit_code);
+ //V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip);
- //rdtscll(tmp_tsc);
- // v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
+ v3_last_exit = (uint32_t)(guest_ctrl->exit_code);
//PrintDebug("SVM Returned\n");
info->num_exits++;
-
-
-
// Save Guest state from VMCB
info->rip = guest_state->rip;
info->vm_regs.rsp = guest_state->rsp;
//PrintDebugVMCB((vmcb_t*)(info->vmm_data));
info->vm_info->run_state = VM_RUNNING;
- rdtscll(info->yield_start_cycle);
-
+ v3_start_time(info);
while (1) {
if (v3_svm_enter(info) == -1) {
#include <palacios/vmm.h>
#include <palacios/vm_guest.h>
+#ifndef CONFIG_DEBUG_TIME
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
static int handle_cpufreq_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
struct vm_time * time_state = &(info->time_state);
int v3_start_time(struct guest_info * info) {
/* We start running with guest_time == host_time */
uint64_t t = v3_get_host_time(info);
+
+ PrintDebug("Starting initial guest time as %llu\n", t);
info->time_state.last_update = t;
info->time_state.pause_time = t;
return 0;
int v3_pause_time(struct guest_info * info) {
V3_ASSERT(info->time_state.pause_time == 0);
info->time_state.pause_time = v3_get_guest_time(info);
+ PrintDebug("Time paused at guest time as %llu\n",
+ info->time_state.pause_time);
return 0;
}
int v3_resume_time(struct guest_info * info) {
uint64_t t = v3_get_host_time(info);
V3_ASSERT(info->time_state.pause_time != 0);
-#ifdef OPTION_TIME_ADJUST_TSC_OFFSET
-#endif
info->time_state.host_offset =
(sint64_t)info->time_state.pause_time - (sint64_t)t;
+#ifdef OPTION_TIME_ADJUST_TSC_OFFSET
+ /* XXX Adjust host_offset towards zero based on resolution/accuracy
+ * constraints. */
+#endif
info->time_state.pause_time = 0;
+ PrintDebug("Time resumed paused at guest time as %llu "
+ "offset %lld from host time.\n", t, info->time_state.host_offset);
+
return 0;
}
tsc_offset_low = (uint32_t)(info->time_state.host_offset & 0xffffffff);
check_vmcs_write(VMCS_TSC_OFFSET_HIGH, tsc_offset_high);
check_vmcs_write(VMCS_TSC_OFFSET, tsc_offset_low);
-
+ PrintDebug("Stored 0x %x %x into vmcs TSC offset.\n",
+ tsc_offset_high, tsc_offset_low);
if (info->vm_info->run_state == VM_STOPPED) {
info->vm_info->run_state = VM_RUNNING;
ret = v3_vmx_launch(&(info->vm_regs), info, &(info->ctrl_regs));
}
break;
+
+#if 0
+ case VMEXIT_RDTSC:
+ if (v3_handle_rdtsc(info) == -1) {
+ PrintError("Error Handling RDTSC instruction\n");
+ return -1;
+ }
+
+ break;
+#endif
+
case VMEXIT_CPUID:
if (v3_handle_cpuid(info) == -1) {
PrintError("Error Handling CPUID instruction\n");