ia64/xen-unstable

changeset 11630:ef41783c664a

[HVM] Fix HLT with interrupts disabled. Only take down
the domain if no other VCPUs are online.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Sep 26 14:01:38 2006 +0100 (2006-09-26)
parents 184884cfaa0b
children 7fca81d456b2
files xen/arch/x86/hvm/hvm.c
line diff
     1.1 --- a/xen/arch/x86/hvm/hvm.c	Tue Sep 26 12:17:51 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/hvm.c	Tue Sep 26 14:01:38 2006 +0100
     1.3 @@ -337,6 +337,33 @@ int cpu_get_interrupt(struct vcpu *v, in
     1.4      return -1;
     1.5  }
     1.6  
     1.7 +static void hvm_vcpu_down(void)
     1.8 +{
     1.9 +    struct vcpu *v = current;
    1.10 +    struct domain *d = v->domain;
    1.11 +    int online_count = 0;
    1.12 +
    1.13 +    DPRINTK("DOM%d/VCPU%d: going offline.\n", d->domain_id, v->vcpu_id);
    1.14 +
    1.15 +    /* Doesn't halt us immediately, but we'll never return to guest context. */
    1.16 +    set_bit(_VCPUF_down, &v->vcpu_flags);
    1.17 +    vcpu_sleep_nosync(v);
    1.18 +
    1.19 +    /* Any other VCPUs online? ... */
    1.20 +    LOCK_BIGLOCK(d);
    1.21 +    for_each_vcpu ( d, v )
    1.22 +        if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
    1.23 +            online_count++;
    1.24 +    UNLOCK_BIGLOCK(d);
    1.25 +
    1.26 +    /* ... Shut down the domain if not. */
    1.27 +    if ( online_count == 0 )
    1.28 +    {
    1.29 +        DPRINTK("DOM%d: all CPUs offline -- powering off.\n", d->domain_id);
    1.30 +        domain_shutdown(d, SHUTDOWN_poweroff);
    1.31 +    }
    1.32 +}
    1.33 +
    1.34  void hvm_hlt(unsigned long rflags)
    1.35  {
    1.36      struct vcpu *v = current;
    1.37 @@ -344,18 +371,12 @@ void hvm_hlt(unsigned long rflags)
    1.38      s_time_t next_pit = -1, next_wakeup;
    1.39  
    1.40      /*
    1.41 -     * Detect machine shutdown.  Only do this for vcpu 0, to avoid potentially 
    1.42 -     * shutting down the domain early. If we halt with interrupts disabled, 
    1.43 -     * that's a pretty sure sign that we want to shut down.  In a real 
    1.44 -     * processor, NMIs are the only way to break out of this.
    1.45 +     * If we halt with interrupts disabled, that's a pretty sure sign that we
    1.46 +     * want to shut down. In a real processor, NMIs are the only way to break
    1.47 +     * out of this.
    1.48       */
    1.49 -    if ( (v->vcpu_id == 0) && !(rflags & X86_EFLAGS_IF) )
    1.50 -    {
    1.51 -        printk("D%d: HLT with interrupts disabled -- shutting down.\n",
    1.52 -               current->domain->domain_id);
    1.53 -        domain_shutdown(current->domain, SHUTDOWN_poweroff);
    1.54 -        return;
    1.55 -    }
    1.56 +    if ( unlikely(!(rflags & X86_EFLAGS_IF)) )
    1.57 +        return hvm_vcpu_down();
    1.58  
    1.59      if ( !v->vcpu_id )
    1.60          next_pit = get_scheduled(v, pt->irq, pt);
    1.61 @@ -578,17 +599,20 @@ int hvm_bringup_ap(int vcpuid, int tramp
    1.62      struct vcpu_guest_context *ctxt;
    1.63      int rc = 0;
    1.64  
    1.65 -    /* current must be HVM domain BSP */
    1.66 -    if ( !(hvm_guest(bsp) && bsp->vcpu_id == 0) ) {
    1.67 -        printk("Not calling hvm_bringup_ap from BSP context.\n");
    1.68 +    BUG_ON(!hvm_guest(bsp));
    1.69 +
    1.70 +    if ( bsp->vcpu_id != 0 )
    1.71 +    {
    1.72 +        DPRINTK("Not calling hvm_bringup_ap from BSP context.\n");
    1.73          domain_crash_synchronous();
    1.74      }
    1.75  
    1.76      if ( (v = d->vcpu[vcpuid]) == NULL )
    1.77          return -ENOENT;
    1.78  
    1.79 -    if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL ) {
    1.80 -        printk("Failed to allocate memory in hvm_bringup_ap.\n");
    1.81 +    if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
    1.82 +    {
    1.83 +        DPRINTK("Failed to allocate memory in hvm_bringup_ap.\n");
    1.84          return -ENOMEM;
    1.85      }
    1.86  
    1.87 @@ -601,13 +625,15 @@ int hvm_bringup_ap(int vcpuid, int tramp
    1.88      UNLOCK_BIGLOCK(d);
    1.89  
    1.90      if ( rc != 0 )
    1.91 -        printk("AP %d bringup failed in boot_vcpu %x.\n", vcpuid, rc);
    1.92 -    else {
    1.93 -        if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) )
    1.94 -            vcpu_wake(d->vcpu[vcpuid]);
    1.95 -        printk("AP %d bringup suceeded.\n", vcpuid);
    1.96 +    {
    1.97 +        DPRINTK("AP %d bringup failed in boot_vcpu %x.\n", vcpuid, rc);
    1.98 +        return rc;
    1.99      }
   1.100  
   1.101 +    if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) )
   1.102 +        vcpu_wake(d->vcpu[vcpuid]);
   1.103 +    DPRINTK("AP %d bringup suceeded.\n", vcpuid);
   1.104 +
   1.105      xfree(ctxt);
   1.106  
   1.107      return rc;