Initialization
Initial startup
The first code executed in the NetBSD kernel is low-level startup
code provided as part of the board-specific software. This code is
specified by the SYSTEM_FIRST_OBJ and SYSTEM_FIRST_SFILE defines in the
Makefile fragment mk.vx115_vep (discussed in the section on configuration); the source file is vx115_vep_start.S in
this project.
This assembly file is responsible for setting up the system so initial
kernel execution can take place. It performs the following operations.
- Copy the kernel to RAM
- Set up initial MMU page tables, using all section (1 MB) maps to start. In particular:
- Map all physical addresses to same virtual addresses (VA == PA), for any peripherals that may need this
- Map the physical peripheral space to the corresponding virtual address range
- Do this so can use bus mapping functions during setup in the init_arm( ) function
- Map the RAM with VA == PA, but set to be cacheable
- Map kernel virtual addresses to RAM physical addresses
- Enable the MMU
The initial MMU mapping is really just to allow the kernel to start
executing from its relocated location in RAM, before it sets up its
real page tables in the init_arm( ) routine, and to allow it to access peripherals during configuration.
Machine startup
The file vx115_vep_machdep.c provides platform-specific initialization.
This file defines several functions and data structures: an initarm( )
function that performs basic system initialization, a cpu_reboot( )
function that restarts the system on reboot, and a pmap_devmap
structure that defines the peripheral virtual-to-physical memory
mapping. Fortunately, the vast majority of these functions are common
across platforms, so existing code can be used with minor
modifications. The vx115_vep_machdep.c file was based on the
smdk2800_machdep.c source, and used the cpu_reboot function verbatim
and the initarm function with minor changes.
struct pmap_devmap vx115_vep_devmap[ ]
- array of specifications of virtual-physical memory mappings for peripherals
initarm( )
The initarm( ) function provides basic machine setup. It's called
during initialization from arch/arm/arm32/locore.S, before the kernel
main( ) function is called in kern/init_main.c. The initialization
performed in this function is as follows.
- call set_cpufuncs to set up basic cpu functions
- call pmap_devmap_register(vx115_vep_devmap) so can use
bus_space_map; the appropriate ranges must have been mapped in
vx115_vep_start.S
- call vx115_intr_bootstrap(PIC1_BASE_PHYS, PIC1_SIZE) to do early setup of interrupts needed for spl functionality
- call consinit for early console output
- set up bootconfig struct
- set values of memory parameters
- physical_start, physical_end, physical_freestart, physical_freeend, physmem
- allocate pages for L1 page directory and L2 page tables
- allocate pages for vectors, stacks, msgbuf
- set up page tables
- call pmap_link_l2pt to link L2 page tables into L1 page table
- call pmap_chunk to map a chunk of memory into L1/L2 page
tables, pmap_entry to map a single page, pmap_section to map a single
section
- call pmap_devmap_bootstrap to map static devices
- call cpu_domains to set cpu domains
- call setttb to set page table base
- call cpu_tlb_flushID to flush TLB for I and D
- call arm32_vector_init
- call set_stackptr to set stack pointers
- set data abort, prefetch abort, undefined instruction handlers
- call uvm_setpagesize to set up page size
- call uvm_page_physload to load physical pages into VM system, and add free pages to free page pool
- call pmap_bootstrap to initialize the BSD page map structure from the ARM-specific page tables built above
- return stack pointer
consinit( )
The consinit( ) function is used to initialize the serial console just
sufficiently to allow console messages to be printed. Further
initialization of the serial interface is deferred to the autoconfig
process.
Comments/questions: jsevy@cs.drexel.edu