#include <palacios/vmm_halt.h>
#include <palacios/vmm_intr.h>
+#include <palacios/vmm_lowlevel.h>
+#include <palacios/vmm_perftune.h>
-
-#ifndef CONFIG_DEBUG_HALT
+#ifndef V3_CONFIG_DEBUG_HALT
#undef PrintDebug
#define PrintDebug(fmt, args...)
#endif
-
//
// This should trigger a #GP if cpl != 0, otherwise, yield to host
//
-int v3_handle_halt(struct guest_info * info) {
-
+int v3_handle_halt(struct guest_info * info)
+{
+
if (info->cpl != 0) {
v3_raise_exception(info, GPF_EXCEPTION);
} else {
-
- uint64_t yield_start = 0;
- uint64_t yield_stop = 0;
- uint32_t gap = 0;
+ uint64_t start_cycles;
- PrintDebug("CPU Yield\n");
-
- while(1){
- if (v3_intr_pending(info)) {
- /* if there is pending interrupt, just return */
- break;
- }
-
- rdtscll(yield_start);
- v3_yield(info);
- rdtscll(yield_stop);
-
- gap = yield_stop - yield_start;
- /*
- If we got here, either an interrupt has occured or
- sufficient time has passed that we may need to inject
- a timer interrupt.
- First, we will update time, which may or may not inject an
- interrupt
- */
- v3_update_time(info, gap);
- info->time_state.cached_hlt_tsc += gap;
-
- /* At this point, we either have some combination of
- interrupts, including perhaps a timer interrupt, or
- no interrupt.
- */
- if (!v3_intr_pending(info)) {
- /* if no interrupt, then we do halt*/
- asm("hlt");
- }
- }
+ PrintDebug(info->vm_info, info, "CPU Yield\n");
+
+ start_cycles = v3_get_host_time(&info->time_state);
+
+ while (!v3_intr_pending(info) && (info->vm_info->run_state == VM_RUNNING)) {
+ uint64_t t, cycles;
+
+ t = v3_get_host_time(&info->time_state);
+
+ /* Yield, allowing time to pass while yielded */
+ v3_strategy_driven_yield(info, v3_cycle_diff_in_usec(info, start_cycles, t));
+
+ cycles = v3_get_host_time(&info->time_state) - t;
+
+ v3_advance_time(info, &cycles);
+
+ v3_update_timers(info);
+
+
+
+ /* At this point, we either have some combination of
+ interrupts, including perhaps a timer interrupt, or
+ no interrupt.
+ */
+ if (!v3_intr_pending(info)) {
+ /* if no interrupt, then we do halt */
+ /* asm("hlt"); */
+ }
+
+ // participate in any barrier that might be raised
+ v3_wait_at_barrier(info);
+
+ // stop if the VM is being halted
+ if (info->core_run_state == CORE_STOPPED) {
+ break;
+ }
-#if 0
- /* WARNING!!! WARNING!!!
- *
- * DO NOT REMOVE THIS CONDITIONAL!!!
- *
- * It is common for an OS to issue an IO op, and then sit in a halt loop
- * waiting for the device to complete and raise an irq.
- * If you remove this then the timer interrupt will ALWAYS subvert the completion
- * interrupt and stall the guest.
- */
- if (!v3_intr_pending(info)) {
- v3_advance_time(info);
}
-#endif
- //PrintError("HLT instruction issued\n");
-
- PrintDebug("CPU Yield Done (%d cycles)\n", gap);
+ /* V3_Print(info->vm_info, info, "palacios: done with halt\n"); */
info->rip += 1;
}