2 * Generic interfaces for flexible system dump
4 * Started: Oct 2002 - Suparna Bhattacharya (suparna@in.ibm.com)
6 * Copyright (C) 2002 International Business Machines Corp.
8 * This code is released under version 2 of the GNU GPL.
11 #ifndef _LINUX_DUMP_METHODS_H
12 #define _LINUX_DUMP_METHODS_H
15 * Inspired by Matt Robinson's suggestion of introducing dump
16 * methods as a way to enable different crash dump facilities to
17 * coexist where each employs its own scheme or dumping policy.
19 * The code here creates a framework for flexible dump by defining
20 * a set of methods and providing associated helpers that differentiate
21 * between the underlying mechanism (how to dump), overall scheme
22 * (sequencing of stages and data dumped and associated quiescing),
23 * output format (what the dump output looks like), target type
24 * (where to save the dump; see dumpdev.h), and selection policy
25 * (state/data to dump).
27 * These sets of interfaces can be mixed and matched to build a
28 * dumper suitable for a given situation, allowing for
29 * flexibility as well appropriate degree of code reuse.
30 * For example all features and options of lkcd (including
31 * granular selective dumping in the near future) should be
32 * available even when say, the 2 stage soft-boot based mechanism
33 * is used for taking disruptive dumps.
35 * Todo: Additionally modules or drivers may supply their own
36 * custom dumpers which extend dump with module specific
37 * information or hardware state, and can even tweak the
38 * mechanism when it comes to saving state relevant to
42 #include <linux/sched.h>
43 #include <linux/slab.h>
44 #include <linux/highmem.h>
45 #include <linux/dumpdev.h>
46 #include <asm/page.h> /* get_order */
50 #define MAX_MBANKS_PER_NODE 8
51 #define MAX_MBANKS (MAX_NUMNODES * MAX_MBANKS_PER_NODE)
54 /* To customise selection of pages to be dumped in a given pass/group */
55 struct dump_data_filter{
57 int (*selector)(int, unsigned long, unsigned long);
58 ulong level_mask; /* dump level(s) for which this filter applies */
59 loff_t start[MAX_MBANKS], end[MAX_MBANKS]; /* location range applicable */
60 ulong num_mbanks; /* Number of memory banks. Greater than one for discontig memory (NUMA) */
65 * Determined by the kind of dump mechanism and appropriate
68 struct dump_scheme_ops {
69 /* sets aside memory, inits data structures etc */
70 int (*configure)(const char *devid);
71 /* releases resources */
72 int (*unconfigure)(void);
74 /* ordering of passes, invoking iterator */
75 int (*sequencer)(void);
76 /* iterates over system data, selects and acts on data to dump */
77 int (*iterator)(int, int (*)(unsigned long, unsigned long),
78 struct dump_data_filter *);
79 /* action when data is selected for dump */
80 int (*save_data)(unsigned long, unsigned long);
81 /* action when data is to be excluded from dump */
82 int (*skip_data)(unsigned long, unsigned long);
83 /* policies for space, multiple dump devices etc */
84 int (*write_buffer)(void *, unsigned long);
88 /* the name serves as an anchor to locate the scheme after reboot */
90 struct dump_scheme_ops *ops;
91 struct list_head list;
94 /* Quiescing/Silence levels (controls IPI callback behaviour) */
95 extern enum dump_silence_levels {
96 DUMP_SOFT_SPIN_CPUS = 1,
97 DUMP_HARD_SPIN_CPUS = 2,
101 /* determined by the dump (file) format */
102 struct dump_fmt_ops {
104 int (*configure_header)(const char *, const struct pt_regs *);
105 int (*update_header)(void); /* update header and write it out */
106 /* save curr context */
107 void (*save_context)(int, const struct pt_regs *,
108 struct task_struct *);
109 /* typically called by the save_data action */
110 /* add formatted data to the dump buffer */
111 int (*add_data)(unsigned long, unsigned long);
112 int (*update_end_marker)(void);
117 char name[32]; /* lcrash, crash, elf-core etc */
118 struct dump_fmt_ops *ops;
119 struct list_head list;
123 * Modules will be able add their own data capture schemes by
124 * registering their own dumpers. Typically they would use the
125 * primary dumper as a template and tune it with their routines.
129 /* The combined dumper profile (mechanism, scheme, dev, fmt) */
131 char name[32]; /* singlestage, overlay (stg1), passthru(stg2), pull */
132 struct dump_scheme *scheme;
133 struct dump_fmt *fmt;
134 struct __dump_compress *compress;
135 struct dump_data_filter *filter;
136 struct dump_dev *dev;
137 /* state valid only for active dumper(s) - per instance */
138 /* run time state/context */
141 loff_t curr_offset; /* current logical offset into dump device */
142 loff_t curr_loc; /* current memory location */
143 void *curr_buf; /* current position in the dump buffer */
144 void *dump_buf; /* starting addr of dump buffer */
145 int header_dirty; /* whether the header needs to be written out */
147 struct list_head dumper_list; /* links to other dumpers */
150 /* Starting point to get to the current configured state */
157 struct dumper *dumper;
159 unsigned long dump_addr; /* relevant only for in-memory dumps */
160 struct list_head dump_dev_list;
163 extern struct dump_config dump_config;
165 /* Wrappers that invoke the methods for the current (active) dumper */
167 /* Scheme operations */
169 static inline int dump_sequencer(void)
171 return dump_config.dumper->scheme->ops->sequencer();
174 static inline int dump_iterator(int pass, int (*action)(unsigned long,
175 unsigned long), struct dump_data_filter *filter)
177 return dump_config.dumper->scheme->ops->iterator(pass, action, filter);
180 #define dump_save_data dump_config.dumper->scheme->ops->save_data
181 #define dump_skip_data dump_config.dumper->scheme->ops->skip_data
183 static inline int dump_write_buffer(void *buf, unsigned long len)
185 return dump_config.dumper->scheme->ops->write_buffer(buf, len);
188 static inline int dump_configure(const char *devid)
190 return dump_config.dumper->scheme->ops->configure(devid);
193 static inline int dump_unconfigure(void)
195 return dump_config.dumper->scheme->ops->unconfigure();
198 /* Format operations */
200 static inline int dump_configure_header(const char *panic_str,
201 const struct pt_regs *regs)
203 return dump_config.dumper->fmt->ops->configure_header(panic_str, regs);
206 static inline void dump_save_context(int cpu, const struct pt_regs *regs,
207 struct task_struct *tsk)
209 dump_config.dumper->fmt->ops->save_context(cpu, regs, tsk);
212 static inline int dump_save_this_cpu(const struct pt_regs *regs)
214 int cpu = smp_processor_id();
216 dump_save_context(cpu, regs, current);
220 static inline int dump_update_header(void)
222 return dump_config.dumper->fmt->ops->update_header();
225 static inline int dump_update_end_marker(void)
227 return dump_config.dumper->fmt->ops->update_end_marker();
230 static inline int dump_add_data(unsigned long loc, unsigned long sz)
232 return dump_config.dumper->fmt->ops->add_data(loc, sz);
235 /* Compression operation */
236 static inline int dump_compress_data(char *src, int slen, char *dst,
239 return dump_config.dumper->compress->compress_func(src, slen,
240 dst, DUMP_DPC_PAGE_SIZE, loc);
244 /* Prototypes of some default implementations of dump methods */
246 extern struct __dump_compress dump_none_compression;
248 /* Default scheme methods (dump_scheme.c) */
250 extern int dump_generic_sequencer(void);
251 extern int dump_page_iterator(int pass, int (*action)(unsigned long, unsigned
252 long), struct dump_data_filter *filter);
253 extern int dump_generic_save_data(unsigned long loc, unsigned long sz);
254 extern int dump_generic_skip_data(unsigned long loc, unsigned long sz);
255 extern int dump_generic_write_buffer(void *buf, unsigned long len);
256 extern int dump_generic_configure(const char *);
257 extern int dump_generic_unconfigure(void);
258 #ifdef CONFIG_DISCONTIGMEM
259 extern void dump_reconfigure_mbanks(void);
262 /* Default scheme template */
263 extern struct dump_scheme dump_scheme_singlestage;
265 /* Default dump format methods */
267 extern int dump_lcrash_configure_header(const char *panic_str,
268 const struct pt_regs *regs);
269 extern void dump_lcrash_save_context(int cpu, const struct pt_regs *regs,
270 struct task_struct *tsk);
271 extern int dump_generic_update_header(void);
272 extern int dump_lcrash_add_data(unsigned long loc, unsigned long sz);
273 extern int dump_lcrash_update_end_marker(void);
275 /* Default format (lcrash) template */
276 extern struct dump_fmt dump_fmt_lcrash;
278 /* Default dump selection filter table */
281 * Entries listed in order of importance and correspond to passes
282 * The last entry (with a level_mask of zero) typically reflects data that
283 * won't be dumped -- this may for example be used to identify data
284 * that will be skipped for certain so the corresponding memory areas can be
285 * utilized as scratch space.
287 extern struct dump_data_filter dump_filter_table[];
289 /* Some pre-defined dumpers */
290 extern struct dumper dumper_singlestage;
291 extern struct dumper dumper_stage1;
292 extern struct dumper dumper_stage2;
294 /* These are temporary */
295 #define DUMP_MASK_HEADER DUMP_LEVEL_HEADER
296 #define DUMP_MASK_KERN DUMP_LEVEL_KERN
297 #define DUMP_MASK_USED DUMP_LEVEL_USED
298 #define DUMP_MASK_UNUSED DUMP_LEVEL_ALL_RAM
299 #define DUMP_MASK_REST 0 /* dummy for now */
301 /* Helpers - move these to dump.h later ? */
303 int dump_generic_execute(const char *panic_str, const struct pt_regs *regs);
304 extern int dump_ll_write(void *buf, unsigned long len);
306 static inline void dumper_reset(void)
308 dump_config.dumper->curr_buf = dump_config.dumper->dump_buf;
309 dump_config.dumper->curr_loc = 0;
310 dump_config.dumper->curr_offset = 0;
311 dump_config.dumper->count = 0;
312 dump_config.dumper->curr_pass = 0;
316 * May later be moulded to perform boot-time allocations so we can dump
317 * earlier during bootup
319 static inline void *dump_alloc_mem(unsigned long size)
321 return (void *) __get_free_pages(GFP_KERNEL, get_order(size));
324 static inline void dump_free_mem(void *buf)
328 /* ignore reserved pages (e.g. post soft boot stage) */
329 if (buf && (page = virt_to_page(buf))) {
330 if (PageReserved(page))
334 * Allocated using __get_free_pages().
336 free_pages((unsigned long)buf,
337 get_order(DUMP_BUFFER_SIZE + 3 * DUMP_PAGE_SIZE));
341 #endif /* _LINUX_DUMP_METHODS_H */