X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_time.c;h=7814acb215a38ac3b9c26ec26ab8f40aa01d400f;hb=ccd9ddb5d9279fe8fcdacfc3bcd466eb3da70791;hp=86eaa022dc25e45569cb930ca32483eb5c125fdc;hpb=266af4b5b19da7bee8e7445288c7c1cb3ee194c7;p=palacios-OLD.git diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index 86eaa02..7814acb 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -12,13 +12,31 @@ * All rights reserved. * * Author: Jack Lange + * Patrick G. Bridges * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ -#include "palacios/vmm_time.h" -#include "palacios/vmm.h" +#include +#include +#include + +#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); + + info->vm_regs.rbx = time_state->cpu_freq; + + PrintDebug("Guest request cpu frequency: return %ld\n", (long)info->vm_regs.rbx); + + return 0; +} + void v3_init_time(struct guest_info * info) { @@ -26,16 +44,53 @@ void v3_init_time(struct guest_info * info) { time_state->cpu_freq = V3_CPU_KHZ(); - time_state->guest_tsc = 0; - time_state->cached_host_tsc = 0; - // time_state->pending_cycles = 0; - + time_state->pause_time = 0; + time_state->last_update = 0; + time_state->host_offset = 0; + INIT_LIST_HEAD(&(time_state->timers)); time_state->num_timers = 0; + + v3_register_hypercall(info->vm_info, TIME_CPUFREQ_HCALL, handle_cpufreq_hcall, NULL); +} + +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.last_update = t; + info->time_state.pause_time = t; + info->yield_start_cycle = 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->time_state); + 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->time_state); + V3_ASSERT(info->time_state.pause_time != 0); + info->time_state.host_offset = + (sint64_t)info->time_state.pause_time - (sint64_t)t; +#ifdef CONFIG_TIME_TSC_OFFSET_ADJUST + /* 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; +} -int v3_add_timer(struct guest_info * info, struct vm_timer_ops * ops, void * private_data) { +int v3_add_timer(struct guest_info * info, struct vm_timer_ops * ops, + void * private_data) { struct vm_timer * timer = NULL; timer = (struct vm_timer *)V3_Malloc(sizeof(struct vm_timer)); V3_ASSERT(timer != NULL); @@ -58,18 +113,15 @@ int v3_remove_timer(struct guest_info * info, struct vm_timer * timer) { return 0; } - - -void v3_update_time(struct guest_info * info, ullong_t cycles) { +void v3_update_timers(struct guest_info * info) { struct vm_timer * tmp_timer; - - info->time_state.guest_tsc += cycles; + uint64_t old_time = info->time_state.last_update; + uint64_t cycles; + + info->time_state.last_update = v3_get_guest_time(&info->time_state); + cycles = info->time_state.last_update - old_time; list_for_each_entry(tmp_timer, &(info->time_state.timers), timer_link) { - tmp_timer->ops->update_time(cycles, info->time_state.cpu_freq, tmp_timer->private_data); + tmp_timer->ops->update_timer(info, cycles, info->time_state.cpu_freq, tmp_timer->private_data); } - - - - //info->time_state.pending_cycles = 0; }