diff -r edfb58ca4d96 xen/arch/ia64/linux-xen/smp.c --- a/xen/arch/ia64/linux-xen/smp.c Tue Mar 25 12:37:17 2008 -0600 +++ b/xen/arch/ia64/linux-xen/smp.c Fri Mar 28 06:58:55 2008 +0900 @@ -91,10 +91,20 @@ struct call_data_struct { atomic_t finished; }; +struct call_data_regs_struct { + void (*func) (void *info, struct cpu_user_regs *); + void *info; + long wait; + atomic_t started; + atomic_t finished; +}; + static volatile struct call_data_struct *call_data; +static volatile struct call_data_regs_struct *call_data_regs; #define IPI_CALL_FUNC 0 #define IPI_CPU_STOP 1 +#define IPI_CALL_FUNC_REGS 2 /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; @@ -183,7 +193,35 @@ handle_IPI (int irq, void *dev_id, struc atomic_inc(&data->finished); } break; - +#ifdef XEN + case IPI_CALL_FUNC_REGS: + { + struct call_data_regs_struct *data; + void (*func)(void *info, struct cpu_user_regs *); + void *info; + int wait; + + /* release the 'pointer lock' */ + data = (struct call_data_regs_struct *) call_data_regs; + func = data->func; + info = data->info; + wait = data->wait; + + mb(); + atomic_inc(&data->started); + /* + * At this point the structure may be gone unless + * wait is true. + */ + (*func)(info, regs); + + /* Notify the sending CPU that the task is done. */ + mb(); + if (wait) + atomic_inc(&data->finished); + } + break; +#endif case IPI_CPU_STOP: stop_this_cpu(); break; @@ -455,6 +493,41 @@ on_selected_cpus(cpumask_t selected, voi return 0; } + +int +on_selected_cpus_regs(cpumask_t selected, + void (*func) (void *info, struct cpu_user_regs *), void *info, + int retry, int wait) +{ + struct call_data_regs_struct data; + unsigned int cpu, nr_cpus = cpus_weight(selected); + + ASSERT(local_irq_is_enabled()); + + if (!nr_cpus) + return 0; + + data.func = func; + data.info = info; + data.wait = wait; + atomic_set(&data.started, 0); + atomic_set(&data.finished, 0); + + spin_lock(&call_lock); + + call_data_regs = &data; + wmb(); + + for_each_cpu_mask(cpu, selected) + send_IPI_single(cpu, IPI_CALL_FUNC_REGS); + + while (atomic_read(wait ? &data.finished : &data.started) != nr_cpus) + cpu_relax(); + + spin_unlock(&call_lock); + + return 0; +} #endif /* diff -r edfb58ca4d96 xen/arch/ia64/xen/xenmisc.c --- a/xen/arch/ia64/xen/xenmisc.c Tue Mar 25 12:37:17 2008 -0600 +++ b/xen/arch/ia64/xen/xenmisc.c Fri Mar 28 06:58:55 2008 +0900 @@ -123,6 +123,50 @@ void audit_domains_key(unsigned char key { } +inline void dump_execution_state(struct cpu_user_regs *regs) +{ + struct unw_frame_info info; + struct switch_stack *sw; + struct pt_regs *pt_regs = (struct pt_regs *)regs; + + if (pt_regs == NULL){ + pt_regs = guest_cpu_user_regs(); + show_registers(pt_regs); + } else { + sw = (struct switch_stack *)(current->arch._thread.ksp + 16); + unw_init_from_interruption(&info, current, pt_regs, sw); + show_registers(pt_regs); + ia64_do_show_stack(&info, NULL); + } +} + +void __dump_execstate(void *unused, struct cpu_user_regs *regs) +{ + dump_execution_state(NULL); + printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id()); + if ( is_idle_vcpu(current) ) + printk("No guest context (CPU is idle).\n"); + else + dump_execution_state(regs); // dump_execution_state(guest_cpu_user_regs()); ??? // +} + +void _dump_registers(struct cpu_user_regs *regs) +{ + unsigned int cpu; + + /* Get local execution state out immediately, in case we get stuck. */ + printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id()); + __dump_execstate(NULL, regs); + + for_each_online_cpu ( cpu ) + { + if ( cpu == smp_processor_id() ) + continue; + printk("\n*** Dumping CPU%d host state: ***\n", cpu); + on_selected_cpus_regs(cpumask_of_cpu(cpu), __dump_execstate, NULL, 1, 1); + } +} + void panic_domain(struct pt_regs *regs, const char *fmt, ...) { va_list args; diff -r edfb58ca4d96 xen/include/asm-ia64/xenprocessor.h --- a/xen/include/asm-ia64/xenprocessor.h Tue Mar 25 12:37:17 2008 -0600 +++ b/xen/include/asm-ia64/xenprocessor.h Fri Mar 28 06:58:55 2008 +0900 @@ -250,6 +250,8 @@ typedef union { }; } ia64_pkr_t; -#define dump_execution_state() printk("FIXME: implement ia64 dump_execution_state()\n"); +extern inline void dump_execution_state(struct cpu_user_regs *); +extern inline void __dump_execstate(void *, struct cpu_user_regs *); +extern inline void _dump_registers(struct cpu_user_regs *); #endif // _ASM_IA64_XENPROCESSOR_H