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;
} 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) \
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__
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;
//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",
*/
// disable global interrupts for vm state transition
+
v3_clgi();
}
+ // 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;
// 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 {
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;
}
#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;
#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);
+}
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;