diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 16:07:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 16:07:55 -0400 |
commit | b278240839e20fa9384ea430df463b367b90e04e (patch) | |
tree | f99f0c8cdd4cc7f177cd75440e6bd181cded7fb3 /arch/x86_64/mm/pageattr.c | |
parent | dd77a4ee0f3981693d4229aa1d57cea9e526ff47 (diff) | |
parent | 3f75f42d7733e73aca5c78326489efd4189e0111 (diff) |
Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: (225 commits)
[PATCH] Don't set calgary iommu as default y
[PATCH] i386/x86-64: New Intel feature flags
[PATCH] x86: Add a cumulative thermal throttle event counter.
[PATCH] i386: Make the jiffies compares use the 64bit safe macros.
[PATCH] x86: Refactor thermal throttle processing
[PATCH] Add 64bit jiffies compares (for use with get_jiffies_64)
[PATCH] Fix unwinder warning in traps.c
[PATCH] x86: Allow disabling early pci scans with pci=noearly or disallowing conf1
[PATCH] x86: Move direct PCI scanning functions out of line
[PATCH] i386/x86-64: Make all early PCI scans dependent on CONFIG_PCI
[PATCH] Don't leak NT bit into next task
[PATCH] i386/x86-64: Work around gcc bug with noreturn functions in unwinder
[PATCH] Fix some broken white space in ia32_signal.c
[PATCH] Initialize argument registers for 32bit signal handlers.
[PATCH] Remove all traces of signal number conversion
[PATCH] Don't synchronize time reading on single core AMD systems
[PATCH] Remove outdated comment in x86-64 mmconfig code
[PATCH] Use string instructions for Core2 copy/clear
[PATCH] x86: - restore i8259A eoi status on resume
[PATCH] i386: Split multi-line printk in oops output.
...
Diffstat (limited to 'arch/x86_64/mm/pageattr.c')
-rw-r--r-- | arch/x86_64/mm/pageattr.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 2685b1f3671c..3e231d762aaa 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c | |||
@@ -108,8 +108,8 @@ static void revert_page(unsigned long address, pgprot_t ref_prot) | |||
108 | BUG_ON(pud_none(*pud)); | 108 | BUG_ON(pud_none(*pud)); |
109 | pmd = pmd_offset(pud, address); | 109 | pmd = pmd_offset(pud, address); |
110 | BUG_ON(pmd_val(*pmd) & _PAGE_PSE); | 110 | BUG_ON(pmd_val(*pmd) & _PAGE_PSE); |
111 | pgprot_val(ref_prot) |= _PAGE_PSE; | ||
112 | large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot); | 111 | large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot); |
112 | large_pte = pte_mkhuge(large_pte); | ||
113 | set_pte((pte_t *)pmd, large_pte); | 113 | set_pte((pte_t *)pmd, large_pte); |
114 | } | 114 | } |
115 | 115 | ||
@@ -119,32 +119,28 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, | |||
119 | { | 119 | { |
120 | pte_t *kpte; | 120 | pte_t *kpte; |
121 | struct page *kpte_page; | 121 | struct page *kpte_page; |
122 | unsigned kpte_flags; | ||
123 | pgprot_t ref_prot2; | 122 | pgprot_t ref_prot2; |
124 | kpte = lookup_address(address); | 123 | kpte = lookup_address(address); |
125 | if (!kpte) return 0; | 124 | if (!kpte) return 0; |
126 | kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); | 125 | kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); |
127 | kpte_flags = pte_val(*kpte); | ||
128 | if (pgprot_val(prot) != pgprot_val(ref_prot)) { | 126 | if (pgprot_val(prot) != pgprot_val(ref_prot)) { |
129 | if ((kpte_flags & _PAGE_PSE) == 0) { | 127 | if (!pte_huge(*kpte)) { |
130 | set_pte(kpte, pfn_pte(pfn, prot)); | 128 | set_pte(kpte, pfn_pte(pfn, prot)); |
131 | } else { | 129 | } else { |
132 | /* | 130 | /* |
133 | * split_large_page will take the reference for this | 131 | * split_large_page will take the reference for this |
134 | * change_page_attr on the split page. | 132 | * change_page_attr on the split page. |
135 | */ | 133 | */ |
136 | |||
137 | struct page *split; | 134 | struct page *split; |
138 | ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE)); | 135 | ref_prot2 = pte_pgprot(pte_clrhuge(*kpte)); |
139 | |||
140 | split = split_large_page(address, prot, ref_prot2); | 136 | split = split_large_page(address, prot, ref_prot2); |
141 | if (!split) | 137 | if (!split) |
142 | return -ENOMEM; | 138 | return -ENOMEM; |
143 | set_pte(kpte,mk_pte(split, ref_prot2)); | 139 | set_pte(kpte, mk_pte(split, ref_prot2)); |
144 | kpte_page = split; | 140 | kpte_page = split; |
145 | } | 141 | } |
146 | page_private(kpte_page)++; | 142 | page_private(kpte_page)++; |
147 | } else if ((kpte_flags & _PAGE_PSE) == 0) { | 143 | } else if (!pte_huge(*kpte)) { |
148 | set_pte(kpte, pfn_pte(pfn, ref_prot)); | 144 | set_pte(kpte, pfn_pte(pfn, ref_prot)); |
149 | BUG_ON(page_private(kpte_page) == 0); | 145 | BUG_ON(page_private(kpte_page) == 0); |
150 | page_private(kpte_page)--; | 146 | page_private(kpte_page)--; |
@@ -190,10 +186,12 @@ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot) | |||
190 | * lowmem */ | 186 | * lowmem */ |
191 | if (__pa(address) < KERNEL_TEXT_SIZE) { | 187 | if (__pa(address) < KERNEL_TEXT_SIZE) { |
192 | unsigned long addr2; | 188 | unsigned long addr2; |
193 | pgprot_t prot2 = prot; | 189 | pgprot_t prot2; |
194 | addr2 = __START_KERNEL_map + __pa(address); | 190 | addr2 = __START_KERNEL_map + __pa(address); |
195 | pgprot_val(prot2) &= ~_PAGE_NX; | 191 | /* Make sure the kernel mappings stay executable */ |
196 | err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC); | 192 | prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot))); |
193 | err = __change_page_attr(addr2, pfn, prot2, | ||
194 | PAGE_KERNEL_EXEC); | ||
197 | } | 195 | } |
198 | } | 196 | } |
199 | up_write(&init_mm.mmap_sem); | 197 | up_write(&init_mm.mmap_sem); |