Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

208 lines
5.0 KiB

//++
//
// Copyright (c) 1993 IBM Corporation
//
// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
// contains copyrighted material. Use of this file is restricted
// by the provisions of a Motorola Software License Agreement.
//
// Module Name:
//
// pxcache.s
//
// Abstract:
//
// This module implements the routines to flush cache on the PowerPC.
//
// Author:
//
// Peter L. Johnston ([email protected]) September 1993
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
// 27-Dec-93 plj Added 603 support.
// 13-Mar-94 plj Fixed problem introduced during switch to PAS;
// added 604 support.
// 07-Oct-94 saj Check for length=0 in Range functions
//--
#include "kxppc.h"
#include "halppc.h"
.extern HalpIoControlBase
// NOTE: The 603's "I-Cache Flash Invalidate" and the 604's
// "I-Cache Invalidate All" basically perform the same function
// although the usage is slightly different. In the 603 case,
// ICFI must be cleared under program control after it is set.
// In the 604 the bit clears automatically.
.set HID0_ICFI, 0x0800 // I-Cache Flash Invalidate
.set HID0, 1008 // SPR # for HID0
.set BLOCK_SIZE, 32
.set BLOCK_LOG2, 5 // Should be == log2(BLOCK_SIZE)
.set BASE, 0x80000000 // base addr of valid cacheable region
//++
//
// Routine Description:
//
// The D-Cache is flushed by loading 1 byte per cache line from a
// valid address range, then flushing that address range.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(HalSweepDcache)
mfsprg r.5, 1 // Get PCR->FirstLevelDcacheSize
lwz r.4, PcFirstLevelDcacheSize(r.5)
LWI (r.3, BASE) // Get a valid virtual address
srwi r.4, r.4, BLOCK_LOG2 // Convert to # cache lines
//
// Load r.4 cache lines starting from virtual address in r.3
//
mtctr r.4
DISABLE_INTERRUPTS(r.10,r.12)
sync // ensure ALL previous stores completed
subi r.6, r.3, BLOCK_SIZE // bias addr for pre-index
FillLoop:
lbzu r.0, BLOCK_SIZE(r.6) // Read memory to force cache fill
bdnz FillLoop // into cache
ENABLE_INTERRUPTS(r.10)
mtctr r.4
FlushRange:
dcbf r.0, r.3 // flush block
addi r.3, r.3, BLOCK_SIZE // bump address
bdnz FlushRange
LEAF_EXIT(HalSweepDcache)
//++
//
// Routine Description:
//
// The I-Cache is flushed by toggling the Icache flash invalidate bit
// in HID0. Invalidation is all that is necessary. Flushing to main
// memory is not needed since the Icache can never be dirty.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(HalSweepIcache)
LWI (r.3, BASE)
FlashInvalidateIcache:
mfspr r.3, HID0
ori r.4, r.3, HID0_ICFI // Cache Flash Invalidate
isync
mtspr HID0, r.4 // Flash invalidate I-Cache
mtspr HID0, r.3 // re-enable (not needed on 604)
LEAF_EXIT(HalSweepIcache)
//
// Routine Description:
//
// The D-Cache is flushed by issuing a data cache block flush (DCBF)
// instruction for each data block in the range.
//
// Arguments:
//
// r.3 - Starting address
// r.4 - Length
//
// Return Value:
//
// None.
//
//
LEAF_ENTRY(HalSweepDcacheRange)
andi. r.5, r.3, BLOCK_SIZE-1 // Get block offset of Start Addr
or. r.4, r.4, r.4 // Check for Length == 0
addi r.4, r.4, BLOCK_SIZE-1 // bump Length by BLOCK_SIZE-1
add r.4, r.4, r.5
srwi r.4, r.4, BLOCK_LOG2 // Compute # of cache blocks to flush
mtctr r.4
bne+ FlushRange // Branch if Length != 0
LEAF_EXIT(HalSweepDcacheRange)
//
// Routine Description:
//
// The I-Cache is flushed by issuing a Instruction Cache Block
// Invalidate (ICBI) instruction for each data block in the range.
// If the range is large, the entire Icache can be invalidated by
// branching to FlashInvalidateIcache.
//
// Arguments:
//
// r.3 - Starting address
// r.4 - Length
//
// Return Value:
//
// None.
//
//
LEAF_ENTRY(HalSweepIcacheRange)
andi. r.5, r.3, BLOCK_SIZE-1 // Get block offset of Start Addr
or. r.4, r.4, r.4 // Check for Length == 0
addi r.4, r.4, BLOCK_SIZE-1 // bump Length by BLOCK_SIZE-1
add r.4, r.4, r.5
srwi r.4, r.4, BLOCK_LOG2 // Compute # of cache blocks to flush
beqlr- // return if Length == 0
mtctr r.4
#if 0
//
// Possible speedup: If Length is fairly large (e.g. greater than 1/2
// of the cache size), we will flash invalidate the entire cache, else
// only sweep the desired range.
//
li r.5, 16384/BLOCK_SIZE // # Icache lines on 604
cmpwi r.6, 3 // possible values are 3 or 4
bgt Threshold // Branch if 604
li r.5, 8192/BLOCK_SIZE // # Icache lines on 603
Threshold:
srwi r.5, r.5, 1 // r.5 = IcacheLines/2
cmpl 0,0, r.4, r.5
bgt FlashInvalidateIcache
#endif
InvalidateIcache:
icbi 0, r.3 // invalidate block in I-cache
addi r.3, r.3, BLOCK_SIZE // bump address by BLOCK_SIZE
bdnz InvalidateIcache
LEAF_EXIT(HalSweepIcacheRange)