From: Jack Lange Date: Fri, 7 Aug 2009 22:15:37 +0000 (-0500) Subject: added yield functionality X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=e23a867d9dcecc70fc76adc0f89404dbc50e5b78 added yield functionality --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 7568636..eb85d7d 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -163,6 +163,10 @@ struct guest_info { v3_vm_operating_mode_t run_state; void * vmm_data; + uint64_t yield_cycle_period; + uint64_t yield_start_cycle; + + uint_t enable_profiler; struct v3_profiler profiler; diff --git a/palacios/include/palacios/vmm.h b/palacios/include/palacios/vmm.h index e1a883d..8114c77 100644 --- a/palacios/include/palacios/vmm.h +++ b/palacios/include/palacios/vmm.h @@ -188,18 +188,9 @@ } while (0) -#define V3_Yield(addr) \ - do { \ - extern struct v3_os_hooks * os_hooks; \ - if ((os_hooks) && (os_hooks)->yield_cpu) { \ - (os_hooks)->yield_cpu(); \ - } \ - } while (0) \ - \ - \ - \ - \ - \ + + + /* ** */ #define V3_ASSERT(x) \ @@ -226,6 +217,9 @@ typedef enum v3_cpu_arch {V3_INVALID_CPU, V3_SVM_CPU, V3_SVM_REV3_CPU, V3_VMX_CP v3_cpu_mode_t v3_get_host_cpu_mode(); +void v3_yield(struct guest_info * info); +void v3_yield_cond(struct guest_info * info); + #endif //!__V3VEE__ @@ -303,6 +297,8 @@ struct v3_vm_config { int enable_swap; + unsigned long schedule_freq; // in HZ + v3_disk_type_t pri_disk_type; v3_disk_connection_t pri_disk_con; union v3_disk_info pri_disk_info; diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 6d8cdd2..5fadae1 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -277,10 +277,14 @@ static int start_svm_guest(struct guest_info *info) { //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); info->run_state = VM_RUNNING; - + rdtscll(info->yield_start_cycle); + + while (1) { ullong_t tmp_tsc; + // Conditionally yield the CPU if the timeslice has expired + v3_yield_cond(info); /* PrintDebug("SVM Entry to CS=%p rip=%p...\n", @@ -289,6 +293,7 @@ static int start_svm_guest(struct guest_info *info) { */ // disable global interrupts for vm state transition + v3_clgi(); @@ -318,6 +323,9 @@ static int start_svm_guest(struct guest_info *info) { } + // Conditionally yield the CPU if the timeslice has expired + v3_yield_cond(info); + if (v3_handle_svm_exit(info) != 0) { vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); addr_t host_addr; diff --git a/palacios/src/palacios/svm_halt.c b/palacios/src/palacios/svm_halt.c index fea77ba..16239e8 100644 --- a/palacios/src/palacios/svm_halt.c +++ b/palacios/src/palacios/svm_halt.c @@ -33,9 +33,9 @@ // This should trigger a #GP if cpl!=0, otherwise, yield to host // -int v3_handle_svm_halt(struct guest_info * info) -{ - if (info->cpl!=0) { +int v3_handle_svm_halt(struct guest_info * info) { + + if (info->cpl != 0) { v3_raise_exception(info, GPF_EXCEPTION); } else { @@ -46,19 +46,20 @@ int v3_handle_svm_halt(struct guest_info * info) PrintDebug("CPU Yield\n"); rdtscll(yield_start); - V3_Yield(); + v3_yield(info); rdtscll(yield_stop); //v3_update_time(info, yield_stop - yield_start); gap = yield_stop - yield_start; - if (!v3_intr_pending(info)) { - v3_raise_irq(info, 0); - } + + v3_raise_irq(info, 0); + PrintDebug("CPU Yield Done (%d cycles)\n", gap); info->rip+=1; } + return 0; } diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c index a20399b..82073f0 100644 --- a/palacios/src/palacios/vmm.c +++ b/palacios/src/palacios/vmm.c @@ -28,8 +28,8 @@ #include -/* These should be the only global variables in Palacios */ -/* They are architecture specific variables */ + + v3_cpu_arch_t v3_cpu_type; struct v3_os_hooks * os_hooks = NULL; @@ -101,3 +101,31 @@ v3_cpu_mode_t v3_get_host_cpu_mode() { #endif + +#define V3_Yield(addr) \ + do { \ + extern struct v3_os_hooks * os_hooks; \ + if ((os_hooks) && (os_hooks)->yield_cpu) { \ + (os_hooks)->yield_cpu(); \ + } \ + } while (0) \ + + +void v3_yield_cond(struct guest_info * info) { + uint64_t cur_cycle; + rdtscll(cur_cycle); + + if (cur_cycle > (info->yield_start_cycle + info->yield_cycle_period)) { + + PrintDebug("Conditional Yield (cur_cyle=%p, start_cycle=%p, period=%p)\n", + (void *)cur_cycle, (void *)info->yield_start_cycle, (void *)info->yield_cycle_period); + + V3_Yield(); + rdtscll(info->yield_start_cycle); + } +} + +void v3_yield(struct guest_info * info) { + V3_Yield(); + rdtscll(info->yield_start_cycle); +} diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index 397b228..5bfe537 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -104,6 +104,14 @@ int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_p info->enable_profiler = 0; } + if (config_ptr->schedule_freq == 0) { + // set the schedule frequency to 100 HZ + config_ptr->schedule_freq = 100; + } + + PrintDebug("CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), (void *)config_ptr->schedule_freq); + + info->yield_cycle_period = (V3_CPU_KHZ() * 1000) / config_ptr->schedule_freq; // Initial CPU operating mode info->cpu_mode = REAL;