diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-06 15:59:59 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-06 15:59:59 -0500 |
commit | ccf18968b1bbc2fb117190a1984ac2a826dac228 (patch) | |
tree | 7bc8fbf5722aecf1e84fa50c31c657864cba1daa /arch/i386/mm | |
parent | e91c021c487110386a07facd0396e6c3b7cf9c1f (diff) | |
parent | d99cf9d679a520d67f81d805b7cb91c68e1847f0 (diff) |
Merge ../torvalds-2.6/
Diffstat (limited to 'arch/i386/mm')
-rw-r--r-- | arch/i386/mm/init.c | 24 | ||||
-rw-r--r-- | arch/i386/mm/pageattr.c | 27 |
2 files changed, 45 insertions, 6 deletions
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 06e26f006238..7df494b51a5b 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -735,6 +735,30 @@ void free_initmem(void) | |||
735 | printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); | 735 | printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); |
736 | } | 736 | } |
737 | 737 | ||
738 | #ifdef CONFIG_DEBUG_RODATA | ||
739 | |||
740 | extern char __start_rodata, __end_rodata; | ||
741 | void mark_rodata_ro(void) | ||
742 | { | ||
743 | unsigned long addr = (unsigned long)&__start_rodata; | ||
744 | |||
745 | for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) | ||
746 | change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO); | ||
747 | |||
748 | printk ("Write protecting the kernel read-only data: %luk\n", | ||
749 | (unsigned long)(&__end_rodata - &__start_rodata) >> 10); | ||
750 | |||
751 | /* | ||
752 | * change_page_attr() requires a global_flush_tlb() call after it. | ||
753 | * We do this after the printk so that if something went wrong in the | ||
754 | * change, the printk gets out at least to give a better debug hint | ||
755 | * of who is the culprit. | ||
756 | */ | ||
757 | global_flush_tlb(); | ||
758 | } | ||
759 | #endif | ||
760 | |||
761 | |||
738 | #ifdef CONFIG_BLK_DEV_INITRD | 762 | #ifdef CONFIG_BLK_DEV_INITRD |
739 | void free_initrd_mem(unsigned long start, unsigned long end) | 763 | void free_initrd_mem(unsigned long start, unsigned long end) |
740 | { | 764 | { |
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index f600fc244f02..c30a16df6440 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/processor.h> | 13 | #include <asm/processor.h> |
14 | #include <asm/tlbflush.h> | 14 | #include <asm/tlbflush.h> |
15 | #include <asm/pgalloc.h> | 15 | #include <asm/pgalloc.h> |
16 | #include <asm/sections.h> | ||
16 | 17 | ||
17 | static DEFINE_SPINLOCK(cpa_lock); | 18 | static DEFINE_SPINLOCK(cpa_lock); |
18 | static struct list_head df_list = LIST_HEAD_INIT(df_list); | 19 | static struct list_head df_list = LIST_HEAD_INIT(df_list); |
@@ -36,7 +37,8 @@ pte_t *lookup_address(unsigned long address) | |||
36 | return pte_offset_kernel(pmd, address); | 37 | return pte_offset_kernel(pmd, address); |
37 | } | 38 | } |
38 | 39 | ||
39 | static struct page *split_large_page(unsigned long address, pgprot_t prot) | 40 | static struct page *split_large_page(unsigned long address, pgprot_t prot, |
41 | pgprot_t ref_prot) | ||
40 | { | 42 | { |
41 | int i; | 43 | int i; |
42 | unsigned long addr; | 44 | unsigned long addr; |
@@ -54,7 +56,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot) | |||
54 | pbase = (pte_t *)page_address(base); | 56 | pbase = (pte_t *)page_address(base); |
55 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { | 57 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { |
56 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, | 58 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, |
57 | addr == address ? prot : PAGE_KERNEL)); | 59 | addr == address ? prot : ref_prot)); |
58 | } | 60 | } |
59 | return base; | 61 | return base; |
60 | } | 62 | } |
@@ -98,11 +100,18 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) | |||
98 | */ | 100 | */ |
99 | static inline void revert_page(struct page *kpte_page, unsigned long address) | 101 | static inline void revert_page(struct page *kpte_page, unsigned long address) |
100 | { | 102 | { |
101 | pte_t *linear = (pte_t *) | 103 | pgprot_t ref_prot; |
104 | pte_t *linear; | ||
105 | |||
106 | ref_prot = | ||
107 | ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) | ||
108 | ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE; | ||
109 | |||
110 | linear = (pte_t *) | ||
102 | pmd_offset(pud_offset(pgd_offset_k(address), address), address); | 111 | pmd_offset(pud_offset(pgd_offset_k(address), address), address); |
103 | set_pmd_pte(linear, address, | 112 | set_pmd_pte(linear, address, |
104 | pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, | 113 | pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, |
105 | PAGE_KERNEL_LARGE)); | 114 | ref_prot)); |
106 | } | 115 | } |
107 | 116 | ||
108 | static int | 117 | static int |
@@ -123,10 +132,16 @@ __change_page_attr(struct page *page, pgprot_t prot) | |||
123 | if ((pte_val(*kpte) & _PAGE_PSE) == 0) { | 132 | if ((pte_val(*kpte) & _PAGE_PSE) == 0) { |
124 | set_pte_atomic(kpte, mk_pte(page, prot)); | 133 | set_pte_atomic(kpte, mk_pte(page, prot)); |
125 | } else { | 134 | } else { |
126 | struct page *split = split_large_page(address, prot); | 135 | pgprot_t ref_prot; |
136 | struct page *split; | ||
137 | |||
138 | ref_prot = | ||
139 | ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) | ||
140 | ? PAGE_KERNEL_EXEC : PAGE_KERNEL; | ||
141 | split = split_large_page(address, prot, ref_prot); | ||
127 | if (!split) | 142 | if (!split) |
128 | return -ENOMEM; | 143 | return -ENOMEM; |
129 | set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL)); | 144 | set_pmd_pte(kpte,address,mk_pte(split, ref_prot)); |
130 | kpte_page = split; | 145 | kpte_page = split; |
131 | } | 146 | } |
132 | get_page(kpte_page); | 147 | get_page(kpte_page); |