2020-09-30 17:12:29 +02:00

209 lines
5.0 KiB
ArmAsm
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//++
//
// 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 (plj@vnet.ibm.com) 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)