diff --git a/sys/riscv/include/machdep.h b/sys/riscv/include/machdep.h index 1cd34c22d64..ccfa22db312 100644 --- a/sys/riscv/include/machdep.h +++ b/sys/riscv/include/machdep.h @@ -42,7 +42,6 @@ struct riscv_bootparams { 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 dtbp_phys; /* Device tree blob physical addr */ }; extern vm_paddr_t physmap[]; diff --git a/sys/riscv/include/metadata.h b/sys/riscv/include/metadata.h new file mode 100644 index 00000000000..2d9d8242163 --- /dev/null +++ b/sys/riscv/include/metadata.h @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Mitchell Horne + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * 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_METADATA_H_ +#define _MACHINE_METADATA_H_ + +#define MODINFOMD_DTBP 0x1001 + +#endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/riscv/include/vmparam.h b/sys/riscv/include/vmparam.h index 1ed90e4a15e..8c8a871a0ed 100644 --- a/sys/riscv/include/vmparam.h +++ b/sys/riscv/include/vmparam.h @@ -192,6 +192,8 @@ #define KERNENTRY (0) +#define VM_EARLY_DTB_ADDRESS (VM_MAX_KERNEL_ADDRESS - (2 * L2_SIZE)) + /* * How many physical pages per kmem arena virtual page. */ diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c index d164ef8d326..fa5ca242102 100644 --- a/sys/riscv/riscv/genassym.c +++ b/sys/riscv/riscv/genassym.c @@ -56,10 +56,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include ASSYM(KERNBASE, KERNBASE); ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); ASSYM(VM_MAX_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS); +ASSYM(VM_EARLY_DTB_ADDRESS, VM_EARLY_DTB_ADDRESS); ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); @@ -104,4 +106,3 @@ ASSYM(RISCV_BOOTPARAMS_KERN_PHYS, offsetof(struct riscv_bootparams, kern_phys)); 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_DTBP_PHYS, offsetof(struct riscv_bootparams, dtbp_phys)); diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S index a794851bcb6..0f4a84260c4 100644 --- a/sys/riscv/riscv/locore.S +++ b/sys/riscv/riscv/locore.S @@ -217,9 +217,8 @@ va: la t0, initstack sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp) - li t0, (VM_MAX_KERNEL_ADDRESS - 2 * L2_SIZE) + li t0, (VM_EARLY_DTB_ADDRESS) sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp) - sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp) mv a0, sp call _C_LABEL(initriscv) /* Off we go */ diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 8dc05a70e28..872d6406077 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -93,6 +94,7 @@ __FBSDID("$FreeBSD$"); #endif #ifdef FDT +#include #include #include #endif @@ -741,11 +743,19 @@ add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap, #ifdef FDT static void -try_load_dtb(caddr_t kmdp, vm_offset_t dtbp) +try_load_dtb(caddr_t kmdp) { + vm_offset_t dtbp; + + dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); #if defined(FDT_DTB_STATIC) - dtbp = (vm_offset_t)&fdt_static_dtb; + /* + * In case the device tree blob was not retrieved (from metadata) try + * to use the statically embedded one. + */ + if (dtbp == (vm_offset_t)NULL) + dtbp = (vm_offset_t)&fdt_static_dtb; #endif if (dtbp == (vm_offset_t)NULL) { @@ -777,13 +787,14 @@ cache_setup(void) * RISCVTODO: This needs to be done via loader (when it's available). */ vm_offset_t -fake_preload_metadata(struct riscv_bootparams *rvbp __unused) +fake_preload_metadata(struct riscv_bootparams *rvbp) { static uint32_t fake_preload[35]; #ifdef DDB vm_offset_t zstart = 0, zend = 0; #endif vm_offset_t lastaddr; + size_t dtb_size; int i; i = 0; @@ -824,10 +835,23 @@ fake_preload_metadata(struct riscv_bootparams *rvbp __unused) #endif #endif lastaddr = (vm_offset_t)&end; + + /* Copy the DTB to KVA space. */ + lastaddr = roundup(lastaddr, sizeof(int)); + fake_preload[i++] = MODINFO_METADATA | MODINFOMD_DTBP; + fake_preload[i++] = sizeof(vm_offset_t); + *(vm_offset_t *)&fake_preload[i] = (vm_offset_t)lastaddr; + i += sizeof(vm_offset_t) / sizeof(uint32_t); + dtb_size = fdt_totalsize(rvbp->dtbp_virt); + memmove((void *)lastaddr, (const void *)rvbp->dtbp_virt, dtb_size); + lastaddr = roundup(lastaddr + dtb_size, sizeof(int)); + fake_preload[i++] = 0; fake_preload[i] = 0; preload_metadata = (void *)fake_preload; + KASSERT(i < nitems(fake_preload), ("Too many fake_preload items")); + return (lastaddr); } @@ -836,8 +860,6 @@ initriscv(struct riscv_bootparams *rvbp) { struct mem_region mem_regions[FDT_MEM_REGIONS]; struct pcpu *pcpup; - vm_offset_t rstart, rend; - vm_offset_t s, e; int mem_regions_sz; vm_offset_t lastaddr; vm_size_t kernlen; @@ -873,7 +895,7 @@ initriscv(struct riscv_bootparams *rvbp) kern_envp = NULL; #ifdef FDT - try_load_dtb(kmdp, rvbp->dtbp_virt); + try_load_dtb(kmdp); #endif /* Load the physical memory ranges */ @@ -884,21 +906,9 @@ initriscv(struct riscv_bootparams *rvbp) if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, NULL) != 0) panic("Cannot get physical memory regions"); - s = rvbp->dtbp_phys; - e = s + DTB_SIZE_MAX; - for (i = 0; i < mem_regions_sz; i++) { - rstart = mem_regions[i].mr_start; - rend = (mem_regions[i].mr_start + mem_regions[i].mr_size); - - if ((rstart < s) && (rend > e)) { - /* Exclude DTB region. */ - add_physmap_entry(rstart, (s - rstart), physmap, &physmap_idx); - add_physmap_entry(e, (rend - e), physmap, &physmap_idx); - } else { - add_physmap_entry(mem_regions[i].mr_start, - mem_regions[i].mr_size, physmap, &physmap_idx); - } + add_physmap_entry(mem_regions[i].mr_start, + mem_regions[i].mr_size, physmap, &physmap_idx); } #endif diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c index 86b10cc9c03..9a8a83906a2 100644 --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -558,6 +558,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) vm_offset_t freemempos; vm_offset_t dpcpu, msgbufpv; vm_paddr_t end, max_pa, min_pa, pa, start; + pt_entry_t *l2p; int i; printf("pmap_bootstrap %lx %lx %lx\n", l1pt, kernstart, kernlen); @@ -610,6 +611,15 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) freemempos = pmap_bootstrap_l3(l1pt, VM_MAX_KERNEL_ADDRESS - L2_SIZE, freemempos); + /* + * Invalidate the mapping we created for the DTB. At this point a copy + * has been created, and we no longer need it. We want to avoid the + * possibility of an aliased mapping in the future. + */ + l2p = pmap_l2(kernel_pmap, VM_EARLY_DTB_ADDRESS); + KASSERT((pmap_load(l2p) & PTE_V) != 0, ("dtpb not mapped")); + pmap_clear(l2p); + sfence_vma(); #define alloc_pages(var, np) \