ChangeSet 1.1628, 2005/06/01 15:44:07+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx
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@xxxxxxxxxxxxx>
tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c | 5
tools/libxc/xc_domain.c | 7
xen/arch/ia64/xenmisc.c | 3
xen/arch/x86/mm.c | 18 ++
xen/common/dom0_ops.c | 1
xen/common/domain.c | 86 +++++++----
xen/common/schedule.c | 12 +
xen/include/asm-x86/mm.h | 17 --
xen/include/public/dom0_ops.h | 3
xen/include/xen/mm.h | 4
xen/include/xen/sched.h | 11 -
xen/include/xen/softirq.h | 3
12 files changed, 112 insertions(+), 58 deletions(-)
diff -Nru a/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
b/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
--- a/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
2005-06-01 11:02:43 -04:00
+++ b/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
2005-06-01 11:02:43 -04:00
@@ -42,8 +42,7 @@
#define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */
-#define DOMFLAGS_CRASHED (1<<1) /* Crashed domain; frozen for postmortem. */
-#define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut itself down. */
+#define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut down. */
#define DOMFLAGS_PAUSED (1<<3) /* Currently paused by control software. */
#define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */
#define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */
@@ -220,7 +219,7 @@
if (myxcwait(current_domain, &w, 0))
return -1;
- if (w & (DOMFLAGS_CRASHED|DOMFLAGS_DYING)) {
+ if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) {
*status = 'W';
return 0;
}
diff -Nru a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c 2005-06-01 11:02:43 -04:00
+++ b/tools/libxc/xc_domain.c 2005-06-01 11:02:43 -04:00
@@ -86,7 +86,6 @@
info->domid = (u16)op.u.getdomaininfo.domain;
info->dying = !!(op.u.getdomaininfo.flags & DOMFLAGS_DYING);
- info->crashed = !!(op.u.getdomaininfo.flags & DOMFLAGS_CRASHED);
info->shutdown = !!(op.u.getdomaininfo.flags & DOMFLAGS_SHUTDOWN);
info->paused = !!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED);
info->blocked = !!(op.u.getdomaininfo.flags & DOMFLAGS_BLOCKED);
@@ -95,6 +94,12 @@
info->shutdown_reason =
(op.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) &
DOMFLAGS_SHUTDOWNMASK;
+
+ if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
+ {
+ info->shutdown = 0;
+ info->crashed = 1;
+ }
info->nr_pages = op.u.getdomaininfo.tot_pages;
info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT);
diff -Nru a/xen/arch/ia64/xenmisc.c b/xen/arch/ia64/xenmisc.c
--- a/xen/arch/ia64/xenmisc.c 2005-06-01 11:02:42 -04:00
+++ b/xen/arch/ia64/xenmisc.c 2005-06-01 11:02:42 -04:00
@@ -304,7 +304,8 @@
printf(buf);
if (regs) show_registers(regs);
domain_pause_by_systemcontroller(current->domain);
- set_bit(_DOMF_crashed, ed->domain->domain_flags);
+ ed->domain->shutdown_code = SHUTDOWN_crash;
+ set_bit(_DOMF_shutdown, ed->domain->domain_flags);
if (ed->domain->domain_id == 0) {
int i = 1000000000L;
// if domain0 crashes, just periodically print out panic
diff -Nru a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c 2005-06-01 11:02:43 -04:00
+++ b/xen/arch/x86/mm.c 2005-06-01 11:02:43 -04:00
@@ -2971,6 +2971,24 @@
free_xenheap_page((unsigned long)d->arch.ptwr[PTWR_PT_INACTIVE].page);
}
+void cleanup_writable_pagetable(struct domain *d)
+{
+ if ( unlikely(!VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
+ return;
+
+ if ( unlikely(shadow_mode_enabled(d)) )
+ {
+ shadow_sync_all(d);
+ }
+ else
+ {
+ if ( d->arch.ptwr[PTWR_PT_ACTIVE].l1va )
+ ptwr_flush(d, PTWR_PT_ACTIVE);
+ if ( d->arch.ptwr[PTWR_PT_INACTIVE].l1va )
+ ptwr_flush(d, PTWR_PT_INACTIVE);
+ }
+}
+
int map_pages_to_xen(
unsigned long virt,
unsigned long pfn,
diff -Nru a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c 2005-06-01 11:02:43 -04:00
+++ b/xen/common/dom0_ops.c 2005-06-01 11:02:43 -04:00
@@ -353,7 +353,6 @@
op->u.getdomaininfo.flags = flags |
((d->domain_flags & DOMF_dying) ? DOMFLAGS_DYING : 0) |
- ((d->domain_flags & DOMF_crashed) ? DOMFLAGS_CRASHED : 0) |
((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
diff -Nru a/xen/common/domain.c b/xen/common/domain.c
--- a/xen/common/domain.c 2005-06-01 11:02:42 -04:00
+++ b/xen/common/domain.c 2005-06-01 11:02:43 -04:00
@@ -134,11 +134,7 @@
show_registers(guest_cpu_user_regs());
#endif
- set_bit(_DOMF_crashed, &d->domain_flags);
-
- send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC);
-
- raise_softirq(SCHEDULE_SOFTIRQ);
+ domain_shutdown(SHUTDOWN_crash);
}
@@ -150,9 +146,49 @@
}
+static struct domain *domain_shuttingdown[NR_CPUS];
+
+static void domain_shutdown_finalise(void)
+{
+ struct domain *d;
+ struct exec_domain *ed;
+
+ d = domain_shuttingdown[smp_processor_id()];
+ domain_shuttingdown[smp_processor_id()] = NULL;
+
+ BUG_ON(d == NULL);
+ BUG_ON(d == current->domain);
+ BUG_ON(!test_bit(_DOMF_shuttingdown, &d->domain_flags));
+ BUG_ON(test_bit(_DOMF_shutdown, &d->domain_flags));
+
+ /* Make sure that every vcpu is descheduled before we finalise. */
+ for_each_exec_domain ( d, ed )
+ while ( test_bit(_VCPUF_running, &ed->vcpu_flags) )
+ cpu_relax();
+
+ sync_lazy_execstate_cpuset(d->cpuset);
+ BUG_ON(d->cpuset != 0);
+
+ sync_pagetable_state(d);
+
+ set_bit(_DOMF_shutdown, &d->domain_flags);
+ clear_bit(_DOMF_shuttingdown, &d->domain_flags);
+
+ send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC);
+}
+
+static __init int domain_shutdown_finaliser_init(void)
+{
+ open_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ, domain_shutdown_finalise);
+ return 0;
+}
+__initcall(domain_shutdown_finaliser_init);
+
+
void domain_shutdown(u8 reason)
{
struct domain *d = current->domain;
+ struct exec_domain *ed;
if ( d->domain_id == 0 )
{
@@ -173,14 +209,18 @@
}
}
- if ( (d->shutdown_code = reason) == SHUTDOWN_crash )
- set_bit(_DOMF_crashed, &d->domain_flags);
- else
- set_bit(_DOMF_shutdown, &d->domain_flags);
-
- send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC);
+ /* Mark the domain as shutting down. */
+ d->shutdown_code = reason;
+ if ( !test_and_set_bit(_DOMF_shuttingdown, &d->domain_flags) )
+ {
+ /* This vcpu won the race to finalise the shutdown. */
+ domain_shuttingdown[smp_processor_id()] = d;
+ raise_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ);
+ }
- raise_softirq(SCHEDULE_SOFTIRQ);
+ /* Put every vcpu to sleep, but don't wait (avoids inter-vcpu deadlock). */
+ for_each_exec_domain ( d, ed )
+ domain_sleep_nosync(ed);
}
@@ -190,8 +230,7 @@
struct domain **pd;
atomic_t old, new;
- if ( !test_bit(_DOMF_dying, &d->domain_flags) )
- BUG();
+ BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags));
/* May be already destructed, or get_domain() can race us. */
_atomic_set(old, 0);
@@ -225,10 +264,9 @@
void exec_domain_pause(struct exec_domain *ed)
{
- ASSERT(ed != current);
+ BUG_ON(ed == current);
atomic_inc(&ed->pausecnt);
- domain_sleep(ed);
- sync_lazy_execstate_cpuset(ed->domain->cpuset & (1UL << ed->processor));
+ domain_sleep_sync(ed);
}
void domain_pause(struct domain *d)
@@ -237,17 +275,15 @@
for_each_exec_domain( d, ed )
{
- ASSERT(ed != current);
+ BUG_ON(ed == current);
atomic_inc(&ed->pausecnt);
- domain_sleep(ed);
+ domain_sleep_sync(ed);
}
-
- sync_lazy_execstate_cpuset(d->cpuset);
}
void exec_domain_unpause(struct exec_domain *ed)
{
- ASSERT(ed != current);
+ BUG_ON(ed == current);
if ( atomic_dec_and_test(&ed->pausecnt) )
domain_wake(ed);
}
@@ -266,12 +302,10 @@
for_each_exec_domain ( d, ed )
{
- ASSERT(ed != current);
+ BUG_ON(ed == current);
if ( !test_and_set_bit(_VCPUF_ctrl_pause, &ed->vcpu_flags) )
- domain_sleep(ed);
+ domain_sleep_sync(ed);
}
-
- sync_lazy_execstate_cpuset(d->cpuset);
}
void domain_unpause_by_systemcontroller(struct domain *d)
diff -Nru a/xen/common/schedule.c b/xen/common/schedule.c
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|