patch-2.1.44 linux/arch/mips/kernel/r4xx0.S

Next file: linux/arch/mips/kernel/r6000_fpu.S
Previous file: linux/arch/mips/kernel/r4k_switch.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.43/linux/arch/mips/kernel/r4xx0.S linux/arch/mips/kernel/r4xx0.S
@@ -1,829 +0,0 @@
-/*
- * arch/mips/kernel/r4xx0.S
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * Written 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!
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/mipsregs.h>
-#include <asm/segment.h>
-#include <asm/stackframe.h>
-
-#ifdef __SMP__
-#error "Fix this for SMP"
-#else
-#define current current_set
-#endif
-
-MODE_ALIAS	=	0x0016			# uncachable
-
-		.text
-		.set	mips3
-		.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
-		tlbp
-		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     : %08lx\n")
-		dmfc0	a1,CP0_EPC
-		PRINT("c0_epc                   : %08lx\n")
-		jal	show_regs
-		move	a0,sp
-		jal	dump_tlb_all
-		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
-		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) nonexistent 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
-		.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)
-		tlbp					# find faulting entry
-		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
-		mfc0	a1,CP0_BADVADDR
-		PRINT("c0_badvaddr == %08lx\n")
-		mfc0	a1,CP0_INDEX
-		PRINT("c0_index    == %08x\n")
-		mfc0	a1,CP0_ENTRYHI
-		PRINT("c0_entryhi  == %08x\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
-		.set	noat
-		SAVE_ALL
-		dmfc0	a2,CP0_BADVADDR
-		STI
-		.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)
-		tlbp					# find faulting entry
-		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
-
-/*
- * Until SAVE_ALL/RESTORE_ALL handle registers 64-bit wide we have to
- * disable interrupts here.
- */
-		.set	noreorder
-		LEAF(tlbflush)
-		mfc0	t3,CP0_STATUS
-		ori	t4,t3,1
-		xori	t4,1
-		mtc0	t4,CP0_STATUS
-		li	t0,PM_4K
-		mtc0	t0,CP0_PAGEMASK
-		la	t0,boot_info
-		lw	t0,OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-		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
-		mtc0	t3,CP0_STATUS			# delay slot
-		END(tlbflush)
-
-		/*
-		 * Code necessary to switch tasks on an Linux/MIPS machine.
-		 */
-		.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
-		 */
-		sw	s0,TOFF_REG16(t0)
-		sw	s1,TOFF_REG17(t0)
-		sw	s2,TOFF_REG18(t0)
-		sw	s3,TOFF_REG19(t0)
-		sw	s4,TOFF_REG20(t0)
-		sw	s5,TOFF_REG21(t0)
-		sw	s6,TOFF_REG22(t0)
-		sw	s7,TOFF_REG23(t0)
-		sw	gp,TOFF_REG28(t0)
-		sw	sp,TOFF_REG29(t0)
-		sw	fp,TOFF_REG30(t0)
-
-		/*
-		 * Save floating point state
-		 */
-		sll	t2,t1,2
-		bgez	t2,2f
-		sw	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:		lw	s0,TOFF_REG16(a0)
-		lw	s1,TOFF_REG17(a0)
-		lw	s2,TOFF_REG18(a0)
-		lw	s3,TOFF_REG19(a0)
-		lw	s4,TOFF_REG20(a0)
-		lw	s5,TOFF_REG21(a0)
-		lw	s6,TOFF_REG22(a0)
-		lw	s7,TOFF_REG23(a0)
-		lw	gp,TOFF_REG28(a0)
-		lw	sp,TOFF_REG29(a0)
-		lw	fp,TOFF_REG30(a0)
-		lw	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
-		j	tlbflush
-		tlbwi 					# delay slot
-		END(load_pgd)
-
-/*
- * Some bits in the config register
- */
-#define CONFIG_DB       (1<<4)
-#define CONFIG_IB       (1<<5)
-
-/*
- * Flush instruction/data caches
- *
- * Parameters: a0 - starting address to flush
- *             a1 - size of area to be flushed
- *             a2 - which caches to be flushed
- *
- * FIXME:      - ignores parameters in a0/a1
- *             - doesn't know about second level caches
- */
-		.set	noreorder
-		LEAF(sys_cacheflush)
-		andi	t1,a2,DCACHE
-		beqz	t1,do_icache
-		li	t0,KSEG0			# delay slot
-
-		/*
-		 * Writeback data cache, even lines
-		 */
-		li	t1,CACHELINES-1
-1:		cache	Index_Writeback_Inv_D,0(t0)
-		cache	Index_Writeback_Inv_D,32(t0)
-		cache	Index_Writeback_Inv_D,64(t0)
-		cache	Index_Writeback_Inv_D,96(t0)
-		cache	Index_Writeback_Inv_D,128(t0)
-		cache	Index_Writeback_Inv_D,160(t0)
-		cache	Index_Writeback_Inv_D,192(t0)
-		cache	Index_Writeback_Inv_D,224(t0)
-		cache	Index_Writeback_Inv_D,256(t0)
-		cache	Index_Writeback_Inv_D,288(t0)
-		cache	Index_Writeback_Inv_D,320(t0)
-		cache	Index_Writeback_Inv_D,352(t0)
-		cache	Index_Writeback_Inv_D,384(t0)
-		cache	Index_Writeback_Inv_D,416(t0)
-		cache	Index_Writeback_Inv_D,448(t0)
-		cache	Index_Writeback_Inv_D,480(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-		/*
-		 * Writeback data cache, odd lines
-		 * Only needed for 16 byte line size
-		 */
-		mfc0	t1,CP0_CONFIG
-		andi	t1,CONFIG_DB
-		bnez	t1,do_icache
-		li	t1,CACHELINES-1
-1:		cache	Index_Writeback_Inv_D,16(t0)
-		cache	Index_Writeback_Inv_D,48(t0)
-		cache	Index_Writeback_Inv_D,80(t0)
-		cache	Index_Writeback_Inv_D,112(t0)
-		cache	Index_Writeback_Inv_D,144(t0)
-		cache	Index_Writeback_Inv_D,176(t0)
-		cache	Index_Writeback_Inv_D,208(t0)
-		cache	Index_Writeback_Inv_D,240(t0)
-		cache	Index_Writeback_Inv_D,272(t0)
-		cache	Index_Writeback_Inv_D,304(t0)
-		cache	Index_Writeback_Inv_D,336(t0)
-		cache	Index_Writeback_Inv_D,368(t0)
-		cache	Index_Writeback_Inv_D,400(t0)
-		cache	Index_Writeback_Inv_D,432(t0)
-		cache	Index_Writeback_Inv_D,464(t0)
-		cache	Index_Writeback_Inv_D,496(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-do_icache:	andi	t1,a2,ICACHE
-		beqz	t1,done
-
-		/*
-		 * Flush instruction cache, even lines
-		 */
-		lui	t0,0x8000
-		li	t1,CACHELINES-1
-1: 		cache	Index_Invalidate_I,0(t0)	
-		cache	Index_Invalidate_I,32(t0)
-		cache	Index_Invalidate_I,64(t0)
-		cache	Index_Invalidate_I,96(t0)
-		cache	Index_Invalidate_I,128(t0)
-		cache	Index_Invalidate_I,160(t0)
-		cache	Index_Invalidate_I,192(t0)
-		cache	Index_Invalidate_I,224(t0)
-		cache	Index_Invalidate_I,256(t0)
-		cache	Index_Invalidate_I,288(t0)
-		cache	Index_Invalidate_I,320(t0)
-		cache	Index_Invalidate_I,352(t0)
-		cache	Index_Invalidate_I,384(t0)
-		cache	Index_Invalidate_I,416(t0)
-		cache	Index_Invalidate_I,448(t0)
-		cache	Index_Invalidate_I,480(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-		/*
-		 * Flush instruction cache, even lines
-		 * Only needed for 16 byte line size
-		 */
-		mfc0	t1,CP0_CONFIG
-		andi	t1,CONFIG_IB
-		bnez	t1,done
-		li	t1,CACHELINES-1
-1:		cache	Index_Invalidate_I,16(t0)
-		cache	Index_Invalidate_I,48(t0)
-		cache	Index_Invalidate_I,80(t0)
-		cache	Index_Invalidate_I,112(t0)
-		cache	Index_Invalidate_I,144(t0)
-		cache	Index_Invalidate_I,176(t0)
-		cache	Index_Invalidate_I,208(t0)
-		cache	Index_Invalidate_I,240(t0)
-		cache	Index_Invalidate_I,272(t0)
-		cache	Index_Invalidate_I,304(t0)
-		cache	Index_Invalidate_I,336(t0)
-		cache	Index_Invalidate_I,368(t0)
-		cache	Index_Invalidate_I,400(t0)
-		cache	Index_Invalidate_I,432(t0)
-		cache	Index_Invalidate_I,464(t0)
-		cache	Index_Invalidate_I,496(t0)
-		addiu	t0,512
-		bnez	t1,1b
-		subu	t1,1
-
-done:		j	ra
-		nop
-		END(sys_cacheflush)
-
-/*
- * Update the TLB - or how instruction scheduling makes code unreadable ...
- *
- * MIPS doesn't need any external MMU info: the kernel page tables contain
- * all the necessary information.  We use this hook though to load the
- * TLB as early as possible with uptodate information avoiding unnecessary
- * exceptions.
- *
- * Parameters: a0 - struct vm_area_struct *vma	(ignored)
- *             a1 - unsigned long address
- *             a2 - pte_t pte
- */
-		.set	noreorder
-		LEAF(update_mmu_cache)
-		/*
-		 * Step 1: Wipe out old TLB information.  Not sure if
-		 * we really need that step; call it paranoia ...
-		 * In order to do that we need to disable interrupts.
-		 */
-		mfc0	t0,CP0_STATUS		# interrupts off
-		ori	t1,t0,1
-		xori	t1,1
-		mtc0	t1,CP0_STATUS
-		li	t3,TLBMAP		# then wait 3 cycles
-		ori	t1,a1,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,a1,12		# wait again three cycles
-		sll	t4,t4,PTRLOG
-		dmtc0	zero,CP0_ENTRYLO0
-		tlbp				# now query the TLB
-		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 a entry for the pgd ...
-		 */
-1:		mtc0	t3,CP0_ENTRYHI
-		nop				# wait 3 cycles
-		nop
-		nop
-		tlbp				# TLB lookup
-		nop
-		nop
-		mfc0	t1,CP0_INDEX		# wait 3 cycles
-		bltz	t1,1f			# No old entry?
-		nop		
-		tlbwi				# gotcha ...
-		/*
-		 * Step 2: Reload the TLB with new information.  We can skip
-		 * this but this should speed the mess a bit by avoiding
-		 * tlbl/tlbs exceptions. (To be done)
-		 */
-1:		jr	ra
-		mtc0	t0,CP0_STATUS		# delay slot
-		END(update_mmu_cache)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov