📄 startup.s
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
// TITLE("Kernel Initialization")
//------------------------------------------------------------------------------
//
//
// Module Name:
//
// startup.s
//
// Abstract:
//
// This module implements the code necessary to initialize the Kernel to
// run on an R4000 series processor.
//
//
// Environment:
//
// Kernel mode only.
//
//------------------------------------------------------------------------------
#include "ksmips.h"
#include "nkintr.h"
#include "kpage.h"
#include "mem_mips.h"
#define jalfix(func) \
jal func; \
nop;
#if 0 // PERP
#define LIGHTS(t0, t1, value) \
lui t0, 0xaa00; \
li t1, value; \
sw t1, 0x1010(t0);
#endif
#if 0
#define LIGHTS(t0, t1, value) \
lui t0, 0xb040; \
lh t1, 2(t0); \
and t1, 0xff; \
or t1, value<<8; \
sh t1, 2(t0);
#endif
#ifndef LIGHTS
#define LIGHTS(t0, t1, value)
#endif
//------------------------------------------------------------------------------
// KPAGE : allocate RAM space for the KDATA section (mapped to high address)
//------------------------------------------------------------------------------
.data .KDATA
.globl KPAGE_VIRT
KPAGE_VIRT: .space KPAGE_LENGTH
.text
//
// the following 4 variables can be updated by OEM using FIXUPVAR in config.bib
// to tell us what the CPU type is and we'll by-pass CPU type detection if the
// value changed.
// fNKMIPS16Sup - set to 1 if the CPU support MIPS16 instructions, 0 if not
// fNKTinyPageSup - set to 1 if the CPU support tiny pages (e.g. R41XX processors), 0 if not
// fNKHasFPU - set to 1 if the FPU exist, 0 if not
// fNKExHandlerNeedNops - set to 1 if need to insert 2-nop at the beginning of exception handler
//
// we'll try our best to detect the CPU types if the values are left unchanged (-1).
//
// NOTE: you MUST change all 4 if you need to change any of them.
//
.globl fNKMIPS16Sup
.globl fNKTinyPageSup
.globl fNKHasFPU
.globl fNKExHandlerNeedNops
fNKMIPS16Sup: .word -1
fNKTinyPageSup: .word -1
fNKHasFPU: .word -1
fNKExHandlerNeedNops: .word -1
// legacy MIPSII
#define PRID_R41XX 0x0C00 // bit 8-15 of prid == 0xC
#define R41XX_M16SUP 0x00100000 // bit 20 of config on R41XX indicate MIPS16 support
// MIPS32/MIPS64
#define CFG1_MIPS16 0x4 // bit 2 of config1 indicate MIPS16 support
#define CFG1_FPU 0x1 // bit 0 of config1 indicate FPU
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(KernelStart)
.set noreorder
mtc0 zero, cause // Clear interrupts
mtc0 zero, entryhi // Clear asid
mtc0 zero, context // clear the context register
mtc0 zero, entrylo0
mtc0 zero, entrylo1
mtc0 zero, pagemask
mtc0 zero, count // clear count (time since restart)
move k0, zero
move k1, zero
lw s0, fNKMIPS16Sup
lw s1, fNKTinyPageSup
lw s2, fNKHasFPU
lw s6, fNKExHandlerNeedNops
li t0, -1
bne t0, s0, 3f // don't bother detect if value changed
nop
// try to figure out the information from config+procid registers
move s0, zero // default no MIPS16 support
move s1, zero // default not tiny page support
move s2, zero // default no FPU
move s6, zero // default don't need to add no-op for exception handler
mfc0 t0, config // (t0) = config register
nop // 1 cycle hazard??
bltz t0, 2f // bit 31 config indicate if config1 register exist
nop
// bit 31 is 0, legacy MIPSII CPUs
mfc0 t2, prid // t2 = prid
nop // 1 cycle hazard??
andi t2, t2, 0xff00 // bit [8-15] is the processor family
li t1, PRID_R41XX // (t1) = prid of R41XX family (0xc00)
bne t2, t1, 3f // use default if not R41XX
nop
// R41XX (t0) == config register
li s1, 1 // support tiny page
move s6, s1 // need to insert no-op for exception handler
li t1, R41XX_M16SUP // MIPS16 support is bit 20 of config register on R41XX
j 3f
and s0, t0, t1 // (delay slot) s0 == support MIPS16
2:
// MIPS32/MIPS64
//mfc0 t0, config, 1 // read config1 register
.word 0x40088001 // encoding for MIPS32 instruction "mfc0 t0, config, 1"
andi s0, t0, CFG1_MIPS16 // (s0) = support MIPS16?
andi s2, t0, CFG1_FPU // (s2) = has FPU?
3:
//
// (s0) - non-zero if support MIPS16
// (s1) - non-zero if support tiny page (R41XX)
// (s2) - non-zero if support FPU (might not be needed since we can detect FPU by try-except
// (s6) - non-zero if need to insert no-op at the beginning of exception handler
//
// CPU with tiny page support need a different pagemask
beqz s1, 4f
li s3, PFN_SHIFT_MIPS32 // (delay slot) (s3) = default PFN_SHIFT
// tiny page support
li t0, 0x1800 // page mask for 4K pagesize on R4100
li s3, PFN_SHIFT_R41XX // PFN_SHIFT is different with tiny page support
mtc0 t0, pagemask
4:
// (s3) = PFN_SHIFT
li s4, PAGE_SIZE // (s4) = PAGE_SIZE
srlv s4, s4, s3 // (s4) = (PAGE_SIZE >> PFN_SHIFT) == PFN_INCR
la t3, KPAGE_VIRT
li t1, 0xA0000000
or t3, t3, t1
li t1, PFN_MASK
and t4, t3, t1 // (t4) = (KPAGE_VIRT | 0xa0000000) & PFN_MASK
srlv t4, t4, s3 // (t4) >>= PFN_SHIFT
// t3 = virtual uncached KPAGE base
// t4 = PFN of KPAGE_BASE
//
// Zero out kernel data page.
//
move t0, t3
li t1, KPAGE_LENGTH
8: sw zero, (t0)
subu t1, 4
bgtz t1, 8b
addiu t0, 4
LIGHTS(t0,t1, 0xCC)
//
// Initialize SectionTable in KPage
//
addi t0, t3, (SectionTable-KData)
li t1, SECTION_MASK+1
la t2, NullSection
9: sw t2, (t0)
subu t1, 1
bgtz t1, 9b
addiu t0, 4
//
// Initialize the interrupt dispatch tables
//
addi t0, t3, (FalseInt-KData)
la t1, FalseInterrupt
sw t1, (t0)
la t1, DisabledInterruptHandler
sw t1, 4(t0)
sw t1, 8(t0)
sw t1, 12(t0)
sw t1, 16(t0)
sw t1, 20(t0)
sw t1, 24(t0)
//
// Load temp stack pointer & global pointer.
//
addi sp, t3, (KStack-KData)
li gp, 0
li t1, 0x80000000
sw t1, HandleBase-KData(t3)
la t1, APICallReturn
sw t1, PtrAPIRet-KData(t3)
LIGHTS(t0,t1, 0xF0)
// Initialize address translation hardware.
li v0, 0x80000000 // Unmapped address
lw v1, OEMTLBSize // (v1) = index & loop counter
10: mtc0 zero, entrylo0 // Clear entrylo0 - Invalid entry
mtc0 zero, entrylo1 // Clear entrylo1 - Invalid entry
mtc0 v0, entryhi // Clear entryhi - Ivalid address
mtc0 v1, index // Set index
add v0, 0x2000
ssnop // super scalar core requires 4 integer instructions
ssnop // to guarantee a 2 cycle hazard
ssnop
tlbwi // Write entry (indexed)
addiu v1, v1, -1 // Decrement index, loop counter
bgez v1, 10b // If not done (<0) do next one
nop
//
// Initialize wired TLB entries as follows:
// 0: virtual 0x00005000 to the kernel's data page (read-only)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -