enable floppy module generation for boot cd
[linux-2.6.git] / drivers / dump / dump_memdev.c
1 /*
2  * Implements the dump driver interface for saving a dump in available
3  * memory areas. The saved pages may be written out to persistent storage  
4  * after a soft reboot.
5  *
6  * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
7  *
8  * Copyright (C) 2002 International Business Machines Corp. 
9  *
10  * This code is released under version 2 of the GNU GPL.
11  *
12  * The approach of tracking pages containing saved dump using map pages 
13  * allocated as needed has been derived from the Mission Critical Linux 
14  * mcore dump implementation. 
15  *
16  * Credits and a big thanks for letting the lkcd project make use of 
17  * the excellent piece of work and also helping with clarifications 
18  * and tips along the way are due to:
19  *      Dave Winchell <winchell@mclx.com> (primary author of mcore)
20  *      Jeff Moyer <moyer@mclx.com>
21  *      Josh Huber <huber@mclx.com>
22  *
23  * For those familiar with the mcore code, the main differences worth
24  * noting here (besides the dump device abstraction) result from enabling 
25  * "high" memory pages (pages not permanently mapped in the kernel 
26  * address space) to be used for saving dump data (because of which a 
27  * simple virtual address based linked list cannot be used anymore for 
28  * managing free pages), an added level of indirection for faster 
29  * lookups during the post-boot stage, and the idea of pages being 
30  * made available as they get freed up while dump to memory progresses 
31  * rather than one time before starting the dump. The last point enables 
32  * a full memory snapshot to be saved starting with an initial set of 
33  * bootstrap pages given a good compression ratio. (See dump_overlay.c)
34  *
35  */
36
37 /*
38  * -----------------MEMORY LAYOUT ------------------
39  * The memory space consists of a set of discontiguous pages, and
40  * discontiguous map pages as well, rooted in a chain of indirect
41  * map pages (also discontiguous). Except for the indirect maps 
42  * (which must be preallocated in advance), the rest of the pages 
43  * could be in high memory.
44  *
45  * root
46  *  |    ---------    --------        --------
47  *  -->  | .  . +|--->|  .  +|------->| . .  |       indirect 
48  *       --|--|---    ---|----        --|-|---       maps
49  *         |  |          |              | |     
50  *    ------  ------   -------     ------ -------
51  *    | .  |  | .  |   | .  . |    | .  | |  . . |   maps 
52  *    --|---  --|---   --|--|--    --|--- ---|-|--
53  *     page    page    page page   page   page page  data
54  *                                                   pages
55  *
56  * Writes to the dump device happen sequentially in append mode.
57  * The main reason for the existence of the indirect map is
58  * to enable a quick way to lookup a specific logical offset in
59  * the saved data post-soft-boot, e.g. to writeout pages
60  * with more critical data first, even though such pages
61  * would have been compressed and copied last, being the lowest
62  * ranked candidates for reuse due to their criticality.
63  * (See dump_overlay.c)
64  */
65 #include <linux/mm.h>
66 #include <linux/highmem.h>
67 #include <linux/bootmem.h>
68 #include <linux/dump.h>
69 #include "dump_methods.h"
70
71 #define DUMP_MAP_SZ (PAGE_SIZE / sizeof(unsigned long)) /* direct map size */
72 #define DUMP_IND_MAP_SZ DUMP_MAP_SZ - 1  /* indirect map size */
73 #define DUMP_NR_BOOTSTRAP       64  /* no of bootstrap pages */
74
75 extern int dump_low_page(struct page *);
76
77 /* check if the next entry crosses a page boundary */
78 static inline int is_last_map_entry(unsigned long *map)
79 {
80         unsigned long addr = (unsigned long)(map + 1);
81
82         return (!(addr & (PAGE_SIZE - 1)));
83 }
84
85 /* Todo: should have some validation checks */
86 /* The last entry in the indirect map points to the next indirect map */
87 /* Indirect maps are referred to directly by virtual address */
88 static inline unsigned long *next_indirect_map(unsigned long *map)
89 {
90         return (unsigned long *)map[DUMP_IND_MAP_SZ];
91 }
92
93 #ifdef CONFIG_CRASH_DUMP_SOFTBOOT
94 /* Called during early bootup - fixme: make this __init */
95 void dump_early_reserve_map(struct dump_memdev *dev)
96 {
97         unsigned long *map1, *map2;
98         loff_t off = 0, last = dev->last_used_offset >> PAGE_SHIFT;
99         int i, j;
100         
101         printk("Reserve bootmap space holding previous dump of %lld pages\n",
102                         last);
103         map1= (unsigned long *)dev->indirect_map_root;
104
105         while (map1 && (off < last)) {
106                 reserve_bootmem(virt_to_phys((void *)map1), PAGE_SIZE);
107                 for (i=0;  (i < DUMP_MAP_SZ - 1) && map1[i] && (off < last); 
108                         i++, off += DUMP_MAP_SZ) {
109                         pr_debug("indirect map[%d] = 0x%lx\n", i, map1[i]);
110                         if (map1[i] >= max_low_pfn)
111                                 continue;
112                         reserve_bootmem(map1[i] << PAGE_SHIFT, PAGE_SIZE);
113                         map2 = pfn_to_kaddr(map1[i]);
114                         for (j = 0 ; (j < DUMP_MAP_SZ) && map2[j] && 
115                                 (off + j < last); j++) {
116                                 pr_debug("\t map[%d][%d] = 0x%lx\n", i, j, 
117                                         map2[j]);
118                                 if (map2[j] < max_low_pfn) {
119                                         reserve_bootmem(map2[j] << PAGE_SHIFT,
120                                                 PAGE_SIZE);
121                                 }
122                         }
123                 }
124                 map1 = next_indirect_map(map1);
125         }
126         dev->nr_free = 0; /* these pages don't belong to this boot */
127 }
128 #endif
129
130 /* mark dump pages so that they aren't used by this kernel */
131 void dump_mark_map(struct dump_memdev *dev)
132 {
133         unsigned long *map1, *map2;
134         loff_t off = 0, last = dev->last_used_offset >> PAGE_SHIFT;
135         struct page *page;
136         int i, j;
137         
138         printk("Dump: marking pages in use by previous dump\n");
139         map1= (unsigned long *)dev->indirect_map_root;
140
141         while (map1 && (off < last)) {
142                 page = virt_to_page(map1);      
143                 set_page_count(page, 1);
144                 for (i=0;  (i < DUMP_MAP_SZ - 1) && map1[i] && (off < last); 
145                         i++, off += DUMP_MAP_SZ) {
146                         pr_debug("indirect map[%d] = 0x%lx\n", i, map1[i]);
147                         page = pfn_to_page(map1[i]);
148                         set_page_count(page, 1);
149                         map2 = kmap_atomic(page, KM_DUMP);
150                         for (j = 0 ; (j < DUMP_MAP_SZ) && map2[j] && 
151                                 (off + j < last); j++) {
152                                 pr_debug("\t map[%d][%d] = 0x%lx\n", i, j, 
153                                         map2[j]);
154                                 page = pfn_to_page(map2[j]);
155                                 set_page_count(page, 1);
156                         }
157                 }
158                 map1 = next_indirect_map(map1);
159         }
160 }
161         
162
163 /* 
164  * Given a logical offset into the mem device lookup the 
165  * corresponding page 
166  *      loc is specified in units of pages 
167  * Note: affects curr_map (even in the case where lookup fails)
168  */
169 struct page *dump_mem_lookup(struct dump_memdev *dump_mdev, unsigned long loc)
170 {
171         unsigned long *map;
172         unsigned long i, index = loc / DUMP_MAP_SZ;
173         struct page *page = NULL;
174         unsigned long curr_pfn, curr_map, *curr_map_ptr = NULL;
175
176         map = (unsigned long *)dump_mdev->indirect_map_root;
177         if (!map)
178                 return NULL;
179
180         if (loc > dump_mdev->last_offset >> PAGE_SHIFT)
181                 return NULL;
182
183         /* 
184          * first locate the right indirect map 
185          * in the chain of indirect maps 
186          */
187         for (i = 0; i + DUMP_IND_MAP_SZ < index ; i += DUMP_IND_MAP_SZ) {
188                 if (!(map = next_indirect_map(map)))
189                         return NULL;
190         }
191         /* then the right direct map */
192         /* map entries are referred to by page index */
193         if ((curr_map = map[index - i])) {
194                 page = pfn_to_page(curr_map);
195                 /* update the current traversal index */
196                 /* dump_mdev->curr_map = &map[index - i];*/
197                 curr_map_ptr = &map[index - i];
198         }
199
200         if (page)
201                 map = kmap_atomic(page, KM_DUMP);
202         else 
203                 return NULL;
204
205         /* and finally the right entry therein */
206         /* data pages are referred to by page index */
207         i = index * DUMP_MAP_SZ;
208         if ((curr_pfn = map[loc - i])) {
209                 page = pfn_to_page(curr_pfn);
210                 dump_mdev->curr_map = curr_map_ptr;
211                 dump_mdev->curr_map_offset = loc - i;
212                 dump_mdev->ddev.curr_offset = loc << PAGE_SHIFT;
213         } else {
214                 page = NULL;
215         }
216         kunmap_atomic(map, KM_DUMP);
217
218         return page;
219 }
220                         
221 /* 
222  * Retrieves a pointer to the next page in the dump device 
223  * Used during the lookup pass post-soft-reboot 
224  */
225 struct page *dump_mem_next_page(struct dump_memdev *dev)
226 {
227         unsigned long i; 
228         unsigned long *map;     
229         struct page *page = NULL;
230
231         if (dev->ddev.curr_offset + PAGE_SIZE >= dev->last_offset) {
232                 return NULL;
233         }
234
235         if ((i = (unsigned long)(++dev->curr_map_offset)) >= DUMP_MAP_SZ) {
236                 /* move to next map */  
237                 if (is_last_map_entry(++dev->curr_map)) {
238                         /* move to the next indirect map page */
239                         printk("dump_mem_next_page: go to next indirect map\n");
240                         dev->curr_map = (unsigned long *)*dev->curr_map;
241                         if (!dev->curr_map)
242                                 return NULL;
243                 }
244                 i = dev->curr_map_offset = 0;
245                 pr_debug("dump_mem_next_page: next map 0x%lx, entry 0x%lx\n",
246                                 dev->curr_map, *dev->curr_map);
247
248         };
249         
250         if (*dev->curr_map) {
251                 map = kmap_atomic(pfn_to_page(*dev->curr_map), KM_DUMP);
252                 if (map[i])
253                         page = pfn_to_page(map[i]);
254                 kunmap_atomic(map, KM_DUMP);
255                 dev->ddev.curr_offset += PAGE_SIZE;
256         };
257
258         return page;
259 }
260
261 /* Copied from dump_filters.c */
262 static inline int kernel_page(struct page *p)
263 {
264         /* FIXME: Need to exclude hugetlb pages. Clue: reserved but inuse */
265         return (PageReserved(p) && !PageInuse(p)) || (!PageLRU(p) && PageInuse(p));
266 }
267
268 static inline int user_page(struct page *p)
269 {
270         return PageInuse(p) && (!PageReserved(p) && PageLRU(p));
271 }
272
273 int dump_reused_by_boot(struct page *page)
274 {
275         /* Todo
276          * Checks:
277          * if PageReserved 
278          * if < __end + bootmem_bootmap_pages for this boot + allowance 
279          * if overwritten by initrd (how to check ?)
280          * Also, add more checks in early boot code
281          * e.g. bootmem bootmap alloc verify not overwriting dump, and if
282          * so then realloc or move the dump pages out accordingly.
283          */
284
285         /* Temporary proof of concept hack, avoid overwriting kern pages */
286
287         return (kernel_page(page) || dump_low_page(page) || user_page(page));
288 }
289
290
291 /* Uses the free page passed in to expand available space */
292 int dump_mem_add_space(struct dump_memdev *dev, struct page *page)
293 {
294         struct page *map_page;
295         unsigned long *map;     
296         unsigned long i; 
297
298         if (!dev->curr_map)
299                 return -ENOMEM; /* must've exhausted indirect map */
300
301         if (!*dev->curr_map || dev->curr_map_offset >= DUMP_MAP_SZ) {
302                 /* add map space */
303                 *dev->curr_map = page_to_pfn(page);
304                 dev->curr_map_offset = 0;
305                 return 0;
306         }
307
308         /* add data space */
309         i = dev->curr_map_offset;
310         map_page = pfn_to_page(*dev->curr_map);
311         map = (unsigned long *)kmap_atomic(map_page, KM_DUMP);
312         map[i] = page_to_pfn(page);
313         kunmap_atomic(map, KM_DUMP);
314         dev->curr_map_offset = ++i;
315         dev->last_offset += PAGE_SIZE;
316         if (i >= DUMP_MAP_SZ) {
317                 /* move to next map */
318                 if (is_last_map_entry(++dev->curr_map)) {
319                         /* move to the next indirect map page */
320                         pr_debug("dump_mem_add_space: using next"
321                         "indirect map\n");
322                         dev->curr_map = (unsigned long *)*dev->curr_map;
323                 }
324         }               
325         return 0;
326 }
327
328
329 /* Caution: making a dest page invalidates existing contents of the page */
330 int dump_check_and_free_page(struct dump_memdev *dev, struct page *page)
331 {
332         int err = 0;
333
334         /* 
335          * the page can be used as a destination only if we are sure
336          * it won't get overwritten by the soft-boot, and is not
337          * critical for us right now.
338          */
339         if (dump_reused_by_boot(page))
340                 return 0;
341
342         if ((err = dump_mem_add_space(dev, page))) {
343                 printk("Warning: Unable to extend memdev space. Err %d\n",
344                 err);
345                 return 0;
346         }
347
348         dev->nr_free++;
349         return 1;
350 }
351
352
353 /* Set up the initial maps and bootstrap space  */
354 /* Must be called only after any previous dump is written out */
355 int dump_mem_open(struct dump_dev *dev, unsigned long devid)
356 {
357         struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
358         unsigned long nr_maps, *map, *prev_map = &dump_mdev->indirect_map_root;
359         void *addr;
360         struct page *page;
361         unsigned long i = 0;
362         int err = 0;
363
364         /* Todo: sanity check for unwritten previous dump */
365
366         /* allocate pages for indirect map (non highmem area) */
367         nr_maps = num_physpages / DUMP_MAP_SZ; /* maps to cover entire mem */
368         for (i = 0; i < nr_maps; i += DUMP_IND_MAP_SZ) {
369                 if (!(map = (unsigned long *)dump_alloc_mem(PAGE_SIZE))) {
370                         printk("Unable to alloc indirect map %ld\n", 
371                                 i / DUMP_IND_MAP_SZ);
372                         return -ENOMEM;
373                 }
374                 clear_page(map);
375                 *prev_map = (unsigned long)map;
376                 prev_map = &map[DUMP_IND_MAP_SZ];
377         };
378                 
379         dump_mdev->curr_map = (unsigned long *)dump_mdev->indirect_map_root;
380         dump_mdev->curr_map_offset = 0; 
381
382         /* 
383          * allocate a few bootstrap pages: at least 1 map and 1 data page
384          * plus enough to save the dump header
385          */
386         i = 0;
387         do {
388                 if (!(addr = dump_alloc_mem(PAGE_SIZE))) {
389                         printk("Unable to alloc bootstrap page %ld\n", i);
390                         return -ENOMEM;
391                 }
392
393                 page = virt_to_page(addr);
394                 if (dump_low_page(page)) {
395                         dump_free_mem(addr);
396                         continue;
397                 }
398
399                 if (dump_mem_add_space(dump_mdev, page)) {
400                         printk("Warning: Unable to extend memdev "
401                                         "space. Err %d\n", err);
402                         dump_free_mem(addr);
403                         continue;
404                 }
405                 i++;
406         } while (i < DUMP_NR_BOOTSTRAP);
407
408         printk("dump memdev init: %ld maps, %ld bootstrap pgs, %ld free pgs\n",
409                 nr_maps, i, dump_mdev->last_offset >> PAGE_SHIFT);
410         
411         dump_mdev->last_bs_offset = dump_mdev->last_offset;
412
413         return 0;
414 }
415
416 /* Releases all pre-alloc'd pages */
417 int dump_mem_release(struct dump_dev *dev)
418 {
419         struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
420         struct page *page, *map_page;
421         unsigned long *map, *prev_map;
422         void *addr;
423         int i;
424
425         if (!dump_mdev->nr_free)
426                 return 0;
427
428         pr_debug("dump_mem_release\n");
429         page = dump_mem_lookup(dump_mdev, 0);
430         for (i = 0; page && (i < DUMP_NR_BOOTSTRAP - 1); i++) {
431                 if (PageHighMem(page))
432                         break;
433                 addr = page_address(page);
434                 if (!addr) {
435                         printk("page_address(%p) = NULL\n", page);
436                         break;
437                 }
438                 pr_debug("Freeing page at 0x%lx\n", addr); 
439                 dump_free_mem(addr);
440                 if (dump_mdev->curr_map_offset >= DUMP_MAP_SZ - 1) {
441                         map_page = pfn_to_page(*dump_mdev->curr_map);
442                         if (PageHighMem(map_page))
443                                 break;
444                         page = dump_mem_next_page(dump_mdev);
445                         addr = page_address(map_page);
446                         if (!addr) {
447                                 printk("page_address(%p) = NULL\n", 
448                                         map_page);
449                                 break;
450                         }
451                         pr_debug("Freeing map page at 0x%lx\n", addr);
452                         dump_free_mem(addr);
453                         i++;
454                 } else {
455                         page = dump_mem_next_page(dump_mdev);
456                 }
457         }
458
459         /* now for the last used bootstrap page used as a map page */
460         if ((i < DUMP_NR_BOOTSTRAP) && (*dump_mdev->curr_map)) {
461                 map_page = pfn_to_page(*dump_mdev->curr_map);
462                 if ((map_page) && !PageHighMem(map_page)) {
463                         addr = page_address(map_page);
464                         if (!addr) {
465                                 printk("page_address(%p) = NULL\n", map_page);
466                         } else {
467                                 pr_debug("Freeing map page at 0x%lx\n", addr);
468                                 dump_free_mem(addr);
469                                 i++;
470                         }
471                 }
472         }
473
474         printk("Freed %d bootstrap pages\n", i);
475
476         /* free the indirect maps */
477         map = (unsigned long *)dump_mdev->indirect_map_root;
478
479         i = 0;
480         while (map) {
481                 prev_map = map;
482                 map = next_indirect_map(map);
483                 dump_free_mem(prev_map);
484                 i++;
485         }
486
487         printk("Freed %d indirect map(s)\n", i);
488
489         /* Reset the indirect map */
490         dump_mdev->indirect_map_root = 0;
491         dump_mdev->curr_map = 0;
492
493         /* Reset the free list */
494         dump_mdev->nr_free = 0;
495
496         dump_mdev->last_offset = dump_mdev->ddev.curr_offset = 0;
497         dump_mdev->last_used_offset = 0;
498         dump_mdev->curr_map = NULL;
499         dump_mdev->curr_map_offset = 0;
500         return 0;
501 }
502
503 /*
504  * Long term:
505  * It is critical for this to be very strict. Cannot afford
506  * to have anything running and accessing memory while we overwrite 
507  * memory (potential risk of data corruption).
508  * If in doubt (e.g if a cpu is hung and not responding) just give
509  * up and refuse to proceed with this scheme.
510  *
511  * Note: I/O will only happen after soft-boot/switchover, so we can 
512  * safely disable interrupts and force stop other CPUs if this is
513  * going to be a disruptive dump, no matter what they
514  * are in the middle of.
515  */
516 /* 
517  * ATM Most of this is already taken care of in the nmi handler 
518  * We may halt the cpus rightaway if we know this is going to be disruptive 
519  * For now, since we've limited ourselves to overwriting free pages we
520  * aren't doing much here. Eventually, we'd have to wait to make sure other
521  * cpus aren't using memory we could be overwriting
522  */
523 int dump_mem_silence(struct dump_dev *dev)
524 {
525         struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
526
527         if (dump_mdev->last_offset > dump_mdev->last_bs_offset) {
528                 /* prefer to run lkcd config & start with a clean slate */
529                 return -EEXIST;
530         }
531         return 0;
532 }
533
534 extern int dump_overlay_resume(void);
535
536 /* Trigger the next stage of dumping */
537 int dump_mem_resume(struct dump_dev *dev)
538 {
539         dump_overlay_resume(); 
540         return 0;
541 }
542
543 /* 
544  * Allocate mem dev pages as required and copy buffer contents into it.
545  * Fails if the no free pages are available
546  * Keeping it simple and limited for starters (can modify this over time)
547  *  Does not handle holes or a sparse layout
548  *  Data must be in multiples of PAGE_SIZE
549  */
550 int dump_mem_write(struct dump_dev *dev, void *buf, unsigned long len)
551 {
552         struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
553         struct page *page;
554         unsigned long n = 0;
555         void *addr;
556         unsigned long *saved_curr_map, saved_map_offset;
557         int ret = 0;
558
559         pr_debug("dump_mem_write: offset 0x%llx, size %ld\n", 
560                 dev->curr_offset, len);
561
562         if (dev->curr_offset + len > dump_mdev->last_offset)  {
563                 printk("Out of space to write\n");
564                 return -ENOSPC;
565         }
566         
567         if ((len & (PAGE_SIZE - 1)) || (dev->curr_offset & (PAGE_SIZE - 1)))
568                 return -EINVAL; /* not aligned in units of page size */
569
570         saved_curr_map = dump_mdev->curr_map;
571         saved_map_offset = dump_mdev->curr_map_offset;
572         page = dump_mem_lookup(dump_mdev, dev->curr_offset >> PAGE_SHIFT);
573
574         for (n = len; (n > 0) && page; n -= PAGE_SIZE, buf += PAGE_SIZE ) {
575                 addr = kmap_atomic(page, KM_DUMP);
576                 /* memset(addr, 'x', PAGE_SIZE); */
577                 memcpy(addr, buf, PAGE_SIZE);
578                 kunmap_atomic(addr, KM_DUMP);
579                 /* dev->curr_offset += PAGE_SIZE; */
580                 page = dump_mem_next_page(dump_mdev);
581         }
582
583         dump_mdev->curr_map = saved_curr_map;
584         dump_mdev->curr_map_offset = saved_map_offset;
585
586         if (dump_mdev->last_used_offset < dev->curr_offset)
587                 dump_mdev->last_used_offset = dev->curr_offset;
588
589         return (len - n) ? (len - n) : ret ;
590 }
591
592 /* dummy - always ready */
593 int dump_mem_ready(struct dump_dev *dev, void *buf)
594 {
595         return 0;
596 }
597
598 /* 
599  * Should check for availability of space to write upto the offset 
600  * affects only the curr_offset; last_offset untouched 
601  * Keep it simple: Only allow multiples of PAGE_SIZE for now 
602  */
603 int dump_mem_seek(struct dump_dev *dev, loff_t offset)
604 {
605         struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
606
607         if (offset & (PAGE_SIZE - 1))
608                 return -EINVAL; /* allow page size units only for now */
609         
610         /* Are we exceeding available space ? */
611         if (offset > dump_mdev->last_offset) {
612                 printk("dump_mem_seek failed for offset 0x%llx\n",
613                         offset);
614                 return -ENOSPC; 
615         }
616
617         dump_mdev->ddev.curr_offset = offset;
618         return 0;
619 }
620
621 struct dump_dev_ops dump_memdev_ops = {
622         .open           = dump_mem_open,
623         .release        = dump_mem_release,
624         .silence        = dump_mem_silence,
625         .resume         = dump_mem_resume,
626         .seek           = dump_mem_seek,
627         .write          = dump_mem_write,
628         .read           = NULL, /* not implemented at the moment */
629         .ready          = dump_mem_ready
630 };
631
632 static struct dump_memdev default_dump_memdev = {
633         .ddev = {.type_name = "memdev", .ops = &dump_memdev_ops,
634                  .device_id = 0x14}
635         /* assume the rest of the fields are zeroed by default */
636 };      
637         
638 /* may be overwritten if a previous dump exists */
639 struct dump_memdev *dump_memdev = &default_dump_memdev;
640