diff options
Diffstat (limited to 'arch/mips/mips3')
-rw-r--r-- | arch/mips/mips3/Makefile | 25 | ||||
-rw-r--r-- | arch/mips/mips3/cache.c | 309 | ||||
-rw-r--r-- | arch/mips/mips3/cpu.c | 96 | ||||
-rw-r--r-- | arch/mips/mips3/fp-context.S | 170 | ||||
-rw-r--r-- | arch/mips/mips3/memcpy.S | 185 | ||||
-rw-r--r-- | arch/mips/mips3/memset.c | 82 | ||||
-rw-r--r-- | arch/mips/mips3/pagetables.c | 297 | ||||
-rw-r--r-- | arch/mips/mips3/r4xx0.S | 841 | ||||
-rw-r--r-- | arch/mips/mips3/showregs.c | 36 |
9 files changed, 0 insertions, 2041 deletions
diff --git a/arch/mips/mips3/Makefile b/arch/mips/mips3/Makefile deleted file mode 100644 index e0f6bcf29..000000000 --- a/arch/mips/mips3/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# -# Makefile for the MIPS III specific parts of the Linux/MIPS kernel. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -.S.s: - $(CPP) $(CFLAGS) $< -o $*.s -.S.o: - $(CC) $(CFLAGS) -c $< -o $*.o - -all: mips.o -EXTRA_ASFLAGS = -mips3 -mcpu=r4400 -O_TARGET := mips.o -O_OBJS := cache.o cpu.o fp-context.o memcpy.o memset.o r4xx0.o pagetables.o \ - showregs.o - -copy_user.o: copy_user.S -r4xx0.o: r4xx0.S - -clean: - -include $(TOPDIR)/Rules.make diff --git a/arch/mips/mips3/cache.c b/arch/mips/mips3/cache.c deleted file mode 100644 index 3fac95b75..000000000 --- a/arch/mips/mips3/cache.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Cache maintenance for R4000/R4400/R4600 CPUs. - * - * 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. - * - * (C) Copyright 1996 by Ralf Baechle - * FIXME: Support for SC/MC version is missing. - */ -#include <linux/kernel.h> -#include <asm/addrspace.h> -#include <asm/asm.h> -#include <asm/bootinfo.h> -#include <asm/cache.h> -#include <asm/mipsregs.h> -#include <asm/page.h> -#include <asm/system.h> - -#define STR(x) __STR(x) -#define __STR(x) #x - -unsigned long page_colour_mask; - -/* - * Size of the caches - * Line size of the caches - */ -unsigned int dcache_size, icache_size; -unsigned int dcache_line_size, icache_line_size; -unsigned long dcache_line_mask, icache_line_mask; - -/* - * Profiling counter - */ -extern unsigned int dflushes; -extern unsigned int iflushes; - -/* - * Pointers to code for particular CPU sub family. - */ -static void (*wb_inv_d_cache)(void); -static void (*inv_i_cache)(void); - -#define CACHELINES 512 /* number of cachelines (kludgy) */ - -extern inline void cache(unsigned int cacheop, unsigned long addr, - unsigned long offset, void *fault) -{ - __asm__ __volatile__ ( - "1:\tcache\t%0,%2+%1\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%3\n\t" - ".text" - : /* no outputs */ - :"ri" (cacheop), - "o" (*(unsigned char *)addr), - "ri" (offset), - "ri" (fault)); -} - -/* - * Code for R4000 style primary caches. - * - * R4000 style caches are direct-mapped, virtual indexed and physical tagged. - * The size of cache line is either 16 or 32 bytes. - * SC/MC versions of the CPUs add support for an second level cache with - * upto 4mb configured as either joint or split I/D. These level two - * caches with direct support from CPU aren't yet supported. - */ - -static void r4000_wb_inv_d_cache(void) -{ - unsigned long addr = KSEG0; - int i; - - for (i=CACHELINES;i;i--) { - cache(Index_Writeback_Inv_D, addr, 0, &&fault); - addr += 32; - } - if (read_32bit_cp0_register(CP0_CONFIG) & CONFIG_DB) - return; - for (i=CACHELINES;i;i--) { - cache(Index_Writeback_Inv_D, addr, 16, &&fault); - addr += 32; - } -fault: -} - -static void r4000_inv_i_cache(void) -{ - unsigned long addr = KSEG0; - int i; - - for (i=CACHELINES;i;i--) { - cache(Index_Invalidate_I, addr, 0, &&fault); - addr += 32; - } - if (read_32bit_cp0_register(CP0_CONFIG) & CONFIG_IB) - return; - for (i=CACHELINES;i;i--) { - cache(Index_Invalidate_I, addr, 16, &&fault); - addr += 32; - } -fault: -} - -/* - * Code for R4600 style primary caches. - * - * R4600 has two way primary caches with 32 bytes line size. The way to - * flush is selected by bith 12 of the physical address given as argument - * to an Index_* cache operation. CPU supported second level caches are - * not available. - * - * R4600 v1.0 bug: Flush way 2, then way 1 of the instruction cache when - * using Index_Invalidate_I. IDT says this should work but is untested. - * If this should not work, we have to disable interrupts for the broken - * chips. The CPU might otherwise execute code from the wrong cache way - * during an interrupt. - */ -static void r4600_wb_inv_d_cache(void) -{ - unsigned long addr = KSEG0; - int i; - - for (i=CACHELINES;i;i-=2) { - cache(Index_Writeback_Inv_D, addr, 8192, &&fault); - cache(Index_Writeback_Inv_D, addr, 0, &&fault); - addr += 32; - } -fault: -} - -static void r4600_inv_i_cache(void) -{ - unsigned long addr = KSEG0; - int i; - - for (i=CACHELINES;i;i-=2) { - cache(Index_Invalidate_I, addr, 8192, &&fault); - cache(Index_Invalidate_I, addr, 0, &&fault); - addr += 32; - } -fault: -} - -/* - * Flush the cache of R4x00. - * - * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Invalidate_D, - * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only - * operate correctly if the internal data cache refill buffer is empty. These - * CACHE instructions should be separated from any potential data cache miss - * by a load instruction to an uncached address to empty the response buffer." - * (Revision 2.0 device errata from IDT available on http://www.idt.com/ - * in .pdf format.) - * - * To do: Use Hit_Invalidate where possible to be more economic. - * Handle SC & MC versions. - * The decission to nuke the entire cache might be based on a better - * decission algorithem based on the real costs. - * Handle different cache sizes. - * Combine the R4000 and R4600 cases. - */ -extern inline void -flush_d_cache(unsigned long addr, unsigned long size) -{ - unsigned long end; - unsigned long a; - - dflushes++; - if (1 || size >= dcache_size) { - wb_inv_d_cache(); - return; - } - - /* - * Workaround for R4600 bug. Explanation see above. - */ - *(volatile unsigned long *)KSEG1; - - /* - * Ok, we only have to invalidate parts of the cache. - */ - a = addr & dcache_line_mask; - end = (addr + size) & dcache_line_mask; - while (1) { - cache(Hit_Writeback_Inv_D, a, 0, &&fault); - if (a == end) break; - a += dcache_line_size; - } -fault: - return; -} - -extern inline void -flush_i_cache(unsigned long addr, unsigned long size) -{ - unsigned long end; - unsigned long a; - - iflushes++; - if (1 || size >= icache_size) { - inv_i_cache(); - return; - } - - /* - * Ok, we only have to invalidate parts of the cache. - */ - a = addr & icache_line_mask; - end = (addr + size) & dcache_line_mask; - while (1) { - cache(Hit_Invalidate_I, a, 0, &&fault); - if (a == end) break; - a += icache_line_size; - } -fault: - return; -} - -asmlinkage void -mips3_cacheflush(unsigned long addr, unsigned long size, unsigned int flags) -{ - if (!(flags & CF_ALL)) - printk("mips3_cacheflush called without cachetype parameter\n"); - if (!(flags & CF_VIRTUAL)) - return; /* Nothing to do */ - if (flags & CF_DCACHE) - flush_d_cache(addr, size); - if (flags & CF_ICACHE) - flush_i_cache(addr, size); -} - -/* Going away. */ -asmlinkage void fd_cacheflush(unsigned long addr, unsigned long size) -{ - cacheflush(addr, size, CF_DCACHE|CF_VIRTUAL); -} - -void mips3_cache_init(void) -{ - extern asmlinkage void handle_vcei(void); - extern asmlinkage void handle_vced(void); - unsigned int c0_config = read_32bit_cp0_register(CP0_CONFIG); - - switch (mips_cputype) { - case CPU_R4000MC: case CPU_R4400MC: - case CPU_R4000SC: case CPU_R4400SC: - /* - * Handlers not implemented yet. - */ - set_except_vector(14, handle_vcei); - set_except_vector(31, handle_vced); - break; - default: - } - - /* - * Which CPU are we running on? There are different styles - * of primary caches in the MIPS R4xx0 CPUs. - */ - switch (mips_cputype) { - case CPU_R4000MC: case CPU_R4400MC: - case CPU_R4000SC: case CPU_R4400SC: - case CPU_R4000PC: case CPU_R4400PC: - inv_i_cache = r4000_inv_i_cache; - wb_inv_d_cache = r4000_wb_inv_d_cache; - break; - case CPU_R4600: case CPU_R4700: - inv_i_cache = r4600_inv_i_cache; - wb_inv_d_cache = r4600_wb_inv_d_cache; - break; - default: - panic("Don't know about cache type ..."); - } - cacheflush = mips3_cacheflush; - - /* - * Find the size of primary instruction and data caches. - * For most CPUs these sizes are the same. - */ - dcache_size = 1 << (12 + ((c0_config >> 6) & 7)); - icache_size = 1 << (12 + ((c0_config >> 9) & 7)); - page_colour_mask = (dcache_size - 1) & ~(PAGE_SIZE - 1); - - /* - * Cache line sizes - */ - dcache_line_size = (c0_config & CONFIG_DB) ? 32 : 16; - dcache_line_mask = ~(dcache_line_size - 1); - icache_line_size = (c0_config & CONFIG_IB) ? 32 : 16; - icache_line_mask = ~(icache_line_size - 1); - - printk("Primary D-cache size %dkb bytes, %d byte lines.\n", - dcache_size >> 10, dcache_line_size); - printk("Primary I-cache size %dkb bytes, %d byte lines.\n", - icache_size >> 10, icache_line_size); - - /* - * Second level cache. - * FIXME ... - */ - if (!(c0_config & CONFIG_SC)) { - printk("S-cache detected. This type of of cache is not " - "supported yet.\n"); - } -} diff --git a/arch/mips/mips3/cpu.c b/arch/mips/mips3/cpu.c deleted file mode 100644 index cd8a293e5..000000000 --- a/arch/mips/mips3/cpu.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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) 1996 Ralf Baechle - */ -#include <linux/sched.h> - -#include <asm/bootinfo.h> -#include <asm/cache.h> -#include <asm/mipsregs.h> -#include <asm/page.h> -#include <asm/processor.h> -#include <asm/system.h> - -extern asmlinkage void mips3_cacheflush(unsigned long addr, unsigned long nbytes, unsigned int flags); - -void (*mips_cache_init)(void); -void (*switch_to_user_mode)(struct pt_regs *regs); - -static void -mips3_switch_to_user_mode(struct pt_regs *regs) -{ - regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER; -} - -unsigned long (*thread_saved_pc)(struct thread_struct *t); - -/* - * Return saved PC of a blocked thread. - */ -static unsigned long mips3_thread_saved_pc(struct thread_struct *t) -{ - return ((unsigned long long *)(unsigned long)t->reg29)[11]; -} - -unsigned long (*get_wchan)(struct task_struct *p); - -static unsigned long mips3_get_wchan(struct task_struct *p) -{ - /* - * This one depends on the frame size of schedule(). Do a - * "disass schedule" in gdb to find the frame size. Also, the - * code assumes that sleep_on() follows immediately after - * interruptible_sleep_on() and that add_timer() follows - * immediately after interruptible_sleep(). Ugly, isn't it? - * Maybe adding a wchan field to task_struct would be better, - * after all... - */ - unsigned long schedule_frame; - unsigned long pc; - - pc = thread_saved_pc(&p->tss); - if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) { - schedule_frame = ((unsigned long long *)(long)p->tss.reg30)[10]; - return (unsigned long)((unsigned long long *)schedule_frame)[9]; - } - return pc; -} - -void (*pgd_init)(unsigned long page); -void (*copy_page)(unsigned long to, unsigned long from); -asmlinkage void (*restore_fp_context)(struct sigcontext *sc); -asmlinkage void (*save_fp_context)(struct sigcontext *sc); - -void -mips3_cpu_init(void) -{ - extern void mips3_cache_init(void); - extern void mips3_pgd_init_32byte_lines(unsigned long page); - extern void mips3_pgd_init_16byte_lines(unsigned long page); - extern void mips3_clear_page_32byte_lines(unsigned long page); - extern void mips3_clear_page_16byte_lines(unsigned long page); - extern void mips3_copy_page_32byte_lines(unsigned long to, unsigned long from); - extern void mips3_copy_page_16byte_lines(unsigned long to, unsigned long from); - extern void mips3_copy_page(unsigned long to, unsigned long from); - extern asmlinkage void mips3_restore_fp_context(struct sigcontext *sc); - extern asmlinkage void mips3_save_fp_context(struct sigcontext *sc); - - mips_cache_init = mips3_cache_init; - if (read_32bit_cp0_register(CP0_CONFIG) & CONFIG_DB) { - pgd_init = mips3_pgd_init_32byte_lines; - clear_page = mips3_clear_page_32byte_lines; - copy_page = mips3_copy_page_32byte_lines; - } else { - pgd_init = mips3_pgd_init_16byte_lines; - clear_page = mips3_clear_page_16byte_lines; - copy_page = mips3_copy_page_16byte_lines; - } - switch_to_user_mode = mips3_switch_to_user_mode; - thread_saved_pc = mips3_thread_saved_pc; - get_wchan = mips3_get_wchan; - restore_fp_context = mips3_restore_fp_context; - save_fp_context = mips3_save_fp_context; -} diff --git a/arch/mips/mips3/fp-context.S b/arch/mips/mips3/fp-context.S deleted file mode 100644 index 5e04aa61f..000000000 --- a/arch/mips/mips3/fp-context.S +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Save/restore floating point context for signal handlers. - * - * 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) 1996 by Ralf Baechle - */ -#include <asm/asm.h> -#include <asm/fpregdef.h> -#include <asm/mipsregs.h> -#include <asm/regdef.h> -#include <asm/sigcontext.h> - -#define SDC1(r,m) \ -7: sdc1 r,m; \ - .section __ex_table,"a"; \ - PTR 7b,bad_stack; \ - .text - -#define SW(r,m) \ -7: sw r,m; \ - .section __ex_table,"a"; \ - PTR 7b,bad_stack; \ - .text - -#define LDC1(r,m) \ -7: ldc1 r,m; \ - .section __ex_table,"a"; \ - PTR 7b,bad_stack; \ - .text - -#define LW(r,m) \ -7: lw r,m; \ - .section __ex_table,"a"; \ - PTR 7b,bad_stack; \ - .text - - .set noreorder -/* - * Save floating point context - */ -LEAF(mips3_save_fp_context) - mfc0 t1,CP0_STATUS - sll t2,t1,2 - bgez t2,2f - sll t2,t1,5 # delay slot - bgez t2,1f - cfc1 t1,fcr31 # delay slot - /* - * Store the 16 odd double precision registers - */ - SDC1 ($f1,(SC_FPREGS+8)(a0)) - SDC1 ($f3,(SC_FPREGS+24)(a0)) - SDC1 ($f5,(SC_FPREGS+40)(a0)) - SDC1 ($f7,(SC_FPREGS+56)(a0)) - SDC1 ($f9,(SC_FPREGS+72)(a0)) - SDC1 ($f11,(SC_FPREGS+88)(a0)) - SDC1 ($f13,(SC_FPREGS+104)(a0)) - SDC1 ($f15,(SC_FPREGS+120)(a0)) - SDC1 ($f17,(SC_FPREGS+136)(a0)) - SDC1 ($f19,(SC_FPREGS+152)(a0)) - SDC1 ($f21,(SC_FPREGS+168)(a0)) - SDC1 ($f23,(SC_FPREGS+184)(a0)) - SDC1 ($f25,(SC_FPREGS+200)(a0)) - SDC1 ($f27,(SC_FPREGS+216)(a0)) - SDC1 ($f29,(SC_FPREGS+232)(a0)) - SDC1 ($f31,(SC_FPREGS+248)(a0)) - - /* - * Store the 16 even double precision registers - */ -1: SDC1 ($f0,(SC_FPREGS+0)(a0)) - SDC1 ($f2,(SC_FPREGS+16)(a0)) - SDC1 ($f4,(SC_FPREGS+32)(a0)) - SDC1 ($f6,(SC_FPREGS+48)(a0)) - SDC1 ($f8,(SC_FPREGS+64)(a0)) - SDC1 ($f10,(SC_FPREGS+80)(a0)) - SDC1 ($f12,(SC_FPREGS+96)(a0)) - SDC1 ($f14,(SC_FPREGS+112)(a0)) - SDC1 ($f16,(SC_FPREGS+128)(a0)) - SDC1 ($f18,(SC_FPREGS+144)(a0)) - SDC1 ($f20,(SC_FPREGS+160)(a0)) - SDC1 ($f22,(SC_FPREGS+176)(a0)) - SDC1 ($f24,(SC_FPREGS+192)(a0)) - SDC1 ($f26,(SC_FPREGS+208)(a0)) - SDC1 ($f28,(SC_FPREGS+224)(a0)) - SDC1 ($f30,(SC_FPREGS+240)(a0)) - SW t1,SC_FPC_CSR(a0) - cfc1 t0,$0 # implementation/version - jr ra - .set nomacro - SW t1,SC_FPC_EIR(a0) # delay slot - .set macro - -2: jr ra - .set nomacro - nop # delay slot - .set macro - END(mips3_save_fp_context) - -/* - * Restore fpu state: - * - fp gp registers - * - cp1 status/control register - * - * We base the decission which registers to restore from the signal stack - * frame on the current content of c0_status, not on the content of the - * stack frame which might have been changed by the user. - */ -LEAF(mips3_restore_fp_context) - mfc0 t1,CP0_STATUS - sll t0,t1,2 - bgez t0,2f - sll t0,t1,5 # delay slot - bgez t0,1f - LW t0,SC_FPC_CSR(a0) # delay slot - /* - * Restore the 16 odd double precision registers only - * when enabled in the cp0 status register. - */ - LDC1 ($f1,(SC_FPREGS+8)(a0)) - LDC1 ($f3,(SC_FPREGS+24)(a0)) - LDC1 ($f5,(SC_FPREGS+40)(a0)) - LDC1 ($f7,(SC_FPREGS+56)(a0)) - LDC1 ($f9,(SC_FPREGS+72)(a0)) - LDC1 ($f11,(SC_FPREGS+88)(a0)) - LDC1 ($f13,(SC_FPREGS+104)(a0)) - LDC1 ($f15,(SC_FPREGS+120)(a0)) - LDC1 ($f17,(SC_FPREGS+136)(a0)) - LDC1 ($f19,(SC_FPREGS+152)(a0)) - LDC1 ($f21,(SC_FPREGS+168)(a0)) - LDC1 ($f23,(SC_FPREGS+184)(a0)) - LDC1 ($f25,(SC_FPREGS+200)(a0)) - LDC1 ($f27,(SC_FPREGS+216)(a0)) - LDC1 ($f29,(SC_FPREGS+232)(a0)) - LDC1 ($f31,(SC_FPREGS+248)(a0)) - - /* - * Restore the 16 even double precision registers - * when cp1 was enabled in the cp0 status register. - */ -1: LDC1 ($f0,(SC_FPREGS+0)(a0)) - LDC1 ($f2,(SC_FPREGS+16)(a0)) - LDC1 ($f4,(SC_FPREGS+32)(a0)) - LDC1 ($f6,(SC_FPREGS+48)(a0)) - LDC1 ($f8,(SC_FPREGS+64)(a0)) - LDC1 ($f10,(SC_FPREGS+80)(a0)) - LDC1 ($f12,(SC_FPREGS+96)(a0)) - LDC1 ($f14,(SC_FPREGS+112)(a0)) - LDC1 ($f16,(SC_FPREGS+128)(a0)) - LDC1 ($f18,(SC_FPREGS+144)(a0)) - LDC1 ($f20,(SC_FPREGS+160)(a0)) - LDC1 ($f22,(SC_FPREGS+176)(a0)) - LDC1 ($f24,(SC_FPREGS+192)(a0)) - LDC1 ($f26,(SC_FPREGS+208)(a0)) - LDC1 ($f28,(SC_FPREGS+224)(a0)) - LDC1 ($f30,(SC_FPREGS+240)(a0)) - jr ra - .set nomacro - ctc1 t0,fcr31 # delay slot - .set macro - -2: jr ra - .set nomacro - nop # delay slot - .set macro - END(mips3_restore_fp_context) - .set reorder diff --git a/arch/mips/mips3/memcpy.S b/arch/mips/mips3/memcpy.S deleted file mode 100644 index 6f03032a6..000000000 --- a/arch/mips/mips3/memcpy.S +++ /dev/null @@ -1,185 +0,0 @@ -/* - * arch/mips/mips3/memcpy.S - * - * 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) 1996 by Ralf Baechle - * - * Less stupid memcpy/user_copy implementation for 64 bit MIPS CPUs. - * Much faster than the old memcpy but definately work in progress. - * The list of tricks for a good memcpy is long ... - */ -#include <asm/asm.h> -#include <asm/regdef.h> -#include <asm/mipsregs.h> - -#define BLOCK_SIZE (SZREG*4) - -#define SWAP(x,y) \ - subu x,x,y; \ - addu y,x,y; \ - subu x,y,x - -#define EX(addr,handler) \ - .section __ex_table,"a"; \ - PTR addr, handler; \ - .text -#define UEX(addr,handler) \ - EX(addr,handler); \ - EX(addr+4,handler) - - .set noreorder - .set noat - -/* ---------------------------------------------------------------------- */ - -not_dw_aligned: -/* - * At least one address is missaligned. - * Let's see if we can fix the alignment. - */ - LONG_SUBU v1,zero,a0 - andi v1,SZREG-1 - sltu t0,v0,v1 - MOVN(v1,v0,t0) - beqz v1,still_not_aligned - LONG_ADDU v1,a0 # delay slot -1: lb $1,(a1) - EX(1b, fault) - LONG_ADDIU a1,1 -2: sb $1,(a0) - EX(2b, fault) - LONG_ADDIU a0,1 - bne a0,v1,1b - LONG_SUBU v0,1 # delay slot - -/* - * Ok, now the destination address is 8-byte aligned. - * Is the source also aligned? - */ - andi t0,a1,SZREG-1 - beqz t0,align8 # fine ... - -/* - * Bad. We could only fix the alignment of the destination address. - * Now let's copy in the usual BLOCK_SIZE byte blocks using unaligned - * load and aligned stores. - */ -still_not_aligned: - ori v1,v0,BLOCK_SIZE-1 # delay slot - xori v1,BLOCK_SIZE-1 - beqz v1,copy_left_over - nop # delay slot - LONG_SUBU v0,v1 - LONG_ADDU v1,a0 - -1: uld t0,(a1) - UEX(1b, fault) -2: uld t1,8(a1) - UEX(2b, fault) -2: uld t2,16(a1) - UEX(2b, fault) -2: uld t3,24(a1) - UEX(2b, fault) -2: sd t0,(a0) - EX(2b, fault) -2: sd t1,8(a0) - EX(2b, fault_plus_one_reg) -2: sd t2,16(a0) - EX(2b, fault_plus_two_reg) -2: sd t3,24(a0) - EX(2b, fault_plus_three_reg) - LONG_ADDIU a0,BLOCK_SIZE - bne a0,v1,1b - LONG_ADDIU a1,BLOCK_SIZE # delay slot -9: - b copy_left_over # < BLOCK_SIZE bytes left - nop # delay slot - -/* ---------------------------------------------------------------------- */ - -LEAF(__copy_user) - - or t1,a0,a1 - andi t1,SZREG-1 - bnez t1,not_dw_aligned - move v0,a2 # delay slot - -align8: - ori v1,v0,BLOCK_SIZE-1 - xori v1,BLOCK_SIZE-1 - beqz v1,copy_left_over - nop # delay slot - LONG_SUBU v0,v1 - LONG_ADDU v1,a0 - -1: ld t0,(a1) - EX(1b, fault) -2: ld t1,8(a1) - EX(2b, fault) -2: ld t2,16(a1) - EX(2b, fault) -2: ld t3,24(a1) - EX(2b, fault) -2: sd t0,(a0) - EX(2b, fault) -2: sd t1,8(a0) - EX(2b, fault_plus_one_reg) -2: sd t2,16(a0) - EX(2b, fault_plus_two_reg) -2: sd t3,24(a0) - EX(2b, fault_plus_three_reg) - LONG_ADDIU a0,BLOCK_SIZE - bne a0,v1,1b - LONG_ADDIU a1,BLOCK_SIZE # delay slot -9: - -/* - * We've got upto 31 bytes left to copy ... - */ -copy_left_over: - beqz v0,3f - nop # delay slot -1: lb $1,(a1) - EX(1b, fault) - LONG_ADDIU a1,1 -2: sb $1,(a0) - EX(2b, fault) - LONG_SUBU v0,1 - bnez v0,1b - LONG_ADDIU a0,1 -3: jr ra - nop # delay slot - - END(__copy_user) - .set at - .set reorder - -/* ---------------------------------------------------------------------- */ - -/* - * Access fault. The number of not copied bytes is in v0. We have to - * correct the number of the not copied bytes in v0 in case of a access - * fault in an unrolled loop, then return. - */ - -fault: jr ra -fault_plus_one_reg: LONG_ADDIU v0,SZREG - jr ra -fault_plus_two_reg: LONG_ADDIU v0,SZREG*2 - jr ra -fault_plus_three_reg: LONG_ADDIU v0,SZREG*3 - jr ra - -/* ---------------------------------------------------------------------- */ - -/* - * For now we use __copy_user for __memcpy, too. This is efficient (one - * instruction penatly) and smaller but adds unwanted error checking we don't - * need. This hopefully doesn't cover any bugs. The memcpy() wrapper in - * <asm/string.h> takes care of the return value in a way GCC can optimize. - */ - .globl __memcpy -__memcpy = __copy_user diff --git a/arch/mips/mips3/memset.c b/arch/mips/mips3/memset.c deleted file mode 100644 index e92a0907f..000000000 --- a/arch/mips/mips3/memset.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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) 1996 by Ralf Baechle - * - * Less stupid memset for 64 bit MIPS CPUs. - */ -#include <linux/linkage.h> -#include <linux/string.h> - -static void __inline__ b_memset(void *s, unsigned long long c, size_t count) -{ - unsigned char *p = s; - - while(count--) - *(p++) = c; -} - -static void __inline__ dw_memset(void *s, unsigned long long c, size_t count) -{ - unsigned long long *p = s; - - count >>= 3; - while(count--) - *(p++) = c; -} - -asm( ".globl\t__generic_memset_b\n\t" - ".align\t2\n\t" - ".type\t__generic_memset_b,@function\n\t" - ".ent\t__generic_memset_b,0\n\t" - ".frame\t$29,0,$31\n" - "__generic_memset_b:\n\t" - "andi\t$5,0xff\n\t" - "dsll\t$2,$5,8\n\t" - "or\t$5,$2\n\t" - "dsll\t$2,$5,16\n\t" - "or\t$5,$2\n\t" - "dsll32\t$2,$5,0\n\t" - "or\t$5,$2\n\t" - ".end\t__generic_memset_b\n\t" - ".size\t__generic_memset_b,.-t__generic_memset_b"); - -/* - * Fill small area bytewise. For big areas fill the source bytewise - * until the pointer is doubleword aligned, then fill in doublewords. - * Fill the rest again in single bytes. - */ -void __generic_memset_dw(void *s, unsigned long long c, size_t count) -{ - unsigned long i; - - /* - * Fill small areas bytewise. - */ - if (count <= 16) { - b_memset(s, c, count); - return; - } - - /* - * Pad for 8 byte boundary - */ - i = 8 - ((unsigned long)s & 7); - b_memset(s, c, i); - s += i; - count -= i; - - /* - * Now start filling with aligned doublewords - */ - dw_memset(s, c, count); - s += (count | 7) ^ 7; - count &= 7; - - /* - * And do what ever is left over again with single bytes. - */ - b_memset(s, c, count); -} diff --git a/arch/mips/mips3/pagetables.c b/arch/mips/mips3/pagetables.c deleted file mode 100644 index e8cb83d03..000000000 --- a/arch/mips/mips3/pagetables.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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) 1996 Ralf Baechle - * - * Functions that manipulate entire pages. - * - * Not nice to have all these functions in two versions for cpus with - * different cache line size but it seems to be by far the fastest thing - * to schedule the cache instructions immediately before the store - * instructions. For example using the clear_page() version for 16 byte - * lines on machine with 32 byte lines gives a measured penalty of - * ~1280 cycles per page. - */ -#include <linux/mm.h> -#include <asm/cache.h> -#include <asm/mipsconfig.h> -#include <asm/page.h> -#include <asm/pgtable.h> - -extern unsigned int dflushes; - -/* - * Initialize new page directory with pointers to invalid ptes. - */ -void mips3_pgd_init_32byte_lines(unsigned long page) -{ - unsigned long dummy1, dummy2; - - /* - * We generate dirty lines in the datacache, overwrite them - * then writeback the cache. - */ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "dsll32\t$1,%2,0\n\t" - "dsrl32\t%2,$1,0\n\t" - "or\t%2,$1\n" - "1:\tcache\t%5,(%0)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%2,8(%0)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%2,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%5,-32(%0)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%2,-24(%0)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t%0,%1,1b\n\t" - "sd\t%2,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (dummy1), - "=&r" (dummy2) - :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) | - _PAGE_TABLE), - "0" (page), - "1" (page + PAGE_SIZE - 64), - "i" (Create_Dirty_Excl_D) - :"$1"); - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "1:\tcache\t%3,(%0)\n\t" - "bne\t%0,%1,1b\n\t" - "daddiu\t%0,32\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1) - :"0" (page), - "r" (page + PAGE_SIZE - 32), - "i" (Hit_Writeback_D)); - dflushes++; - -#if 0 - cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL); -#endif -} - -/* - * Initialize new page directory with pointers to invalid ptes - */ -void mips3_pgd_init_16byte_lines(unsigned long page) -{ - unsigned long dummy1, dummy2; - - /* - * We generate dirty lines in the datacache, overwrite them - * then writeback the cache. - */ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "dsll32\t$1,%2,0\n\t" - "dsrl32\t%2,$1,0\n\t" - "or\t%2,$1\n" - "1:\tcache\t%5,(%0)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%2,8(%0)\n\t" - "cache\t%5,16(%0)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%2,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%5,-32(%0)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%2,-24(%0)\n\t" - "cache\t%5,-16(%0)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t%0,%1,1b\n\t" - "sd\t%2,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (dummy1), - "=&r" (dummy2) - :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) | - _PAGE_TABLE), - "0" (page), - "1" (page + PAGE_SIZE - 64), - "i" (Create_Dirty_Excl_D) - :"$1"); - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "1:\tcache\t%3,(%0)\n\t" - "bne\t%0,%1,1b\n\t" - "daddiu\t%0,16\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1) - :"0" (page), - "r" (page + PAGE_SIZE - 16), - "i" (Hit_Writeback_D)); - dflushes++; - -#if 0 - cacheflush(page, PAGE_SIZE, CF_DCACHE|CF_VIRTUAL); -#endif -} - -/* - * Zero an entire page. - */ - -void (*clear_page)(unsigned long page); - -void mips3_clear_page_32byte_lines(unsigned long page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - -void mips3_clear_page_16byte_lines(unsigned long page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - -/* - * This is still inefficient. We only can do better if we know the - * virtual address where the copy will be accessed. - */ -void (*copy_page)(unsigned long to, unsigned long from); - -void mips3_copy_page_32byte_lines(unsigned long to, unsigned long from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "ld\t%4,16(%1)\n\t" - "ld\t%5,24(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "sd\t%4,16(%0)\n\t" - "sd\t%5,24(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "ld\t%4,-16(%1)\n\t" - "ld\t%5,-8(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "sd\t%4,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t%5,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -void mips3_copy_page_16byte_lines(unsigned long to, unsigned long from) -{ - unsigned dummy1, dummy2; - unsigned long reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "cache\t%7,16(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "cache\t%7,-16(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} diff --git a/arch/mips/mips3/r4xx0.S b/arch/mips/mips3/r4xx0.S deleted file mode 100644 index a282998ac..000000000 --- a/arch/mips/mips3/r4xx0.S +++ /dev/null @@ -1,841 +0,0 @@ -/* - * arch/mips/mips3/r4xx0.S - * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse - * - * This file contains most of the R4xx0 specific routines. Due to the - * similarities this should hopefully also be fine for the R10000. For - * now we especially support the R10000 by not invalidating entries out of - * the TLB before calling the C handlers. - * - * This code is evil magic. Read appendix F (coprocessor 0 hazards) of - * all R4xx0 manuals and think about that MIPS means "Microprocessor without - * Interlocked Pipeline Stages" before you even think about changing this code! - * - * CAVEATS: The R4000/R4400/R4600 manual say that the operation of a memory - * reference associated with a instruction immediately after a tlpb - * instruction is undefined. It seems that the R4600 v2.0 also - * failes to handle the case where a tlbp instruction follows a - * (mapped???) memory reference. In this case c0_index gets - * overwritten by some value which I suppose to be the entry - * mapping the associated instruction's memory reference. - * - * This needs a complete overhaul; it was written for a Linux kernel that - * handled it's page tables the old i386 way ... - */ -#include <linux/config.h> - -#include <asm/asm.h> -#include <asm/bootinfo.h> -#include <asm/cache.h> -#include <asm/fpregdef.h> -#include <asm/mipsconfig.h> -#include <asm/mipsregs.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/regdef.h> -#include <asm/stackframe.h> - -/* - * Use this to activate extra TLB error checking - */ -#define CONF_DEBUG_TLB - -/* - * Use this to activate extra TLB profiling code - * (not implemented yet) - */ -#undef CONF_PROFILE_TLB - -#ifdef __SMP__ -#error "Fix this for SMP" -#else -#define current current_set -#endif - -MODE_ALIAS = 0x0016 # uncachable - - .text - .set noreorder - - .align 5 - NESTED(handle_tlbl, FR_SIZE, sp) - .set noat - /* - * Check whether this is a refill or an invalid exception - * - * NOTE: Some MIPS manuals say that the R4x00 sets the - * BadVAddr only when EXL == 0. This is wrong - BadVAddr - * is being set for all Reload, Invalid and Modified - * exceptions. - */ - mfc0 k0,CP0_BADVADDR - mfc0 k1,CP0_ENTRYHI - ori k0,0x1fff - xori k0,0x1fff - andi k1,0xff - or k0,k1 - mfc0 k1,CP0_ENTRYHI - mtc0 k0,CP0_ENTRYHI - nop # for R4[04]00 pipeline - nop - nop - nop - tlbp - nop - nop # for R4[04]00 pipeline - nop - mfc0 k0,CP0_INDEX - bgez k0,invalid_tlbl # bad addr in c0_badvaddr - mtc0 k1,CP0_ENTRYHI # delay slot - /* - * Damn... The next nop is required on my R4400PC V5.0, but - * I don't know why - at least there is no documented - * reason as for the others :-( - */ - nop - -#ifdef CONF_DEBUG_TLB - /* - * OK, this is a double fault. Let's see whether this is - * due to an invalid entry in the page_table. - */ - dmfc0 k0,CP0_BADVADDR - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - andi k1,(_PAGE_PRESENT|_PAGE_ACCESSED) - bnez k1,reload_pgd_entries - nop # delay slot - - .set noat - SAVE_ALL - .set at - PRINT("Double fault caused by invalid entries in pgd:\n") - dmfc0 a1,CP0_BADVADDR - PRINT("Double fault address : %016Lx\n") - dmfc0 a1,CP0_EPC - PRINT("c0_epc : %016Lx\n") - jal show_regs - move a0,sp - jal dump_tlb_nonwired - nop - dmfc0 a0,CP0_BADVADDR - jal dump_list_current - nop - .set noat - STI - .set at - PANIC("Corrupted pagedir") - .set noat - -reload_pgd_entries: -#endif /* CONF_DEBUG_TLB */ - - /* - * Load missing pair of entries from the pgd and return. - */ - dmfc0 k1,CP0_CONTEXT -// mfc0 k1,CP0_CONTEXT - dsra k1,1 - lwu k0,(k1) # Never causes nested exception - lwu k1,4(k1) - dsrl k0,6 # Convert to EntryLo format - dsrl k1,6 # Convert to EntryLo format - dmtc0 k0,CP0_ENTRYLO0 - dmtc0 k1,CP0_ENTRYLO1 - nop # for R4[04]00 pipeline - tlbwr - nop # for R4[04]00 pipeline - nop - nop - /* - * We don't know whether the original access was read or - * write, so return and see what happens... - */ - eret - - /* - * Handle invalid exception - * - * There are two possible causes for an invalid (tlbl) - * exception: - * 1) pages with present bit set but the valid bit clear - * 2) nonexistant pages - * Case one needs fast handling, therefore don't save - * registers yet. - * - * k0 contains c0_index. - */ -invalid_tlbl: -#ifdef CONFIG_TLB_SHUTDOWN - /* - * Remove entry so we don't need to care later - * For sake of the R4000 V2.2 pipeline the tlbwi insn - * has been moved down. Moving it around is juggling with - * explosives... - */ - lui k1,0x0008 - or k0,k1 - dsll k0,13 - dmtc0 k0,CP0_ENTRYHI - dmtc0 zero,CP0_ENTRYLO0 - dmtc0 zero,CP0_ENTRYLO1 -#endif - /* - * Test present bit in entry - */ - dmfc0 k0,CP0_BADVADDR - srl k0,12 - sll k0,2 -#ifdef CONFIG_TLB_SHUTDOWN - tlbwi # do not move! -#endif - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - andi k1,(_PAGE_PRESENT|_PAGE_READ) - xori k1,(_PAGE_PRESENT|_PAGE_READ) - bnez k1,nopage_tlbl - /* - * Present and read bits are set -> set valid and accessed bits - */ - lw k1,(k0) # delay slot - ori k1,(_PAGE_VALID|_PAGE_ACCESSED) - sw k1,(k0) - eret - - /* - * Page doesn't exist. Lots of work which is less important - * for speed needs to be done, so hand it all over to the - * kernel memory management routines. - */ -nopage_tlbl: SAVE_ALL - dmfc0 a2,CP0_BADVADDR - STI - REG_S sp,FR_ORIG_REG2(sp) - .set at - /* - * a0 (struct pt_regs *) regs - * a1 (unsigned long) 0 for read access - * a2 (unsigned long) faulting virtual address - */ - move a0,sp - jal do_page_fault - li a1,0 # delay slot - j ret_from_sys_call - nop # delay slot - END(handle_tlbl) - - .text - .align 5 - NESTED(handle_tlbs, FR_SIZE, sp) - .set noat - /* - * It is impossible that is a nested reload exception. - * Therefore this must be a invalid exception. - * Two possible cases: - * 1) Page exists but not dirty. - * 2) Page doesn't exist yet. Hand over to the kernel. - * - * Test whether present bit in entry is set - */ - dmfc0 k0,CP0_BADVADDR - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - nop - nop - tlbp # find faulting entry - nop - andi k1,(_PAGE_PRESENT|_PAGE_WRITE) - xori k1,(_PAGE_PRESENT|_PAGE_WRITE) - bnez k1,nopage_tlbs - /* - * Present and writable bits set: set accessed and dirty bits. - */ - lw k1,(k0) # delay slot - ori k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \ - _PAGE_VALID|_PAGE_DIRTY) - sw k1,(k0) - /* - * Now reload the entry into the TLB - */ - ori k0,0x0004 - xori k0,0x0004 - lw k1,4(k0) - lw k0,(k0) - srl k1,6 - srl k0,6 - dmtc0 k1,CP0_ENTRYLO1 - dmtc0 k0,CP0_ENTRYLO0 - nop # for R4[04]00 pipeline - tlbwi - nop # for R4[04]00 pipeline - nop - nop - eret - - /* - * Page doesn't exist. Lots of work which is less important - * for speed needs to be done, so hand it all over to the - * kernel memory management routines. - */ -nopage_tlbs: -nowrite_mod: -#ifdef CONFIG_TLB_SHUTDOWN - /* - * Remove entry so we don't need to care later - */ - mfc0 k0,CP0_INDEX -#ifdef CONF_DEBUG_TLB - bgez k0,2f - nop - /* - * We got a tlbs exception but found no matching entry in - * the tlb. This should never happen. Paranoia makes us - * check it, though. - */ - SAVE_ALL - jal show_regs - move a0,sp - .set at - dmfc0 a1,CP0_BADVADDR - PRINT("c0_badvaddr == %016Lx\n") - mfc0 a1,CP0_INDEX - PRINT("c0_index == %08x\n") - dmfc0 a1,CP0_ENTRYHI - PRINT("c0_entryhi == %016Lx\n") - .set noat - STI - .set at - PANIC("Tlbs or tlbm exception with no matching entry in tlb") -1: j 1b - nop -2: -#endif /* CONF_DEBUG_TLB */ - lui k1,0x0008 - or k0,k1 - dsll k0,13 - dmtc0 k0,CP0_ENTRYHI - dmtc0 zero,CP0_ENTRYLO0 - dmtc0 zero,CP0_ENTRYLO1 - nop # for R4[04]00 pipeline - nop # R4000 V2.2 requires 4 NOPs - nop - nop - tlbwi -#endif /* CONFIG_TLB_SHUTDOWN */ - .set noat - SAVE_ALL - dmfc0 a2,CP0_BADVADDR - STI - REG_S sp,FR_ORIG_REG2(sp) - .set at - /* - * a0 (struct pt_regs *) regs - * a1 (unsigned long) 1 for write access - * a2 (unsigned long) faulting virtual address - */ - move a0,sp - jal do_page_fault - li a1,1 # delay slot - j ret_from_sys_call - nop # delay slot - END(handle_tlbs) - - .align 5 - NESTED(handle_mod, FR_SIZE, sp) - .set noat - /* - * Two possible cases: - * 1) Page is writable but not dirty -> set dirty and return - * 2) Page is not writable -> call C handler - */ - dmfc0 k0,CP0_BADVADDR - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - nop - nop - tlbp # find faulting entry - nop - andi k1,_PAGE_WRITE - beqz k1,nowrite_mod - /* - * Present and writable bits set: set accessed and dirty bits. - */ - lw k1,(k0) # delay slot - ori k1,(_PAGE_ACCESSED|_PAGE_DIRTY) - sw k1,(k0) - /* - * Now reload the entry into the tlb - */ - ori k0,0x0004 - xori k0,0x0004 - lw k1,4(k0) - lw k0,(k0) - srl k1,6 - srl k0,6 - dmtc0 k1,CP0_ENTRYLO1 - dmtc0 k0,CP0_ENTRYLO0 - nop # for R4[04]00 pipeline - nop - nop - tlbwi - nop # for R4[04]00 pipeline - nop - nop - eret - END(handle_mod) - .set at - -/* - * Flush the complete TLB - */ - .set noreorder - LEAF(tlbflush) - li t0,PM_4K - mtc0 t0,CP0_PAGEMASK - lw t0,mips_tlb_entries /* mips_tlb_enbtries is set */ - /* by bi_EarlySnarf() */ - dmtc0 zero,CP0_ENTRYLO0 - dmtc0 zero,CP0_ENTRYLO1 - mfc0 t2,CP0_WIRED -1: subu t0,1 - mtc0 t0,CP0_INDEX - lui t1,0x0008 - or t1,t0,t1 - dsll t1,13 - dmtc0 t1,CP0_ENTRYHI - bne t2,t0,1b - tlbwi # delay slot - jr ra - nop # delay slot - END(tlbflush) - -/* - * Flush a single entry from the TLB - * - * Parameters: a0 - unsigned long address - */ - .set noreorder - LEAF(tlbflush_page) - /* - * Step 1: Wipe out old TLB information. Not shure if - * we really need that step; call it paranoia ... - * In order to do that we need to disable interrupts. - */ - li t3,TLBMAP # then wait 3 cycles - ori t1,a0,0xfff # mask off low 12 bits - xori t1,0xfff - mfc0 t2,CP0_ENTRYHI # copy ASID into address - andi t2,0xff - or t2,t1 - mtc0 t2,CP0_ENTRYHI - srl t4,a0,12 # wait again three cycles - sll t4,t4,PTRLOG - dmtc0 zero,CP0_ENTRYLO0 - nop - tlbp # now query the TLB - nop - addu t3,t4 # wait another three cycles - ori t3,0xffff - xori t3,0xffff - mfc0 t1,CP0_INDEX - bltz t1,1f # No old entry? - dmtc0 zero,CP0_ENTRYLO1 - or t3,t1 # wait one cycle - tlbwi - /* - * But there still might be an entry for the pgd ... - */ -1: mtc0 t3,CP0_ENTRYHI - nop # wait 3 cycles - nop - nop - nop - tlbp # TLB lookup - nop - nop - nop - mfc0 t1,CP0_INDEX # wait 3 cycles - bltz t1,1f # No old entry? - nop - tlbwi # gotcha ... -1: jr ra - nop # delay slot - END(tlbflush_page) - -/* - * Code necessary to switch tasks on an Linux/MIPS machine. - * FIXME: We don't need to disable interrupts anymore. - * FIXME: Do some cache magic for faster loading/saving. - */ - .align 5 - LEAF(resume) - /* - * Current task's task_struct - */ - lui t5,%hi(current) - lw t0,%lo(current)(t5) - - /* - * Save status register - */ - mfc0 t1,CP0_STATUS - addu t0,a1 # Add tss offset - sw t1,TOFF_CP0_STATUS(t0) - - /* - * Disable interrupts - */ - ori t2,t1,0x1f - xori t2,0x1e - mtc0 t2,CP0_STATUS - - /* - * Save non-scratch registers - * All other registers have been saved on the kernel stack - */ - sd s0,TOFF_REG16(t0) - sd s1,TOFF_REG17(t0) - sd s2,TOFF_REG18(t0) - sd s3,TOFF_REG19(t0) - sd s4,TOFF_REG20(t0) - sd s5,TOFF_REG21(t0) - sd s6,TOFF_REG22(t0) - sd s7,TOFF_REG23(t0) - sd gp,TOFF_REG28(t0) - sd sp,TOFF_REG29(t0) - sd fp,TOFF_REG30(t0) - - /* - * Save floating point state - */ - sll t2,t1,2 - bgez t2,2f - sd ra,TOFF_REG31(t0) # delay slot - sll t2,t1,5 - bgez t2,1f - sdc1 $f0,(TOFF_FPU+0)(t0) # delay slot - /* - * Store the 16 odd double precision registers - */ - sdc1 $f1,(TOFF_FPU+8)(t0) - sdc1 $f3,(TOFF_FPU+24)(t0) - sdc1 $f5,(TOFF_FPU+40)(t0) - sdc1 $f7,(TOFF_FPU+56)(t0) - sdc1 $f9,(TOFF_FPU+72)(t0) - sdc1 $f11,(TOFF_FPU+88)(t0) - sdc1 $f13,(TOFF_FPU+104)(t0) - sdc1 $f15,(TOFF_FPU+120)(t0) - sdc1 $f17,(TOFF_FPU+136)(t0) - sdc1 $f19,(TOFF_FPU+152)(t0) - sdc1 $f21,(TOFF_FPU+168)(t0) - sdc1 $f23,(TOFF_FPU+184)(t0) - sdc1 $f25,(TOFF_FPU+200)(t0) - sdc1 $f27,(TOFF_FPU+216)(t0) - sdc1 $f29,(TOFF_FPU+232)(t0) - sdc1 $f31,(TOFF_FPU+248)(t0) - - /* - * Store the 16 even double precision registers - */ -1: cfc1 t1,fcr31 - sdc1 $f2,(TOFF_FPU+16)(t0) - sdc1 $f4,(TOFF_FPU+32)(t0) - sdc1 $f6,(TOFF_FPU+48)(t0) - sdc1 $f8,(TOFF_FPU+64)(t0) - sdc1 $f10,(TOFF_FPU+80)(t0) - sdc1 $f12,(TOFF_FPU+96)(t0) - sdc1 $f14,(TOFF_FPU+112)(t0) - sdc1 $f16,(TOFF_FPU+128)(t0) - sdc1 $f18,(TOFF_FPU+144)(t0) - sdc1 $f20,(TOFF_FPU+160)(t0) - sdc1 $f22,(TOFF_FPU+176)(t0) - sdc1 $f24,(TOFF_FPU+192)(t0) - sdc1 $f26,(TOFF_FPU+208)(t0) - sdc1 $f28,(TOFF_FPU+224)(t0) - sdc1 $f30,(TOFF_FPU+240)(t0) - sw t1,(TOFF_FPU+256)(t0) - - /* - * Switch current task - */ -2: sw a0,%lo(current)(t5) - addu a0,a1 # Add tss offset - - /* - * Switch address space - */ - - /* - * (Choose new ASID for process) - * This isn't really required, but would speed up - * context switching. - */ - - /* - * Switch the root pointer - */ - lw t0,TOFF_PG_DIR(a0) - li t1,TLB_ROOT - mtc0 t1,CP0_ENTRYHI - mtc0 zero,CP0_INDEX - srl t0,6 - ori t0,MODE_ALIAS - mtc0 t0,CP0_ENTRYLO0 - mtc0 zero,CP0_ENTRYLO1 - lw a2,TOFF_CP0_STATUS(a0) - - /* - * Flush tlb - * (probably not needed, doesn't clobber a0-a3) - */ - jal tlbflush - tlbwi # delay slot - - /* - * Restore fpu state: - * - cp0 status register bits - * - fp gp registers - * - cp1 status/control register - */ - ori t1,a2,1 # pipeline magic - xori t1,1 - mtc0 t1,CP0_STATUS - sll t0,a2,2 - bgez t0,2f - sll t0,a2,5 # delay slot - bgez t0,1f - ldc1 $f0,(TOFF_FPU+0)(a0) # delay slot - /* - * Restore the 16 odd double precision registers only - * when enabled in the cp0 status register. - */ - ldc1 $f1,(TOFF_FPU+8)(a0) - ldc1 $f3,(TOFF_FPU+24)(a0) - ldc1 $f5,(TOFF_FPU+40)(a0) - ldc1 $f7,(TOFF_FPU+56)(a0) - ldc1 $f9,(TOFF_FPU+72)(a0) - ldc1 $f11,(TOFF_FPU+88)(a0) - ldc1 $f13,(TOFF_FPU+104)(a0) - ldc1 $f15,(TOFF_FPU+120)(a0) - ldc1 $f17,(TOFF_FPU+136)(a0) - ldc1 $f19,(TOFF_FPU+152)(a0) - ldc1 $f21,(TOFF_FPU+168)(a0) - ldc1 $f23,(TOFF_FPU+184)(a0) - ldc1 $f25,(TOFF_FPU+200)(a0) - ldc1 $f27,(TOFF_FPU+216)(a0) - ldc1 $f29,(TOFF_FPU+232)(a0) - ldc1 $f31,(TOFF_FPU+248)(a0) - - /* - * Restore the 16 even double precision registers - * when cp1 was enabled in the cp0 status register. - */ -1: lw t0,(TOFF_FPU+256)(a0) - ldc1 $f2,(TOFF_FPU+16)(a0) - ldc1 $f4,(TOFF_FPU+32)(a0) - ldc1 $f6,(TOFF_FPU+48)(a0) - ldc1 $f8,(TOFF_FPU+64)(a0) - ldc1 $f10,(TOFF_FPU+80)(a0) - ldc1 $f12,(TOFF_FPU+96)(a0) - ldc1 $f14,(TOFF_FPU+112)(a0) - ldc1 $f16,(TOFF_FPU+128)(a0) - ldc1 $f18,(TOFF_FPU+144)(a0) - ldc1 $f20,(TOFF_FPU+160)(a0) - ldc1 $f22,(TOFF_FPU+176)(a0) - ldc1 $f24,(TOFF_FPU+192)(a0) - ldc1 $f26,(TOFF_FPU+208)(a0) - ldc1 $f28,(TOFF_FPU+224)(a0) - ldc1 $f30,(TOFF_FPU+240)(a0) - ctc1 t0,fcr31 - - /* - * Restore non-scratch registers - */ -2: ld s0,TOFF_REG16(a0) - ld s1,TOFF_REG17(a0) - ld s2,TOFF_REG18(a0) - ld s3,TOFF_REG19(a0) - ld s4,TOFF_REG20(a0) - ld s5,TOFF_REG21(a0) - ld s6,TOFF_REG22(a0) - ld s7,TOFF_REG23(a0) - ld gp,TOFF_REG28(a0) - ld sp,TOFF_REG29(a0) - ld fp,TOFF_REG30(a0) - ld ra,TOFF_REG31(a0) - - /* - * Restore status register - */ - lw t0,TOFF_KSP(a0) - sw t0,kernelsp - - jr ra - mtc0 a2,CP0_STATUS # delay slot - END(resume) - -/* - * Load a new root pointer into the tlb - */ - .set noreorder - LEAF(load_pgd) - /* - * Switch the root pointer - */ - mfc0 t0,CP0_STATUS - ori t1,t0,1 - xori t1,1 - mtc0 t1,CP0_STATUS - srl a0,6 - ori a0,MODE_ALIAS - li t1,TLB_ROOT - mtc0 t1,CP0_ENTRYHI - mtc0 zero,CP0_INDEX - mtc0 a0,CP0_ENTRYLO0 - mtc0 zero,CP0_ENTRYLO1 - mtc0 t0,CP0_STATUS - jr ra - tlbwi # delay slot - END(load_pgd) - -/* - * do_syscall calls the function in a1 with upto 7 arguments. If over - * four arguments are being requested, the additional arguments will - * be copied from the user stack pointed to by a0->reg29. - * - * FIXME: This function will fail for syscalls with more than four - * arguments from kernelspace. - * - * a0 (struct pt_regs *) pointer to user registers - * a1 (syscall_t) pointer to syscall to do - * a2 (int) number of arguments to syscall - */ -#if defined (__MIPSEB__) && defined (__mips64) -#define bo 4 -#else -#define bo 0 -#endif - .set reorder - .text -NESTED(do_syscalls, 64, sp) - LONG_SUBU sp,64 - REG_S ra,56(sp) - dsll a2,a2,PTRLOG - lw t1,dst(a2) - move t2,a1 - REG_L t0,FR_REG29(a0) # get old user stack pointer - jalr t1 - -7: lw t1,24+bo(t0) # parameter #7 from usp - REG_S t1,SZREG*6(sp) -6: lw t1,20+bo(t0) # parameter #6 from usp - REG_S t1,SZREG*5(sp) -5: lw t1,16+bo(t0) # parameter #5 from usp - REG_S t1,SZREG*4(sp) - -4: lw a3,FR_REG7+bo(a0) # 4 args -3: lw a2,FR_REG6+bo(a0) # 3 args -2: lw a1,FR_REG5+bo(a0) # 2 args -1: lw a0,FR_REG4+bo(a0) # 1 args - jalr t2 - ld ra,56(sp) - addiu sp,64 - jr ra -0: jalr t2 # 0 args, just pass a0 - ld ra,56(sp) - LONG_ADDIU sp,64 - jr ra - END(do_syscalls) - - .rdata - .align PTRLOG -dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b - - .section __ex_table,"a" - PTR 7b,bad_stack - PTR 6b,bad_stack - PTR 5b,bad_stack - .text - -#ifdef CONFIG_REVERSE - -/* - * Same as above but for processes running with reverse byte order. - * When exec(2)ing a file the system detects normal/reverse byteorder in - * an executable and - * - sets the appropriate vector for syscalls and other low level - * routines that depend of userspace byteorder. - * - set the reverse byteorder flag in c0_status - * - marks the process as reverse in the process table. - */ -#define REG_SWAP(r,t) \ - .set push; \ - .set noat; \ - sll $1,r,24; \ - andi t,r,0xff00; \ - sll t,$t,8; \ - or $1,t; \ - srl t,r,8; \ - andi t,$t,0xff00; \ - or $1,t; \ - srl r,r,24; \ - or $1,r; \ - .set pop - - .set reorder - .text -NESTED(do_syscalls_rev, 64, sp) - LONG_SUBU sp,64 - REG_S ra,56(sp) - dsll a2,a2,PTRLOG - lw t1,dst_rev(a2) - move t2,a1 - REG_L t0,FR_REG29(a0) # get old user stack pointer - jalr t1 - -7: lw t1,24+bo(t0) # parameter #7 from usp - REG_SWAP(t1,v0) # convert byteorder - REG_S t1,SZREG*6(sp) -6: lw t1,20+bo(t0) # parameter #6 from usp - REG_SWAP(t1,v0) # convert byteorder - REG_S t1,SZREG*5(sp) -5: lw t1,16+bo(t0) # parameter #5 from usp - REG_SWAP(t1,v0) # convert byteorder - REG_S t1,SZREG*4(sp) - -4: lw a3,FR_REG7+bo(a0) # 4 args -3: lw a2,FR_REG6+bo(a0) # 3 args -2: lw a1,FR_REG5+bo(a0) # 2 args -1: lw a0,FR_REG4+bo(a0) # 1 args - jalr t2 - ld ra,56(sp) - addiu sp,64 - jr ra -0: jalr t2 # 0 args, just pass a0 - ld ra,56(sp) - LONG_ADDIU sp,64 - jr ra - END(do_syscalls) - - .rdata - .align PTRLOG -dst_rev: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b - - .section __ex_table,"a" - PTR 7b,bad_stack - PTR 6b,bad_stack - PTR 5b,bad_stack - .text - -#endif /* CONFIG_REVERSE */ diff --git a/arch/mips/mips3/showregs.c b/arch/mips/mips3/showregs.c deleted file mode 100644 index 651cb6a24..000000000 --- a/arch/mips/mips3/showregs.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * linux/arch/mips/mips3/showregs.c - * - * Copyright (C) 1995, 1996 Ralf Baechle - */ -#include <linux/kernel.h> -#include <linux/ptrace.h> - -void show_regs(struct pt_regs * regs) -{ - /* - * Saved main processor registers - */ - printk("$0 : %016Lx %016Lx %016Lx %016Lx\n", - 0ULL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %016Lx %016Lx %016Lx %016Lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %016Lx %016Lx %016Lx %016Lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12: %016Lx %016Lx %016Lx %016Lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16: %016Lx %016Lx %016Lx %016Lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20: %016Lx %016Lx %016Lx %016Lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24: %016Lx %016Lx\n", - regs->regs[24], regs->regs[25]); - printk("$28: %016Lx %016Lx %016Lx %016Lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - - /* - * Saved cp0 registers - */ - printk("epc : %016Lx\nStatus: %08x\nCause : %08x\n", - regs->cp0_epc, regs->cp0_status, regs->cp0_cause); -} |