This commit was manufactured by cvs2svn to create tag 'before-xenU'.
[linux-2.6.git] / drivers / dump / dump_methods.h
1 /*
2  * Generic interfaces for flexible system dump 
3  *
4  * Started: Oct 2002 -  Suparna Bhattacharya (suparna@in.ibm.com)
5  *
6  * Copyright (C) 2002 International Business Machines Corp. 
7  *
8  * This code is released under version 2 of the GNU GPL.
9  */
10
11 #ifndef _LINUX_DUMP_METHODS_H
12 #define _LINUX_DUMP_METHODS_H
13
14 /*
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.
18  *
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).
26  * 
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.
34  *
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
39  * them.
40  */
41
42 #include <linux/sched.h>
43 #include <linux/slab.h>
44 #include <linux/highmem.h>
45 #include <linux/dumpdev.h>
46
47 #define MAX_PASSES      6
48 #define MAX_DEVS        4
49
50
51 /* To customise selection of pages to be dumped in a given pass/group */
52 struct dump_data_filter{
53         char name[32];
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) */
58 };
59
60
61 /* 
62  * Determined by the kind of dump mechanism and appropriate 
63  * overall scheme 
64  */ 
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); 
70
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); 
82 };
83
84 struct dump_scheme {
85         /* the name serves as an anchor to locate the scheme after reboot */
86         char name[32]; 
87         struct dump_scheme_ops *ops;
88         struct list_head list;
89 };
90
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,
95         DUMP_HALT_CPUS          = 3,
96 } dump_silence_level;
97
98 /* determined by the dump (file) format */
99 struct dump_fmt_ops {
100         /* build header */
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);
110 };
111
112 struct dump_fmt {
113         unsigned long magic; 
114         char name[32];  /* lcrash, crash, elf-core etc */
115         struct dump_fmt_ops *ops;
116         struct list_head list;
117 };
118
119 /* 
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.
123  * Still Todo.
124  */
125
126 /* The combined dumper profile (mechanism, scheme, dev, fmt) */
127 struct dumper {
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 */
136         int curr_pass;
137         unsigned long count;
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 */
143         int header_len; 
144         struct list_head dumper_list; /* links to other dumpers */
145 };      
146
147 /* Starting point to get to the current configured state */
148 struct dump_config {
149         ulong level;
150         ulong flags;
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;
155 };      
156
157 extern struct dump_config dump_config;
158
159 /* Used to save the dump config across a reboot for 2-stage dumps: 
160  * 
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.
165  */
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;
172         struct dump_fmt fmt;
173         struct __dump_compress compress;
174         struct dump_data_filter filter_table[MAX_PASSES];
175         struct dump_anydev dev[MAX_DEVS]; /* target dump device */
176 };
177
178
179 /* Wrappers that invoke the methods for the current (active) dumper */
180
181 /* Scheme operations */
182
183 static inline int dump_sequencer(void)
184 {
185         return dump_config.dumper->scheme->ops->sequencer();
186 }
187
188 static inline int dump_iterator(int pass, int (*action)(unsigned long, 
189         unsigned long), struct dump_data_filter *filter)
190 {
191         return dump_config.dumper->scheme->ops->iterator(pass, action, filter);
192 }
193
194 #define dump_save_data dump_config.dumper->scheme->ops->save_data
195 #define dump_skip_data dump_config.dumper->scheme->ops->skip_data
196
197 static inline int dump_write_buffer(void *buf, unsigned long len)
198 {
199         return dump_config.dumper->scheme->ops->write_buffer(buf, len);
200 }
201
202 static inline int dump_configure(unsigned long devid)
203 {
204         return dump_config.dumper->scheme->ops->configure(devid);
205 }
206
207 static inline int dump_unconfigure(void)
208 {
209         return dump_config.dumper->scheme->ops->unconfigure();
210 }
211
212 /* Format operations */
213
214 static inline int dump_configure_header(const char *panic_str, 
215         const struct pt_regs *regs)
216 {
217         return dump_config.dumper->fmt->ops->configure_header(panic_str, regs);
218 }
219
220 static inline void dump_save_context(int cpu, const struct pt_regs *regs, 
221                 struct task_struct *tsk)
222 {
223         dump_config.dumper->fmt->ops->save_context(cpu, regs, tsk);
224 }
225
226 static inline int dump_save_this_cpu(const struct pt_regs *regs)
227 {
228         int cpu = smp_processor_id();
229
230         dump_save_context(cpu, regs, current);
231         return 1;
232 }
233
234 static inline int dump_update_header(void)
235 {
236         return dump_config.dumper->fmt->ops->update_header();
237 }
238
239 static inline int dump_update_end_marker(void)
240 {
241         return dump_config.dumper->fmt->ops->update_end_marker();
242 }
243
244 static inline int dump_add_data(unsigned long loc, unsigned long sz)
245 {
246         return dump_config.dumper->fmt->ops->add_data(loc, sz);
247 }
248
249 /* Compression operation */
250 static inline int dump_compress_data(char *src, int slen, char *dst)
251 {
252         return dump_config.dumper->compress->compress_func(src, slen, 
253                 dst, DUMP_DPC_PAGE_SIZE);
254 }
255
256
257 /* Prototypes of some default implementations of dump methods */
258
259 extern struct __dump_compress dump_none_compression;
260
261 /* Default scheme methods (dump_scheme.c) */
262
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);
271
272 /* Default scheme template */
273 extern struct dump_scheme dump_scheme_singlestage;
274
275 /* Default dump format methods */
276
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);
284
285 /* Default format (lcrash) template */
286 extern struct dump_fmt dump_fmt_lcrash;
287
288 /* Default dump selection filter table */
289
290 /* 
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.
296  */   
297 extern struct dump_data_filter dump_filter_table[];
298
299 /* Some pre-defined dumpers */
300 extern struct dumper dumper_singlestage;
301 extern struct dumper dumper_stage1;
302 extern struct dumper dumper_stage2;
303
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 */
310
311 /* Helpers - move these to dump.h later ? */
312
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);
316
317 static inline void dumper_reset(void)
318 {
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;
324 }
325
326 /* 
327  * May later be moulded to perform boot-time allocations so we can dump 
328  * earlier during bootup 
329  */
330 static inline void *dump_alloc_mem(unsigned long size)
331 {
332         return kmalloc(size, GFP_KERNEL);
333 }
334
335 static inline void dump_free_mem(void *buf)
336 {
337         struct page *page;
338
339         /* ignore reserved pages (e.g. post soft boot stage) */
340         if (buf && (page = virt_to_page(buf))) {
341                 if (PageReserved(page))
342                         return;
343         }
344
345         kfree(buf);
346 }
347
348
349 #endif /*  _LINUX_DUMP_METHODS_H */