Pekka Enberg | e5b2bb5 | 2009-03-03 13:15:06 +0200 | [diff] [blame] | 1 | #include <linux/swap.h> |
| 2 | #include <asm/cacheflush.h> |
| 3 | #include <asm/page.h> |
| 4 | #include <asm/sections.h> |
| 5 | #include <asm/system.h> |
| 6 | |
| 7 | void free_init_pages(char *what, unsigned long begin, unsigned long end) |
| 8 | { |
| 9 | unsigned long addr = begin; |
| 10 | |
| 11 | if (addr >= end) |
| 12 | return; |
| 13 | |
| 14 | /* |
| 15 | * If debugging page accesses then do not free this memory but |
| 16 | * mark them not present - any buggy init-section access will |
| 17 | * create a kernel page fault: |
| 18 | */ |
| 19 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 20 | printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", |
| 21 | begin, PAGE_ALIGN(end)); |
| 22 | set_memory_np(begin, (end - begin) >> PAGE_SHIFT); |
| 23 | #else |
| 24 | /* |
| 25 | * We just marked the kernel text read only above, now that |
| 26 | * we are going to free part of that, we need to make that |
| 27 | * writeable first. |
| 28 | */ |
| 29 | set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); |
| 30 | |
| 31 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); |
| 32 | |
| 33 | for (; addr < end; addr += PAGE_SIZE) { |
| 34 | ClearPageReserved(virt_to_page(addr)); |
| 35 | init_page_count(virt_to_page(addr)); |
| 36 | memset((void *)(addr & ~(PAGE_SIZE-1)), |
| 37 | POISON_FREE_INITMEM, PAGE_SIZE); |
| 38 | free_page(addr); |
| 39 | totalram_pages++; |
| 40 | } |
| 41 | #endif |
| 42 | } |
| 43 | |
| 44 | void free_initmem(void) |
| 45 | { |
| 46 | free_init_pages("unused kernel memory", |
| 47 | (unsigned long)(&__init_begin), |
| 48 | (unsigned long)(&__init_end)); |
| 49 | } |