From: Patrick G. Bridges Date: Fri, 17 Feb 2012 18:59:56 +0000 (-0700) Subject: Start at new guest time representaion X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=c445b653bb1fe979e7146fb6b15923bc99277784 Start at new guest time representaion --- diff --git a/palacios/include/palacios/vmm_time.h b/palacios/include/palacios/vmm_time.h index e6a88a3..1e3c7fd 100644 --- a/palacios/include/palacios/vmm_time.h +++ b/palacios/include/palacios/vmm_time.h @@ -41,16 +41,15 @@ struct vm_core_time { uint32_t host_cpu_freq; // in kHZ uint32_t guest_cpu_freq; // can be lower than host CPU freq! - sint64_t guest_host_offset;// Offset of monotonic guest time from host time - sint64_t tsc_guest_offset; // Offset of guest TSC from monotonic guest time + uint64_t guest_cycles; + sint64_t tsc_guest_offset; // Offset of guest TSC from guest cycles - uint64_t last_update; // Last time (in monotonic guest time) the + uint64_t last_update; // Last time (in guest cycles) the // timers were updated - uint64_t initial_time; // Time when VMM started. + uint64_t initial_time; // Host time when VMM started. uint64_t enter_time; // Host time the guest was last entered uint64_t exit_time; // Host time the the VM was exited to - uint64_t pause_time; // Time at which the VM core was paused struct v3_msr tsc_aux; // Auxilliary MSR for RDTSCP // Installed Timers slaved off of the guest monotonic TSC @@ -99,8 +98,6 @@ struct v3_timer * v3_add_timer(struct guest_info * info, struct v3_timer_ops * o int v3_remove_timer(struct guest_info * info, struct v3_timer * timer); void v3_update_timers(struct guest_info * info); - - // Functions to return the different notions of time in Palacios. static inline uint64_t v3_get_host_time(struct vm_core_time *t) { uint64_t tmp; @@ -109,29 +106,18 @@ static inline uint64_t v3_get_host_time(struct vm_core_time *t) { } // Returns *monotonic* guest time. -static inline uint64_t v3_compute_guest_time(struct vm_core_time *t, uint64_t ht) { - if (t->pause_time) - return t->pause_time + t->guest_host_offset; - else - return ht + t->guest_host_offset; -} - static inline uint64_t v3_get_guest_time(struct vm_core_time *t) { - return v3_compute_guest_time(t, v3_get_host_time(t)); -} - -// Returns the TSC value seen by the guest -static inline uint64_t v3_compute_guest_tsc(struct vm_core_time *t, uint64_t ht) { - return v3_compute_guest_time(t, ht) + t->tsc_guest_offset; + return t->guest_cycles; } static inline uint64_t v3_get_guest_tsc(struct vm_core_time *t) { - return v3_compute_guest_tsc(t, v3_get_host_time(t)); + return v3_get_guest_time(t) + t->tsc_guest_offset; } // Returns offset of guest TSC from host TSC static inline sint64_t v3_tsc_host_offset(struct vm_core_time *time_state) { - return time_state->guest_host_offset + time_state->tsc_guest_offset; + uint64_t host_time = v3_get_host_time(time_state); + return ((sint64_t)host_time - (sint64_t)time_state->guest_cycles) + time_state->tsc_guest_offset; } // Functions for handling exits on the TSC when fully virtualizing diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index 9c0fe18..0466172 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -91,46 +91,16 @@ int v3_start_time(struct guest_info * info) { /* We start running with guest_time == host_time */ uint64_t t = v3_get_host_time(&info->time_state); - PrintDebug("Starting initial guest time as %llu\n", t); - info->time_state.enter_time = 0; info->time_state.exit_time = t; - info->time_state.last_update = t; info->time_state.initial_time = t; info->yield_start_cycle = t; - return 0; -} - -int v3_pause_time( struct guest_info * info ) -{ - struct vm_core_time * time_state = &(info->time_state); - if (time_state->pause_time != 0) { - PrintError("Attempted to pause time when time already paused.\n"); - return -1; - } - time_state->pause_time = v3_get_host_time( time_state ); - - return 0; -} - -int v3_resume_time( struct guest_info * info ) -{ - struct vm_core_time * time_state = &(info->time_state); - uint64_t host_time, guest_time; - sint64_t offset; - - if (time_state->pause_time == 0) { - PrintError("Attempted to resume time when time not paused.\n"); - return -1; - } - - host_time = v3_get_host_time(time_state); - guest_time = v3_compute_guest_time(time_state, host_time); - offset = (sint64_t)guest_time - (sint64_t)host_time; - time_state->guest_host_offset = offset; - time_state->pause_time = 0; - + info->time_state.last_update = 0; + info->time_state.guest_cycles = 0; + PrintDebug("Starting time for core %d at host time %llu/guest time %llu.\n", + info->vcpu_id, t, info->time_state.guest_cycles); + v3_yield(info); return 0; } @@ -138,7 +108,7 @@ int v3_offset_time( struct guest_info * info, sint64_t offset ) { struct vm_core_time * time_state = &(info->time_state); PrintDebug("Adding additional offset of %lld to guest time.\n", offset); - time_state->guest_host_offset += offset; + time_state->guest_cycles += offset; return 0; } @@ -178,7 +148,7 @@ static int yield_host_time(struct guest_info * info) { * time to account for the time paused even if the geust isn't * usually paused in the VMM. */ host_time = v3_get_host_time(time_state); - old_guest_time = v3_compute_guest_time(time_state, host_time); + old_guest_time = v3_get_guest_time(time_state); target_host_time = compute_target_host_time(info, old_guest_time); while (target_host_time > host_time) { @@ -186,7 +156,7 @@ static int yield_host_time(struct guest_info * info) { host_time = v3_get_host_time(time_state); } - guest_time = v3_compute_guest_time(time_state, host_time); + guest_time = v3_get_guest_time(time_state); /* We do *not* assume the guest timer was paused in the VM. If it was * this offseting is 0. If it wasn't, we need this. */ @@ -255,11 +225,13 @@ v3_time_exit_vm( struct guest_info * info, uint64_t * guest_cycles ) struct vm_core_time * time_state = &(info->time_state); time_state->exit_time = v3_get_host_time(time_state); - -#ifdef V3_CONFIG_TIME_DILATION - v3_pause_time( info ); -#endif - + if (guest_cycles) { + time_state->guest_cycles += *guest_cycles; + } else { + uint64_t cycles_exec; + cycles_exec = time_state->exit_time - time_state->enter_time; + time_state->guest_cycles += cycles_exec; + } return 0; } @@ -268,16 +240,15 @@ int v3_time_enter_vm( struct guest_info * info ) { struct vm_core_time * time_state = &(info->time_state); - uint64_t host_time; + uint64_t host_time, vmm_cycles; host_time = v3_get_host_time(time_state); time_state->enter_time = host_time; -#ifdef V3_CONFIG_TIME_DILATION - v3_resume_time( info ); -#else - time_state->guest_host_offset = 0; -#endif - + vmm_cycles = host_time - time_state->exit_time; + /* XXX How do we want to take into account host/guest CPU speed differences + * and time dilation here? Probably time just won't advance in the VMM in that + * case so its irrelvant XXX */ + time_state->guest_cycles += vmm_cycles; return 0; } @@ -465,8 +436,8 @@ int v3_init_time_vm(struct v3_vm_info * vm) { ret = v3_register_hypercall(vm, TIME_CPUFREQ_HCALL, handle_cpufreq_hcall, NULL); - PrintDebug("Setting base time dilation factor.\n"); vm->time_state.td_mult = 1; + PrintDebug("Setting base time dilation factor to %d.\n", vm->time_state.td_mult); return ret; } @@ -506,12 +477,10 @@ void v3_init_time_core(struct guest_info * info) { time_state->initial_time = 0; time_state->last_update = 0; - time_state->guest_host_offset = 0; time_state->tsc_guest_offset = 0; time_state->enter_time = 0; time_state->exit_time = 0; - time_state->pause_time = 0; - + time_state->guest_cycles = 0; INIT_LIST_HEAD(&(time_state->timers)); time_state->num_timers = 0; diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index b5ec768..2eb4ae1 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -894,7 +894,7 @@ int v3_vmx_enter(struct guest_info * info) { // Perform last-minute time bookkeeping prior to entering the VM v3_time_enter_vm(info); - + tsc_offset = v3_tsc_host_offset(&info->time_state); tsc_offset_high = (uint32_t)(( tsc_offset >> 32) & 0xffffffff); tsc_offset_low = (uint32_t)(tsc_offset & 0xffffffff);