📄 ppc403.s
字号:
mfspr r5, SPRG2
mfspr r6, SPRG3
rfi
//
// Address in kernel space. Check if kernel server call or reference to
// an "un-mapped" space. For an "un-mapped" space reference, generate
// a large (16mb) TLB entry to map the region. For an api call, jump to
// the initial api handler code in the KPage.
//
// (r3) = saved CR value
// (r5) = missing virtual address
// (M_TW) = saved R0
// (SPRG0) = saved R3
// (SPRG1) = saved R4
// (SPRG2) = saved R5
// (SPRG3) = saved R6
//
TBKSpace:
lis r6, API_MAX >> 16
ori r6, r6, API_MAX & 0xFFFF
cmplw r6, r5
bgt- TBKMap // not an api call or return
//
// Setup to invoke the API call or return code.
//
// NOTE: Since this is a C or C++ function call or return,
// it is not necessary to restore r11, r12, and CR0.
//
subi r11, r5, FIRST_METHOD // FIRST_METHOD based index
mfspr r12, SRR1
mfspr r3, SPRG0
mfspr r4, SPRG1
mfspr r5, SPRG2
mfspr r6, SPRG3
ba KPageAPIHandler
//
// Invalid address.
// Set up parameters and branch to the General exception handler.
//
// (r5) == Exception address
//
ITBInvalid:
li r4, ID_CPAGE_FAULT // Exception type in r4
mtcr r3 // restore saved parms
mfspr r3, SPRG0
mfspr r6, SPRG3
ba KPageGeneralHandler
.org ITBMiss+0x100 // Fill out the vector
//
// Instruction TLB error 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
//
//
ITBError:
mtspr SPRG1, r4
mtspr SPRG2, r5
li r4, ID_CPAGE_FAULT // (r4) = ITLB error interrupt code
mfspr r5, SRR0
ba KPageGeneralHandler
// .org ITBError + 0x100
// Data TLB error handler
//
// Entry: (MSR) External interrupts disabled
// Instruction Relocate OFF
// Data Relocate OFF
// (DEAR) Instruction address at time of interrupt
// (SRR1) MSR at time of interrupt
//
DTBError:
mtspr SPRG1, r4
mtspr SPRG2, r5
li r4, ID_DPAGE_FAULT
mfspr r5, DEAR
ba KPageGeneralHandler // Call the general exception handler
// .org DTBError+0x100
//
// ClockHandler
//
// The clock interrupts are routed on the PPC403 so that the PIT, FIT, and
// watchdog timers all dispatch to the 0x10xx exception vectors. Since there
// is not an architected PowerPC Timer interrupt, the kernel will simply
// convert these to hardware interrupts, and dispatch them via
// OEMInterruptHandler.
//
//
ClockHandler:
ba 0x0500 // Offset 0x1000 - PIT Interrupt
nop
nop
nop
ba 0x0500 // Offset 0x1010 - FIT Interrupt
nop
nop
nop
ba 0x0500 // Offset 0x1020 - Watchdog int.
ClockHandlerEnd:
//
//
// TLBInit
//
// Perform the processor specific TLB Initialization:
//
// Any processor specific TLB initialization is performed here, and two
// fixed translations are created:
//
// 1) KSEG Mapping. All address with bit 0 set are mapped 1-to-1
//
// 2) KPage Mapping. The KPAGE is mapped Virtual=Physical. The mapping
// is writable and executable in kernel mode, but
// read-only in user mode
//
//
// Parameters:
//
// r3 - Address of OEMMemoryMap of Physical -> Virtual mappings
//
LEAF_ENTRY(TLBInit)
//
// Build up the Virtual to Physical translation table for the 512MB superpage.
// This table is based upon the Physical to Virtual mappings stored in
// OEMMemoryMap.
//
//
// Translate OEMMemoryMap to KPfnMap
// (r4) Virtual Address
// (r5) Physical Address
// (r6) Size
KPFNMapStart:
// Get entry size
lwz r6, 8(r3)
// Divide size by 16. This gives us the number of
// KPFN entries covered.
srawi r6, r6, 4
// If the size is zero, we're done
cmpi 0, 0, r6, 0
beq KPFNMapDone
// Get physical and virtual address
lwz r4, 0(r3)
lwz r5, 4(r3)
// For each address, rotate the upper byte into the low byte
// and mask it off.
rlwinm r4, r4, 8, 0x0000001F // KSEG address high byte. Bits 31-29 are always 100.
rlwinm r5, r5, 8, 0x000000FF // Physical address high byte.
// Now fill the KPFN entries
mtctr r6
FillLoop:
stb r5, kPFNMap(r4)
addi r4, r4, 1
addi r5, r5, 1
bdnz FillLoop
// Next entry...
addi r3, r3, 12
b KPFNMapStart
KPFNMapDone:
//
// Init TLBs
//
tlbia // clear out all TLB entries
//
// Set up the Zone Protection Register (ZPR) for the zones used by
// the TLB entries
//
LWI(r3, ZPR_INIT)
mtspr ZPR, r3
li r3, 0
mtspr PID, r3 // Setup PID for global mappings
isync
//
// Load reserved entry for KPage into the Data TLB.
// The KPage is mapped so that <KPAGE Virtual> == <KPAGE Physical> == KPAGE_BASE
// The KPage is actually 4KB (four one-K pages) mapped as a single page
//
// Map user mode only for the 2 pages at 0x5800 (requires 2 more tlbs)
//
li r4, TB_KPAGE // load TB index
li r3, (KPAGE_BASE | PG_PROT_EXECUTE | PTE_ZONE2)
#if UNCACHED
ori r3, r3, PG_NOCACHE // Disable kpage caching for testing
#endif
tlbwelo r3, r4 // write low part
li r3, (KPAGE_BASE | 0xc0) // Set EPN, Valid, Size=4KB
tlbwehi r3, r4 // write high part
isync // Sync the istream
LEAF_EXIT(TLBInit)
//
// FlushTLB
//
// Flush all TLB entries.
//
// Use tlbia to invalidate all entries, and then refill the reserved KPage
// translation
//
LEAF_ENTRY(FlushTLB)
//
// Prevent interrupt from occuring between tlbia and the
// KPage translation update:
//
mfmsr r6
rlwinm r0, r6, 0, ~MSR_EE
mtmsr r0
//
// Set PID to zero. KSeg TBMiss following tlbia will be global
//
mfspr r5, PID // save the current PID value
li r3, 0 // set PID=0 for shared entry
mtspr PID, r3
isync
tlbia // Invalidate all entries
isync // Ensure ITLB consistent
//
// Reset the valid bit for the reserved Kpage translation:
// PID == 0. This is a global translation:
//
li r4, TB_KPAGE // KPage translation index
tlbrehi r3, r4 // read the translation
ori r3, r3, PTE_VALID | PTE_LE // set the valid and little
// endian bits
tlbwehi r3, r4 // and update the entry
mtspr PID, r5 // restore original PID
isync
mtmsr r6 // restore MSR
LEAF_EXIT(FlushTLB)
// SetPID - set PID register
//
// This function is needed because the C compiler won't accept registers
// it doesn't know about in the _sregister_set() call.
//
// Entry (r3) = new address space ID
// Exit none
// Uses none
LEAF_ENTRY(SetPID)
isync
mtspr PID, r3
isync
LEAF_EXIT(SetPID)
//
// LEAF_ENTRY(CPUIdentify)
//
// Returns information about the current processor.
//
// Entry none
// Exit (r3) = Processor type (401 or 403)
//
LEAF_ENTRY(CPUIdentify)
// The MEM (Family Member) field of the PVR (PVR[12:15]) is used to
// determine if we have a 401 or 403.
// MEM=0x1 => 401
// MEM=0x0 => 403
//
// PVR CPU
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 0x00200200 - 403GC
// 0x00201400 - 403GCX
// 0x0022xxxx - 401B2
// 0x0023xxxx - 401C2
// 0x0024xxxx - 401D2
mfspr r4, PVR // Grab the PVR
rlwinm. r4, r4, 0, 0x00070000 // PVR[12:15]
li r3, 403 // Assume 403
beq ProcType403 // MEM == 0 so have a 403
ProcType401: // Have a 401
li r3, 401
ProcType403:
LEAF_EXIT(CPUIdentify)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -