Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added yield functionality
Jack Lange [Fri, 7 Aug 2009 22:15:37 +0000 (17:15 -0500)]
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm.h
palacios/src/palacios/svm.c
palacios/src/palacios/svm_halt.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_config.c

index 7568636..eb85d7d 100644 (file)
@@ -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;
index e1a883d..8114c77 100644 (file)
     } 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;
index 6d8cdd2..5fadae1 100644 (file)
@@ -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;
index fea77ba..16239e8 100644 (file)
@@ -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;
 }
index a20399b..82073f0 100644 (file)
@@ -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);
+}
index 397b228..5bfe537 100644 (file)
@@ -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;