Pekka Enberg | 540aca0 | 2009-03-04 11:46:40 +0200 | [diff] [blame] | 1 | #include <linux/ioport.h> |
Pekka Enberg | e5b2bb5 | 2009-03-03 13:15:06 +0200 | [diff] [blame] | 2 | #include <linux/swap.h> |
Pekka Enberg | 540aca0 | 2009-03-04 11:46:40 +0200 | [diff] [blame] | 3 | |
Pekka Enberg | e5b2bb5 | 2009-03-03 13:15:06 +0200 | [diff] [blame] | 4 | #include <asm/cacheflush.h> |
| 5 | #include <asm/page.h> |
Pekka Enberg | 540aca0 | 2009-03-04 11:46:40 +0200 | [diff] [blame] | 6 | #include <asm/page_types.h> |
Pekka Enberg | e5b2bb5 | 2009-03-03 13:15:06 +0200 | [diff] [blame] | 7 | #include <asm/sections.h> |
| 8 | #include <asm/system.h> |
| 9 | |
Pekka Enberg | 540aca0 | 2009-03-04 11:46:40 +0200 | [diff] [blame] | 10 | /* |
| 11 | * devmem_is_allowed() checks to see if /dev/mem access to a certain address |
| 12 | * is valid. The argument is a physical page number. |
| 13 | * |
| 14 | * |
| 15 | * On x86, access has to be given to the first megabyte of ram because that area |
| 16 | * contains bios code and data regions used by X and dosemu and similar apps. |
| 17 | * Access has to be given to non-kernel-ram areas as well, these contain the PCI |
| 18 | * mmio resources as well as potential bios/acpi data regions. |
| 19 | */ |
| 20 | int devmem_is_allowed(unsigned long pagenr) |
| 21 | { |
| 22 | if (pagenr <= 256) |
| 23 | return 1; |
| 24 | if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) |
| 25 | return 0; |
| 26 | if (!page_is_ram(pagenr)) |
| 27 | return 1; |
| 28 | return 0; |
| 29 | } |
| 30 | |
Pekka Enberg | e5b2bb5 | 2009-03-03 13:15:06 +0200 | [diff] [blame] | 31 | void free_init_pages(char *what, unsigned long begin, unsigned long end) |
| 32 | { |
| 33 | unsigned long addr = begin; |
| 34 | |
| 35 | if (addr >= end) |
| 36 | return; |
| 37 | |
| 38 | /* |
| 39 | * If debugging page accesses then do not free this memory but |
| 40 | * mark them not present - any buggy init-section access will |
| 41 | * create a kernel page fault: |
| 42 | */ |
| 43 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 44 | printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", |
| 45 | begin, PAGE_ALIGN(end)); |
| 46 | set_memory_np(begin, (end - begin) >> PAGE_SHIFT); |
| 47 | #else |
| 48 | /* |
| 49 | * We just marked the kernel text read only above, now that |
| 50 | * we are going to free part of that, we need to make that |
| 51 | * writeable first. |
| 52 | */ |
| 53 | set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); |
| 54 | |
| 55 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); |
| 56 | |
| 57 | for (; addr < end; addr += PAGE_SIZE) { |
| 58 | ClearPageReserved(virt_to_page(addr)); |
| 59 | init_page_count(virt_to_page(addr)); |
| 60 | memset((void *)(addr & ~(PAGE_SIZE-1)), |
| 61 | POISON_FREE_INITMEM, PAGE_SIZE); |
| 62 | free_page(addr); |
| 63 | totalram_pages++; |
| 64 | } |
| 65 | #endif |
| 66 | } |
| 67 | |
| 68 | void free_initmem(void) |
| 69 | { |
| 70 | free_init_pages("unused kernel memory", |
| 71 | (unsigned long)(&__init_begin), |
| 72 | (unsigned long)(&__init_end)); |
| 73 | } |
Pekka Enberg | 731ddea | 2009-03-04 11:13:40 +0200 | [diff] [blame^] | 74 | |
| 75 | #ifdef CONFIG_BLK_DEV_INITRD |
| 76 | void free_initrd_mem(unsigned long start, unsigned long end) |
| 77 | { |
| 78 | free_init_pages("initrd memory", start, end); |
| 79 | } |
| 80 | #endif |