From: Jack Lange <jarusl@cs.northwestern.edu>
Date: Fri, 7 Aug 2009 22:15:37 +0000 (-0500)
Subject: added yield functionality
X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=e23a867d9dcecc70fc76adc0f89404dbc50e5b78;p=palacios.git

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 <palacios/vmm_lowlevel.h>
 
 
-/* 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;