From 1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 4 Dec 1999 03:58:56 +0000 Subject: Merge with Linux 2.3.21. --- arch/mips64/mm/Makefile | 2 +- arch/mips64/mm/andes.c | 8 +-- arch/mips64/mm/extable.c | 4 +- arch/mips64/mm/fault.c | 6 +- arch/mips64/mm/init.c | 160 +++++++++++++++++++++++++++++++++++++---------- arch/mips64/mm/loadmmu.c | 9 +-- arch/mips64/mm/r4xx0.c | 62 ++++++------------ arch/mips64/mm/tfp.c | 7 +-- arch/mips64/mm/umap.c | 2 +- 9 files changed, 156 insertions(+), 104 deletions(-) (limited to 'arch/mips64/mm') diff --git a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile index dc9459a41..17100d9f6 100644 --- a/arch/mips64/mm/Makefile +++ b/arch/mips64/mm/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1 1999/08/18 23:37:47 ralf Exp $ +# $Id: Makefile,v 1.2 1999/08/20 21:13:33 ralf Exp $ # # Makefile for the Linux/MIPS-specific parts of the memory manager. # diff --git a/arch/mips64/mm/andes.c b/arch/mips64/mm/andes.c index e048a1203..dec5940c8 100644 --- a/arch/mips64/mm/andes.c +++ b/arch/mips64/mm/andes.c @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.1 1999/08/18 23:37:47 ralf Exp $ +/* $Id: andes.c,v 1.3 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -89,11 +89,6 @@ andes_load_pgd(unsigned long pg_dir) { } -static void -andes_pgd_init(unsigned long page) -{ -} - static int andes_user_mode(struct pt_regs *regs) { @@ -117,7 +112,6 @@ void __init ld_mmu_andes(void) user_mode = andes_user_mode; load_pgd = andes_load_pgd; - pgd_init = andes_pgd_init; flush_cache_all(); flush_tlb_all(); diff --git a/arch/mips64/mm/extable.c b/arch/mips64/mm/extable.c index 7a7ab27ea..f9ae91ae0 100644 --- a/arch/mips64/mm/extable.c +++ b/arch/mips64/mm/extable.c @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: extable.c,v 1.2 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -14,7 +14,7 @@ extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __stop___ex_table[]; -static inline unsigned +static inline unsigned long search_one_table(const struct exception_table_entry *first, const struct exception_table_entry *last, unsigned long value) diff --git a/arch/mips64/mm/fault.c b/arch/mips64/mm/fault.c index 09fbedbff..b7091a83d 100644 --- a/arch/mips64/mm/fault.c +++ b/arch/mips64/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.2 1999/09/28 22:25:52 ralf Exp $ +/* $Id: fault.c,v 1.5 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -45,8 +45,7 @@ unsigned long asid_cache; * routines. */ asmlinkage void -do_page_fault(struct pt_regs *regs, unsigned long write, - unsigned long address) +do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { struct vm_area_struct * vma; struct task_struct *tsk = current; @@ -147,6 +146,7 @@ no_context: printk(KERN_ALERT "Unable to handle kernel paging request at virtual " "address %08lx, epc == %08lx, ra == %08lx\n", address, regs->cp0_epc, regs->regs[31]); +while(1); die("Oops", regs, write); do_exit(SIGKILL); diff --git a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c index 6a0e3c195..2b889669c 100644 --- a/arch/mips64/mm/init.c +++ b/arch/mips64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.3 1999/08/20 21:59:05 ralf Exp $ +/* $Id: init.c,v 1.5 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -49,11 +49,92 @@ void __bad_pte(pmd_t *pmd) pmd_set(pmd, BAD_PAGETABLE); } +/* Fixme, we need something like BAD_PMDTABLE ... */ +void __bad_pmd(pgd_t *pgd) +{ + printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + pgd_set(pgd, (pmd_t *) BAD_PAGETABLE); +} + +extern inline void pgd_init(unsigned long page) +{ + unsigned long *p, *end; + + p = (unsigned long *) page; + end = p + PTRS_PER_PGD; + + while (p < end) { + p[0] = (unsigned long) invalid_pmd_table; + p[1] = (unsigned long) invalid_pmd_table; + p[2] = (unsigned long) invalid_pmd_table; + p[3] = (unsigned long) invalid_pmd_table; + p[4] = (unsigned long) invalid_pmd_table; + p[5] = (unsigned long) invalid_pmd_table; + p[6] = (unsigned long) invalid_pmd_table; + p[7] = (unsigned long) invalid_pmd_table; + p += 8; + } +} + +pgd_t *get_pgd_slow(void) +{ + pgd_t *ret, *init; + + ret = (pgd_t *) __get_free_pages(GFP_KERNEL, 1); + if (ret) { + init = pgd_offset(&init_mm, 0); + pgd_init((unsigned long)ret); + } + return ret; +} + +extern inline void pmd_init(unsigned long addr) +{ + unsigned long *p, *end; + + p = (unsigned long *) addr; + end = p + PTRS_PER_PMD; + + while (p < end) { + p[0] = (unsigned long) invalid_pte_table; + p[1] = (unsigned long) invalid_pte_table; + p[2] = (unsigned long) invalid_pte_table; + p[3] = (unsigned long) invalid_pte_table; + p[4] = (unsigned long) invalid_pte_table; + p[5] = (unsigned long) invalid_pte_table; + p[6] = (unsigned long) invalid_pte_table; + p[7] = (unsigned long) invalid_pte_table; + p += 8; + } +} + +pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) +{ + pmd_t *pmd; + + pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 1); + if (pgd_none(*pgd)) { + if (pmd) { + pmd_init((unsigned long)pmd); + pgd_set(pgd, pmd); + return pmd + offset; + } + pgd_set(pgd, BAD_PMDTABLE); + return NULL; + } + free_page((unsigned long)pmd); + if (pgd_bad(*pgd)) { + __bad_pmd(pgd); + return NULL; + } + return (pmd_t *) pgd_page(*pgd) + offset; +} + pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) { pte_t *page; - page = (pte_t *) __get_free_page(GFP_USER); + page = (pte_t *) __get_free_pages(GFP_USER, 1); if (pmd_none(*pmd)) { if (page) { clear_page((unsigned long)page); @@ -75,7 +156,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) { pte_t *page; - page = (pte_t *) __get_free_page(GFP_KERNEL); + page = (pte_t *) __get_free_pages(GFP_KERNEL, 1); if (pmd_none(*pmd)) { if (page) { clear_page((unsigned long)page); @@ -85,7 +166,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) pmd_set(pmd, BAD_PAGETABLE); return NULL; } - free_page((unsigned long)page); + free_pages((unsigned long)page, 1); if (pmd_bad(*pmd)) { __bad_pte(pmd); return NULL; @@ -93,6 +174,23 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) return (pte_t *) pmd_page(*pmd) + offset; } +int do_check_pgt_cache(int low, int high) +{ + int freed = 0; + + if (pgtable_cache_size > high) { + do { + if (pgd_quicklist) + free_pgd_slow(get_pgd_fast()), freed++; + if (pmd_quicklist) + free_pmd_slow(get_pmd_fast()), freed++; + if (pte_quicklist) + free_pte_slow(get_pte_fast()), freed++; + } while (pgtable_cache_size > low); + } + return freed; +} + asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) { @@ -143,21 +241,19 @@ static inline unsigned long setup_zero_pages(void) return size; } -int do_check_pgt_cache(int low, int high) +extern inline void pte_init(unsigned long page) { - int freed = 0; + unsigned long *p, *end, bp; - if(pgtable_cache_size > high) { - do { - if(pgd_quicklist) - free_pgd_slow(get_pgd_fast()), freed++; - if(pmd_quicklist) - free_pmd_slow(get_pmd_fast()), freed++; - if(pte_quicklist) - free_pte_slow(get_pte_fast()), freed++; - } while(pgtable_cache_size > low); + bp = pte_val(BAD_PAGE); + p = (unsigned long *) page; + end = p + PTRS_PER_PTE; + + while (p < end) { + p[0] = p[1] = p[2] = p[3] = + p[4] = p[5] = p[6] = p[7] = bp; + p += 8; } - return freed; } /* @@ -173,27 +269,24 @@ int do_check_pgt_cache(int low, int high) * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ +pmd_t * __bad_pmd_table(void) +{ + extern pmd_t invalid_pmd_table[PTRS_PER_PMD]; + unsigned long page; + + page = (unsigned long) invalid_pmd_table; + pte_init(page); + + return (pmd_t *) page; +} + pte_t * __bad_pagetable(void) { extern char empty_bad_page_table[PAGE_SIZE]; - unsigned long dummy1, dummy2, page; + unsigned long page; page = (unsigned long) empty_bad_page_table; - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "dsll\t$1, %1, 32\n\t" - "dsrl\t%1, $1, 32\n\t" - "or\t%1, $1\n\t" - "daddiu\t$1, %0, %4\n" - "1:\tdaddiu\t%0, 8\n\t" - "bne\t$1, %0, 1b\n\t" - " sd\t%1, -8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2) - :"0" (page), "1" (pte_val(BAD_PAGE)), "i" (PAGE_SIZE) - :"$1"); + pte_init(page); return (pte_t *) page; } @@ -231,7 +324,7 @@ void show_mem(void) printk("%d reserved pages\n", reserved); printk("%d pages shared\n", shared); printk("%d pages swap cached\n",cached); - printk("%ld pages in page table cache\n",pgtable_cache_size); + printk("%ld pages in page table cache\n", pgtable_cache_size); printk("%d free pages\n", free); #ifdef CONFIG_NET show_net_buffers(); @@ -246,6 +339,7 @@ paging_init(unsigned long start_mem, unsigned long end_mem) /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2); + pmd_init((unsigned long)invalid_pmd_table); return free_area_init(start_mem, end_mem); } diff --git a/arch/mips64/mm/loadmmu.c b/arch/mips64/mm/loadmmu.c index 0c9be7291..3053b9dbd 100644 --- a/arch/mips64/mm/loadmmu.c +++ b/arch/mips64/mm/loadmmu.c @@ -1,4 +1,4 @@ -/* $Id: loadmmu.c,v 1.1 1999/08/18 23:37:48 ralf Exp $ +/* $Id: loadmmu.c,v 1.6 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -46,7 +46,6 @@ void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); /* Miscellaneous. */ void (*load_pgd)(unsigned long pg_dir); -void (*pgd_init)(unsigned long page); void (*update_mmu_cache)(struct vm_area_struct * vma, unsigned long address, pte_t pte); @@ -54,15 +53,11 @@ void (*show_regs)(struct pt_regs *); int (*user_mode)(struct pt_regs *); -asmlinkage void *(*resume)(void *last, void *next); - -extern void ld_mmu_r2300(void); extern void ld_mmu_r4xx0(void); -extern void ld_mmu_r6000(void); extern void ld_mmu_tfp(void); extern void ld_mmu_andes(void); -void __init loadmmu(void) +void __init load_mmu(void) { switch(mips_cputype) { case CPU_R4000PC: diff --git a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c index b026dc4a6..4cd61e19b 100644 --- a/arch/mips64/mm/r4xx0.c +++ b/arch/mips64/mm/r4xx0.c @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.3 1999/09/28 22:25:52 ralf Exp $ +/* $Id: r4xx0.c,v 1.6 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -21,6 +21,7 @@ #include #include #include +#include #include /* CP0 hazard avoidance. */ @@ -798,10 +799,8 @@ r4k_flush_cache_range_s16d16i16(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; __save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -838,10 +837,8 @@ r4k_flush_cache_range_s32d16i16(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -878,10 +875,8 @@ r4k_flush_cache_range_s64d16i16(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -918,10 +913,8 @@ r4k_flush_cache_range_s128d16i16(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -958,10 +951,8 @@ r4k_flush_cache_range_s32d32i32(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -998,10 +989,8 @@ r4k_flush_cache_range_s64d32i32(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1038,10 +1027,8 @@ r4k_flush_cache_range_s128d32i32(struct mm_struct *mm, unsigned long start, pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int text; save_and_cli(flags); - text = vma->vm_flags & VM_EXEC; while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -2142,23 +2129,6 @@ static void r4k_load_pgd(unsigned long pg_dir) { } -static void r4k_pgd_init(unsigned long page) -{ - unsigned long *p = (unsigned long *) page; - int i; - - for(i = 0; i < USER_PTRS_PER_PGD; i+=8) { - p[i + 0] = (unsigned long) invalid_pte_table; - p[i + 1] = (unsigned long) invalid_pte_table; - p[i + 2] = (unsigned long) invalid_pte_table; - p[i + 3] = (unsigned long) invalid_pte_table; - p[i + 4] = (unsigned long) invalid_pte_table; - p[i + 5] = (unsigned long) invalid_pte_table; - p[i + 6] = (unsigned long) invalid_pte_table; - p[i + 7] = (unsigned long) invalid_pte_table; - } -} - #ifdef DEBUG_TLBUPDATE static unsigned long ehi_debug[NTLB_ENTRIES]; static unsigned long el0_debug[NTLB_ENTRIES]; @@ -2243,29 +2213,34 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, } #endif -static void r4k_show_regs(struct pt_regs * regs) +static void r4k_show_regs(struct pt_regs *regs) { /* Saved main processor registers. */ - printk("$0 : %08lx %08lx %08lx %08lx\n", + printk("$0 : %016lx %016lx %016lx %016lx\n", 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %08lx %08lx %08lx %08lx\n", + printk("$4 : %016lx %016lx %016lx %016lx\n", regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx\n", + printk("$8 : %016lx %016lx %016lx %016lx\n", regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12: %08lx %08lx %08lx %08lx\n", + printk("$12 : %016lx %016lx %016lx %016lx\n", regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx\n", + printk("$16 : %016lx %016lx %016lx %016lx\n", regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20: %08lx %08lx %08lx %08lx\n", + printk("$20 : %016lx %016lx %016lx %016lx\n", regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24: %08lx %08lx\n", + printk("$24 : %016lx %016lx\n", regs->regs[24], regs->regs[25]); - printk("$28: %08lx %08lx %08lx %08lx\n", + printk("$28 : %016lx %016lx %016lx %016lx\n", regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); + printk("Hi : %016lx\n", regs->hi); + printk("Lo : %016lx\n", regs->lo); /* Saved cp0 registers. */ - printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, regs->cp0_status, regs->cp0_cause); + printk("epc : %016lx\nbadvaddr: %016lx\n", + regs->cp0_epc, regs->cp0_badvaddr); + printk("Status : %08x\nCause : %08x\n", + (unsigned int) regs->cp0_status, (unsigned int) regs->cp0_cause); +//{static int x = 3; x--; if(!x) while(1);} } /* Detect and size the various r4k caches. */ @@ -2546,7 +2521,6 @@ void __init ld_mmu_r4xx0(void) flush_tlb_page = r4k_flush_tlb_page; load_pgd = r4k_load_pgd; - pgd_init = r4k_pgd_init; update_mmu_cache = r4k_update_mmu_cache; show_regs = r4k_show_regs; diff --git a/arch/mips64/mm/tfp.c b/arch/mips64/mm/tfp.c index 46345a40e..517a617b0 100644 --- a/arch/mips64/mm/tfp.c +++ b/arch/mips64/mm/tfp.c @@ -1,4 +1,4 @@ -/* $Id: tfp.c,v 1.2 1999/08/21 22:19:16 ralf Exp $ +/* $Id: tfp.c,v 1.4 1999/11/23 17:12:50 ralf Exp $ * * tfp.c: MMU and cache routines specific to the r8000 (TFP). * @@ -78,10 +78,6 @@ static void tfp_load_pgd(unsigned long pg_dir) { } -static void tfp_pgd_init(unsigned long page) -{ -} - static int tfp_user_mode(struct pt_regs *regs) { return (regs->cp0_status & ST0_KSU) == KSU_USER; @@ -104,7 +100,6 @@ void __init ld_mmu_tfp(void) user_mode = tfp_user_mode; load_pgd = tfp_load_pgd; - pgd_init = tfp_pgd_init; flush_cache_all(); flush_tlb_all(); diff --git a/arch/mips64/mm/umap.c b/arch/mips64/mm/umap.c index 90d6f19fd..847cc8cb3 100644 --- a/arch/mips64/mm/umap.c +++ b/arch/mips64/mm/umap.c @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: umap.c,v 1.1 1999/08/18 21:46:52 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive -- cgit v1.2.3