diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halntp/mips/j4cache.s | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halntp/mips/j4cache.s')
-rw-r--r-- | private/ntos/nthals/halntp/mips/j4cache.s | 1804 |
1 files changed, 1804 insertions, 0 deletions
diff --git a/private/ntos/nthals/halntp/mips/j4cache.s b/private/ntos/nthals/halntp/mips/j4cache.s new file mode 100644 index 000000000..555a2c8c0 --- /dev/null +++ b/private/ntos/nthals/halntp/mips/j4cache.s @@ -0,0 +1,1804 @@ +// TITLE("Cache Flush") +//++ +// +// Copyright (c) 1991-1993 Microsoft Corporation +// +// Module Name: +// +// j4cache.s +// +// Abstract: +// +// This module implements the code necessary for cache operations on +// a MIPS R4000. +// +// Environment: +// +// Kernel mode only. +// +//-- + +#include "halmips.h" + +// +// Define cache operations constants. +// + +#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache) +#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache) +#define FLUSH_BASE 0xfffe0000 // flush base address +#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) +#define ECACHE_PROTECTION_BITS ((1 << ENTRYLO_V) | (2 << ENTRYLO_C) | (1 << ENTRYLO_D)) +#define ECACHE_CONTROL_PHYSICAL_BASE 0xD0000000 +#define FLUSH_BASE_HACK FLUSH_BASE +#define PMP_CONTROL_VIRTUAL_BASE 0xFFFFC000 +#define PMP_CONTROL_PHYSICAL_BASE 0xC0000000 +#define GLOBAL_CTRL_ECE 0x00800080 + + + SBTTL("Change Color Page") +//++ +// +// VOID +// HalChangeColorPage ( +// IN PVOID NewColor, +// IN PVOID OldColor, +// IN ULONG PageFrame +// ) +// +// Routine Description: +// +// This function changes the color of a page if the old and new colors +// do not match. +// +// The algorithm used to change colors for a page is as follows: +// +// 1. Purge (hit/invalidate) the page from the instruction cache +// using the old color. +// +// 2. Purge (hit/invalidate) the page from the data cache using +// the old color. +// +// Arguments: +// +// NewColor (a0) - Supplies the page aligned virtual address of the +// new color of the page to change. +// +// OldColor (a1) - Supplies the page aligned virtual address of the +// old color of the page to change. +// +// PageFrame (a2) - Supplies the page frame number of the page that +// is changed. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 + .space 3 * 4 // fill +CpRa: .space 4 // saved return address +CpFrameLength: // length of stack frame +CpA0: .space 4 // (a0) +CpA1: .space 4 // (a1) +CpA2: .space 4 // (a2) +CpA3: .space 4 // (a3) + + NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero) + + subu sp,sp,CpFrameLength // allocate stack frame + sw ra,CpRa(sp) // save return address + + PROLOGUE_END + + and a0,a0,COLOR_BITS // isolate new color bits + and a1,a1,COLOR_BITS // isolate old color bits + beq a0,a1,10f // if eq, colors match + sw a1,CpA1(sp) // save old color bits + sw a2,CpA2(sp) // save page frame + +// +// Purge the instruction cache using the old page color. +// + + move a0,a1 // set color value + move a1,a2 // set page frame number + li a2,PAGE_SIZE // set length of purge + jal HalPurgeIcachePage // purge instruction cache page + +// +// Flush the data cache using the old page color. +// + + lw a0,CpA1(sp) // get old color bits + lw a1,CpA2(sp) // get page frame number + li a2,PAGE_SIZE // set length of purge + jal HalFlushDcachePage // purge data cache page +10: lw ra,CpRa(sp) // get return address + addu sp,sp,CpFrameLength // deallocate stack frame + j ra // return + + .end HalChangeColorPage + + SBTTL("Flush Data Cache Page") +//++ +// +// VOID +// HalFlushDcachePage ( +// IN PVOID Color, +// IN ULONG PageFrame, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function flushes (hit/writeback/invalidate) up to a page of data +// from the data cache. +// +// Arguments: +// +// Color (a0) - Supplies the starting virtual address and color of the +// data that is flushed. +// +// PageFrame (a1) - Supplies the page frame number of the page that +// is flushed. +// +// Length (a2) - Supplies the length of the region in the page that is +// flushed. +// +// Return Value: +// +// None. +// +//-- + + + LEAF_ENTRY(HalFlushDcachePage) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + // + // Determine if the ECache is + // present (active) which means + // it is enabled. + // + la t0,HalpPmpExternalCachePresent + lw t0,0(t0) + beq t0,zero, noECacheFlushDcachePage + + DISABLE_INTERRUPTS(t5) // disable interrupts + + // + // Calculate the tlbapping values + // and determine which half of the + // tlb entry to use for the on-chip + // cache. + // + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color and offset bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,11f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +11: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + bnel zero,v0,16f // if ne, second level cache present + move t4,v0 // set flush block size + +16: + + // + // Now calculate the tlb mapping values + // for the ECache invalidate space and + // use the other "unused" tlb entry. + // + li t6, (ECACHE_CONTROL_PHYSICAL_BASE >> 2) + li t7, ((ECACHE_CONTROL_PHYSICAL_BASE >> PAGE_SHIFT) << ENTRYLO_PFN) + or t6, t6, t7 + li t7, (((512*1024)-1) >> PAGE_SHIFT) + and t7, a1, t7 + sll t7, t7, ENTRYLO_PFN + or t6, t6, t7 + li t7, ECACHE_PROTECTION_BITS + or t6, t6, t7 + + move a3, zero + beql t1, zero, 17f + move t1, t6 + + move t2, t6 + addiu a3, a3, 1 + .set at + .set reorder + +// +// Now we actually do the mapping +// by directly writing the TLB +// +17: + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,31f // if eq, no blocks to flush + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + subu t9,t9,t4 // compute ending loop address + + // + // Now we use the mapped + // vaddr based on which half + // of the tlb entry we used + // for the ECache mapping. + // + move t6, t8 + li t7, PAGE_SIZE + beql a3, zero, 21f + subu t6, t6, t7 + + addu t6, t6, t7 + +// +// Flush the primary data cache and +// invalidate the external cache. +// +21: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block + nop + sw zero,0(t6) // ECache line invalidate + addu t6,t6,t4 // compute next address + bne t8,t9,21b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + // + // Now we will mark the ECache page + // invalid before exiting ... + // +31: + .set noreorder + .set noat + +#if 1 + + //mtc0 zero, entrylo0 + //mtc0 zero, entrylo1 + //nop + +#else + beq zero, a3, 22f + nop + + mtc0 zero, entrylo1 + b 23f + nop + +22: + mtc0 zero, entrylo0 + nop + +23: + +#endif + + //nop + //nop + //nop + //tlbwi + //nop + //nop + //nop + + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// This section of code is only executed +// if the processor is not an R4600/R4700 or +// it is an R4600/R4700 but there is no ECache. +// +noECacheFlushDcachePage: + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color and offset bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,10f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +10: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + bnel zero,v0,15f // if ne, second level cache present + move t4,v0 // set flush block size + .set at + .set reorder + +// +// Flush a page from the data cache. +// + +15: DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,30f // if eq, no blocks to flush + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + bne zero,v0,40f // if ne, second level cache present + subu t9,t9,t4 // compute ending loop address + +// +// Flush the primary data cache only. +// + +20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block + bne t8,t9,20b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + +30: ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// Flush the primary and secondary data caches. +// + + .set noreorder + .set noat +40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block + bne t8,t9,40b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + .end HalFlushDcachePage + + + SBTTL("Purge Data Cache Page") +//++ +// +// VOID +// HalPurgeDcachePage ( +// IN PVOID Color, +// IN ULONG PageFrame, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function purges (hit/invalidate) up to a page of data from the +// data cache. +// +// Arguments: +// +// Color (a0) - Supplies the starting virtual address and color of the +// data that is purged. +// +// PageFrame (a1) - Supplies the page frame number of the page that +// is purged. +// +// Length (a2) - Supplies the length of the region in the page that is +// purged. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalPurgeDcachePage) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + // + // Determine if the ECache is + // present (active) which means + // it is enabled. + // + la t0,HalpPmpExternalCachePresent + lw t0,0(t0) + beq t0,zero, noECachePurgeDcachePage + + DISABLE_INTERRUPTS(t5) // disable interrupts + + // + // Calculate the tlb mapping values + // and determine which half of the + // tlb entry to use for the on-chip + // cache. + // + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,11f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +11: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + bnel zero,v0,16f // if ne, second level cache present + move t4,v0 // set purge block size + + // + // Now calculate the tlb mapping values + // for the ECache invalidate space and + // use the other "unused" tlb entry. + // +16: + li t6, (ECACHE_CONTROL_PHYSICAL_BASE >> 2) + li t7, ((ECACHE_CONTROL_PHYSICAL_BASE >> PAGE_SHIFT) << ENTRYLO_PFN) + or t6, t6, t7 + li t7, (((512*1024)-1) >> PAGE_SHIFT) + and t7, a1, t7 + sll t7, t7, ENTRYLO_PFN + or t6, t6, t7 + li t7, ECACHE_PROTECTION_BITS + or t6, t6, t7 + + move a3, zero + beql t1, zero, 17f + move t1, t6 + + move t2, t6 + addiu a3, a3, 1 + .set at + .set reorder + +// +// Now we actually do the mapping +// by directly writing the TLB +// +17: + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,31f // if eq, no blocks to purge + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + subu t9,t9,t4 // compute ending loop address + + // + // Now we use the mapped + // vaddr based on which half + // of the tlb entry we used + // for the ECache mapping. + // + move t6, t8 + li t7, PAGE_SIZE + beql a3, zero, 21f + subu t6, t6, t7 + + addu t6, t6, t7 + +// +// Purge the primary data cache and +// invalidate the external cache. +// +21: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block + nop + sw zero,0(t6) // ECache line invalidate + addu t6,t6,t4 // compute next address + bne t8,t9,21b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + // + // Now we will mark the ECache page + // invalid before exiting ... + // +31: + .set noreorder + .set noat + +#if 1 + + //mtc0 zero, entrylo0 + //mtc0 zero, entrylo1 + //nop + +#else + + beq zero, a3, 22f + nop + + mtc0 zero, entrylo1 + b 23f + nop + +22: + mtc0 zero, entrylo0 + nop + +23: + +#endif + + //nop + //nop + //nop + //tlbwi + //nop + //nop + //nop + + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + +// +// This section of code is only executed +// if the processor is not an R4600/R4700 or +// it is an R4600/R4700 but there is no ECache. +// +noECachePurgeDcachePage: + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,10f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +10: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + bnel zero,v0,15f // if ne, second level cache present + move t4,v0 // set purge block size + .set at + .set reorder + +// +// Purge data from the data cache. +// + +15: DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,30f // if eq, no blocks to purge + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + bne zero,v0,40f // if ne, second level cache present + subu t9,t9,t4 // compute ending loop address + +// +// Purge the primary data cache only. +// + +20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block + bne t8,t9,20b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + +30: ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// Purge the primary and secondary data caches. +// + + .set noreorder + .set noat +40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block + bne t8,t9,40b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + .end HalPurgeDcachePage + + SBTTL("Purge Instruction Cache Page") +//++ +// +// VOID +// HalPurgeIcachePage ( +// IN PVOID Color, +// IN ULONG PageFrame, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function purges (hit/invalidate) up to a page of data from the +// instruction cache. +// +// Arguments: +// +// Color (a0) - Supplies the starting virtual address and color of the +// data that is purged. +// +// PageFrame (a1) - Supplies the page frame number of the page that +// is purged. +// +// Length (a2) - Supplies the length of the region in the page that is +// purged. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalPurgeIcachePage) + +#if DBG + + lw t0,KeIcacheFlushCount // get address of icache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + // + // Determine if the ECache is + // present (active) which means + // it is enabled. + // + la t0,HalpPmpExternalCachePresent + lw t0,0(t0) + beq t0,zero, noECachePurgeIcachePage + + DISABLE_INTERRUPTS(t5) // disable interrupts + + // + // Calculate the tlb mapping values + // and determine which half of the + // tlb entry to use for the on-chip + // cache. + // + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,11f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +11: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size + bnel zero,v0,16f // if ne, second level cache present + move t4,v0 // set purge block size + + // + // Now calculate the tlb mapping values + // for the ECache invalidate space and + // use the other "unused" tlb entry. + // +16: + + li t6, (ECACHE_CONTROL_PHYSICAL_BASE >> 2) + li t7, ((ECACHE_CONTROL_PHYSICAL_BASE >> PAGE_SHIFT) << ENTRYLO_PFN) + or t6, t6, t7 + li t7, (((512*1024)-1) >> PAGE_SHIFT) + and t7, a1, t7 + sll t7, t7, ENTRYLO_PFN + or t6, t6, t7 + li t7, ECACHE_PROTECTION_BITS + or t6, t6, t7 + + move a3, zero + beql t1, zero, 17f + move t1, t6 + + move t2, t6 + addiu a3, a3, 1 + .set at + .set reorder + +// +// Now we actually do the mapping +// by directly writing the TLB +// +17: + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,31f // if eq, no blocks to purge + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + subu t9,t9,t4 // compute ending loop address + + // + // Now we use the mapped + // vaddr based on which half + // of the tlb entry we used + // for the ECache mapping. + // + move t6, t8 + li t7, PAGE_SIZE + beql a3, zero, 21f + subu t6, t6, t7 + + addu t6, t6, t7 + +// +// Purge the primary instruction cache and +// invalidate the external cache. +// +21: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block + nop + sw zero,0(t6) // ECache line invalidate + addu t6,t6,t4 // compute next address + bne t8,t9,21b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + // + // Now we will mark the ECache page + // invalid before exiting ... + // +31: + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// This section of code is only executed +// if the processor is not an R4600/R4700 or +// it is an R4600/R4700 but there is no ECache. +// +noECachePurgeIcachePage: + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,10f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +10: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size + bnel zero,v0,15f // if ne, second level cache present + move t4,v0 // set purge block size + .set at + .set reorder + +// +// Purge data from the instruction cache. +// + +15: DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,30f // if eq, no blocks to purge + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + bne zero,v0,40f // if ne, second level cache present + subu t9,t9,t4 // compute ending loop address + +// +// Purge the primary instruction cache only. +// + +20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block + bne t8,t9,20b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + +30: ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// Purge the primary and secondary instruction caches. +// + + .set noreorder + .set noat +40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block + bne t8,t9,40b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + .end HalPurgeIcachePage + + SBTTL("Sweep Data Cache") +//++ +// +// VOID +// HalpSweepDcache ( +// VOID +// ) +// +// Routine Description: +// +// This function sweeps (index/writeback/invalidate) the entire data cache. +// +// Arguments: +// +// a0 contains the virtual address of the ECache invalidate +// register (if enabled); otherwise, it is NULL. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpSweepDcache) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + // + // Determine if ECache is active + // + .set noreorder + .set noat + beq a0, zero, noECacheSweepDcache + nop + + // + // Get vaddr of ECache invalidate register + // + lw t2, HalpExtPmpControl + .set at + .set reorder + +////////////////////////////////////////////////////////////////////////// +// +// This section is executed only +// if the sweep routine was called +// via HalFlushIoBuffer() +// +////////////////////////////////////////////////////////////////////////// +ECacheSweepDcache: + + DISABLE_INTERRUPTS(t5) + + lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size + lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + // + // Determine if this is an R4600/R4700 + // and if so then we need to deal + // with the two-way set associativity. + // + .set noreorder + .set noat + mfc0 t3, prid + nop + nop + nop + li t0, 2 + srl t3, t3, 12 + bne t3, t0, 60f + nop + .set at + .set reorder + +// +// Sweep the primary data cache (R4600/R4700 only). +// + + .set noreorder + .set noat +50: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + nop // fill + cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index + bne a0,a1,50b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + // + // Invalidate the ECache + // + lb t1, 0(t2) // External PMP Control + ori t1, t1, 1 + sb t1, 0(t2) + andi t1, t1, 0xFE + sb t1, 0(t2) + ori t1, t1, 1 + sb t1, 0(t2) + lb zero, 0(t2) // External cache INVALIDATED + + ENABLE_INTERRUPTS(t5) + + j ra + +// +// Sweep the primary data cache (except R4600/R4700). +// + .set noreorder + .set noat +60: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + bne a0,a1,60b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + // + // Invalidate the ECache + // + lb t1, 0(t2) // External PMP Control + ori t1, t1, 1 + sb t1, 0(t2) + andi t1, t1, 0xFE + sb t1, 0(t2) + ori t1, t1, 1 + sb t1, 0(t2) + lb zero, 0(t2) // External cache INVALIDATED + + ENABLE_INTERRUPTS(t5) + + j ra + +////////////////////////////////////////////////////////////// +// +// This section of code is executed +// there is no ECache active ... +// +////////////////////////////////////////////////////////////// +noECacheSweepDcache: + + lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size + lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + // + // Determine if this is an R4600/R4700 + // and if so then we need to deal + // with the two-way set associativity. + // + .set noreorder + .set noat + mfc0 t3, prid + nop + nop + nop + li t0, 2 + srl t3, t3, 12 + bne t3, t0, 10f + nop + .set at + .set reorder + +// +// Sweep the primary data cache (R4600/R4700 only). +// + + DISABLE_INTERRUPTS(t5) + + .set noreorder + .set noat +50: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + nop // fill + cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index + bne a0,a1,50b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) + + j ra // return + +// +// Sweep the primary data cache (except R4600/R4700). +// + +10: + DISABLE_INTERRUPTS(t5) + + .set noreorder + .set noat +11: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + bne a0,a1,11b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size + lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size + beq zero,t1,40f // if eq, no second level cache + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + +// +// Sweep the secondary data cache (except R4600/R4700). +// + + .set noreorder + .set noat +20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index + bne a0,a1,20b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + +40: + ENABLE_INTERRUPTS(t5) + + j ra // return + + .end HalpSweepDcache + + SBTTL("Sweep Data Cache Range") +//++ +// +// VOID +// HalSweepDcacheRange ( +// IN PVOID BaseAddress, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function sweeps (index/writeback/invalidate) the specified range +// of virtual addresses from the primary data cache. +// +// Arguments: +// +// BaseAddress (a0) - Supplies the base address of the range that is swept +// from the data cache. +// +// Length (a1) - Supplies the length of the range that is swept from the +// data cache. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalSweepDcacheRange) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result conditionally + +#endif + + and a0,a0,COLOR_MASK // isolate color and offset bits + or a0,a0,KSEG0_BASE // convert to physical address + lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size + addu a1,a0,a1 // compute ending cache address + subu a1,a1,t0 // compute ending block address + + // + // Determine if this is an R4600/R4700 + // and if so then we need to deal + // with the two-way set associativity. + // + .set noreorder + .set noat + mfc0 t1, prid + nop + nop + nop + li t2, 2 + srl t1, t1, 12 + bne t1, t2, 20f + nop + .set at + .set reorder + +// +// Sweep the primary data cache (only R4600/R4700). +// + + DISABLE_INTERRUPTS(t5) + + .set noreorder + .set noat +10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + nop + cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // do other set on Orion + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t0 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) + + j ra + +// +// Sweep the primary data cache (except R4600/R4700). +// + .set noreorder + .set noat +20: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + bne a0,a1,20b // if ne, more to invalidate + addu a0,a0,t0 // compute address of next block + .set at + .set reorder + + j ra // return + + .end HalSweepDcacheRange + + SBTTL("Sweep Instruction Cache") +//++ +// +// VOID +// HalpSweepIcache ( +// VOID +// ) +// +// Routine Description: +// +// This function sweeps (index/invalidate) the entire instruction cache. +// +// Arguments: +// +// a0 contains the virtual address of the ECache invalidate +// register (if enabled); otherwise, it is NULL. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpSweepIcache) + +#if DBG + + lw t0,KeIcacheFlushCount // get address of icache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + // + // Determine if ECache is active + // + .set noreorder + .set noat + beq a0, zero, noECacheSweepIcache + nop + + // + // Get vaddr of ECache invalidate register + // + lw t2, HalpExtPmpControl + .set at + .set reorder + +// +// Invalidate the External Cache +// +ECacheSweepIcache: + + DISABLE_INTERRUPTS(t5) // disable interrupts + + lb t1, 4(t2) + ori t1, t1, 1 + sb t1, 4(t2) + andi t1, t1, 0xFE + sb t1, 4(t2) + ori t1, t1, 1 + sb t1, 4(t2) + lb zero, 4(t2) // ECache INVALIDATED + + + lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size + lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + // + // Determine if this is an R4600/R4700 + // and if so then we need to deal + // with the two-way set associativity. + // + .set noreorder + .set noat + mfc0 t3, prid + nop + nop + nop + li t2, 2 + srl t3, t3, 12 + bne t3, t2, 60f + nop + .set at + .set reorder + +// +// Sweep the primary instruction cache (R4600/R4700 only). +// + + .set noreorder + .set noat +50: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + nop // fill + cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index + bne a0,a1,50b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra + +// +// Sweep the primary instruction cache (except R4600/R4700). +// + .set noreorder + .set noat +60: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + bne a0,a1,60b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) + + j ra + +// +// No ECache section +// +noECacheSweepIcache: + + // + // Determine if this is an R4600/R4700 + // and if so then we need to deal + // with the two-way set associativity. + // + .set noreorder + .set noat + mfc0 t3, prid + nop + nop + nop + li t2, 2 + srl t3, t3, 12 + bne t3, t2, 60f + nop + .set at + .set reorder + +// +// Sweep the primary instruction cache (R4600/R4700 only). +// + lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size + lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + DISABLE_INTERRUPTS(t0) // disable interrupts + + .set noreorder + .set noat +50: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + nop // fill + cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index + bne a0,a1,50b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t0) // enable interrupts + + j ra + +// +// Sweep the secondary instruction cache (except R4600/R4700). +// +60: + DISABLE_INTERRUPTS(t5) + + lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size + lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size + beq zero,t1,20f // if eq, no second level cache + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + .set noreorder + .set noat +10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + +// +// Sweep the primary instruction cache (except R4600/R4700). +// +20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size + lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + .set noreorder + .set noat +40: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + bne a0,a1,40b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) + + j ra // return + + .end HalpSweepIcache + + + SBTTL("Sweep Instruction Cache Range") +//++ +// +// VOID +// HalSweepIcacheRange ( +// IN PVOID BaseAddress, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function sweeps (index/invalidate) the specified range of addresses +// from the instruction cache. +// +// Arguments: +// +// BaseAddress (a0) - Supplies the base address of the range that is swept +// from the instruction cache. +// +// Length (a1) - Supplies the length of the range that is swept from the +// instruction cache. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalSweepIcacheRange) + +#if DBG + + lw t0,KeIcacheFlushCount // get address of icache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + and a0,a0,COLOR_MASK // isolate color and offset bits + or a0,a0,KSEG0_BASE // convert to physical address + lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size + addu a1,a0,a1 // compute ending cache address + subu a1,a1,t0 // compute ending block address + + // + // Determine if this is an R4600/R4700 + // and if so then we need to deal + // with the two-way set associativity. + // + .set noreorder + .set noat + mfc0 t3, prid + nop + nop + nop + li t2, 2 + srl t3, t3, 12 + bne t3, t2, 20f + nop + .set at + .set reorder + +// +// Sweep the primary instruction cache (only R4600/R4700) +// + + DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat +10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + nop + cache INDEX_INVALIDATE_I,8192(a0) // do other set on Orion + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t0 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra + +// +// Sweep the primary instruction cache (except R4600/R4700) +// + .set noreorder + .set noat +20: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + bne a0,a1,20b // if ne, more to invalidate + addu a0,a0,t0 // compute address of next block + .set at + .set reorder + + j ra // return + + .end HalSweepIcacheRange + + SBTTL("Zero Page") +//++ +// +// VOID +// HalZeroPage ( +// IN PVOID NewColor, +// IN PVOID OldColor, +// IN ULONG PageFrame +// ) +// +// Routine Description: +// +// This function zeros a page of memory. +// +// The algorithm used to zero a page is as follows: +// +// 1. Purge (hit/invalidate) the page from the instruction cache +// using the old color iff the old color is not the same as +// the new color. +// +// 2. Purge (hit/invalidate) the page from the data cache using +// the old color iff the old color is not the same as the new +// color. +// +// 3. Create (create/dirty/exclusive) the page in the data cache +// using the new color. +// +// 4. Write zeros to the page using the new color. +// +// Arguments: +// +// NewColor (a0) - Supplies the page aligned virtual address of the +// new color of the page that is zeroed. +// +// OldColor (a1) - Supplies the page aligned virtual address of the +// old color of the page that is zeroed. +// +// PageFrame (a2) - Supplies the page frame number of the page that +// is zeroed. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 + .space 3 * 4 // fill +ZpRa: .space 4 // saved return address +ZpFrameLength: // length of stack frame +ZpA0: .space 4 // (a0) +ZpA1: .space 4 // (a1) +ZpA2: .space 4 // (a2) +ZpA3: .space 4 // (a3) + + NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero) + + subu sp,sp,ZpFrameLength // allocate stack frame + sw ra,ZpRa(sp) // save return address + + PROLOGUE_END + + and a0,a0,COLOR_BITS // isolate new color bits + and a1,a1,COLOR_BITS // isolate old color bits + sw a0,ZpA0(sp) // save new color bits + sw a2,ZpA2(sp) // save page frame + +// +// If the old page color is not equal to the new page color, then change +// the color of the page. +// + + beq a0,a1,10f // if eq, colors match + jal KeChangeColorPage // chagne page color + +// +// Create dirty exclusive cache blocks and zero the data. +// + +10: lw a3,ZpA0(sp) // get new color bits + lw a1,ZpA2(sp) // get page frame number + + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy + li t0,FLUSH_BASE // get base flush address + or t0,t0,a3 // compute new color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a3,a3,0x1000 // isolate TB entry index + beql zero,a3,20f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +20: mfc0 t3,wired // get TB entry index + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + .set at + .set reorder + + DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + addu t9,t0,PAGE_SIZE // compute ending address of block + dmtc1 zero,f0 // set write pattern + bne zero,v0,50f // if ne, second level cache present + and t8,t4,0x10 // test if 16-byte cache block + +// +// Zero page in primary data cache only. +// + +30: sdc1 f0,0(t0) // zero 64-byte block + sdc1 f0,8(t0) // + sdc1 f0,16(t0) // + sdc1 f0,24(t0) // + sdc1 f0,32(t0) // + sdc1 f0,40(t0) // + sdc1 f0,48(t0) // + addu t0,t0,64 // advance to next 64-byte block + bne t0,t9,30b // if ne, more to zero + sdc1 f0,-8(t0) // + + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + lw ra,ZpRa(sp) // get return address + addu sp,sp,ZpFrameLength // deallocate stack frame + j ra // return + +// +// Zero page in primary and secondary data caches. +// + + .set noreorder + .set noat + +50: sdc1 f0,0(t0) // zero 64-byte block + sdc1 f0,8(t0) // + sdc1 f0,16(t0) // + sdc1 f0,24(t0) // + sdc1 f0,32(t0) // + sdc1 f0,40(t0) // + sdc1 f0,48(t0) // + addu t0,t0,64 // advance to next 64-byte block + bne t0,t9,50b // if ne, more to zero + sdc1 f0,-8(t0) // + + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + lw ra,ZpRa(sp) // get return address + addu sp,sp,ZpFrameLength // deallocate stack frame + j ra // return + + .end HalZeroPage |