📄 ppc403.s
字号:
// TITLE("TLB Management and support routines")
//++
//
//
// Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
//
// Module Name:
//
// ppc403.s
//
// Abstract:
//
// Initialization of the TLB support for the PPC403 kernel
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
.machine ppc403gc
#define UNCACHED 0 // Disable caching
//
// Definition of Special Purpose Registers (SPRs) used on PPC403
//
#define ESR 0x3d4 // Exception Status Register
#define DAR 0x3d5 // == DEAR on PPC403
//
// The TLB Handlers are defined here and then copied into low memory
// The four handlers ITBMiss, DTBMiss, ITBError, and DTBError are copied
// into the correct location for each processor
// Each vector must be limited to 256 bytes (64 instructions)
//
#define DTBErrorVector 0x0300
#define ITBErrorVector 0x0400
#define DTBMissVector 0x1100
#define ITBMissVector 0x1200
#define ClockIntVector 0x1000
//
// The PPC403 uses a software TLB replacement algorithm. This is currently
// a simple round robin method. There are 64 (unified) TB entries on the 403,
// and two are reserved for the KPAGE and KSEG mappings.
//
#define TB_ENTRIES 62 // # of replaceable TB Entries
#define TB_KSEG 62 // TB Entry for Kernel mapping
#define TB_KPAGE 63 // TB Entry for KPage mapping
//
// The following TLB registers are used within the TLB routines
//
#define PID 0x3B1
#define ZPR 0x3B0
#define DEAR 0x3D5
#undef DAR
#define DAR DEAR // 403 doesn't use architected DAR
//
// Storage access control is maintained via the Zone Protection register.
// Each TLB entry contains a ZSEL field which is an index into one of 16
// storage control zones. For Wince, three zones are defined:
//
// Zone 0: Normal mapping All access controlled by PTE Wr & Ex fields
// Zone 1: KSEG mapping Kernel-only Read, Write and Execute
// Zone 2: KPAGE mapping Kernel rwx, User Mode Read/Execute only
//
// The ZSEL field is in bits 24:27 of the TLBLO register. Since only three
// zones are defined for Windows CE, only two bits are required to identify
// the zone. The ZPR is setup so that the top two bits of the ZSEL field are
// ignored. The upper two bits of the ZSEL field (bits 24:25) are used as
// software PTE flags
//
#define PTE_ZONE0 0x0000 // PTE Field Bits for Zone 0
#define PTE_ZONE1 0x0010
#define PTE_ZONE2 0x0020
#define ZPR_ZONE0 0x40000000 // ZPR<0> = 01b
#define ZPR_ZONE1 0x00000000 // ZPR<1> = 00b
#define ZPR_ZONE2 0x08000000 // ZPR<2> = 10b
#define ZPR_INIT 0x48484848 // Zone selection mapping
#define PTE_VALID 0x0040 // Valid bit in PTEHI
#define PTE_LE 0x0020 // Little endian bit in
// PTEHI on PPC401; on
// PPC403 it's reserved, but
// okay to write to
.text
//
// Data TLB miss handler
//
// Entry: (MSR) External interrupts disabled
// Instruction Relocate OFF
// Data Relocate OFF
// (SRR0) Instruction address at time of interrupt
// (SRR1) MSR at time of interrupt
// (DEAR) Effective address of the failed access
//
// Usage:
// r3 == Condition register (r3 => SPRG0)
// r4 == TLB Low (r4 => SPRG1)
// r5 == Exception address (TLBHI) (r5 => SPRG2)
// r6 == misc. pointer (r6 => SPRG3)
//
// This routine sets up registers and branches to the common TB fill code
//
DTBMiss:
mtspr SPRG2, r5
mfspr r5, DEAR // (r5) = faulting address
mtspr SPRG0, r3
mfcr r3 // (r3) = saved condition register
mtcrf 0x80, r5 // (CR0) = Upper nibble of EA
mtspr SPRG1, r4
mtspr SPRG3, r6
bt- 0, TBKMap // else create a KSEG mapping
//
// Common TB Fill handler used by ITBMiss and DTBMiss.
// Note: This code is duplicated, but identical, between ITBMISS & DTBMiss
//
// r5 == Effective address which caused the miss
//
DTBFill: // Common UTB Fill code:
//
// Lookup a user virtual address in the kernel virtual memory tables to find the
// physical address translation to be loaded into the TLB.
//
rlwinm r6, r5, (32-VA_SECTION)+2, SECTION_MASK*4 // (r6) = section index
lwz r4, SectionTable(r6) // (r4) = ptr to SECTION
rlwinm r6, r4, 8, 27, 31 // Make r4 physical by
lbz r6, kPFNMap(r6) // doing V->P memory
rlwimi r4, r6, 24, 0xFF000000 // map lookup
rlwinm r6, r5, (32-VA_BLOCK)+2, BLOCK_MASK*4 // (r6) = block index
lwzx r6, r6, r4 // -> MEMBLOCK structure
cmplwi r6, 0x1000 // Invalid MEMBLOCK ??
rlwinm r4, r6, 8, 27, 31 // Extract PFN
blt- DTBInvalid
//
// memblock[0] will reside in ROM, other memblock entries may reside in
// RAM. The PFNMap must be used to properly retreive the physical address
// of the memblock structure.
//
lbz r4, kPFNMap(r4) // Load translated PFN
rlwimi r6, r4, 24,0xFF000000 // make it physical
lwz r4, CurAKey(0) // (r4) = current AKey
lwz r5, mb_lock(r6) // MEMBLOCK access lock
and. r4, r4, r5
mfspr r5, DEAR // restore EA
beq- DTBInvalid // access not allowed
rlwinm r4, r5, (32-VA_PAGE)+2, PAGE_MASK*4 // (r4) = page index
add r4, r6, r4
lwz r4, mb_pages(r4) // (r4) = PTE entry
andi. r6, r4, 0x01 // Test Valid bit.
beq- DTBInvalid // Invalid access
rlwinm r5, r5, 0, 0, 21 // Clear out page offset
// End of Common fill code.
b TBUpdate // go to common update code
//
// Invalid address.
// Set up parameters and branch to the General exception handler.
//
// (r5) == Exception address
//
DTBInvalid:
li r4, ID_DPAGE_FAULT // Exception type in r4
mtcr r3 // restore saved parms
mfspr r3, SPRG0
mfspr r6, SPRG3
ba KPageGeneralHandler
//
// Kernel space address. Create a large (16MB) page mapping for the address:
// TODO: Set PID to zero and make this a global translation.
//
TBKMap:
// bt- 1, DTBInvalid // Invalid 0xC quadrant
rlwinm. r4, r5, 0, 1, 1 // Isolate EA bit 30
bne DTBInvalid // Invalid if bit 30 set
rlwinm r5, r5, 0, 0, 7 // Align to 16MBytes
ori r5, r5, 0x3c0 // Insert Valid, Size=16MB
rlwinm r4, r5, 8, 27, 31 // Extract PFN
lbz r4, kPFNMap(r4) // Load translated PFN
slwi r4, r4, 24 // align to 16MBytes
rlwimi r4, r5, 5, 29, 29 // Copy Uncached Bit from VA
ori r4, r4, (PTE_ZONE1 | PG_PROT_WRITE | PG_PROT_EXECUTE)
b TBUpdate
.org DTBMiss+0x100 // Fill out the vector
//
// Instruction TLB miss handler
//
// Entry: (MSR) External interrupts disabled
// Instruction Relocate OFF
// Data Relocate OFF
// (SRR0) Instruction address at time of interrupt
// (SRR1) MSR at time of interrupt
//
// Usage:
// r3 == Condition register (r3 => SPRG0)
// r4 == TLB Low (r4 => SPRG1)
// r5 == Exception address (TLBHI) (r5 => SPRG2)
// r6 == misc. pointer (r6 => SPRG3)
//
ITBMiss:
mtspr SPRG2, r5
mfspr r5, SRR0 // (r5) = fauling address
mtspr SPRG0, r3
mfcr r3 // (r3) = saved condition register
mtcrf 0x80, r5 // (CR0) = Upper nibble of EA
mtspr SPRG1, r4
mtspr SPRG3, r6
bt- 0, TBKSpace // high bit set, kernel space addr
//
// Common TB Fill handler used by ITBMiss and DTBMiss.
// Note: This code is duplicated, but identical, between ITBMISS & DTBMiss
//
// r5 == Effective address which caused the miss
//
ITBFill: // Common UTB Fill code:
//
// Lookup a user virtual address in the kernel virtual memory tables to find the
// physical address translation to be loaded into the TLB.
//
rlwinm r6, r5, (32-VA_SECTION)+2, SECTION_MASK*4 // (r6) = section index
lwz r4, SectionTable(r6) // (r4) = ptr to SECTION
rlwinm r6, r5, (32-VA_BLOCK)+2, BLOCK_MASK*4 // (r6) = block index
rlwinm r4, r4, 0, 0x0fffffff // make it physical
lwzx r6, r6, r4 // -> MEMBLOCK structure
rlwinm r6, r6, 0, 0x0fffffff // make it physical
cmplwi r6, 0x1000 // Invalid MEMBLOCK ??
lwz r4, CurAKey(0) // (r4) = current AKey
blt- ITBInvalid
lwz r5, mb_lock(r6) // MEMBLOCK access lock
and. r4, r4, r5
mfspr r5, SRR0 // restore EA
beq- ITBInvalid // access not allowed
rlwinm r4, r5, (32-VA_PAGE)+2, PAGE_MASK*4 // (r4) = page index
add r4, r6, r4
lwz r4, mb_pages(r4) // (r4) = PTE entry
andi. r6, r4, 0x01 // Test Valid bit.
beq- ITBInvalid // Invalid access
rlwinm r5, r5, 0, 0, 21 // Clear out page offset
// End of Common fill code.
//
// Load a new entry into the TB.
//
// (r5) == TLBHI (EPN and size fields)
// (r4) == TLBLO (RPN, Wr, Ex, Zone, and cache-inhibit fields)
// The cache-inhibit bit is copied to the Guarded bit.
//
TBUpdate:
lwz r6, TBIndex(0) // Get next TB index
#if UNCACHED
rlwinm r4, r4, 0, 0, 30 // TESTING: Clear valid (guarded) bit
ori r4, r4, PG_NOCACHE
#else
rlwimi r4, r4, 32-2, 31, 31 // Copy Inhibit to Guarded
#endif
tlbwelo r4, r6 // write entry low part
ori r5, r5, PTE_VALID | PTE_LE // Insert valid, little
// endian bits
tlbwehi r5, r6 // write entry hi part
addi r6, r6, 1 // bump TB index
cmpwi r6, TB_ENTRIES
blt TBExit
li r6, 0 // reset TB index
TBExit:
stw r6, TBIndex(0) // update the index
//
// New entry loaded into the TLB. Restore registers and continue.
//
// (r0) = condition register
// (SPRG0) = saved R3
// (SPRG1) = saved R4
// (SPRG2) = saved R5
// (SPRG3) = saved R6
mtcrf 0xff, r3 // restore condition register
mfspr r3, SPRG0
mfspr r4, SPRG1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -