summaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/andes.c7
-rw-r--r--arch/mips/mm/fault.c39
-rw-r--r--arch/mips/mm/init.c123
-rw-r--r--arch/mips/mm/r2300.c7
-rw-r--r--arch/mips/mm/r4xx0.c3
-rw-r--r--arch/mips/mm/r6000.c5
-rw-r--r--arch/mips/mm/tfp.c5
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;