From: kettenis Date: Fri, 2 Jul 2021 10:42:22 +0000 (+0000) Subject: Cleanup early bootstrap code. This mostly realigns the code with the X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=19eb7a60a01edeed36c0aa7e020e819b7d21a035;p=openbsd Cleanup early bootstrap code. This mostly realigns the code with the FreeBSD code from which it was derived. In particular, it uses the same trick to switch page tables as FreeBSD, which is what we use to spin up the secondary CPUs already. This avoids having to install a temporary 1:1 mapping. ok mlarkin@ --- diff --git a/sys/arch/riscv64/include/bootconfig.h b/sys/arch/riscv64/include/bootconfig.h index 270fd68e0ad..4d6f8ae3ae9 100644 --- a/sys/arch/riscv64/include/bootconfig.h +++ b/sys/arch/riscv64/include/bootconfig.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bootconfig.h,v 1.3 2021/05/12 01:20:52 jsg Exp $ */ +/* $OpenBSD: bootconfig.h,v 1.4 2021/07/02 10:42:22 kettenis Exp $ */ /*- * Copyright (c) 2015-2017 Ruslan Bukin @@ -32,37 +32,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _MACHINE_BOOTCONFIG_H_ #define _MACHINE_BOOTCONFIG_H_ struct riscv_bootparams { -#if 0 - vaddr_t modulep; -#endif vaddr_t kern_l1pt; /* L1 page table for the kernel */ - uint64_t kern_delta; /* PA - VA */ + paddr_t kern_phys; vaddr_t kern_stack; -#if 0 - void *arg0; // passed to kernel in R0 - void *arg1; // passed to kernel in R1 - void *arg2; // passed to kernel in R2 -#endif vaddr_t dtbp_virt; /* Device tree blob virtual addr */ - vaddr_t dtbp_phys; /* Device tree blob physical addr */ + paddr_t dtbp_phys; /* Device tree blob physical addr */ }; -extern char *boot_file; - -// XXX ??? -extern paddr_t physmap[]; -extern u_int physmap_idx; - -// XXX ??? -vaddr_t fake_preload_metadata(struct riscv_bootparams *rbp); -void initriscv(struct riscv_bootparams *); - #endif /* _MACHINE_BOOTCONFIG_H_ */ diff --git a/sys/arch/riscv64/include/vmparam.h b/sys/arch/riscv64/include/vmparam.h index 22a6fd5c07b..16858dc63c3 100644 --- a/sys/arch/riscv64/include/vmparam.h +++ b/sys/arch/riscv64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.4 2021/06/15 09:52:04 matthieu Exp $ */ +/* $OpenBSD: vmparam.h,v 1.5 2021/07/02 10:42:22 kettenis Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -184,7 +184,6 @@ extern paddr_t dmap_phys_base; extern paddr_t dmap_phys_max; extern vaddr_t dmap_virt_max; extern vaddr_t vm_max_kernel_address; -extern vaddr_t init_pt_va; #endif /* virtual sizes (bytes) for various kernel submaps */ diff --git a/sys/arch/riscv64/riscv64/genassym.cf b/sys/arch/riscv64/riscv64/genassym.cf index 07a170d78fc..4f9cb44139f 100644 --- a/sys/arch/riscv64/riscv64/genassym.cf +++ b/sys/arch/riscv64/riscv64/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.5 2021/06/30 22:20:56 kettenis Exp $ +# $OpenBSD: genassym.cf,v 1.6 2021/07/02 10:42:22 kettenis Exp $ # # Copyright (c) 2020 Brian Bamsch # All rights reserved. @@ -92,8 +92,8 @@ member ci_gmon endif struct riscv_bootparams -member kern_l1pt -member kern_delta -member kern_stack -member dtbp_virt -member dtbp_phys +member RISCV_BOOTPARAMS_KERN_L1PT kern_l1pt +member RISCV_BOOTPARAMS_KERN_PHYS kern_phys +member RISCV_BOOTPARAMS_KERN_STACK kern_stack +member RISCV_BOOTPARAMS_DTBP_VIRT dtbp_virt +member RISCV_BOOTPARAMS_DTBP_PHYS dtbp_phys diff --git a/sys/arch/riscv64/riscv64/locore.S b/sys/arch/riscv64/riscv64/locore.S index 0916f401eb4..adfb81cd551 100644 --- a/sys/arch/riscv64/riscv64/locore.S +++ b/sys/arch/riscv64/riscv64/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.12 2021/06/29 21:27:53 kettenis Exp $ */ +/* $OpenBSD: locore.S,v 1.13 2021/07/02 10:42:22 kettenis Exp $ */ /*- * Copyright (c) 2015-2018 Ruslan Bukin @@ -34,21 +34,28 @@ * SUCH DAMAGE. */ -#include +#include "assym.h" + #include #include #include #include -#include #include #include +#define VM_EARLY_DTB_ADDRESS (VM_MAX_KERNEL_ADDRESS - (2 * L2_SIZE)) .globl kernbase .set kernbase, KERNBASE - /* Reset vector */ .text +/* + * Main entry point. Arguments are as follows: + * - a0 = esym + * - a2 = dtbp + * + * It is expected that only a single CPU will enter here. + */ .globl _start_kern_bootstrap _start_kern_bootstrap: @@ -58,126 +65,74 @@ _start_kern_bootstrap: lla gp, __global_pointer$ .option pop - /* Get the physical address kernel loaded to */ - lla t0, virt_map //virt_map is a phy addr where its own va is stored. - ld t1, 0(t0) - sub t1, t1, t0 //t1 = t1 - t0 = va - pa, va<-->pa offset - li t2, KERNBASE //KERNBASE is virtual addr - sub s9, t2, t1 //s9 = physmem base of kernel - /* - * EFIBOOT passes: - * a0 = esym - * a1 = 0 - * a2 = dtb + * Page tables setup */ - la t0, esym - add a3, a0, t1 - sd a3, 0(t0) - mv a1, a2 + /* Get the kernel's load address */ + jal get_physmem - /* - * Page tables - */ + /* Add L1 entry for kernel */ + lla s1, pagetable_l1 + lla s2, pagetable_l2 /* Link to next level PN */ + srli s2, s2, PAGE_SHIFT - /* step0) Identity map kernel @ 0x80000000 */ - /* Build PTE for 1 GiB identity-mapped gigapage */ - lla s1, pagetable_l1 //phy addr - mv s2, s9 //phy addr - li t0, 0xffffffffc0000000 - and s2, s2, t0 - srli s2, s2, PAGE_SHIFT //12, 4K page - slli t5, s2, PTE_PPN0_S //10bit Phys Mem Attribute - li t4, (PTE_KERN | PTE_X) //flag bit - or t6, t4, t5 //t6 now is PTE for a 1 GiB gigapage - - /* Calculate VPN[2] for 1 GiB identity-mapped gigapage */ - mv a5, s9 //va -- identity mapped - srli a5, a5, L1_SHIFT //30, remaining va[63:30] - andi a5, a5, 0x1ff //only use va[38:30] as VPN[2], =0x002 - - /* Store L1 PTE entry */ + li a5, KERNBASE + srli a5, a5, L1_SHIFT /* >> L1_SHIFT */ + andi a5, a5, 0x1ff /* & 0x1ff */ + li t4, PTE_V + slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ + or t6, t4, t5 + + /* Store L1 PTE entry to position */ li a6, PTE_SIZE mulw a5, a5, a6 add t0, s1, a5 - mv s8, t0 // Store address in L1 Page Table to unmap later sd t6, (t0) - /* step1) Add L1 entry for kernel */ - - //calc PTE based on pa - lla s1, pagetable_l1 //phy addr - lla s2, pagetable_l2 - srli s2, s2, PAGE_SHIFT //12, 4K page - slli t5, s2, PTE_PPN0_S //10bit Phys Mem Attribute - li t4, PTE_V //PTE valid - or t6, t4, t5 //t6 now is the PTE for a level 2 page table - - //calc VPN[2] based on va - li a5, KERNBASE //va - srli a5, a5, L1_SHIFT //30 - andi a5, a5, 0x1ff //va[38:30] as VPN[2],==0x100 - - /* Store L1 PTE entry */ - li a6, PTE_SIZE //8 Bytes - mulw a5, a5, a6 //distance in unit of bytes - add t0, s1, a5 //s1 is L1 table base pa - sd t6, (t0) //PTE of a l2 page table is populated to l1 page table - - - /* step2) Level 2 superpages (512 x 2MiB) */ //mega pages: two-level page table + /* Level 2 superpages (512 x 2MiB) */ lla s1, pagetable_l2 - //calc PTE srli t4, s9, L2_SHIFT /* Div physmem base by 2 MiB */ - li t2, 512 /* Build totally 512 entries */ + li t2, 512 /* Build 512 entries */ add t3, t4, t2 - li t5, 0 -2: li t0, (PTE_KERN | PTE_X) - slli t2, t4, PTE_PPN1_S //19 - or t5, t0, t2 //PTE contructed +1: + slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */ + or t5, t0, t2 sd t5, (s1) /* Store PTE entry to position */ - - //iterating addi s1, s1, PTE_SIZE - addi t4, t4, 1 - bltu t4, t3, 2b //512 entries + addi t4, t4, 1 + bltu t4, t3, 1b - /* step3) Create an L1 entry for early devmap */ - lla s1, pagetable_l1 //pa + /* Create an L1 page for early devmap */ + lla s1, pagetable_l1 + lla s2, pagetable_l2_devmap /* Link to next level PN */ + srli s2, s2, PAGE_SHIFT - //calculate PTE based on pa: (PPN) + privilege/permission + ... - lla s2, pagetable_l2_devmap /* Link to next level PN */ //pa - srli s2, s2, PAGE_SHIFT //12, --> PPN - slli t5, s2, PTE_PPN0_S //10, PMA + li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE) + srli a5, a5, L1_SHIFT /* >> L1_SHIFT */ + andi a5, a5, 0x1ff /* & 0x1ff */ li t4, PTE_V - or t6, t4, t5 //PTE contructed - - //calculate VPN[2] index based on va - li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)//devmap is at kernel mem top, va - srli a5, a5, L1_SHIFT //30 - andi a5, a5, 0x1ff //index using va[38:30] + slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */ + or t6, t4, t5 /* Store single level1 PTE entry to position */ li a6, PTE_SIZE - mulw a5, a5, a6 //offset in Bytes - add t0, s1, a5 //find the physical add to write + mulw a5, a5, a6 + add t0, s1, a5 sd t6, (t0) - - /* step4) Create ONE L2 superpage 2MB for DTB */ + /* Create an L2 page superpage for DTB */ lla s1, pagetable_l2_devmap + mv s2, a1 + srli s2, s2, PAGE_SHIFT + /* Mask off any bits that aren't aligned */ + andi s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1) - //calc PTE based on pa - mv s2, a1 //dtb - li t0, 0xffffffffffe00000 - and s2, s2, t0 - srli s2, s2, PAGE_SHIFT //12 - slli t2, s2, PTE_PPN0_S //10 li t0, (PTE_KERN) - or t0, t0, t2 //PTE contructed + slli t2, s2, PTE_PPN0_S /* << PTE_PPN0_S */ + or t0, t0, t2 /* Store PTE entry to position */ li a6, PTE_SIZE @@ -188,21 +143,20 @@ _start_kern_bootstrap: /* Page tables END */ - - /* Calculate virtual address of the first instruction after enable paging */ - lla s3, va //va is a physical addr! - sub s3, s3, s9 //offset comparing to phymem base - li t0, KERNBASE //virt addr - add s3, s3, t0 + /* Setup supervisor trap vector */ + lla t0, va + sub t0, t0, s9 + li t1, KERNBASE + add t0, t0, t1 + csrw stvec, t0 /* Set page tables base register */ - lla s2, pagetable_l1 //pa - srli s2, s2, PAGE_SHIFT //12, --> PPN - li t0, SATP_MODE_SV39 //satp[63:60] = 1000b, enable paging! + lla s2, pagetable_l1 + srli s2, s2, PAGE_SHIFT + li t0, SATP_MODE_SV39 or s2, s2, t0 - sfence.vma //Supervisor Fence for Virtual Memory, to flush TLB + sfence.vma csrw satp, s2 - jr s3 .align 2 va: @@ -212,10 +166,6 @@ va: lla gp, __global_pointer$ .option pop - /* Unmap the identity mapped kernel gigapage */ - sd x0, (s8) // s8 is addr of pte for identity mapped kernel - sfence.vma // Flush the TLB. Goodbye identity mapped kernel! - /* Setup supervisor trap vector */ la t0, cpu_exception_handler csrw stvec, t0 @@ -225,43 +175,49 @@ va: csrw sscratch, t0 /* Initialize stack pointer */ - la s3, initstack_end - mv sp, s3 + la sp, initstack_end - /* Allocate space for thread0 PCB and riscv_bootparams */ - addi sp, sp, -(PCB_SIZEOF + RISCV_BOOTPARAMS_SIZEOF) & ~STACKALIGNBYTES + /* Clear frame pointer */ + mv s0, zero + + /* Allocate space for riscv_bootparams */ + addi sp, sp, -RISCV_BOOTPARAMS_SIZEOF + andi sp, sp, ~STACKALIGNBYTES /* Clear BSS */ - la s0, _C_LABEL(__bss_start) - la s1, _C_LABEL(_end) + la t0, _C_LABEL(__bss_start) + la t1, _C_LABEL(_end) 1: - sd zero, 0(s0) - addi s0, s0, 8 - bltu s0, s1, 1b + sd zero, 0(t0) + addi t0, t0, 8 + bltu t0, t1, 1b /* Fill riscv_bootparams */ - addi sp, sp, -RISCV_BOOTPARAMS_SIZEOF - la t0, pagetable_l1 - sd t0, KERN_L1PT(sp) - - li t0, KERNBASE - sub t0, s9, t0 //offset: PA - VA, used in pmap_* - sd t0, KERN_DELTA(sp) + sd t0, RISCV_BOOTPARAMS_KERN_L1PT(sp) + sd s9, RISCV_BOOTPARAMS_KERN_PHYS(sp) la t0, initstack - sd t0, KERN_STACK(sp) + sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp) - li t0, (VM_MAX_KERNEL_ADDRESS - 2 * L2_SIZE) // XXX Why 2? - li t1, 0x1fffff + li t0, (VM_EARLY_DTB_ADDRESS) + /* Add offset of DTB within superpage */ + li t1, (L2_OFFSET) and t1, a1, t1 add t0, t0, t1 - sd t0, DTBP_VIRT(sp) - sd a1, DTBP_PHYS(sp) + sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp) + sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp) + + /* Set esym to virtual addres of symbol table end */ + lla t0, esym + sub t1, a0, s9 + li t2, KERNBASE + add t1, t1, t2 + sd t1, 0(t0) - mv a0, sp //stack setup, can call C now! - call _C_LABEL(initriscv) // Off we go, defined in machdep.c - call _C_LABEL(main) //defined in openbsd/kern/init_main.c + mv a0, sp + call _C_LABEL(initriscv) /* Off we go */ + call _C_LABEL(main) /* * Get the physical address the kernel is loaded to. Returned in s9. @@ -292,9 +248,10 @@ sigfillsiz: .text ENTRY(sigcode) mv a0, sp - addi a0, a0, SF_SC //actual saved context + addi a0, a0, SF_SC li t0, SYS_sigreturn ecall + .globl _C_LABEL(sigcoderet) _C_LABEL(sigcoderet): /* sigreturn failed, exit */ @@ -304,16 +261,14 @@ END(sigcode) .globl _C_LABEL(esigcode) _C_LABEL(esigcode): - .data .global _C_LABEL(esym) -_C_LABEL(esym): .quad _C_LABEL(end) - +_C_LABEL(esym): + .quad _C_LABEL(end) .align 12 pagetable_l1: .space PAGE_SIZE - .globl pagetable_l2 pagetable_l2: .space PAGE_SIZE pagetable_l2_devmap: @@ -323,10 +278,6 @@ pagetable_l2_devmap: virt_map: .quad virt_map - .globl init_pt_va -init_pt_va: - .quad pagetable_l2 /* XXX: Keep page tables VA */ - #ifdef MULTIPROCESSOR .text diff --git a/sys/arch/riscv64/riscv64/locore0.S b/sys/arch/riscv64/riscv64/locore0.S index 8ac6ab5c3e4..434dc0ecf51 100644 --- a/sys/arch/riscv64/riscv64/locore0.S +++ b/sys/arch/riscv64/riscv64/locore0.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore0.S,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ +/* $OpenBSD: locore0.S,v 1.3 2021/07/02 10:42:22 kettenis Exp $ */ /*- * Copyright (c) 2012-2014 Andrew Turner @@ -28,16 +28,20 @@ * $FreeBSD: head/sys/arm64/arm64/locore.S 282867 2015-05-13 18:57:03Z zbb $ */ -#include #include #include -#include -#include -#include .text +/* + * Main entry point. EFIBOOT passes the following arguments: + * - a0 = esym + * - a1 = 0 + * - a2 = dtbp + */ .globl _start _start: + mv a1, a2 + /* jump to locore.S _start_kern_bootstrap*/ lla t0, _start_kern_bootstrap jr t0 diff --git a/sys/arch/riscv64/riscv64/machdep.c b/sys/arch/riscv64/riscv64/machdep.c index 0327513dd54..a6c778c5d7b 100644 --- a/sys/arch/riscv64/riscv64/machdep.c +++ b/sys/arch/riscv64/riscv64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.23 2021/06/30 22:20:56 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.24 2021/07/02 10:42:22 kettenis Exp $ */ /* * Copyright (c) 2014 Patrick Wildt @@ -544,37 +544,28 @@ int pmap_bootstrap_bs_map(bus_space_tag_t, bus_addr_t, void initriscv(struct riscv_bootparams *rbp) { - long kernbase = (long)_start & ~PAGE_MASK; - long kvo = rbp->kern_delta; paddr_t memstart, memend; + paddr_t ramstart, ramend; + paddr_t start, end; vaddr_t vstart; void *config = (void *)rbp->dtbp_virt; void *fdt = NULL; paddr_t fdt_start = (paddr_t)rbp->dtbp_phys; size_t fdt_size; + struct fdt_reg reg; + void *node; EFI_PHYSICAL_ADDRESS system_table = 0; int (*map_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); - paddr_t ramstart, ramend; - paddr_t start, end; int i; /* Set the per-CPU pointer. */ __asm volatile("mv tp, %0" :: "r"(&cpu_info_primary)); - // NOTE that 1GB of ram is mapped in by default in - // the bootstrap memory config, so nothing is necessary - // until pmap_bootstrap_finalize is called?? - - //NOTE: FDT is already mapped (rbp->dtbp_virt => rbp->dtbp_phys) - // Initialize the Flattened Device Tree if (!fdt_init(config) || fdt_get_size(config) == 0) panic("initriscv: no FDT"); fdt_size = fdt_get_size(config); - struct fdt_reg reg; - void *node; - node = fdt_find_node("/cpus"); if (node != NULL) { char *prop; @@ -682,15 +673,12 @@ initriscv(struct riscv_bootparams *rbp) } /* The bootloader has loaded us into a 64MB block. */ - memstart = KERNBASE + kvo; + memstart = rbp->kern_phys; memend = memstart + 64 * 1024 * 1024; - /* XXX */ - kernbase = KERNBASE; - /* Bootstrap enough of pmap to enter the kernel proper. */ - vstart = pmap_bootstrap(kvo, rbp->kern_l1pt, - kernbase, esym, memstart, memend, ramstart, ramend); + vstart = pmap_bootstrap(rbp->kern_phys - KERNBASE, rbp->kern_l1pt, + KERNBASE, esym, memstart, memend, ramstart, ramend); proc0paddr = (struct user *)rbp->kern_stack;