summaryrefslogtreecommitdiffstats
path: root/arch/mips64/mm
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
commit1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d (patch)
tree357efc7b93f8f5102110d20d293f41360ec212fc /arch/mips64/mm
parentaea27b2e18d69af87e673972246e66657b4fa274 (diff)
Merge with Linux 2.3.21.
Diffstat (limited to 'arch/mips64/mm')
-rw-r--r--arch/mips64/mm/Makefile2
-rw-r--r--arch/mips64/mm/andes.c8
-rw-r--r--arch/mips64/mm/extable.c4
-rw-r--r--arch/mips64/mm/fault.c6
-rw-r--r--arch/mips64/mm/init.c160
-rw-r--r--arch/mips64/mm/loadmmu.c9
-rw-r--r--arch/mips64/mm/r4xx0.c62
-rw-r--r--arch/mips64/mm/tfp.c7
-rw-r--r--arch/mips64/mm/umap.c2
9 files changed, 156 insertions, 104 deletions
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 <asm/pgtable.h>
#include <asm/system.h>
#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
#include <asm/mmu_context.h>
/* 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