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>
51 /* To customise selection of pages to be dumped in a given pass/group */
52 struct dump_data_filter{
54 int (*selector)(int, unsigned long, unsigned long);
55 ulong level_mask; /* dump level(s) for which this filter applies */
56 loff_t start[MAX_NUMNODES], end[MAX_NUMNODES]; /* location range applicable */
57 ulong num_mbanks; /* Number of memory banks. Greater than one for discontig memory (NUMA) */
62 * Determined by the kind of dump mechanism and appropriate
65 struct dump_scheme_ops {
66 /* sets aside memory, inits data structures etc */
67 int (*configure)(unsigned long devid);
68 /* releases resources */
69 int (*unconfigure)(void);
71 /* ordering of passes, invoking iterator */
72 int (*sequencer)(void);
73 /* iterates over system data, selects and acts on data to dump */
74 int (*iterator)(int, int (*)(unsigned long, unsigned long),
75 struct dump_data_filter *);
76 /* action when data is selected for dump */
77 int (*save_data)(unsigned long, unsigned long);
78 /* action when data is to be excluded from dump */
79 int (*skip_data)(unsigned long, unsigned long);
80 /* policies for space, multiple dump devices etc */
81 int (*write_buffer)(void *, unsigned long);
85 /* the name serves as an anchor to locate the scheme after reboot */
87 struct dump_scheme_ops *ops;
88 struct list_head list;
91 /* Quiescing/Silence levels (controls IPI callback behaviour) */
92 extern enum dump_silence_levels {
93 DUMP_SOFT_SPIN_CPUS = 1,
94 DUMP_HARD_SPIN_CPUS = 2,
98 /* determined by the dump (file) format */
101 int (*configure_header)(const char *, const struct pt_regs *);
102 int (*update_header)(void); /* update header and write it out */
103 /* save curr context */
104 void (*save_context)(int, const struct pt_regs *,
105 struct task_struct *);
106 /* typically called by the save_data action */
107 /* add formatted data to the dump buffer */
108 int (*add_data)(unsigned long, unsigned long);
109 int (*update_end_marker)(void);
114 char name[32]; /* lcrash, crash, elf-core etc */
115 struct dump_fmt_ops *ops;
116 struct list_head list;
120 * Modules will be able add their own data capture schemes by
121 * registering their own dumpers. Typically they would use the
122 * primary dumper as a template and tune it with their routines.
126 /* The combined dumper profile (mechanism, scheme, dev, fmt) */
128 char name[32]; /* singlestage, overlay (stg1), passthru(stg2), pull */
129 struct dump_scheme *scheme;
130 struct dump_fmt *fmt;
131 struct __dump_compress *compress;
132 struct dump_data_filter *filter;
133 struct dump_dev *dev;
134 /* state valid only for active dumper(s) - per instance */
135 /* run time state/context */
138 loff_t curr_offset; /* current logical offset into dump device */
139 loff_t curr_loc; /* current memory location */
140 void *curr_buf; /* current position in the dump buffer */
141 void *dump_buf; /* starting addr of dump buffer */
142 int header_dirty; /* whether the header needs to be written out */
144 struct list_head dumper_list; /* links to other dumpers */
147 /* Starting point to get to the current configured state */
151 struct dumper *dumper;
152 unsigned long dump_device;
153 unsigned long dump_addr; /* relevant only for in-memory dumps */
154 struct list_head dump_dev_list;
157 extern struct dump_config dump_config;
159 /* Used to save the dump config across a reboot for 2-stage dumps:
161 * Note: The scheme, format, compression and device type should be
162 * registered at bootup, for this config to be sharable across soft-boot.
163 * The function addresses could have changed and become invalid, and
164 * need to be set up again.
166 struct dump_config_block {
167 u64 magic; /* for a quick sanity check after reboot */
168 struct dump_memdev memdev; /* handle to dump stored in memory */
169 struct dump_config config;
170 struct dumper dumper;
171 struct dump_scheme scheme;
173 struct __dump_compress compress;
174 struct dump_data_filter filter_table[MAX_PASSES];
175 struct dump_anydev dev[MAX_DEVS]; /* target dump device */
179 /* Wrappers that invoke the methods for the current (active) dumper */
181 /* Scheme operations */
183 static inline int dump_sequencer(void)
185 return dump_config.dumper->scheme->ops->sequencer();
188 static inline int dump_iterator(int pass, int (*action)(unsigned long,
189 unsigned long), struct dump_data_filter *filter)
191 return dump_config.dumper->scheme->ops->iterator(pass, action, filter);
194 #define dump_save_data dump_config.dumper->scheme->ops->save_data
195 #define dump_skip_data dump_config.dumper->scheme->ops->skip_data
197 static inline int dump_write_buffer(void *buf, unsigned long len)
199 return dump_config.dumper->scheme->ops->write_buffer(buf, len);
202 static inline int dump_configure(unsigned long devid)
204 return dump_config.dumper->scheme->ops->configure(devid);
207 static inline int dump_unconfigure(void)
209 return dump_config.dumper->scheme->ops->unconfigure();
212 /* Format operations */
214 static inline int dump_configure_header(const char *panic_str,
215 const struct pt_regs *regs)
217 return dump_config.dumper->fmt->ops->configure_header(panic_str, regs);
220 static inline void dump_save_context(int cpu, const struct pt_regs *regs,
221 struct task_struct *tsk)
223 dump_config.dumper->fmt->ops->save_context(cpu, regs, tsk);
226 static inline int dump_save_this_cpu(const struct pt_regs *regs)
228 int cpu = smp_processor_id();
230 dump_save_context(cpu, regs, current);
234 static inline int dump_update_header(void)
236 return dump_config.dumper->fmt->ops->update_header();
239 static inline int dump_update_end_marker(void)
241 return dump_config.dumper->fmt->ops->update_end_marker();
244 static inline int dump_add_data(unsigned long loc, unsigned long sz)
246 return dump_config.dumper->fmt->ops->add_data(loc, sz);
249 /* Compression operation */
250 static inline int dump_compress_data(char *src, int slen, char *dst)
252 return dump_config.dumper->compress->compress_func(src, slen,
253 dst, DUMP_DPC_PAGE_SIZE);
257 /* Prototypes of some default implementations of dump methods */
259 extern struct __dump_compress dump_none_compression;
261 /* Default scheme methods (dump_scheme.c) */
263 extern int dump_generic_sequencer(void);
264 extern int dump_page_iterator(int pass, int (*action)(unsigned long, unsigned
265 long), struct dump_data_filter *filter);
266 extern int dump_generic_save_data(unsigned long loc, unsigned long sz);
267 extern int dump_generic_skip_data(unsigned long loc, unsigned long sz);
268 extern int dump_generic_write_buffer(void *buf, unsigned long len);
269 extern int dump_generic_configure(unsigned long);
270 extern int dump_generic_unconfigure(void);
272 /* Default scheme template */
273 extern struct dump_scheme dump_scheme_singlestage;
275 /* Default dump format methods */
277 extern int dump_lcrash_configure_header(const char *panic_str,
278 const struct pt_regs *regs);
279 extern void dump_lcrash_save_context(int cpu, const struct pt_regs *regs,
280 struct task_struct *tsk);
281 extern int dump_generic_update_header(void);
282 extern int dump_lcrash_add_data(unsigned long loc, unsigned long sz);
283 extern int dump_lcrash_update_end_marker(void);
285 /* Default format (lcrash) template */
286 extern struct dump_fmt dump_fmt_lcrash;
288 /* Default dump selection filter table */
291 * Entries listed in order of importance and correspond to passes
292 * The last entry (with a level_mask of zero) typically reflects data that
293 * won't be dumped -- this may for example be used to identify data
294 * that will be skipped for certain so the corresponding memory areas can be
295 * utilized as scratch space.
297 extern struct dump_data_filter dump_filter_table[];
299 /* Some pre-defined dumpers */
300 extern struct dumper dumper_singlestage;
301 extern struct dumper dumper_stage1;
302 extern struct dumper dumper_stage2;
304 /* These are temporary */
305 #define DUMP_MASK_HEADER DUMP_LEVEL_HEADER
306 #define DUMP_MASK_KERN DUMP_LEVEL_KERN
307 #define DUMP_MASK_USED DUMP_LEVEL_USED
308 #define DUMP_MASK_UNUSED DUMP_LEVEL_ALL_RAM
309 #define DUMP_MASK_REST 0 /* dummy for now */
311 /* Helpers - move these to dump.h later ? */
313 int dump_generic_execute(const char *panic_str, const struct pt_regs *regs);
314 extern int dump_ll_write(void *buf, unsigned long len);
315 int dump_check_and_free_page(struct dump_memdev *dev, struct page *page);
317 static inline void dumper_reset(void)
319 dump_config.dumper->curr_buf = dump_config.dumper->dump_buf;
320 dump_config.dumper->curr_loc = 0;
321 dump_config.dumper->curr_offset = 0;
322 dump_config.dumper->count = 0;
323 dump_config.dumper->curr_pass = 0;
327 * May later be moulded to perform boot-time allocations so we can dump
328 * earlier during bootup
330 static inline void *dump_alloc_mem(unsigned long size)
332 return kmalloc(size, GFP_KERNEL);
335 static inline void dump_free_mem(void *buf)
339 /* ignore reserved pages (e.g. post soft boot stage) */
340 if (buf && (page = virt_to_page(buf))) {
341 if (PageReserved(page))
349 #endif /* _LINUX_DUMP_METHODS_H */