direct-io.hg

changeset 11141:30fb6ea3a1f7

Heuristic to detect windows shutdown + power down domain.

Signed-off-by: Steven Hand <steven@xensource.com>
Signed-off-by: George Dunlap <george.dunlap@xensource.com>
author shand@kneesaa.uk.xensource.com
date Wed Aug 16 14:01:03 2006 +0100 (2006-08-16)
parents 4704cd92242e
children ebd289e3d205
files xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Aug 16 13:53:10 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Aug 16 14:01:03 2006 +0100
     1.3 @@ -2150,8 +2150,9 @@ done:
     1.4  static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
     1.5  {
     1.6      struct vcpu *v = current;
     1.7 -    struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
     1.8 -    s_time_t  next_pit = -1, next_wakeup;
     1.9 +    struct periodic_time *pt = 
    1.10 +        &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
    1.11 +    s_time_t next_pit = -1, next_wakeup;
    1.12  
    1.13      __update_guest_eip(vmcb, 1);
    1.14  
    1.15 @@ -2159,6 +2160,23 @@ static inline void svm_vmexit_do_hlt(str
    1.16      if ( vmcb->vintr.fields.irq || cpu_has_pending_irq(v) )
    1.17         return;
    1.18  
    1.19 +    /* Detect machine shutdown.  Only do this for vcpu 0, to avoid
    1.20 +       potentially shutting down the domain early. */
    1.21 +    if (v->vcpu_id == 0) {
    1.22 +        unsigned long rflags = vmcb->rflags; 
    1.23 +        /* If we halt with interrupts disabled, that's a pretty sure
    1.24 +           sign that we want to shut down.  In a real processor, NMIs
    1.25 +           are the only way to break out of this.  Our SVM code won't
    1.26 +           deliver interrupts, but will wake it up whenever one is
    1.27 +           pending... */
    1.28 +        if(!(rflags & X86_EFLAGS_IF)) {
    1.29 +            printk("D%d: HLT with interrupts enabled @0x%lx  Shutting down.\n",
    1.30 +                   current->domain->domain_id, (unsigned long)vmcb->rip);
    1.31 +            domain_shutdown(current->domain, SHUTDOWN_poweroff);
    1.32 +            return;
    1.33 +        }
    1.34 +    }
    1.35 +
    1.36      if ( !v->vcpu_id )
    1.37          next_pit = get_scheduled(v, pt->irq, pt);
    1.38      next_wakeup = get_apictime_scheduled(v);
     2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Aug 16 13:53:10 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Aug 16 14:01:03 2006 +0100
     2.3 @@ -2054,9 +2054,32 @@ static inline void vmx_do_msr_write(stru
     2.4   */
     2.5  void vmx_vmexit_do_hlt(void)
     2.6  {
     2.7 -    struct vcpu *v=current;
     2.8 -    struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
     2.9 -    s_time_t   next_pit=-1,next_wakeup;
    2.10 +    struct vcpu *v = current;
    2.11 +    struct periodic_time *pt = 
    2.12 +        &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
    2.13 +    s_time_t next_pit = -1, next_wakeup;
    2.14 +
    2.15 +
    2.16 +    /* Detect machine shutdown.  Only do this for vcpu 0, to avoid
    2.17 +       potentially shutting down the domain early. */
    2.18 +    if (v->vcpu_id == 0) {
    2.19 +        unsigned long rflags;
    2.20 +        
    2.21 +        __vmread(GUEST_RFLAGS, &rflags);
    2.22 +        /* If we halt with interrupts disabled, that's a pretty sure
    2.23 +           sign that we want to shut down.  In a real processor, NMIs
    2.24 +           are the only way to break out of this.  Our VMX code won't
    2.25 +           deliver interrupts, but will wake it up whenever one is
    2.26 +           pending... */
    2.27 +        if(!(rflags & X86_EFLAGS_IF)) {
    2.28 +            unsigned long rip;
    2.29 +            __vmread(GUEST_RIP, &rip);
    2.30 +            printk("D%d: HLT with interrupts enabled @0x%lx  Shutting down.\n",
    2.31 +                   current->domain->domain_id, rip);
    2.32 +            domain_shutdown(current->domain, SHUTDOWN_poweroff);
    2.33 +            return;
    2.34 +        }
    2.35 +    }
    2.36  
    2.37      if ( !v->vcpu_id )
    2.38          next_pit = get_scheduled(v, pt->irq, pt);