diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-22 15:38:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-22 15:38:40 -0400 |
commit | 17238005f377888b9d4583835205c77e3d781bb8 (patch) | |
tree | 9cad40902138d08a2694f87736cfebd031dc9542 /arch | |
parent | 34ea646c9f8c18fd2e4332ff3b2b509f878c56f1 (diff) | |
parent | 7fe2ac6882f74e8bd5b3891f63c09cb10aee9d03 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6:
[PARISC] wire up syncfs syscall
[PARISC] wire up the fhandle syscalls
[PARISC] wire up clock_adjtime syscall
[PARISC] wire up fanotify syscalls
[PARISC] prevent speculative re-read on cache flush
[PARISC] only make executable areas executable
[PARISC] fix pacache .size with new binutils
Diffstat (limited to 'arch')
-rw-r--r-- | arch/parisc/include/asm/cacheflush.h | 5 | ||||
-rw-r--r-- | arch/parisc/include/asm/pgtable.h | 9 | ||||
-rw-r--r-- | arch/parisc/include/asm/unistd.h | 10 | ||||
-rw-r--r-- | arch/parisc/kernel/cache.c | 13 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 3 | ||||
-rw-r--r-- | arch/parisc/kernel/head.S | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/module.c | 10 | ||||
-rw-r--r-- | arch/parisc/kernel/pacache.S | 6 | ||||
-rw-r--r-- | arch/parisc/kernel/sys_parisc32.c | 8 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall_table.S | 6 | ||||
-rw-r--r-- | arch/parisc/kernel/vmlinux.lds.S | 1 | ||||
-rw-r--r-- | arch/parisc/mm/init.c | 260 |
12 files changed, 206 insertions, 130 deletions
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index d18328b3f93..da601dd34c0 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
5 | #include <linux/uaccess.h> | 5 | #include <linux/uaccess.h> |
6 | #include <asm/tlbflush.h> | ||
6 | 7 | ||
7 | /* The usual comment is "Caches aren't brain-dead on the <architecture>". | 8 | /* The usual comment is "Caches aren't brain-dead on the <architecture>". |
8 | * Unfortunately, that doesn't apply to PA-RISC. */ | 9 | * Unfortunately, that doesn't apply to PA-RISC. */ |
@@ -112,8 +113,10 @@ void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); | |||
112 | static inline void | 113 | static inline void |
113 | flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) | 114 | flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) |
114 | { | 115 | { |
115 | if (PageAnon(page)) | 116 | if (PageAnon(page)) { |
117 | flush_tlb_page(vma, vmaddr); | ||
116 | flush_dcache_page_asm(page_to_phys(page), vmaddr); | 118 | flush_dcache_page_asm(page_to_phys(page), vmaddr); |
119 | } | ||
117 | } | 120 | } |
118 | 121 | ||
119 | #ifdef CONFIG_DEBUG_RODATA | 122 | #ifdef CONFIG_DEBUG_RODATA |
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 5d7b8ce9fdf..22dadeb5869 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
@@ -177,7 +177,10 @@ struct vm_area_struct; | |||
177 | 177 | ||
178 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED) | 178 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED) |
179 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 179 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) |
180 | #define _PAGE_KERNEL (_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED) | 180 | #define _PAGE_KERNEL_RO (_PAGE_PRESENT | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED) |
181 | #define _PAGE_KERNEL_EXEC (_PAGE_KERNEL_RO | _PAGE_EXEC) | ||
182 | #define _PAGE_KERNEL_RWX (_PAGE_KERNEL_EXEC | _PAGE_WRITE) | ||
183 | #define _PAGE_KERNEL (_PAGE_KERNEL_RO | _PAGE_WRITE) | ||
181 | 184 | ||
182 | /* The pgd/pmd contains a ptr (in phys addr space); since all pgds/pmds | 185 | /* The pgd/pmd contains a ptr (in phys addr space); since all pgds/pmds |
183 | * are page-aligned, we don't care about the PAGE_OFFSET bits, except | 186 | * are page-aligned, we don't care about the PAGE_OFFSET bits, except |
@@ -208,7 +211,9 @@ struct vm_area_struct; | |||
208 | #define PAGE_COPY PAGE_EXECREAD | 211 | #define PAGE_COPY PAGE_EXECREAD |
209 | #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) | 212 | #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) |
210 | #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) | 213 | #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) |
211 | #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) | 214 | #define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL_EXEC) |
215 | #define PAGE_KERNEL_RWX __pgprot(_PAGE_KERNEL_RWX) | ||
216 | #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL_RO) | ||
212 | #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) | 217 | #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) |
213 | #define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) | 218 | #define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) |
214 | 219 | ||
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 3eb82c2a5ec..9cbc2c3bf63 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h | |||
@@ -814,8 +814,14 @@ | |||
814 | #define __NR_recvmmsg (__NR_Linux + 319) | 814 | #define __NR_recvmmsg (__NR_Linux + 319) |
815 | #define __NR_accept4 (__NR_Linux + 320) | 815 | #define __NR_accept4 (__NR_Linux + 320) |
816 | #define __NR_prlimit64 (__NR_Linux + 321) | 816 | #define __NR_prlimit64 (__NR_Linux + 321) |
817 | 817 | #define __NR_fanotify_init (__NR_Linux + 322) | |
818 | #define __NR_Linux_syscalls (__NR_prlimit64 + 1) | 818 | #define __NR_fanotify_mark (__NR_Linux + 323) |
819 | #define __NR_clock_adjtime (__NR_Linux + 324) | ||
820 | #define __NR_name_to_handle_at (__NR_Linux + 325) | ||
821 | #define __NR_open_by_handle_at (__NR_Linux + 326) | ||
822 | #define __NR_syncfs (__NR_Linux + 327) | ||
823 | |||
824 | #define __NR_Linux_syscalls (__NR_syncfs + 1) | ||
819 | 825 | ||
820 | 826 | ||
821 | #define __IGNORE_select /* newselect */ | 827 | #define __IGNORE_select /* newselect */ |
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 3f11331c277..83335f3da5f 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
@@ -304,10 +304,20 @@ void flush_dcache_page(struct page *page) | |||
304 | offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; | 304 | offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; |
305 | addr = mpnt->vm_start + offset; | 305 | addr = mpnt->vm_start + offset; |
306 | 306 | ||
307 | /* The TLB is the engine of coherence on parisc: The | ||
308 | * CPU is entitled to speculate any page with a TLB | ||
309 | * mapping, so here we kill the mapping then flush the | ||
310 | * page along a special flush only alias mapping. | ||
311 | * This guarantees that the page is no-longer in the | ||
312 | * cache for any process and nor may it be | ||
313 | * speculatively read in (until the user or kernel | ||
314 | * specifically accesses it, of course) */ | ||
315 | |||
316 | flush_tlb_page(mpnt, addr); | ||
307 | if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { | 317 | if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { |
308 | __flush_cache_page(mpnt, addr, page_to_phys(page)); | 318 | __flush_cache_page(mpnt, addr, page_to_phys(page)); |
309 | if (old_addr) | 319 | if (old_addr) |
310 | printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); | 320 | printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); |
311 | old_addr = addr; | 321 | old_addr = addr; |
312 | } | 322 | } |
313 | } | 323 | } |
@@ -499,6 +509,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long | |||
499 | { | 509 | { |
500 | BUG_ON(!vma->vm_mm->context); | 510 | BUG_ON(!vma->vm_mm->context); |
501 | 511 | ||
512 | flush_tlb_page(vma, vmaddr); | ||
502 | __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); | 513 | __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); |
503 | 514 | ||
504 | } | 515 | } |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index ead8d2a1034..6f059443914 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -692,6 +692,9 @@ ENTRY(fault_vector_11) | |||
692 | END(fault_vector_11) | 692 | END(fault_vector_11) |
693 | 693 | ||
694 | #endif | 694 | #endif |
695 | /* Fault vector is separately protected and *must* be on its own page */ | ||
696 | .align PAGE_SIZE | ||
697 | ENTRY(end_fault_vector) | ||
695 | 698 | ||
696 | .import handle_interruption,code | 699 | .import handle_interruption,code |
697 | .import do_cpu_irq_mask,code | 700 | .import do_cpu_irq_mask,code |
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index 145c5e4caaa..37aabd772fb 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S | |||
@@ -106,8 +106,9 @@ $bss_loop: | |||
106 | #endif | 106 | #endif |
107 | 107 | ||
108 | 108 | ||
109 | /* Now initialize the PTEs themselves */ | 109 | /* Now initialize the PTEs themselves. We use RWX for |
110 | ldo 0+_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */ | 110 | * everything ... it will get remapped correctly later */ |
111 | ldo 0+_PAGE_KERNEL_RWX(%r0),%r3 /* Hardwired 0 phys addr start */ | ||
111 | ldi (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */ | 112 | ldi (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */ |
112 | load32 PA(pg0),%r1 | 113 | load32 PA(pg0),%r1 |
113 | 114 | ||
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 6e81bb596e5..cedbbb8b18d 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
@@ -61,8 +61,10 @@ | |||
61 | #include <linux/string.h> | 61 | #include <linux/string.h> |
62 | #include <linux/kernel.h> | 62 | #include <linux/kernel.h> |
63 | #include <linux/bug.h> | 63 | #include <linux/bug.h> |
64 | #include <linux/mm.h> | ||
64 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
65 | 66 | ||
67 | #include <asm/pgtable.h> | ||
66 | #include <asm/unwind.h> | 68 | #include <asm/unwind.h> |
67 | 69 | ||
68 | #if 0 | 70 | #if 0 |
@@ -214,7 +216,13 @@ void *module_alloc(unsigned long size) | |||
214 | { | 216 | { |
215 | if (size == 0) | 217 | if (size == 0) |
216 | return NULL; | 218 | return NULL; |
217 | return vmalloc(size); | 219 | /* using RWX means less protection for modules, but it's |
220 | * easier than trying to map the text, data, init_text and | ||
221 | * init_data correctly */ | ||
222 | return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END, | ||
223 | GFP_KERNEL | __GFP_HIGHMEM, | ||
224 | PAGE_KERNEL_RWX, -1, | ||
225 | __builtin_return_address(0)); | ||
218 | } | 226 | } |
219 | 227 | ||
220 | #ifndef CONFIG_64BIT | 228 | #ifndef CONFIG_64BIT |
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index a85823668cb..93ff3d90edd 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S | |||
@@ -817,10 +817,7 @@ ENTRY(purge_kernel_dcache_page) | |||
817 | .procend | 817 | .procend |
818 | ENDPROC(purge_kernel_dcache_page) | 818 | ENDPROC(purge_kernel_dcache_page) |
819 | 819 | ||
820 | 820 | ENTRY(flush_user_dcache_range_asm) | |
821 | .export flush_user_dcache_range_asm | ||
822 | |||
823 | flush_user_dcache_range_asm: | ||
824 | .proc | 821 | .proc |
825 | .callinfo NO_CALLS | 822 | .callinfo NO_CALLS |
826 | .entry | 823 | .entry |
@@ -839,6 +836,7 @@ flush_user_dcache_range_asm: | |||
839 | .exit | 836 | .exit |
840 | 837 | ||
841 | .procend | 838 | .procend |
839 | ENDPROC(flush_user_dcache_range_asm) | ||
842 | 840 | ||
843 | ENTRY(flush_kernel_dcache_range_asm) | 841 | ENTRY(flush_kernel_dcache_range_asm) |
844 | .proc | 842 | .proc |
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 88a0ad14a9c..dc9a6246232 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c | |||
@@ -228,3 +228,11 @@ asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo, | |||
228 | return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo, | 228 | return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo, |
229 | ((loff_t)lenhi << 32) | lenlo); | 229 | ((loff_t)lenhi << 32) | lenlo); |
230 | } | 230 | } |
231 | |||
232 | asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi, | ||
233 | u32 mask_lo, int fd, | ||
234 | const char __user *pathname) | ||
235 | { | ||
236 | return sys_fanotify_mark(fan_fd, flags, ((u64)mask_hi << 32) | mask_lo, | ||
237 | fd, pathname); | ||
238 | } | ||
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 4be85ee10b8..a5b02ce4d41 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S | |||
@@ -420,6 +420,12 @@ | |||
420 | ENTRY_COMP(recvmmsg) | 420 | ENTRY_COMP(recvmmsg) |
421 | ENTRY_SAME(accept4) /* 320 */ | 421 | ENTRY_SAME(accept4) /* 320 */ |
422 | ENTRY_SAME(prlimit64) | 422 | ENTRY_SAME(prlimit64) |
423 | ENTRY_SAME(fanotify_init) | ||
424 | ENTRY_COMP(fanotify_mark) | ||
425 | ENTRY_COMP(clock_adjtime) | ||
426 | ENTRY_SAME(name_to_handle_at) /* 325 */ | ||
427 | ENTRY_COMP(open_by_handle_at) | ||
428 | ENTRY_SAME(syncfs) | ||
423 | 429 | ||
424 | /* Nothing yet */ | 430 | /* Nothing yet */ |
425 | 431 | ||
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 2d9a5c7c76f..e1a55849bfa 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -137,6 +137,7 @@ SECTIONS | |||
137 | . = ALIGN(16384); | 137 | . = ALIGN(16384); |
138 | __init_begin = .; | 138 | __init_begin = .; |
139 | INIT_TEXT_SECTION(16384) | 139 | INIT_TEXT_SECTION(16384) |
140 | . = ALIGN(PAGE_SIZE); | ||
140 | INIT_DATA_SECTION(16) | 141 | INIT_DATA_SECTION(16) |
141 | /* we have to discard exit text and such at runtime, not link time */ | 142 | /* we have to discard exit text and such at runtime, not link time */ |
142 | .exit.text : | 143 | .exit.text : |
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index b1d126258de..5fa1e273006 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
@@ -371,24 +371,158 @@ static void __init setup_bootmem(void) | |||
371 | request_resource(&sysram_resources[0], &pdcdata_resource); | 371 | request_resource(&sysram_resources[0], &pdcdata_resource); |
372 | } | 372 | } |
373 | 373 | ||
374 | static void __init map_pages(unsigned long start_vaddr, | ||
375 | unsigned long start_paddr, unsigned long size, | ||
376 | pgprot_t pgprot, int force) | ||
377 | { | ||
378 | pgd_t *pg_dir; | ||
379 | pmd_t *pmd; | ||
380 | pte_t *pg_table; | ||
381 | unsigned long end_paddr; | ||
382 | unsigned long start_pmd; | ||
383 | unsigned long start_pte; | ||
384 | unsigned long tmp1; | ||
385 | unsigned long tmp2; | ||
386 | unsigned long address; | ||
387 | unsigned long vaddr; | ||
388 | unsigned long ro_start; | ||
389 | unsigned long ro_end; | ||
390 | unsigned long fv_addr; | ||
391 | unsigned long gw_addr; | ||
392 | extern const unsigned long fault_vector_20; | ||
393 | extern void * const linux_gateway_page; | ||
394 | |||
395 | ro_start = __pa((unsigned long)_text); | ||
396 | ro_end = __pa((unsigned long)&data_start); | ||
397 | fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK; | ||
398 | gw_addr = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK; | ||
399 | |||
400 | end_paddr = start_paddr + size; | ||
401 | |||
402 | pg_dir = pgd_offset_k(start_vaddr); | ||
403 | |||
404 | #if PTRS_PER_PMD == 1 | ||
405 | start_pmd = 0; | ||
406 | #else | ||
407 | start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); | ||
408 | #endif | ||
409 | start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); | ||
410 | |||
411 | address = start_paddr; | ||
412 | vaddr = start_vaddr; | ||
413 | while (address < end_paddr) { | ||
414 | #if PTRS_PER_PMD == 1 | ||
415 | pmd = (pmd_t *)__pa(pg_dir); | ||
416 | #else | ||
417 | pmd = (pmd_t *)pgd_address(*pg_dir); | ||
418 | |||
419 | /* | ||
420 | * pmd is physical at this point | ||
421 | */ | ||
422 | |||
423 | if (!pmd) { | ||
424 | pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0), PAGE_SIZE << PMD_ORDER); | ||
425 | pmd = (pmd_t *) __pa(pmd); | ||
426 | } | ||
427 | |||
428 | pgd_populate(NULL, pg_dir, __va(pmd)); | ||
429 | #endif | ||
430 | pg_dir++; | ||
431 | |||
432 | /* now change pmd to kernel virtual addresses */ | ||
433 | |||
434 | pmd = (pmd_t *)__va(pmd) + start_pmd; | ||
435 | for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++, pmd++) { | ||
436 | |||
437 | /* | ||
438 | * pg_table is physical at this point | ||
439 | */ | ||
440 | |||
441 | pg_table = (pte_t *)pmd_address(*pmd); | ||
442 | if (!pg_table) { | ||
443 | pg_table = (pte_t *) | ||
444 | alloc_bootmem_low_pages_node(NODE_DATA(0), PAGE_SIZE); | ||
445 | pg_table = (pte_t *) __pa(pg_table); | ||
446 | } | ||
447 | |||
448 | pmd_populate_kernel(NULL, pmd, __va(pg_table)); | ||
449 | |||
450 | /* now change pg_table to kernel virtual addresses */ | ||
451 | |||
452 | pg_table = (pte_t *) __va(pg_table) + start_pte; | ||
453 | for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++, pg_table++) { | ||
454 | pte_t pte; | ||
455 | |||
456 | /* | ||
457 | * Map the fault vector writable so we can | ||
458 | * write the HPMC checksum. | ||
459 | */ | ||
460 | if (force) | ||
461 | pte = __mk_pte(address, pgprot); | ||
462 | else if (core_kernel_text(vaddr) && | ||
463 | address != fv_addr) | ||
464 | pte = __mk_pte(address, PAGE_KERNEL_EXEC); | ||
465 | else | ||
466 | #if defined(CONFIG_PARISC_PAGE_SIZE_4KB) | ||
467 | if (address >= ro_start && address < ro_end | ||
468 | && address != fv_addr | ||
469 | && address != gw_addr) | ||
470 | pte = __mk_pte(address, PAGE_KERNEL_RO); | ||
471 | else | ||
472 | #endif | ||
473 | pte = __mk_pte(address, pgprot); | ||
474 | |||
475 | if (address >= end_paddr) { | ||
476 | if (force) | ||
477 | break; | ||
478 | else | ||
479 | pte_val(pte) = 0; | ||
480 | } | ||
481 | |||
482 | set_pte(pg_table, pte); | ||
483 | |||
484 | address += PAGE_SIZE; | ||
485 | vaddr += PAGE_SIZE; | ||
486 | } | ||
487 | start_pte = 0; | ||
488 | |||
489 | if (address >= end_paddr) | ||
490 | break; | ||
491 | } | ||
492 | start_pmd = 0; | ||
493 | } | ||
494 | } | ||
495 | |||
374 | void free_initmem(void) | 496 | void free_initmem(void) |
375 | { | 497 | { |
376 | unsigned long addr; | 498 | unsigned long addr; |
377 | unsigned long init_begin = (unsigned long)__init_begin; | 499 | unsigned long init_begin = (unsigned long)__init_begin; |
378 | unsigned long init_end = (unsigned long)__init_end; | 500 | unsigned long init_end = (unsigned long)__init_end; |
379 | 501 | ||
380 | #ifdef CONFIG_DEBUG_KERNEL | 502 | /* The init text pages are marked R-X. We have to |
503 | * flush the icache and mark them RW- | ||
504 | * | ||
505 | * This is tricky, because map_pages is in the init section. | ||
506 | * Do a dummy remap of the data section first (the data | ||
507 | * section is already PAGE_KERNEL) to pull in the TLB entries | ||
508 | * for map_kernel */ | ||
509 | map_pages(init_begin, __pa(init_begin), init_end - init_begin, | ||
510 | PAGE_KERNEL_RWX, 1); | ||
511 | /* now remap at PAGE_KERNEL since the TLB is pre-primed to execute | ||
512 | * map_pages */ | ||
513 | map_pages(init_begin, __pa(init_begin), init_end - init_begin, | ||
514 | PAGE_KERNEL, 1); | ||
515 | |||
516 | /* force the kernel to see the new TLB entries */ | ||
517 | __flush_tlb_range(0, init_begin, init_end); | ||
381 | /* Attempt to catch anyone trying to execute code here | 518 | /* Attempt to catch anyone trying to execute code here |
382 | * by filling the page with BRK insns. | 519 | * by filling the page with BRK insns. |
383 | */ | 520 | */ |
384 | memset((void *)init_begin, 0x00, init_end - init_begin); | 521 | memset((void *)init_begin, 0x00, init_end - init_begin); |
522 | /* finally dump all the instructions which were cached, since the | ||
523 | * pages are no-longer executable */ | ||
385 | flush_icache_range(init_begin, init_end); | 524 | flush_icache_range(init_begin, init_end); |
386 | #endif | ||
387 | 525 | ||
388 | /* align __init_begin and __init_end to page size, | ||
389 | ignoring linker script where we might have tried to save RAM */ | ||
390 | init_begin = PAGE_ALIGN(init_begin); | ||
391 | init_end = PAGE_ALIGN(init_end); | ||
392 | for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) { | 526 | for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) { |
393 | ClearPageReserved(virt_to_page(addr)); | 527 | ClearPageReserved(virt_to_page(addr)); |
394 | init_page_count(virt_to_page(addr)); | 528 | init_page_count(virt_to_page(addr)); |
@@ -618,114 +752,6 @@ void show_mem(unsigned int filter) | |||
618 | #endif | 752 | #endif |
619 | } | 753 | } |
620 | 754 | ||
621 | |||
622 | static void __init map_pages(unsigned long start_vaddr, unsigned long start_paddr, unsigned long size, pgprot_t pgprot) | ||
623 | { | ||
624 | pgd_t *pg_dir; | ||
625 | pmd_t *pmd; | ||
626 | pte_t *pg_table; | ||
627 | unsigned long end_paddr; | ||
628 | unsigned long start_pmd; | ||
629 | unsigned long start_pte; | ||
630 | unsigned long tmp1; | ||
631 | unsigned long tmp2; | ||
632 | unsigned long address; | ||
633 | unsigned long ro_start; | ||
634 | unsigned long ro_end; | ||
635 | unsigned long fv_addr; | ||
636 | unsigned long gw_addr; | ||
637 | extern const unsigned long fault_vector_20; | ||
638 | extern void * const linux_gateway_page; | ||
639 | |||
640 | ro_start = __pa((unsigned long)_text); | ||
641 | ro_end = __pa((unsigned long)&data_start); | ||
642 | fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK; | ||
643 | gw_addr = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK; | ||
644 | |||
645 | end_paddr = start_paddr + size; | ||
646 | |||
647 | pg_dir = pgd_offset_k(start_vaddr); | ||
648 | |||
649 | #if PTRS_PER_PMD == 1 | ||
650 | start_pmd = 0; | ||
651 | #else | ||
652 | start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); | ||
653 | #endif | ||
654 | start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); | ||
655 | |||
656 | address = start_paddr; | ||
657 | while (address < end_paddr) { | ||
658 | #if PTRS_PER_PMD == 1 | ||
659 | pmd = (pmd_t *)__pa(pg_dir); | ||
660 | #else | ||
661 | pmd = (pmd_t *)pgd_address(*pg_dir); | ||
662 | |||
663 | /* | ||
664 | * pmd is physical at this point | ||
665 | */ | ||
666 | |||
667 | if (!pmd) { | ||
668 | pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE << PMD_ORDER); | ||
669 | pmd = (pmd_t *) __pa(pmd); | ||
670 | } | ||
671 | |||
672 | pgd_populate(NULL, pg_dir, __va(pmd)); | ||
673 | #endif | ||
674 | pg_dir++; | ||
675 | |||
676 | /* now change pmd to kernel virtual addresses */ | ||
677 | |||
678 | pmd = (pmd_t *)__va(pmd) + start_pmd; | ||
679 | for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) { | ||
680 | |||
681 | /* | ||
682 | * pg_table is physical at this point | ||
683 | */ | ||
684 | |||
685 | pg_table = (pte_t *)pmd_address(*pmd); | ||
686 | if (!pg_table) { | ||
687 | pg_table = (pte_t *) | ||
688 | alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE); | ||
689 | pg_table = (pte_t *) __pa(pg_table); | ||
690 | } | ||
691 | |||
692 | pmd_populate_kernel(NULL, pmd, __va(pg_table)); | ||
693 | |||
694 | /* now change pg_table to kernel virtual addresses */ | ||
695 | |||
696 | pg_table = (pte_t *) __va(pg_table) + start_pte; | ||
697 | for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) { | ||
698 | pte_t pte; | ||
699 | |||
700 | /* | ||
701 | * Map the fault vector writable so we can | ||
702 | * write the HPMC checksum. | ||
703 | */ | ||
704 | #if defined(CONFIG_PARISC_PAGE_SIZE_4KB) | ||
705 | if (address >= ro_start && address < ro_end | ||
706 | && address != fv_addr | ||
707 | && address != gw_addr) | ||
708 | pte = __mk_pte(address, PAGE_KERNEL_RO); | ||
709 | else | ||
710 | #endif | ||
711 | pte = __mk_pte(address, pgprot); | ||
712 | |||
713 | if (address >= end_paddr) | ||
714 | pte_val(pte) = 0; | ||
715 | |||
716 | set_pte(pg_table, pte); | ||
717 | |||
718 | address += PAGE_SIZE; | ||
719 | } | ||
720 | start_pte = 0; | ||
721 | |||
722 | if (address >= end_paddr) | ||
723 | break; | ||
724 | } | ||
725 | start_pmd = 0; | ||
726 | } | ||
727 | } | ||
728 | |||
729 | /* | 755 | /* |
730 | * pagetable_init() sets up the page tables | 756 | * pagetable_init() sets up the page tables |
731 | * | 757 | * |
@@ -750,14 +776,14 @@ static void __init pagetable_init(void) | |||
750 | size = pmem_ranges[range].pages << PAGE_SHIFT; | 776 | size = pmem_ranges[range].pages << PAGE_SHIFT; |
751 | 777 | ||
752 | map_pages((unsigned long)__va(start_paddr), start_paddr, | 778 | map_pages((unsigned long)__va(start_paddr), start_paddr, |
753 | size, PAGE_KERNEL); | 779 | size, PAGE_KERNEL, 0); |
754 | } | 780 | } |
755 | 781 | ||
756 | #ifdef CONFIG_BLK_DEV_INITRD | 782 | #ifdef CONFIG_BLK_DEV_INITRD |
757 | if (initrd_end && initrd_end > mem_limit) { | 783 | if (initrd_end && initrd_end > mem_limit) { |
758 | printk(KERN_INFO "initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); | 784 | printk(KERN_INFO "initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); |
759 | map_pages(initrd_start, __pa(initrd_start), | 785 | map_pages(initrd_start, __pa(initrd_start), |
760 | initrd_end - initrd_start, PAGE_KERNEL); | 786 | initrd_end - initrd_start, PAGE_KERNEL, 0); |
761 | } | 787 | } |
762 | #endif | 788 | #endif |
763 | 789 | ||
@@ -782,7 +808,7 @@ static void __init gateway_init(void) | |||
782 | */ | 808 | */ |
783 | 809 | ||
784 | map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page), | 810 | map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page), |
785 | PAGE_SIZE, PAGE_GATEWAY); | 811 | PAGE_SIZE, PAGE_GATEWAY, 1); |
786 | } | 812 | } |
787 | 813 | ||
788 | #ifdef CONFIG_HPUX | 814 | #ifdef CONFIG_HPUX |