/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829#include <kern/mips/regdefs.h>30#include <mips/specialreg.h>3132.set noreorder3334.text35.globl __start36.type __start,@function37.ent __start38__start:3940/*41* Stack frame. We save the return address register, even though42* it contains nothing useful. This is for gdb's benefit when it43* comes disassembling. We also need 16 bytes for making a call,44* and we have to align to an 8-byte (64-bit) boundary, so the45* total frame size is 24.46*47* Note that the frame here must match the frame we set up below48* when we switch off the bootup stack. Otherwise, gdb gets very49* confused.50*/51.frame sp, 24, $0 /* 24-byte sp-relative frame; return addr on stack */52.mask 0x80000000, -4 /* register 31 (ra) saved at (sp+24)-4 */53addiu sp, sp, -2454sw ra, 20(sp)5556/*57* The System/161 loader sets up a boot stack for the first58* processor at the top of physical memory, and passes us a single59* string argument. The string lives on the very top of the stack.60* We get its address in a0.61*62* The kernel loads at virtual address 0x80000200, which is63* physical address 0x00000200. The space immediately below this64* is reserved for the exception vector code.65*66* The symbol _end is generated by the linker. It's the address of67* the end of the kernel. It's not a variable; the *value* of the68* _end symbol itself is this address. In C you'd use "&_end".69*70* We set up the memory map like this:71*72* top of memory73* free memory74* P + 0x100075* first thread's stack (1 page)76* P77* wasted space (< 1 page)78* copy of the boot string79* _end80* kernel81* 0x8000020082* exception handlers83* 0x8000000084*85* where P is the next whole page after copying the argument string.86*/8788la s0, _end /* stash _end in a saved register */8990move a1, a0 /* move bootstring to the second argument */91move a0, s0 /* make _end the first argument */92jal strcpy /* call strcpy(_end, bootstring) */93nop /* delay slot */9495move a0, s0 /* make _end the first argument again */96jal strlen /* call strlen(_end) */97nop9899add t0, s0, v0 /* add in the length of the string */100addi t0, t0, 1 /* and the null terminator */101102103addi t0, t0, 4095 /* round up to next page boundary */104li t1, 0xfffff000105and t0, t0, t1106107addi t0, t0, 4096 /* add one page to hold the stack */108109move sp, t0 /* start the kernel stack for the first thread here */110111sw t0, firstfree /* remember the first free page for later */112113/*114* At this point, s0 contains the boot argument string, and no other115* registers contain anything interesting (except the stack pointer).116*/117118/*119* Now set up a stack frame on the real kernel stack: a dummy saved120* return address and four argument slots for making function calls,121* plus a wasted slot for alignment.122*123* (This needs to match the stack frame set up at the top of the124* function, or the debugger gets confused.)125*/126addiu sp, sp, -24127sw $0, 20(sp)128129/*130* Now, copy the exception handler code onto the first page of memory.131*/132133li a0, EXADDR_UTLB134la a1, mips_utlb_handler135la a2, mips_utlb_end136sub a2, a2, a1137jal memmove138nop139140li a0, EXADDR_GENERAL141la a1, mips_general_handler142la a2, mips_general_end143sub a2, a2, a1144jal memmove145nop146147/*148* Flush the instruction cache to make sure the above changes show149* through to instruction fetch.150*/151jal mips_flushicache152nop153154/*155* Initialize the TLB.156*/157jal tlb_reset158nop159160/*161* Load NULL into the register we use for curthread.162*/163li s7, 0164165/*166* Set up the status register.167*168* The MIPS has six hardware interrupt lines and two software interrupts.169* These are individually maskable in the status register. However, we170* don't use this feature (for simplicity) - we only use the master171* interrupt enable/disable flag in bit 0. So enable all of those bits172* now and forget about them.173*174* The BEV bit in the status register, if set, causes the processor to175* jump to a different set of hardwired exception handling addresses.176* This is so that the kernel's exception handling code can be loaded177* into RAM and that the boot ROM's exception handling code can be ROM.178* This flag is normally set at boot time, and we need to be sure to179* clear it.180*181* The KUo/IEo/KUp/IEp/KUc/IEc bits should all start at zero.182*183* We also want all the other random control bits (mostly for cache184* stuff) set to zero.185*186* Thus, the actual value we write is CST_IRQMASK.187*/188189li t0, CST_IRQMASK /* get value */190mtc0 t0, c0_status /* set status register */191192/*193* Load the CPU number into the PTBASE field of the CONTEXT194* register. This is necessary to read from cpustacks[] and195* cputhreads[] on trap entry from user mode. See further196* discussions elsewhere.197*198* Because the boot CPU is CPU 0, we can just send 0.199*/200mtc0 $0, c0_context201202/*203* Load the GP register. This is a MIPS ABI feature; the GP204* register points to an address in the middle of the data segment,205* so data can be accessed relative to GP using one instruction206* instead of the two it takes to set up a full 32-bit address.207*/208la gp, _gp209210/*211* We're all set up!212* Fetch the copy of the bootstring as the argument, and call main.213*/214jal kmain215move a0, s0 /* in delay slot */216217218/*219* kmain shouldn't return. panic.220* Loop back just in case panic returns too.221*/2221:223la a0, panicstr224jal panic225nop /* delay slot */226j 1b227nop /* delay slot */228.end __start229230.rdata231panicstr:232.asciz "kmain returned\n"233234/*235* CPUs started after the boot CPU come here.236*/237.text238.globl cpu_start_secondary239.type cpu_start_secondary,@function240.ent cpu_start_secondary241cpu_start_secondary:242243/*244* When we get here our stack points to the CRAM area of the bus245* controller per-CPU space. This means we can, with a bit of246* caution, call C functions, but nothing very deeply nesting.247* However, we don't need to.248*249* The a0 register contains the value that was put in the second250* word of the CRAM area, which is the (software) cpu number for251* indexing cpustacks[]. None of the other registers contain252* anything useful.253*/254255256/*257* Stack frame. We save the return address register, even though258* it contains nothing useful. This is for gdb's benefit when it259* comes disassembling. We also need 16 bytes for making a call,260* and 4 bytes for alignment, so the total frame size is 24.261*262* Note that the frame here must match the frame we set up below263* when we switch stacks. Otherwise, gdb gets very confused.264*/265.frame sp, 24, $0 /* 24-byte sp-relative frame; return addr on stack */266.mask 0x80000000, -4 /* register 31 (ra) saved at (sp+24)-4 */267addiu sp, sp, -24268sw ra, 20(sp)269270/*271* Fetch the stack out of cpustacks[].272*/273lui t0, %hi(cpustacks) /* load upper half of cpustacks base addr */274sll v0, a0, 2 /* get byte index for array (multiply by 4) */275addu t0, t0, v0 /* add it in */276lw sp, %lo(cpustacks)(t0) /* get the stack pointer */277278/*279* Now fetch curthread out of cputhreads[].280*/281lui t0, %hi(cputhreads) /* load upper half of cpustacks base addr */282sll v0, a0, 2 /* get byte index for array (multiply by 4) */283addu t0, t0, v0 /* add it in */284lw s7, %lo(cputhreads)(t0) /* load curthread register */285286/*287* Initialize the TLB.288*/289jal tlb_reset290nop291292/*293* Set up the status register, as described above.294*/295li t0, CST_IRQMASK /* get value */296mtc0 t0, c0_status /* set status register */297298/*299* Load the CPU number into the PTBASE field of the CONTEXT300* register, as described above.301*/302sll v0, a0, CTX_PTBASESHIFT303mtc0 v0, c0_context304305/*306* Initialize the on-chip timer interrupt.307*308* This should be set to CPU_FREQUENCY/HZ, but we don't have either309* of those values here, so we'll arbitrarily set it to 100,000. It310* will get reset to the right thing after it first fires.311*/312li v0, 100000313mtc0 v0, c0_compare314315316/*317* Load the GP register.318*/319la gp, _gp320321/*322* Set up a stack frame. Store zero into the return address slot so323* we show as the top of the stack.324*/325addiu sp, sp, -24326sw z0, 20(sp)327328/*329* Off to MI code. Pass the cpu number as the argument; it's already330* in the a0 register.331*/332j cpu_hatch333nop /* delay slot for jump */334.end cpu_start_secondary335336337