# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID ef41783c664a14334dd5facc31f0cfa254f5cb77
# Parent 184884cfaa0b23e07e1abe007071b5898b0b21c2
[HVM] Fix HLT with interrupts disabled. Only take down
the domain if no other VCPUs are online.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/hvm.c | 70 +++++++++++++++++++++++++++++++++----------------
1 files changed, 48 insertions(+), 22 deletions(-)
diff -r 184884cfaa0b -r ef41783c664a xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Tue Sep 26 12:17:51 2006 +0100
+++ b/xen/arch/x86/hvm/hvm.c Tue Sep 26 14:01:38 2006 +0100
@@ -337,6 +337,33 @@ int cpu_get_interrupt(struct vcpu *v, in
return -1;
}
+static void hvm_vcpu_down(void)
+{
+ struct vcpu *v = current;
+ struct domain *d = v->domain;
+ int online_count = 0;
+
+ DPRINTK("DOM%d/VCPU%d: going offline.\n", d->domain_id, v->vcpu_id);
+
+ /* Doesn't halt us immediately, but we'll never return to guest context. */
+ set_bit(_VCPUF_down, &v->vcpu_flags);
+ vcpu_sleep_nosync(v);
+
+ /* Any other VCPUs online? ... */
+ LOCK_BIGLOCK(d);
+ for_each_vcpu ( d, v )
+ if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
+ online_count++;
+ UNLOCK_BIGLOCK(d);
+
+ /* ... Shut down the domain if not. */
+ if ( online_count == 0 )
+ {
+ DPRINTK("DOM%d: all CPUs offline -- powering off.\n", d->domain_id);
+ domain_shutdown(d, SHUTDOWN_poweroff);
+ }
+}
+
void hvm_hlt(unsigned long rflags)
{
struct vcpu *v = current;
@@ -344,18 +371,12 @@ void hvm_hlt(unsigned long rflags)
s_time_t next_pit = -1, next_wakeup;
/*
- * Detect machine shutdown. Only do this for vcpu 0, to avoid potentially
- * shutting down the domain early. If we halt with interrupts disabled,
- * that's a pretty sure sign that we want to shut down. In a real
- * processor, NMIs are the only way to break out of this.
+ * If we halt with interrupts disabled, that's a pretty sure sign that we
+ * want to shut down. In a real processor, NMIs are the only way to break
+ * out of this.
*/
- if ( (v->vcpu_id == 0) && !(rflags & X86_EFLAGS_IF) )
- {
- printk("D%d: HLT with interrupts disabled -- shutting down.\n",
- current->domain->domain_id);
- domain_shutdown(current->domain, SHUTDOWN_poweroff);
- return;
- }
+ if ( unlikely(!(rflags & X86_EFLAGS_IF)) )
+ return hvm_vcpu_down();
if ( !v->vcpu_id )
next_pit = get_scheduled(v, pt->irq, pt);
@@ -578,17 +599,20 @@ int hvm_bringup_ap(int vcpuid, int tramp
struct vcpu_guest_context *ctxt;
int rc = 0;
- /* current must be HVM domain BSP */
- if ( !(hvm_guest(bsp) && bsp->vcpu_id == 0) ) {
- printk("Not calling hvm_bringup_ap from BSP context.\n");
+ BUG_ON(!hvm_guest(bsp));
+
+ if ( bsp->vcpu_id != 0 )
+ {
+ DPRINTK("Not calling hvm_bringup_ap from BSP context.\n");
domain_crash_synchronous();
}
if ( (v = d->vcpu[vcpuid]) == NULL )
return -ENOENT;
- if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL ) {
- printk("Failed to allocate memory in hvm_bringup_ap.\n");
+ if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
+ {
+ DPRINTK("Failed to allocate memory in hvm_bringup_ap.\n");
return -ENOMEM;
}
@@ -601,12 +625,14 @@ int hvm_bringup_ap(int vcpuid, int tramp
UNLOCK_BIGLOCK(d);
if ( rc != 0 )
- printk("AP %d bringup failed in boot_vcpu %x.\n", vcpuid, rc);
- else {
- if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) )
- vcpu_wake(d->vcpu[vcpuid]);
- printk("AP %d bringup suceeded.\n", vcpuid);
- }
+ {
+ DPRINTK("AP %d bringup failed in boot_vcpu %x.\n", vcpuid, rc);
+ return rc;
+ }
+
+ if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) )
+ vcpu_wake(d->vcpu[vcpuid]);
+ DPRINTK("AP %d bringup suceeded.\n", vcpuid);
xfree(ctxt);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|