2 * Architecture specific (ppc64) functions for Linux crash dumps.
4 * Created by: Matt Robinson (yakker@sgi.com)
6 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
8 * 2.3 kernel modifications by: Matt D. Robinson (yakker@turbolinux.com)
9 * Copyright 2000 TurboLinux, Inc. All rights reserved.
10 * Copyright 2003, 2004 IBM Corporation
12 * This code is released under version 2 of the GNU GPL.
16 * The hooks for dumping the kernel virtual memory to disk are in this
17 * file. Any time a modification is made to the virtual memory mechanism,
18 * these routines must be changed to use the new mechanisms.
20 #include <linux/types.h>
22 #include <linux/dump.h>
24 #include <linux/vmalloc.h>
25 #include <linux/delay.h>
26 #include <linux/syscalls.h>
27 #include <linux/ioctl32.h>
28 #include <asm/hardirq.h>
29 #include "dump_methods.h"
30 #include <linux/irq.h>
31 #include <asm/machdep.h>
32 #include <asm/uaccess.h>
35 #if defined(CONFIG_KDB) && !defined(CONFIG_DUMP_MODULE)
36 #include <linux/kdb.h>
39 extern cpumask_t irq_affinity[];
41 static cpumask_t saved_affinity[NR_IRQS];
43 static __s32 saved_irq_count; /* saved preempt_count() flags */
45 static int alloc_dha_stack(void)
50 if (dump_header_asm.dha_stack[0])
53 ptr = (void *)vmalloc(THREAD_SIZE * num_online_cpus());
58 for (i = 0; i < num_online_cpus(); i++) {
59 dump_header_asm.dha_stack[i] =
60 (uint64_t)((unsigned long)ptr + (i * THREAD_SIZE));
65 static int free_dha_stack(void)
67 if (dump_header_asm.dha_stack[0]) {
68 vfree((void*)dump_header_asm.dha_stack[0]);
69 dump_header_asm.dha_stack[0] = 0;
74 static int dump_expect_ipi[NR_CPUS];
75 static atomic_t waiting_for_dump_ipi;
77 extern void stop_this_cpu(void *);
79 dump_ipi_handler(struct pt_regs *regs)
81 int cpu = smp_processor_id();
83 if (!dump_expect_ipi[cpu])
85 dump_save_this_cpu(regs);
86 atomic_dec(&waiting_for_dump_ipi);
89 switch (dump_silence_level) {
90 case DUMP_HARD_SPIN_CPUS: /* Spin until dump is complete */
92 barrier(); /* paranoia */
93 if (dump_silence_level != DUMP_HARD_SPIN_CPUS)
95 cpu_relax(); /* kill time nicely */
99 case DUMP_HALT_CPUS: /* Execute halt */
103 case DUMP_SOFT_SPIN_CPUS:
104 /* Mark the task so it spins in schedule */
105 set_tsk_thread_flag(current, TIF_NEED_RESCHED);
112 /* save registers on other processors
113 * If the other cpus don't respond we simply do not get their states.
116 __dump_save_other_cpus(void)
118 int i, cpu = smp_processor_id();
119 int other_cpus = num_online_cpus()-1;
121 if (other_cpus > 0) {
122 atomic_set(&waiting_for_dump_ipi, other_cpus);
123 for (i = 0; i < NR_CPUS; i++)
124 dump_expect_ipi[i] = (i != cpu && cpu_online(i));
126 dump_send_ipi(dump_ipi_handler);
128 * may be we dont need to wait for NMI to be processed.
129 * just write out the header at the end of dumping, if
130 * this IPI is not processed until then, there probably
131 * is a problem and we just fail to capture state of
134 while (atomic_read(&waiting_for_dump_ipi) > 0) {
137 dump_send_ipi(NULL); /* clear handler */
142 * Restore old irq affinities.
145 __dump_reset_irq_affinity(void)
150 memcpy(irq_affinity, saved_affinity, NR_IRQS * sizeof(unsigned long));
153 irq_d = get_irq_desc(i);
154 if (irq_d->handler == NULL) {
157 if (irq_d->handler->set_affinity != NULL) {
158 irq_d->handler->set_affinity(i, saved_affinity[i]);
164 * Routine to save the old irq affinities and change affinities of all irqs to
167 * NB: Need to be expanded to multiple nodes.
170 __dump_set_irq_affinity(void)
173 cpumask_t cpu = CPU_MASK_NONE;
176 cpu_set(smp_processor_id(), cpu);
178 memcpy(saved_affinity, irq_affinity, NR_IRQS * sizeof(unsigned long));
181 irq_d = get_irq_desc(i);
182 if (irq_d->handler == NULL) {
185 irq_affinity[i] = cpu;
186 if (irq_d->handler->set_affinity != NULL) {
187 irq_d->handler->set_affinity(i, irq_affinity[i]);
191 #else /* !CONFIG_SMP */
192 #define __dump_save_other_cpus() do { } while (0)
193 #define __dump_set_irq_affinity() do { } while (0)
194 #define __dump_reset_irq_affinity() do { } while (0)
195 #endif /* !CONFIG_SMP */
198 __dump_save_regs(struct pt_regs *dest_regs, const struct pt_regs *regs)
201 memcpy(dest_regs, regs, sizeof(struct pt_regs));
206 * Name: __dump_configure_header()
207 * Func: Configure the dump header with all proper values.
210 __dump_configure_header(const struct pt_regs *regs)
215 #if defined(CONFIG_KDB) && !defined(CONFIG_DUMP_MODULE)
217 kdb_sysdump(int argc, const char **argv, const char **envp, struct pt_regs *regs)
219 kdb_printf("Dumping to disk...\n");
220 dump("dump from kdb", regs);
221 kdb_printf("Dump Complete\n");
226 static int dw_long(unsigned int fd, unsigned int cmd, unsigned long arg,
229 mm_segment_t old_fs = get_fs();
234 err = sys_ioctl(fd, cmd, (unsigned long)&val);
236 if (!err && put_user((unsigned int) val, (u32 *)arg))
242 * Name: __dump_init()
243 * Func: Initialize the dumping routine process. This is in case
244 * it's necessary in the future.
247 __dump_init(uint64_t local_memory_start)
251 ret = register_ioctl32_conversion(DIOSDUMPDEV, NULL);
252 ret |= register_ioctl32_conversion(DIOGDUMPDEV, NULL);
253 ret |= register_ioctl32_conversion(DIOSDUMPLEVEL, NULL);
254 ret |= register_ioctl32_conversion(DIOGDUMPLEVEL, dw_long);
255 ret |= register_ioctl32_conversion(DIOSDUMPFLAGS, NULL);
256 ret |= register_ioctl32_conversion(DIOGDUMPFLAGS, dw_long);
257 ret |= register_ioctl32_conversion(DIOSDUMPCOMPRESS, NULL);
258 ret |= register_ioctl32_conversion(DIOGDUMPCOMPRESS, dw_long);
259 ret |= register_ioctl32_conversion(DIOSTARGETIP, NULL);
260 ret |= register_ioctl32_conversion(DIOGTARGETIP, NULL);
261 ret |= register_ioctl32_conversion(DIOSTARGETPORT, NULL);
262 ret |= register_ioctl32_conversion(DIOGTARGETPORT, NULL);
263 ret |= register_ioctl32_conversion(DIOSSOURCEPORT, NULL);
264 ret |= register_ioctl32_conversion(DIOGSOURCEPORT, NULL);
265 ret |= register_ioctl32_conversion(DIOSETHADDR, NULL);
266 ret |= register_ioctl32_conversion(DIOGETHADDR, NULL);
267 ret |= register_ioctl32_conversion(DIOGDUMPOKAY, dw_long);
268 ret |= register_ioctl32_conversion(DIOSDUMPTAKE, NULL);
270 printk(KERN_ERR "LKCD: registering ioctl32 translations failed\n");
273 #if defined(FIXME) && defined(CONFIG_KDB) && !defined(CONFIG_DUMP_MODULE)
274 /* This won't currently work because interrupts are off in kdb
275 * and the dump process doesn't understand how to recover.
277 /* ToDo: add a command to query/set dump configuration */
278 kdb_register_repeat("sysdump", kdb_sysdump, "", "use lkcd to dump the system to disk (if configured)", 0, KDB_REPEAT_NONE);
286 * Name: __dump_open()
287 * Func: Open the dump device (architecture specific). This is in
288 * case it's necessary in the future.
298 * Name: __dump_cleanup()
299 * Func: Free any architecture specific data structures. This is called
300 * when the dump module is being removed.
307 ret = unregister_ioctl32_conversion(DIOSDUMPDEV);
308 ret |= unregister_ioctl32_conversion(DIOGDUMPDEV);
309 ret |= unregister_ioctl32_conversion(DIOSDUMPLEVEL);
310 ret |= unregister_ioctl32_conversion(DIOGDUMPLEVEL);
311 ret |= unregister_ioctl32_conversion(DIOSDUMPFLAGS);
312 ret |= unregister_ioctl32_conversion(DIOGDUMPFLAGS);
313 ret |= unregister_ioctl32_conversion(DIOSDUMPCOMPRESS);
314 ret |= unregister_ioctl32_conversion(DIOGDUMPCOMPRESS);
315 ret |= unregister_ioctl32_conversion(DIOSTARGETIP);
316 ret |= unregister_ioctl32_conversion(DIOGTARGETIP);
317 ret |= unregister_ioctl32_conversion(DIOSTARGETPORT);
318 ret |= unregister_ioctl32_conversion(DIOGTARGETPORT);
319 ret |= unregister_ioctl32_conversion(DIOSSOURCEPORT);
320 ret |= unregister_ioctl32_conversion(DIOGSOURCEPORT);
321 ret |= unregister_ioctl32_conversion(DIOSETHADDR);
322 ret |= unregister_ioctl32_conversion(DIOGETHADDR);
323 ret |= unregister_ioctl32_conversion(DIOGDUMPOKAY);
324 ret |= unregister_ioctl32_conversion(DIOSDUMPTAKE);
326 printk(KERN_ERR "LKCD: Unregistering ioctl32 translations failed\n");
332 * Kludge - dump from interrupt context is unreliable (Fixme)
334 * We do this so that softirqs initiated for dump i/o
335 * get processed and we don't hang while waiting for i/o
336 * to complete or in any irq synchronization attempt.
338 * This is not quite legal of course, as it has the side
339 * effect of making all interrupts & softirqs triggered
340 * while dump is in progress complete before currently
341 * pending softirqs and the currently executing interrupt
347 saved_irq_count = irq_count();
348 preempt_count() &= ~(HARDIRQ_MASK|SOFTIRQ_MASK);
354 preempt_count() |= saved_irq_count;
358 * Name: __dump_irq_enable
359 * Func: Reset system so interrupts are enabled.
360 * This is used for dump methods that require interrupts
361 * Eventually, all methods will have interrupts disabled
362 * and this code can be removed.
364 * Change irq affinities
365 * Re-enable interrupts
368 __dump_irq_enable(void)
370 __dump_set_irq_affinity();
377 * Name: __dump_irq_restore
378 * Func: Resume the system state in an architecture-specific way.
381 __dump_irq_restore(void)
384 __dump_reset_irq_affinity();
389 /* Cheap progress hack. It estimates pages to write and
390 * assumes all pages will go -- so it may get way off.
391 * As the progress is not displayed for other architectures, not used at this
395 __dump_progress_add_page(void)
397 unsigned long total_pages = nr_free_pages() + nr_inactive_pages + nr_active_pages;
398 unsigned int percent = (dump_header.dh_num_dump_pages * 100) / total_pages;
401 if (percent > last_percent && percent <= 100) {
402 sprintf(buf, "Dump %3d%% ", percent);
403 ppc64_dump_msg(0x2, buf);
404 last_percent = percent;
410 extern int dump_page_is_ram(unsigned long);
412 * Name: __dump_page_valid()
413 * Func: Check if page is valid to dump.
416 __dump_page_valid(unsigned long index)
418 if (!pfn_valid(index))
421 return dump_page_is_ram(index);
425 * Name: manual_handle_crashdump()
426 * Func: Interface for the lkcd dump command. Calls dump_execute()
429 manual_handle_crashdump(void)
433 get_current_regs(®s);
434 dump_execute("manual", ®s);