Cleanup early bootstrap code. This mostly realigns the code with the
authorkettenis <kettenis@openbsd.org>
Fri, 2 Jul 2021 10:42:22 +0000 (10:42 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 2 Jul 2021 10:42:22 +0000 (10:42 +0000)
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@

sys/arch/riscv64/include/bootconfig.h
sys/arch/riscv64/include/vmparam.h
sys/arch/riscv64/riscv64/genassym.cf
sys/arch/riscv64/riscv64/locore.S
sys/arch/riscv64/riscv64/locore0.S
sys/arch/riscv64/riscv64/machdep.c

index 270fd68..4d6f8ae 100644 (file)
@@ -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 <br@bsdpad.com>
  * 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_ */
index 22a6fd5..16858dc 100644 (file)
@@ -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 */
index 07a170d..4f9cb44 100644 (file)
@@ -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 <bbamsch@google.com>
 # 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
index 0916f40..adfb81c 100644 (file)
@@ -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 <br@bsdpad.com>
  * SUCH DAMAGE.
  */
 
-#include <assym.h>
+#include "assym.h"
+
 #include <sys/syscall.h>
 #include <machine/asm.h>
 #include <machine/param.h>
 #include <machine/vmparam.h>
-#include <machine/trap.h>
 #include <machine/riscvreg.h>
 #include <machine/pte.h>
 
+#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
index 8ac6ab5..434dc0e 100644 (file)
@@ -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
  * $FreeBSD: head/sys/arm64/arm64/locore.S 282867 2015-05-13 18:57:03Z zbb $
  */
 
-#include <sys/syscall.h>
 #include <machine/asm.h>
 #include <machine/param.h>
-#include <machine/trap.h>
-#include <machine/riscvreg.h>
-#include <machine/pte.h>
 
        .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
index 0327513..a6c778c 100644 (file)
@@ -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 <patrick@blueri.se>
@@ -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;