ia64/xen-unstable

changeset 13470:b194a9f3eba2

[IA64] Fix broken switch stack

unw_init_running() needs to be called later in the OS INIT handler
to prevent the switch stack from being broken by calls to other
functions.

Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
author awilliam@xenbuild2.aw
date Tue Jan 23 11:48:29 2007 -0700 (2007-01-23)
parents d12ea0bfecce
children b59b6173455d
files xen/arch/ia64/linux-xen/mca.c
line diff
     1.1 --- a/xen/arch/ia64/linux-xen/mca.c	Tue Jan 23 10:52:07 2007 -0700
     1.2 +++ b/xen/arch/ia64/linux-xen/mca.c	Tue Jan 23 11:48:29 2007 -0700
     1.3 @@ -684,16 +684,7 @@ fetch_min_state (pal_min_state_area_t *m
     1.4  #ifdef XEN
     1.5  static spinlock_t init_dump_lock = SPIN_LOCK_UNLOCKED;
     1.6  static spinlock_t show_stack_lock = SPIN_LOCK_UNLOCKED;
     1.7 -
     1.8 -static void
     1.9 -save_ksp (struct unw_frame_info *info, void *arg)
    1.10 -{
    1.11 -	current->arch._thread.ksp = (__u64)(info->sw) - 16;
    1.12 -	wmb();
    1.13 -}
    1.14 -
    1.15 -/* FIXME */
    1.16 -int try_crashdump(struct pt_regs *a) { return 0; }
    1.17 +static atomic_t num_stopped_cpus = ATOMIC_INIT(0);
    1.18  
    1.19  #define CPU_FLUSH_RETRY_MAX 5
    1.20  static void
    1.21 @@ -716,6 +707,35 @@ init_cache_flush (void)
    1.22  	}
    1.23  	printk("\nPAL cache flush failed. status=%ld\n",rval);
    1.24  }
    1.25 +
    1.26 +static void inline
    1.27 +save_ksp (struct unw_frame_info *info)
    1.28 +{
    1.29 +	current->arch._thread.ksp = (__u64)(info->sw) - 16;
    1.30 +	wmb();
    1.31 +	init_cache_flush();
    1.32 +}	
    1.33 +
    1.34 +static void
    1.35 +freeze_cpu_osinit (struct unw_frame_info *info, void *arg)
    1.36 +{
    1.37 +	save_ksp(info);
    1.38 +	atomic_inc(&num_stopped_cpus);
    1.39 +	printk("%s: CPU%d init handler done\n",
    1.40 +	       __FUNCTION__, smp_processor_id());
    1.41 +	for (;;)
    1.42 +		local_irq_disable();
    1.43 +}
    1.44 +
    1.45 +/* FIXME */
    1.46 +static void
    1.47 +try_crashdump(struct unw_frame_info *info, void *arg)
    1.48 +{ 
    1.49 +	save_ksp(info);
    1.50 +	printk("\nINIT dump complete.  Please reboot now.\n");
    1.51 +	for (;;)
    1.52 +		local_irq_disable();
    1.53 +}
    1.54  #endif /* XEN */
    1.55  
    1.56  static void
    1.57 @@ -741,7 +761,8 @@ init_handler_platform (pal_min_state_are
    1.58  	show_min_state(ms);
    1.59  
    1.60  #ifdef XEN
    1.61 -	printk("Backtrace of current vcpu (vcpu_id %d)\n", current->vcpu_id);
    1.62 +	printk("Backtrace of current vcpu (vcpu_id %d of domid %d)\n",
    1.63 +	       current->vcpu_id, current->domain->domain_id);
    1.64  #else
    1.65  	printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm);
    1.66  	fetch_min_state(ms, pt, sw);
    1.67 @@ -749,20 +770,21 @@ init_handler_platform (pal_min_state_are
    1.68  	unw_init_from_interruption(&info, current, pt, sw);
    1.69  	ia64_do_show_stack(&info, NULL);
    1.70  #ifdef XEN
    1.71 -	unw_init_running(save_ksp, NULL);
    1.72  	spin_unlock(&show_stack_lock);
    1.73 -	wmb();
    1.74 -	init_cache_flush();
    1.75  
    1.76  	if (spin_trylock(&init_dump_lock)) {
    1.77  #ifdef CONFIG_SMP
    1.78 -		udelay(5*1000000);
    1.79 +		int other_cpus = num_online_cpus() - 1;
    1.80 +		int wait = 1000 * other_cpus;
    1.81 +
    1.82 +		while ((atomic_read(&num_stopped_cpus) != other_cpus) && wait--)
    1.83 +			udelay(1000);
    1.84 +		if (other_cpus && wait < 0)
    1.85 +			printk("timeout %d\n", atomic_read(&num_stopped_cpus));
    1.86  #endif
    1.87 -		if (try_crashdump(pt) == 0)
    1.88 -			printk("\nINIT dump complete.  Please reboot now.\n");
    1.89 +		unw_init_running(try_crashdump, pt);
    1.90  	}
    1.91 -	printk("%s: CPU%d init handler done\n",
    1.92 -	       __FUNCTION__, smp_processor_id());
    1.93 +	unw_init_running(freeze_cpu_osinit, NULL);
    1.94  #else /* XEN */
    1.95  #ifdef CONFIG_SMP
    1.96  	/* read_trylock() would be handy... */