diff options
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/andes.c | 7 | ||||
-rw-r--r-- | arch/mips/mm/fault.c | 39 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 123 | ||||
-rw-r--r-- | arch/mips/mm/r2300.c | 7 | ||||
-rw-r--r-- | arch/mips/mm/r4xx0.c | 3 | ||||
-rw-r--r-- | arch/mips/mm/r6000.c | 5 | ||||
-rw-r--r-- | arch/mips/mm/tfp.c | 5 |
7 files changed, 76 insertions, 113 deletions
diff --git a/arch/mips/mm/andes.c b/arch/mips/mm/andes.c index b29dcb274..c0653eb64 100644 --- a/arch/mips/mm/andes.c +++ b/arch/mips/mm/andes.c @@ -1,9 +1,8 @@ -/* +/* $Id: andes.c,v 1.5 1998/05/04 09:12:55 ralf Exp $ + * * andes.c: MMU and cache operations for the R10000 (ANDES). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: andes.c,v 1.4 1998/04/05 11:23:54 ralf Exp $ */ #include <linux/init.h> #include <linux/kernel.h> @@ -13,6 +12,7 @@ #include <asm/pgtable.h> #include <asm/system.h> #include <asm/sgialib.h> +#include <asm/mmu_context.h> extern unsigned long mips_tlb_entries; @@ -104,6 +104,7 @@ __initfunc(void ld_mmu_andes(void)) flush_tlb_mm = andes_flush_tlb_mm; flush_tlb_range = andes_flush_tlb_range; flush_tlb_page = andes_flush_tlb_page; + andes_asid_setup(); add_wired_entry = andes_add_wired_entry; diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index d1ec6cb4c..18bfbf80e 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -1,8 +1,10 @@ -/* $Id: fault.c,v 1.10 1998/09/16 22:50:44 ralf Exp $ +/* $Id: fault.c,v 1.8 1998/09/19 19:16:18 ralf Exp $ * - * arch/mips/mm/fault.c + * 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 + * for more details. * - * Copyright (C) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle */ #include <linux/signal.h> #include <linux/sched.h> @@ -16,6 +18,7 @@ #include <linux/mm.h> #include <linux/smp.h> #include <linux/smp_lock.h> +#include <linux/version.h> #include <asm/hardirq.h> #include <asm/pgtable.h> @@ -24,9 +27,11 @@ #include <asm/system.h> #include <asm/uaccess.h> +#define development_version (LINUX_VERSION_CODE & 0x100) + extern void die(char *, struct pt_regs *, unsigned long write); -unsigned long asid_cache = ASID_FIRST_VERSION; +unsigned long asid_cache; /* * Macro for exception fixup code to access integer registers. @@ -46,9 +51,12 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, struct mm_struct *mm = tsk->mm; unsigned long fixup; - if (in_interrupt()) - die("page fault from irq handler", regs, writeaccess); - lock_kernel(); + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_interrupt() || mm == &init_mm) + goto no_context; #if 0 printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid, address, writeaccess, regs->cp0_epc); @@ -77,8 +85,7 @@ good_area: } handle_mm_fault(tsk, vma, address, writeaccess); up(&mm->mmap_sem); - - goto out; + return; /* * Something tried to access memory that isn't in our memory map.. @@ -100,20 +107,22 @@ bad_area: (unsigned long) regs->regs[31]); #endif force_sig(SIGSEGV, tsk); - goto out; + return; } - /* Did we have an exception handler installed? */ +no_context: + /* Are we prepared to handle this kernel fault? */ fixup = search_exception_table(regs->cp0_epc); if (fixup) { long new_epc; tsk->tss.cp0_baduaddr = address; new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", - tsk->comm, regs->cp0_epc, new_epc); + if (development_version) + printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", + tsk->comm, regs->cp0_epc, new_epc); regs->cp0_epc = new_epc; - goto out; + return; } /* @@ -125,6 +134,4 @@ bad_area: address, regs->cp0_epc, regs->regs[31]); die("Oops", regs, writeaccess); do_exit(SIGKILL); -out: - unlock_kernel(); } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 8bdbffaf8..f7fa99a37 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.8 1998/09/04 21:21:34 ralf Exp $ +/* $Id: init.c,v 1.9 1998/09/19 19:16:18 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 @@ -33,13 +33,8 @@ #ifdef CONFIG_SGI #include <asm/sgialib.h> #endif +#include <asm/mmu_context.h> -/* - * Define this to effectivly disable the userpage colouring shit. - */ -#define CONF_GIVE_A_SHIT_ABOUT_COLOURS - -extern void deskstation_tyne_dma_init(void); extern void show_net_buffers(void); void __bad_pte_kernel(pmd_t *pmd) @@ -58,7 +53,7 @@ pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) { pte_t *page; - page = (pte_t *) __get_free_page(GFP_KERNEL); + page = (pte_t *) __get_free_page(GFP_USER); if (pmd_none(*pmd)) { if (page) { clear_page((unsigned long)page); @@ -243,83 +238,6 @@ pte_t __bad_page(void) return pte_mkdirty(mk_pte(page, PAGE_SHARED)); } -#ifdef __SMP__ -spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED; -#endif -struct upcache user_page_cache[8] __attribute__((aligned(32))); -static unsigned long user_page_order; -unsigned long user_page_colours; - -unsigned long get_user_page_slow(int which) -{ - unsigned long chunk; - struct upcache *up = &user_page_cache[0]; - struct page *p, *res; - int i; - - do { - chunk = __get_free_pages(GFP_KERNEL, user_page_order); - } while(chunk==0); - - p = mem_map + MAP_NR(chunk); - res = p + which; - spin_lock(&user_page_lock); - for (i=user_page_colours; i>=0; i--,p++,up++,chunk+=PAGE_SIZE) { - atomic_set(&p->count, 1); - p->age = PAGE_INITIAL_AGE; - - if (p != res) { - if(up->count < USER_PAGE_WATER) { - p->next = up->list; - up->list = p; - up->count++; - } else - free_pages(chunk, 0); - } - } - spin_unlock(&user_page_lock); - - return page_address(res); -} - -static inline void user_page_setup(void) -{ - unsigned long assoc = 0; - unsigned long dcache_log, icache_log, cache_log; - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - switch(mips_cputype) { - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4400SC: - case CPU_R4400MC: - cache_log = 3; /* => 32k, sucks */ - break; - - case CPU_R4600: /* two way set associative caches? */ - case CPU_R4700: - case CPU_R5000: - case CPU_NEVADA: - assoc = 1; - /* fall through */ - default: - /* use bigger cache */ - icache_log = (config >> 9) & 7; - dcache_log = (config >> 6) & 7; - if (dcache_log > icache_log) - cache_log = dcache_log; - else - cache_log = icache_log; - } - -#ifdef CONF_GIVE_A_SHIT_ABOUT_COLOURS - cache_log = assoc = 0; -#endif - - user_page_order = cache_log - assoc; - user_page_colours = (1 << (cache_log - assoc)) - 1; -} - void show_mem(void) { int i, free = 0, total = 0, reserved = 0; @@ -423,9 +341,6 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10)); - - /* Initialize allocator for colour matched mapped pages. */ - user_page_setup(); } extern char __init_begin, __init_end; @@ -465,3 +380,35 @@ void si_meminfo(struct sysinfo *val) val->sharedram <<= PAGE_SHIFT; return; } + +/* Fixup an immediate instruction */ +__initfunc(static void __i_insn_fixup(unsigned int **start, unsigned int **stop, + unsigned int i_const)) +{ + unsigned int **p, *ip; + + for (p = start;p < stop; p++) { + ip = *p; + *ip = (*ip & 0xffff0000) | i_const; + } +} + +#define i_insn_fixup(section, const) \ +do { \ + extern unsigned int *__start_ ## section; \ + extern unsigned int *__stop_ ## section; \ + __i_insn_fixup(&__start_ ## section, &__stop_ ## section, const); \ +} while(0) + +/* Caller is assumed to flush the caches before the first context switch. */ +__initfunc(void __asid_setup(unsigned int inc, unsigned int mask, + unsigned int version_mask, + unsigned int first_version)) +{ + i_insn_fixup(__asid_inc, inc); + i_insn_fixup(__asid_mask, mask); + i_insn_fixup(__asid_version_mask, version_mask); + i_insn_fixup(__asid_first_version, first_version); + + asid_cache = first_version; +} diff --git a/arch/mips/mm/r2300.c b/arch/mips/mm/r2300.c index 03a0c63e9..8f8e7ddfa 100644 --- a/arch/mips/mm/r2300.c +++ b/arch/mips/mm/r2300.c @@ -1,9 +1,8 @@ -/* +/* $Id: r2300.c,v 1.6 1998/08/25 09:14:46 ralf Exp $ + * * r2300.c: R2000 and R3000 specific mmu/cache code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: r2300.c,v 1.5 1998/04/05 11:23:55 ralf Exp $ */ #include <linux/init.h> #include <linux/kernel.h> @@ -14,6 +13,7 @@ #include <asm/pgtable.h> #include <asm/system.h> #include <asm/sgialib.h> +#include <asm/mmu_context.h> extern unsigned long mips_tlb_entries; @@ -274,6 +274,7 @@ __initfunc(void ld_mmu_r2300(void)) flush_tlb_mm = r2300_flush_tlb_mm; flush_tlb_range = r2300_flush_tlb_range; flush_tlb_page = r2300_flush_tlb_page; + r3000_asid_setup(); load_pgd = r2300_load_pgd; pgd_init = r2300_pgd_init; diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c index 31b636296..1b2ac3674 100644 --- a/arch/mips/mm/r4xx0.c +++ b/arch/mips/mm/r4xx0.c @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.19 1998/08/25 09:14:46 ralf Exp $ +/* $Id: r4xx0.c,v 1.20 1998/10/14 23:40:45 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 @@ -2791,6 +2791,7 @@ __initfunc(void ld_mmu_r4xx0(void)) flush_tlb_mm = r4k_flush_tlb_mm; flush_tlb_range = r4k_flush_tlb_range; flush_tlb_page = r4k_flush_tlb_page; + r4xx0_asid_setup(); load_pgd = r4k_load_pgd; pgd_init = r4k_pgd_init; diff --git a/arch/mips/mm/r6000.c b/arch/mips/mm/r6000.c index 047cb7b2f..b8b442728 100644 --- a/arch/mips/mm/r6000.c +++ b/arch/mips/mm/r6000.c @@ -1,4 +1,5 @@ -/* $Id: r6000.c,v 1.4 1998/04/05 11:23:56 ralf Exp $ +/* $Id: r6000.c,v 1.5 1998/08/25 09:14:47 ralf Exp $ + * * r6000.c: MMU and cache routines for the R6000 processors. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -13,6 +14,7 @@ #include <asm/pgtable.h> #include <asm/system.h> #include <asm/sgialib.h> +#include <asm/mmu_context.h> __asm__(".set mips3"); /* because we know... */ @@ -180,6 +182,7 @@ __initfunc(void ld_mmu_r6000(void)) flush_tlb_mm = r6000_flush_tlb_mm; flush_tlb_range = r6000_flush_tlb_range; flush_tlb_page = r6000_flush_tlb_page; + r6000_asid_setup(); load_pgd = r6000_load_pgd; pgd_init = r6000_pgd_init; diff --git a/arch/mips/mm/tfp.c b/arch/mips/mm/tfp.c index dab618b3e..0d8ab7c86 100644 --- a/arch/mips/mm/tfp.c +++ b/arch/mips/mm/tfp.c @@ -1,4 +1,5 @@ -/* +/* $Id: tfp.c,v 1.6 1998/10/16 19:22:44 ralf Exp $ + * * tfp.c: MMU and cache routines specific to the r8000 (TFP). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -13,6 +14,7 @@ #include <asm/pgtable.h> #include <asm/system.h> #include <asm/sgialib.h> +#include <asm/mmu_context.h> extern unsigned long mips_tlb_entries; @@ -104,6 +106,7 @@ __initfunc(void ld_mmu_tfp(void)) flush_tlb_mm = tfp_flush_tlb_mm; flush_tlb_range = tfp_flush_tlb_range; flush_tlb_page = tfp_flush_tlb_page; + tfp_asid_setup(); add_wired_entry = tfp_add_wired_entry; |