ia64/xen-unstable

changeset 5256:79fea09c3b44

bitkeeper revision 1.1628 (429dc9b7MTwsBkscbFS1sK8SbwJhdg)

Fix domain shutdown so that the new status, and notification to domain0,
occur *after* the domain is fully descheduled and its execution state
synchronised.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jun 01 14:44:07 2005 +0000 (2005-06-01)
parents f16ac5cfa153
children f3d83aed87fa 44063d9f39e4
files tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c tools/libxc/xc_domain.c xen/arch/ia64/xenmisc.c xen/arch/x86/mm.c xen/common/dom0_ops.c xen/common/domain.c xen/common/schedule.c xen/include/asm-x86/mm.h xen/include/public/dom0_ops.h xen/include/xen/mm.h xen/include/xen/sched.h xen/include/xen/softirq.h
line diff
     1.1 --- a/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Wed Jun 01 12:36:40 2005 +0000
     1.2 +++ b/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Wed Jun 01 14:44:07 2005 +0000
     1.3 @@ -42,8 +42,7 @@ int (*myxcwait)(int domain, int *status,
     1.4  
     1.5  
     1.6  #define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
     1.7 -#define DOMFLAGS_CRASHED   (1<<1) /* Crashed domain; frozen for postmortem.  */
     1.8 -#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut itself down.      */
     1.9 +#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
    1.10  #define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
    1.11  #define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
    1.12  #define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
    1.13 @@ -220,7 +219,7 @@ linux_wait (char *status)
    1.14    if (myxcwait(current_domain, &w, 0))
    1.15        return -1;
    1.16    
    1.17 -  if (w & (DOMFLAGS_CRASHED|DOMFLAGS_DYING)) {
    1.18 +  if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) {
    1.19        *status = 'W';
    1.20        return 0;
    1.21    }
     2.1 --- a/tools/libxc/xc_domain.c	Wed Jun 01 12:36:40 2005 +0000
     2.2 +++ b/tools/libxc/xc_domain.c	Wed Jun 01 14:44:07 2005 +0000
     2.3 @@ -86,7 +86,6 @@ int xc_domain_getinfo(int xc_handle,
     2.4          info->domid      = (u16)op.u.getdomaininfo.domain;
     2.5  
     2.6          info->dying    = !!(op.u.getdomaininfo.flags & DOMFLAGS_DYING);
     2.7 -        info->crashed  = !!(op.u.getdomaininfo.flags & DOMFLAGS_CRASHED);
     2.8          info->shutdown = !!(op.u.getdomaininfo.flags & DOMFLAGS_SHUTDOWN);
     2.9          info->paused   = !!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED);
    2.10          info->blocked  = !!(op.u.getdomaininfo.flags & DOMFLAGS_BLOCKED);
    2.11 @@ -96,6 +95,12 @@ int xc_domain_getinfo(int xc_handle,
    2.12              (op.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) & 
    2.13              DOMFLAGS_SHUTDOWNMASK;
    2.14  
    2.15 +        if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
    2.16 +        {
    2.17 +            info->shutdown = 0;
    2.18 +            info->crashed  = 1;
    2.19 +        }
    2.20 +
    2.21          info->nr_pages = op.u.getdomaininfo.tot_pages;
    2.22          info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT);
    2.23          info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
     3.1 --- a/xen/arch/ia64/xenmisc.c	Wed Jun 01 12:36:40 2005 +0000
     3.2 +++ b/xen/arch/ia64/xenmisc.c	Wed Jun 01 14:44:07 2005 +0000
     3.3 @@ -304,7 +304,8 @@ loop:
     3.4  	printf(buf);
     3.5  	if (regs) show_registers(regs);
     3.6  	domain_pause_by_systemcontroller(current->domain);
     3.7 -	set_bit(_DOMF_crashed, ed->domain->domain_flags);
     3.8 +	ed->domain->shutdown_code = SHUTDOWN_crash;
     3.9 +	set_bit(_DOMF_shutdown, ed->domain->domain_flags);
    3.10  	if (ed->domain->domain_id == 0) {
    3.11  		int i = 1000000000L;
    3.12  		// if domain0 crashes, just periodically print out panic
     4.1 --- a/xen/arch/x86/mm.c	Wed Jun 01 12:36:40 2005 +0000
     4.2 +++ b/xen/arch/x86/mm.c	Wed Jun 01 14:44:07 2005 +0000
     4.3 @@ -2971,6 +2971,24 @@ void ptwr_destroy(struct domain *d)
     4.4      free_xenheap_page((unsigned long)d->arch.ptwr[PTWR_PT_INACTIVE].page);
     4.5  }
     4.6  
     4.7 +void cleanup_writable_pagetable(struct domain *d)
     4.8 +{
     4.9 +    if ( unlikely(!VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
    4.10 +        return;
    4.11 +
    4.12 +    if ( unlikely(shadow_mode_enabled(d)) )
    4.13 +    {
    4.14 +        shadow_sync_all(d);
    4.15 +    }
    4.16 +    else
    4.17 +    {
    4.18 +        if ( d->arch.ptwr[PTWR_PT_ACTIVE].l1va )
    4.19 +            ptwr_flush(d, PTWR_PT_ACTIVE);
    4.20 +        if ( d->arch.ptwr[PTWR_PT_INACTIVE].l1va )
    4.21 +            ptwr_flush(d, PTWR_PT_INACTIVE);
    4.22 +    }
    4.23 +}
    4.24 +
    4.25  int map_pages_to_xen(
    4.26      unsigned long virt,
    4.27      unsigned long pfn,
     5.1 --- a/xen/common/dom0_ops.c	Wed Jun 01 12:36:40 2005 +0000
     5.2 +++ b/xen/common/dom0_ops.c	Wed Jun 01 14:44:07 2005 +0000
     5.3 @@ -353,7 +353,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     5.4  
     5.5          op->u.getdomaininfo.flags = flags |
     5.6              ((d->domain_flags & DOMF_dying)    ? DOMFLAGS_DYING    : 0) |
     5.7 -            ((d->domain_flags & DOMF_crashed)  ? DOMFLAGS_CRASHED  : 0) |
     5.8              ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
     5.9              d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
    5.10  
     6.1 --- a/xen/common/domain.c	Wed Jun 01 12:36:40 2005 +0000
     6.2 +++ b/xen/common/domain.c	Wed Jun 01 14:44:07 2005 +0000
     6.3 @@ -134,11 +134,7 @@ void domain_crash(void)
     6.4      show_registers(guest_cpu_user_regs());
     6.5  #endif
     6.6  
     6.7 -    set_bit(_DOMF_crashed, &d->domain_flags);
     6.8 -
     6.9 -    send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC);
    6.10 -
    6.11 -    raise_softirq(SCHEDULE_SOFTIRQ);
    6.12 +    domain_shutdown(SHUTDOWN_crash);
    6.13  }
    6.14  
    6.15  
    6.16 @@ -150,9 +146,49 @@ void domain_crash_synchronous(void)
    6.17  }
    6.18  
    6.19  
    6.20 +static struct domain *domain_shuttingdown[NR_CPUS];
    6.21 +
    6.22 +static void domain_shutdown_finalise(void)
    6.23 +{
    6.24 +    struct domain *d;
    6.25 +    struct exec_domain *ed;
    6.26 +
    6.27 +    d = domain_shuttingdown[smp_processor_id()];
    6.28 +    domain_shuttingdown[smp_processor_id()] = NULL;
    6.29 +
    6.30 +    BUG_ON(d == NULL);
    6.31 +    BUG_ON(d == current->domain);
    6.32 +    BUG_ON(!test_bit(_DOMF_shuttingdown, &d->domain_flags));
    6.33 +    BUG_ON(test_bit(_DOMF_shutdown, &d->domain_flags));
    6.34 +
    6.35 +    /* Make sure that every vcpu is descheduled before we finalise. */
    6.36 +    for_each_exec_domain ( d, ed )
    6.37 +        while ( test_bit(_VCPUF_running, &ed->vcpu_flags) )
    6.38 +            cpu_relax();
    6.39 +
    6.40 +    sync_lazy_execstate_cpuset(d->cpuset);
    6.41 +    BUG_ON(d->cpuset != 0);
    6.42 +
    6.43 +    sync_pagetable_state(d);
    6.44 +
    6.45 +    set_bit(_DOMF_shutdown, &d->domain_flags);
    6.46 +    clear_bit(_DOMF_shuttingdown, &d->domain_flags);
    6.47 +
    6.48 +    send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC);
    6.49 +}
    6.50 +
    6.51 +static __init int domain_shutdown_finaliser_init(void)
    6.52 +{
    6.53 +    open_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ, domain_shutdown_finalise);
    6.54 +    return 0;
    6.55 +}
    6.56 +__initcall(domain_shutdown_finaliser_init);
    6.57 +
    6.58 +
    6.59  void domain_shutdown(u8 reason)
    6.60  {
    6.61      struct domain *d = current->domain;
    6.62 +    struct exec_domain *ed;
    6.63  
    6.64      if ( d->domain_id == 0 )
    6.65      {
    6.66 @@ -173,14 +209,18 @@ void domain_shutdown(u8 reason)
    6.67          }
    6.68      }
    6.69  
    6.70 -    if ( (d->shutdown_code = reason) == SHUTDOWN_crash )
    6.71 -        set_bit(_DOMF_crashed, &d->domain_flags);
    6.72 -    else
    6.73 -        set_bit(_DOMF_shutdown, &d->domain_flags);
    6.74 +    /* Mark the domain as shutting down. */
    6.75 +    d->shutdown_code = reason;
    6.76 +    if ( !test_and_set_bit(_DOMF_shuttingdown, &d->domain_flags) )
    6.77 +    {
    6.78 +        /* This vcpu won the race to finalise the shutdown. */
    6.79 +        domain_shuttingdown[smp_processor_id()] = d;
    6.80 +        raise_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ);
    6.81 +    }
    6.82  
    6.83 -    send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC);
    6.84 -
    6.85 -    raise_softirq(SCHEDULE_SOFTIRQ);
    6.86 +    /* Put every vcpu to sleep, but don't wait (avoids inter-vcpu deadlock). */
    6.87 +    for_each_exec_domain ( d, ed )
    6.88 +        domain_sleep_nosync(ed);
    6.89  }
    6.90  
    6.91  
    6.92 @@ -190,8 +230,7 @@ void domain_destruct(struct domain *d)
    6.93      struct domain **pd;
    6.94      atomic_t      old, new;
    6.95  
    6.96 -    if ( !test_bit(_DOMF_dying, &d->domain_flags) )
    6.97 -        BUG();
    6.98 +    BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags));
    6.99  
   6.100      /* May be already destructed, or get_domain() can race us. */
   6.101      _atomic_set(old, 0);
   6.102 @@ -225,10 +264,9 @@ void domain_destruct(struct domain *d)
   6.103  
   6.104  void exec_domain_pause(struct exec_domain *ed)
   6.105  {
   6.106 -    ASSERT(ed != current);
   6.107 +    BUG_ON(ed == current);
   6.108      atomic_inc(&ed->pausecnt);
   6.109 -    domain_sleep(ed);
   6.110 -    sync_lazy_execstate_cpuset(ed->domain->cpuset & (1UL << ed->processor));
   6.111 +    domain_sleep_sync(ed);
   6.112  }
   6.113  
   6.114  void domain_pause(struct domain *d)
   6.115 @@ -237,17 +275,15 @@ void domain_pause(struct domain *d)
   6.116  
   6.117      for_each_exec_domain( d, ed )
   6.118      {
   6.119 -        ASSERT(ed != current);
   6.120 +        BUG_ON(ed == current);
   6.121          atomic_inc(&ed->pausecnt);
   6.122 -        domain_sleep(ed);
   6.123 +        domain_sleep_sync(ed);
   6.124      }
   6.125 -
   6.126 -    sync_lazy_execstate_cpuset(d->cpuset);
   6.127  }
   6.128  
   6.129  void exec_domain_unpause(struct exec_domain *ed)
   6.130  {
   6.131 -    ASSERT(ed != current);
   6.132 +    BUG_ON(ed == current);
   6.133      if ( atomic_dec_and_test(&ed->pausecnt) )
   6.134          domain_wake(ed);
   6.135  }
   6.136 @@ -266,12 +302,10 @@ void domain_pause_by_systemcontroller(st
   6.137  
   6.138      for_each_exec_domain ( d, ed )
   6.139      {
   6.140 -        ASSERT(ed != current);
   6.141 +        BUG_ON(ed == current);
   6.142          if ( !test_and_set_bit(_VCPUF_ctrl_pause, &ed->vcpu_flags) )
   6.143 -            domain_sleep(ed);
   6.144 +            domain_sleep_sync(ed);
   6.145      }
   6.146 -
   6.147 -    sync_lazy_execstate_cpuset(d->cpuset);
   6.148  }
   6.149  
   6.150  void domain_unpause_by_systemcontroller(struct domain *d)
     7.1 --- a/xen/common/schedule.c	Wed Jun 01 12:36:40 2005 +0000
     7.2 +++ b/xen/common/schedule.c	Wed Jun 01 14:44:07 2005 +0000
     7.3 @@ -190,7 +190,7 @@ void sched_rem_domain(struct exec_domain
     7.4      TRACE_2D(TRC_SCHED_DOM_REM, ed->domain->domain_id, ed->vcpu_id);
     7.5  }
     7.6  
     7.7 -void domain_sleep(struct exec_domain *ed)
     7.8 +void domain_sleep_nosync(struct exec_domain *ed)
     7.9  {
    7.10      unsigned long flags;
    7.11  
    7.12 @@ -200,10 +200,16 @@ void domain_sleep(struct exec_domain *ed
    7.13      spin_unlock_irqrestore(&schedule_data[ed->processor].schedule_lock, flags);
    7.14  
    7.15      TRACE_2D(TRC_SCHED_SLEEP, ed->domain->domain_id, ed->vcpu_id);
    7.16 - 
    7.17 -    /* Synchronous. */
    7.18 +} 
    7.19 +
    7.20 +void domain_sleep_sync(struct exec_domain *ed)
    7.21 +{
    7.22 +    domain_sleep_nosync(ed);
    7.23 +
    7.24      while ( test_bit(_VCPUF_running, &ed->vcpu_flags) && !domain_runnable(ed) )
    7.25          cpu_relax();
    7.26 +
    7.27 +    sync_lazy_execstate_cpuset(ed->domain->cpuset & (1UL << ed->processor));
    7.28  }
    7.29  
    7.30  void domain_wake(struct exec_domain *ed)
     8.1 --- a/xen/include/asm-x86/mm.h	Wed Jun 01 12:36:40 2005 +0000
     8.2 +++ b/xen/include/asm-x86/mm.h	Wed Jun 01 14:44:07 2005 +0000
     8.3 @@ -314,21 +314,8 @@ void ptwr_flush(struct domain *, const i
     8.4  int  ptwr_do_page_fault(struct domain *, unsigned long);
     8.5  int  revalidate_l1(struct domain *, l1_pgentry_t *, l1_pgentry_t *);
     8.6  
     8.7 -#define cleanup_writable_pagetable(_d)                                      \
     8.8 -    do {                                                                    \
     8.9 -        if ( likely(VM_ASSIST((_d), VMASST_TYPE_writable_pagetables)) )     \
    8.10 -        {                                                                   \
    8.11 -            if ( likely(!shadow_mode_enabled(_d)) )                         \
    8.12 -            {                                                               \
    8.13 -                if ( (_d)->arch.ptwr[PTWR_PT_ACTIVE].l1va )                 \
    8.14 -                    ptwr_flush((_d), PTWR_PT_ACTIVE);                       \
    8.15 -                if ( (_d)->arch.ptwr[PTWR_PT_INACTIVE].l1va )               \
    8.16 -                    ptwr_flush((_d), PTWR_PT_INACTIVE);                     \
    8.17 -            }                                                               \
    8.18 -            else                                                            \
    8.19 -                shadow_sync_all(_d);                                        \
    8.20 -        }                                                                   \
    8.21 -    } while ( 0 )
    8.22 +void cleanup_writable_pagetable(struct domain *d);
    8.23 +#define sync_pagetable_state(d) cleanup_writable_pagetable(d)
    8.24  
    8.25  int audit_adjust_pgtables(struct domain *d, int dir, int noisy);
    8.26  
     9.1 --- a/xen/include/public/dom0_ops.h	Wed Jun 01 12:36:40 2005 +0000
     9.2 +++ b/xen/include/public/dom0_ops.h	Wed Jun 01 14:44:07 2005 +0000
     9.3 @@ -72,8 +72,7 @@ typedef struct {
     9.4      domid_t  domain;                  /* NB. IN/OUT variable. */
     9.5      /* OUT variables. */
     9.6  #define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
     9.7 -#define DOMFLAGS_CRASHED   (1<<1) /* Crashed domain; frozen for postmortem.  */
     9.8 -#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut itself down.      */
     9.9 +#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
    9.10  #define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
    9.11  #define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
    9.12  #define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
    10.1 --- a/xen/include/xen/mm.h	Wed Jun 01 12:36:40 2005 +0000
    10.2 +++ b/xen/include/xen/mm.h	Wed Jun 01 14:44:07 2005 +0000
    10.3 @@ -48,4 +48,8 @@ extern struct list_head page_scrub_list;
    10.4  
    10.5  #include <asm/mm.h>
    10.6  
    10.7 +#ifndef sync_pagetable_state
    10.8 +#define sync_pagetable_state(d) ((void)0)
    10.9 +#endif
   10.10 +
   10.11  #endif /* __XEN_MM_H__ */
    11.1 --- a/xen/include/xen/sched.h	Wed Jun 01 12:36:40 2005 +0000
    11.2 +++ b/xen/include/xen/sched.h	Wed Jun 01 14:44:07 2005 +0000
    11.3 @@ -255,7 +255,8 @@ long sched_ctl(struct sched_ctl_cmd *);
    11.4  long sched_adjdom(struct sched_adjdom_cmd *);
    11.5  int  sched_id();
    11.6  void domain_wake(struct exec_domain *d);
    11.7 -void domain_sleep(struct exec_domain *d);
    11.8 +void domain_sleep_nosync(struct exec_domain *d);
    11.9 +void domain_sleep_sync(struct exec_domain *d);
   11.10  
   11.11  /*
   11.12   * Force loading of currently-executing domain state on the specified set
   11.13 @@ -375,9 +376,9 @@ extern struct domain *domain_list;
   11.14   /* Guest shut itself down for some reason. */
   11.15  #define _DOMF_shutdown         4
   11.16  #define DOMF_shutdown          (1UL<<_DOMF_shutdown)
   11.17 - /* Domain has crashed and cannot continue to execute. */
   11.18 -#define _DOMF_crashed          5
   11.19 -#define DOMF_crashed           (1UL<<_DOMF_crashed)
   11.20 + /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */
   11.21 +#define _DOMF_shuttingdown     5
   11.22 +#define DOMF_shuttingdown      (1UL<<_DOMF_shuttingdown)
   11.23   /* Death rattle. */
   11.24  #define _DOMF_dying            6
   11.25  #define DOMF_dying             (1UL<<_DOMF_dying)
   11.26 @@ -386,7 +387,7 @@ static inline int domain_runnable(struct
   11.27  {
   11.28      return ( (atomic_read(&ed->pausecnt) == 0) &&
   11.29               !(ed->vcpu_flags & (VCPUF_blocked|VCPUF_ctrl_pause)) &&
   11.30 -             !(ed->domain->domain_flags & (DOMF_shutdown|DOMF_crashed)) );
   11.31 +             !(ed->domain->domain_flags & (DOMF_shutdown|DOMF_shuttingdown)) );
   11.32  }
   11.33  
   11.34  void exec_domain_pause(struct exec_domain *ed);
    12.1 --- a/xen/include/xen/softirq.h	Wed Jun 01 12:36:40 2005 +0000
    12.2 +++ b/xen/include/xen/softirq.h	Wed Jun 01 14:44:07 2005 +0000
    12.3 @@ -8,7 +8,8 @@
    12.4  #define KEYPRESS_SOFTIRQ                  3
    12.5  #define NMI_SOFTIRQ                       4
    12.6  #define PAGE_SCRUB_SOFTIRQ                5
    12.7 -#define NR_SOFTIRQS                       6
    12.8 +#define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ  6
    12.9 +#define NR_SOFTIRQS                       7
   12.10  
   12.11  #ifndef __ASSEMBLY__
   12.12