Index: sys/riscv/include/machdep.h =================================================================== --- sys/riscv/include/machdep.h +++ sys/riscv/include/machdep.h @@ -42,12 +42,12 @@ vm_offset_t kern_phys; /* Kernel base (physical) addr */ vm_offset_t kern_stack; vm_offset_t dtbp_virt; /* Device tree blob virtual addr */ + vm_offset_t modulep; /* loader(8) metadata */ }; extern vm_paddr_t physmap[PHYS_AVAIL_ENTRIES]; extern u_int physmap_idx; -vm_offset_t fake_preload_metadata(struct riscv_bootparams *rbp); void initriscv(struct riscv_bootparams *); #endif /* _MACHINE_MACHDEP_H_ */ Index: sys/riscv/riscv/genassym.c =================================================================== --- sys/riscv/riscv/genassym.c +++ sys/riscv/riscv/genassym.c @@ -106,3 +106,4 @@ ASSYM(RISCV_BOOTPARAMS_KERN_STACK, offsetof(struct riscv_bootparams, kern_stack)); ASSYM(RISCV_BOOTPARAMS_DTBP_VIRT, offsetof(struct riscv_bootparams, dtbp_virt)); +ASSYM(RISCV_BOOTPARAMS_MODULEP, offsetof(struct riscv_bootparams, modulep)); Index: sys/riscv/riscv/locore.S =================================================================== --- sys/riscv/riscv/locore.S +++ sys/riscv/riscv/locore.S @@ -53,17 +53,20 @@ .text .globl _start _start: + /* + * Upon entry from FreeBSD's loader(8): + * a0 = modulep + * Upon entry from BBL/OpenSBI: + * a0 = hart id + * a1 = dtbp + */ + /* Set the global pointer */ .option push .option norelax lla gp, __global_pointer$ .option pop - /* - * a0 = hart id - * a1 = dtbp - */ - /* Pick a hart to run the boot process. */ lla t0, hart_lottery li t1, 1 @@ -135,6 +138,13 @@ add t0, s1, a5 sd t6, (t0) + /* + * If a0 contains an address, then we booted from loader(8) and don't + * need to map the DTB. + */ + li t2, KERNBASE + bgtu a0, t2, 3f + /* Create an L2 page superpage for DTB */ lla s1, pagetable_l2_devmap mv s2, a1 @@ -154,6 +164,7 @@ /* Page tables END */ /* Setup supervisor trap vector */ +3: lla t0, va sub t0, t0, s9 li t1, KERNBASE @@ -200,12 +211,25 @@ bltu s0, s1, 1b #ifdef SMP - /* Store boot hart id. */ + /* + * Preset boot_hart to be invalid. If we booted via loader(8), then it + * must be retrieved later. + */ la t0, boot_hart + li t1, 0xffffffff + sw t1, 0(t0) + + /* Check if a0 contains modulep (an address) */ + li t2, KERNBASE + bgtu a0, t2, 2f + + /* Otherwise, a0 contains the boot hart, and we can store it now */ sw a0, 0(t0) + mv a0, zero /* load zero for modulep */ #endif /* Fill riscv_bootparams */ +2: la t0, pagetable_l1 sd t0, RISCV_BOOTPARAMS_KERN_L1PT(sp) sd s9, RISCV_BOOTPARAMS_KERN_PHYS(sp) @@ -216,6 +240,8 @@ li t0, (VM_EARLY_DTB_ADDRESS) sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp) + sd a0, RISCV_BOOTPARAMS_MODULEP(sp) + mv a0, sp call _C_LABEL(initriscv) /* Off we go */ call _C_LABEL(mi_startup) Index: sys/riscv/riscv/machdep.c =================================================================== --- sys/riscv/riscv/machdep.c +++ sys/riscv/riscv/machdep.c @@ -723,12 +723,11 @@ /* * Fake up a boot descriptor table. - * RISCVTODO: This needs to be done via loader (when it's available). */ -vm_offset_t +static void fake_preload_metadata(struct riscv_bootparams *rvbp) { - static uint32_t fake_preload[35]; + static uint32_t fake_preload[48]; #ifdef DDB vm_offset_t zstart = 0, zend = 0; #endif @@ -791,6 +790,14 @@ memmove((void *)lastaddr, (const void *)rvbp->dtbp_virt, dtb_size); lastaddr = roundup(lastaddr + dtb_size, sizeof(int)); + PRELOAD_PUSH_VALUE(uint32_t, MODINFO_METADATA | MODINFOMD_KERNEND); + PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t)); + PRELOAD_PUSH_VALUE(vm_offset_t, lastaddr); + + PRELOAD_PUSH_VALUE(uint32_t, MODINFO_METADATA | MODINFOMD_HOWTO); + PRELOAD_PUSH_VALUE(uint32_t, sizeof(int)); + PRELOAD_PUSH_VALUE(int, RB_VERBOSE); + /* End marker */ PRELOAD_PUSH_VALUE(uint32_t, 0); PRELOAD_PUSH_VALUE(uint32_t, 0); @@ -798,7 +805,38 @@ KASSERT(fake_size < sizeof(fake_preload), ("Too many fake_preload items")); +} + +static vm_offset_t +parse_metadata(void) +{ + caddr_t kmdp; + vm_offset_t lastaddr; +#ifdef DDB + vm_offset_t ksym_start, ksym_end; +#endif + char *kern_envp; + /* Find the kernel address */ + kmdp = preload_search_by_type("elf kernel"); + if (kmdp == NULL) + kmdp = preload_search_by_type("elf64 kernel"); + KASSERT(kmdp != NULL, ("No preload metadata found!")); + + /* Read the boot metadata */ + boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); + lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); + kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); + if (kern_envp != NULL) + init_static_kenv(kern_envp, 0); +#ifdef DDB + ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); + ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); + db_fetch_ksymtab(ksym_start, ksym_end); +#endif +#ifdef FDT + try_load_dtb(kmdp); +#endif return (lastaddr); } @@ -810,14 +848,16 @@ int mem_regions_sz; vm_offset_t lastaddr; vm_size_t kernlen; - caddr_t kmdp; +#ifdef FDT + phandle_t chosen; + uint32_t hart; +#endif TSRAW(&thread0, TS_ENTER, __func__, NULL); /* Set the pcpu data, this is needed by pmap_bootstrap */ pcpup = &__pcpu[0]; pcpu_init(pcpup, 0, sizeof(struct pcpu)); - pcpup->pc_hart = boot_hart; /* Set the pcpu pointer */ __asm __volatile("mv tp, %0" :: "r"(pcpup)); @@ -827,22 +867,44 @@ /* Initialize SBI interface. */ sbi_init(); - /* Set the module data location */ - lastaddr = fake_preload_metadata(rvbp); - - /* Find the kernel address */ - kmdp = preload_search_by_type("elf kernel"); - if (kmdp == NULL) - kmdp = preload_search_by_type("elf64 kernel"); - - boothowto = RB_VERBOSE | RB_SINGLE; - boothowto = RB_VERBOSE; + /* Parse the boot metadata. */ + if (rvbp->modulep != 0) { + preload_metadata = (caddr_t)rvbp->modulep; + } else { + fake_preload_metadata(rvbp); + } + lastaddr = parse_metadata(); - kern_envp = NULL; + /* + * Get the boot hart ID. This was either passed in directly from the + * firmware, or needs to be retreived from the device tree. + */ +#ifdef FDT + chosen = OF_finddevice("/chosen"); + if (OF_getprop(chosen, "boot-hartid", &hart, sizeof(hart)) != -1) { + boot_hart = hart; + } +#endif + KASSERT(boot_hart != ~0UL, ("Could not obtain boot hart")); + pcpup->pc_hart = boot_hart; #ifdef FDT - try_load_dtb(kmdp); + /* + * Get the boot hart ID. This was either passed in directly from the + * SBI firmware and handle by locore, or stored in the device tree by + * an earlier boot stage. + */ + chosen = OF_finddevice("/chosen"); + if (OF_getencprop(chosen, "boot-hartid", &hart, sizeof(hart)) != -1) { + boot_hart = (u_long)hart; + } +#endif + if (boot_hart == 0xffffffff) { + panic("Boot hart ID was not properly set"); + } + pcpup->pc_hart = boot_hart; +#ifdef FDT /* * Exclude reserved memory specified by the device tree. Typically, * this contains an entry for memory used by the runtime SBI firmware.