From: Jack Lange Date: Wed, 31 Jul 2013 22:46:09 +0000 (-0500) Subject: Enable cores to be reset via INIT IPI X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=915d7c977583d5f376624216d30676d412a989a7;p=palacios.releases.git Enable cores to be reset via INIT IPI --- diff --git a/palacios/src/devices/apic.c b/palacios/src/devices/apic.c index 86286ce..26ccb11 100644 --- a/palacios/src/devices/apic.c +++ b/palacios/src/devices/apic.c @@ -282,6 +282,12 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u static void set_apic_tpr(struct apic_state *apic, uint32_t val); +static int is_apic_bsp(struct apic_state * apic) { + return ((apic->base_addr_msr.value & 0x0000000000000100LL) != 0); +} + + + // No locking done static void init_apic_state(struct apic_state * apic, uint32_t id) { @@ -861,14 +867,18 @@ static int deliver_ipi(struct apic_state * src_apic, PrintDebug(VM_NONE, VCORE_NONE, " INIT delivery to core %u\n", dst_core->vcpu_id); - // TODO: any APIC reset on dest core (shouldn't be needed, but not sure...) + if (is_apic_bsp(dst_apic)) { + PrintError(VM_NONE, VCORE_NONE, "Attempted to INIT BSP CPU. Ignoring since I have no idea what the hell to do...\n"); + break; + } + - // Sanity check if (dst_apic->ipi_state != INIT_ST) { - PrintError(VM_NONE, VCORE_NONE, " Warning: core %u is not in INIT state (mode = %d), ignored (assuming this is the deassert)\n", - dst_core->vcpu_id, dst_apic->ipi_state); - // Only a warning, since INIT INIT SIPI is common - break; + v3_raise_barrier(dst_core->vm_info, src_apic->core); + dst_core->core_run_state = CORE_STOPPED; + dst_apic->ipi_state = INIT_ST; + v3_lower_barrier(dst_core->vm_info); + } // We transition the target core to SIPI state diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index c226e68..c9ef918 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -815,55 +815,59 @@ int v3_start_svm_guest(struct guest_info * info) { PrintDebug(info->vm_info, info, "Starting SVM core %u (on logical core %u)\n", info->vcpu_id, info->pcpu_id); - if (info->vcpu_id == 0) { - info->core_run_state = CORE_RUNNING; - } else { - PrintDebug(info->vm_info, info, "SVM core %u (on %u): Waiting for core initialization\n", info->vcpu_id, info->pcpu_id); + while (1) { - while (info->core_run_state == CORE_STOPPED) { - - if (info->vm_info->run_state == VM_STOPPED) { - // The VM was stopped before this core was initialized. - return 0; - } + if (info->core_run_state == CORE_STOPPED) { - v3_yield(info,-1); - //PrintDebug(info->vm_info, info, "SVM core %u: still waiting for INIT\n", info->vcpu_id); + if (info->vcpu_id == 0) { + info->core_run_state = CORE_RUNNING; + } else { + PrintDebug(info->vm_info, info, "SVM core %u (on %u): Waiting for core initialization\n", info->vcpu_id, info->pcpu_id); + + while (info->core_run_state == CORE_STOPPED) { + + if (info->vm_info->run_state == VM_STOPPED) { + // The VM was stopped before this core was initialized. + return 0; + } + + v3_yield(info,-1); + //PrintDebug(info->vm_info, info, "SVM core %u: still waiting for INIT\n", info->vcpu_id); + } + + PrintDebug(info->vm_info, info, "SVM core %u(on %u) initialized\n", info->vcpu_id, info->pcpu_id); + + // We'll be paranoid about race conditions here + v3_wait_at_barrier(info); + } + + PrintDebug(info->vm_info, info, "SVM core %u(on %u): I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", + info->vcpu_id, info->pcpu_id, + info->segments.cs.selector, (void *)(info->segments.cs.base), + info->segments.cs.limit, (void *)(info->rip)); + + + + PrintDebug(info->vm_info, info, "SVM core %u: Launching SVM VM (vmcb=%p) (on cpu %u)\n", + info->vcpu_id, (void *)info->vmm_data, info->pcpu_id); + //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); + + v3_start_time(info); } - - PrintDebug(info->vm_info, info, "SVM core %u(on %u) initialized\n", info->vcpu_id, info->pcpu_id); - - // We'll be paranoid about race conditions here - v3_wait_at_barrier(info); - } - - PrintDebug(info->vm_info, info, "SVM core %u(on %u): I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", - info->vcpu_id, info->pcpu_id, - info->segments.cs.selector, (void *)(info->segments.cs.base), - info->segments.cs.limit, (void *)(info->rip)); - - - - PrintDebug(info->vm_info, info, "SVM core %u: Launching SVM VM (vmcb=%p) (on cpu %u)\n", - info->vcpu_id, (void *)info->vmm_data, info->pcpu_id); - //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); - - v3_start_time(info); + + if (info->vm_info->run_state == VM_STOPPED) { + info->core_run_state = CORE_STOPPED; + break; + } + #ifdef V3_CONFIG_PMU_TELEMETRY - v3_pmu_telemetry_start(info); + v3_pmu_telemetry_start(info); #endif - + #ifdef V3_CONFIG_PWRSTAT_TELEMETRY - v3_pwrstat_telemetry_start(info); + v3_pwrstat_telemetry_start(info); #endif - - while (1) { - - if (info->vm_info->run_state == VM_STOPPED) { - info->core_run_state = CORE_STOPPED; - break; - } if (v3_svm_enter(info) == -1) { vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); @@ -898,12 +902,12 @@ int v3_start_svm_guest(struct guest_info * info) { v3_dump_mem((uint8_t *)host_addr, 15); v3_print_stack(info); - + break; } - + v3_wait_at_barrier(info); - + if (info->vm_info->run_state == VM_STOPPED) { info->core_run_state = CORE_STOPPED; diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 2653af0..3a64842 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -1180,56 +1180,60 @@ int v3_start_vmx_guest(struct guest_info * info) { PrintDebug(info->vm_info, info, "Starting VMX core %u\n", info->vcpu_id); - if (info->vcpu_id == 0) { - info->core_run_state = CORE_RUNNING; - } else { - - PrintDebug(info->vm_info, info, "VMX core %u: Waiting for core initialization\n", info->vcpu_id); - - while (info->core_run_state == CORE_STOPPED) { - + while (1) { + if (info->core_run_state == CORE_STOPPED) { + if (info->vcpu_id == 0) { + info->core_run_state = CORE_RUNNING; + } else { + + PrintDebug(info->vm_info, info, "VMX core %u: Waiting for core initialization\n", info->vcpu_id); + + while (info->core_run_state == CORE_STOPPED) { + + if (info->vm_info->run_state == VM_STOPPED) { + // The VM was stopped before this core was initialized. + return 0; + } + + v3_yield(info,-1); + //PrintDebug(info->vm_info, info, "VMX core %u: still waiting for INIT\n",info->vcpu_id); + } + + PrintDebug(info->vm_info, info, "VMX core %u initialized\n", info->vcpu_id); + + // We'll be paranoid about race conditions here + v3_wait_at_barrier(info); + } + + + PrintDebug(info->vm_info, info, "VMX core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", + info->vcpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base), + info->segments.cs.limit, (void *)(info->rip)); + + + PrintDebug(info->vm_info, info, "VMX core %u: Launching VMX VM on logical core %u\n", info->vcpu_id, info->pcpu_id); + + v3_start_time(info); + + if (info->vm_info->run_state == VM_STOPPED) { - // The VM was stopped before this core was initialized. - return 0; + info->core_run_state = CORE_STOPPED; + break; } - - v3_yield(info,-1); - //PrintDebug(info->vm_info, info, "VMX core %u: still waiting for INIT\n",info->vcpu_id); - } + } + - PrintDebug(info->vm_info, info, "VMX core %u initialized\n", info->vcpu_id); - - // We'll be paranoid about race conditions here - v3_wait_at_barrier(info); - } - - - PrintDebug(info->vm_info, info, "VMX core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", - info->vcpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base), - info->segments.cs.limit, (void *)(info->rip)); - - - PrintDebug(info->vm_info, info, "VMX core %u: Launching VMX VM on logical core %u\n", info->vcpu_id, info->pcpu_id); - - v3_start_time(info); - #ifdef V3_CONFIG_PMU_TELEMETRY - v3_pmu_telemetry_start(info); + v3_pmu_telemetry_start(info); #endif - + #ifdef V3_CONFIG_PWRSTAT_TELEMETRY - v3_pwrstat_telemetry_start(info); + v3_pwrstat_telemetry_start(info); #endif - - while (1) { - - if (info->vm_info->run_state == VM_STOPPED) { - info->core_run_state = CORE_STOPPED; - break; - } - + + if (v3_vmx_enter(info) == -1) { - + addr_t host_addr; addr_t linear_addr = 0;