Changeset View
Changeset View
Standalone View
Standalone View
sys/riscv/riscv/locore.S
Show All 40 Lines | |||||
#include <machine/param.h> | #include <machine/param.h> | ||||
#include <machine/trap.h> | #include <machine/trap.h> | ||||
#include <machine/riscvreg.h> | #include <machine/riscvreg.h> | ||||
#include <machine/pte.h> | #include <machine/pte.h> | ||||
.globl kernbase | .globl kernbase | ||||
.set kernbase, KERNBASE | .set kernbase, KERNBASE | ||||
/* Trap entries */ | |||||
.text | .text | ||||
/* | |||||
/* Reset vector */ | * Alternate entry point. Used when booting via SBI firmware. It must be placed | ||||
.text | * at the beginning of the .text section. Arguments are as follows: | ||||
.globl _start | * - a0 = hart ID | ||||
_start: | * - a1 = dtbp | ||||
* | |||||
* Multiple CPUs might enter from this point, so we perform a hart lottery and | |||||
* send the losers to mpentry. | |||||
*/ | |||||
.globl _alt_start | |||||
_alt_start: | |||||
/* Set the global pointer */ | /* Set the global pointer */ | ||||
.option push | .option push | ||||
.option norelax | .option norelax | ||||
lla gp, __global_pointer$ | lla gp, __global_pointer$ | ||||
.option pop | .option pop | ||||
/* | |||||
* a0 = hart id | |||||
* a1 = dtbp | |||||
*/ | |||||
/* Pick a hart to run the boot process. */ | /* Pick a hart to run the boot process. */ | ||||
lla t0, hart_lottery | lla t0, hart_lottery | ||||
li t1, 1 | li t1, 1 | ||||
amoadd.w t0, t1, 0(t0) | amoadd.w t0, t1, 0(t0) | ||||
/* | /* | ||||
* We must jump to mpentry in the non-BSP case because the offset is | * We must jump to mpentry in the non-BSP case because the offset is | ||||
* too large to fit in a 12-bit branch immediate. | * too large to fit in a 12-bit branch immediate. | ||||
*/ | */ | ||||
beqz t0, 1f | beqz t0, 1f | ||||
j mpentry | j mpentry | ||||
1: | |||||
/* Store the boot hart */ | |||||
lla t0, boot_hart | |||||
sw a0, 0(t0) | |||||
mhorne: Note that I've dropped the #ifdef SMP requirement for storing to boot_hart as I believe it is… | |||||
/* Load zero as modulep */ | |||||
mv a0, zero | |||||
j pagetables | |||||
/* | /* | ||||
* Page tables | * Main entry point. This routine is marked as the ELF entry, and is where | ||||
* loader(8) will enter the kernel. Arguments are as follows: | |||||
* - a0 = modulep | |||||
* - a1 = ??? | |||||
* | |||||
* It is expected that only a single CPU will enter here. | |||||
*/ | */ | ||||
1: | .globl _start | ||||
_start: | |||||
/* Set the global pointer */ | |||||
.option push | |||||
.option norelax | |||||
lla gp, __global_pointer$ | |||||
.option pop | |||||
/* | |||||
* Zero a1 to indicate that we have no DTB pointer. It is already | |||||
* included in the loader(8) metadata. | |||||
*/ | |||||
mv a1, zero | |||||
/* | |||||
* Page tables setup | |||||
* a0 - modulep or zero | |||||
* a1 - zero or dtbp | |||||
*/ | |||||
pagetables: | |||||
/* Get the kernel's load address */ | /* Get the kernel's load address */ | ||||
jal get_physmem | jal get_physmem | ||||
/* Add L1 entry for kernel */ | /* Add L1 entry for kernel */ | ||||
lla s1, pagetable_l1 | lla s1, pagetable_l1 | ||||
lla s2, pagetable_l2 /* Link to next level PN */ | lla s2, pagetable_l2 /* Link to next level PN */ | ||||
srli s2, s2, PAGE_SHIFT | srli s2, s2, PAGE_SHIFT | ||||
Show All 11 Lines | pagetables: | ||||
sd t6, (t0) | sd t6, (t0) | ||||
/* Level 2 superpages (512 x 2MiB) */ | /* Level 2 superpages (512 x 2MiB) */ | ||||
lla s1, pagetable_l2 | lla s1, pagetable_l2 | ||||
srli t4, s9, 21 /* Div physmem base by 2 MiB */ | srli t4, s9, 21 /* Div physmem base by 2 MiB */ | ||||
li t2, 512 /* Build 512 entries */ | li t2, 512 /* Build 512 entries */ | ||||
add t3, t4, t2 | add t3, t4, t2 | ||||
li t5, 0 | li t5, 0 | ||||
2: | 1: | ||||
li t0, (PTE_KERN | PTE_X) | li t0, (PTE_KERN | PTE_X) | ||||
slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */ | slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */ | ||||
or t5, t0, t2 | or t5, t0, t2 | ||||
sd t5, (s1) /* Store PTE entry to position */ | sd t5, (s1) /* Store PTE entry to position */ | ||||
addi s1, s1, PTE_SIZE | addi s1, s1, PTE_SIZE | ||||
addi t4, t4, 1 | addi t4, t4, 1 | ||||
bltu t4, t3, 2b | bltu t4, t3, 1b | ||||
/* Create an L1 page for early devmap */ | /* Create an L1 page for early devmap */ | ||||
lla s1, pagetable_l1 | lla s1, pagetable_l1 | ||||
lla s2, pagetable_l2_devmap /* Link to next level PN */ | lla s2, pagetable_l2_devmap /* Link to next level PN */ | ||||
srli s2, s2, PAGE_SHIFT | srli s2, s2, PAGE_SHIFT | ||||
li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE) | li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE) | ||||
srli a5, a5, L1_SHIFT /* >> L1_SHIFT */ | srli a5, a5, L1_SHIFT /* >> L1_SHIFT */ | ||||
andi a5, a5, 0x1ff /* & 0x1ff */ | andi a5, a5, 0x1ff /* & 0x1ff */ | ||||
li t4, PTE_V | li t4, PTE_V | ||||
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ | slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ | ||||
or t6, t4, t5 | or t6, t4, t5 | ||||
/* Store single level1 PTE entry to position */ | /* Store single level1 PTE entry to position */ | ||||
li a6, PTE_SIZE | li a6, PTE_SIZE | ||||
mulw a5, a5, a6 | mulw a5, a5, a6 | ||||
add t0, s1, a5 | add t0, s1, a5 | ||||
sd t6, (t0) | sd t6, (t0) | ||||
/* Check if we have a DTB that needs to be mapped */ | |||||
beqz a1, 2f | |||||
/* Create an L2 page superpage for DTB */ | /* Create an L2 page superpage for DTB */ | ||||
lla s1, pagetable_l2_devmap | lla s1, pagetable_l2_devmap | ||||
mv s2, a1 | mv s2, a1 | ||||
srli s2, s2, PAGE_SHIFT | srli s2, s2, PAGE_SHIFT | ||||
/* Mask off any bits that aren't aligned */ | /* Mask off any bits that aren't aligned */ | ||||
andi s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1) | andi s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1) | ||||
li t0, (PTE_KERN) | li t0, (PTE_KERN) | ||||
slli t2, s2, PTE_PPN0_S /* << PTE_PPN0_S */ | slli t2, s2, PTE_PPN0_S /* << PTE_PPN0_S */ | ||||
or t0, t0, t2 | or t0, t0, t2 | ||||
/* Store PTE entry to position */ | /* Store PTE entry to position */ | ||||
li a6, PTE_SIZE | li a6, PTE_SIZE | ||||
li a5, 510 | li a5, 510 | ||||
mulw a5, a5, a6 | mulw a5, a5, a6 | ||||
add t1, s1, a5 | add t1, s1, a5 | ||||
sd t0, (t1) | sd t0, (t1) | ||||
/* Page tables END */ | /* Page tables END */ | ||||
/* Setup supervisor trap vector */ | /* Setup supervisor trap vector */ | ||||
2: | |||||
lla t0, va | lla t0, va | ||||
sub t0, t0, s9 | sub t0, t0, s9 | ||||
li t1, KERNBASE | li t1, KERNBASE | ||||
add t0, t0, t1 | add t0, t0, t1 | ||||
csrw stvec, t0 | csrw stvec, t0 | ||||
/* Set page tables base register */ | /* Set page tables base register */ | ||||
lla s2, pagetable_l1 | lla s2, pagetable_l1 | ||||
Show All 29 Lines | .option pop | ||||
/* Clear BSS */ | /* Clear BSS */ | ||||
la s0, _C_LABEL(__bss_start) | la s0, _C_LABEL(__bss_start) | ||||
la s1, _C_LABEL(_end) | la s1, _C_LABEL(_end) | ||||
1: | 1: | ||||
sd zero, 0(s0) | sd zero, 0(s0) | ||||
addi s0, s0, 8 | addi s0, s0, 8 | ||||
bltu s0, s1, 1b | bltu s0, s1, 1b | ||||
#ifdef SMP | |||||
/* Store boot hart id. */ | |||||
la t0, boot_hart | |||||
sw a0, 0(t0) | |||||
#endif | |||||
/* Fill riscv_bootparams */ | /* Fill riscv_bootparams */ | ||||
la t0, pagetable_l1 | la t0, pagetable_l1 | ||||
sd t0, RISCV_BOOTPARAMS_KERN_L1PT(sp) | sd t0, RISCV_BOOTPARAMS_KERN_L1PT(sp) | ||||
sd s9, RISCV_BOOTPARAMS_KERN_PHYS(sp) | sd s9, RISCV_BOOTPARAMS_KERN_PHYS(sp) | ||||
la t0, initstack | la t0, initstack | ||||
sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp) | sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp) | ||||
li t0, (VM_EARLY_DTB_ADDRESS) | li t0, (VM_EARLY_DTB_ADDRESS) | ||||
/* Add offset of DTB within superpage */ | /* Add offset of DTB within superpage */ | ||||
li t1, (L2_OFFSET) | li t1, (L2_OFFSET) | ||||
and t1, a1, t1 | and t1, a1, t1 | ||||
add t0, t0, t1 | add t0, t0, t1 | ||||
sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp) | sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp) | ||||
sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp) | sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp) | ||||
sd a0, RISCV_BOOTPARAMS_MODULEP(sp) | |||||
mv a0, sp | mv a0, sp | ||||
call _C_LABEL(initriscv) /* Off we go */ | call _C_LABEL(initriscv) /* Off we go */ | ||||
call _C_LABEL(mi_startup) | call _C_LABEL(mi_startup) | ||||
/* | /* | ||||
* Get the physical address the kernel is loaded to. Returned in s9. | * Get the physical address the kernel is loaded to. Returned in s9. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 124 Lines • Show Last 20 Lines |
Note that I've dropped the #ifdef SMP requirement for storing to boot_hart as I believe it is better that the boot CPU always have access to its hart ID. The PLIC driver requires it, for example, and could cause issues if a !SMP system was running on a hart != 0.