aboutsummaryrefslogtreecommitdiff
path: root/sys/riscv/riscv
diff options
context:
space:
mode:
authorMitchell Horne <mhorne@FreeBSD.org>2020-04-06 22:48:43 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2020-04-06 22:48:43 +0000
commit24891abdb2843c61ba8496ddb8935d894692f135 (patch)
tree571415efb821031c65c1b7be0777dfb5881bd06d /sys/riscv/riscv
parent44c27d70a56151072da4636352653214f91f2cf7 (diff)
downloadsrc-24891abdb2843c61ba8496ddb8935d894692f135.tar.gz
src-24891abdb2843c61ba8496ddb8935d894692f135.zip
RISC-V: copy the DTB to early KVA
The location of the device-tree blob is passed to the kernel by the previous booting stage (i.e. BBL or OpenSBI). Currently, we leave it untouched and mark the 1MB of memory holding it as unavailable. Instead, do what is done by other fake_preload_metadata() routines and copy to the DTB to KVA space. This is more in line with what loader(8) will provide us in the future, and it allows us to reclaim the hole in physical memory. Reviewed by: markj, kp (earlier version) Differential Revision: https://reviews.freebsd.org/D24152
Notes
Notes: svn path=/head/; revision=359673
Diffstat (limited to 'sys/riscv/riscv')
-rw-r--r--sys/riscv/riscv/genassym.c3
-rw-r--r--sys/riscv/riscv/locore.S3
-rw-r--r--sys/riscv/riscv/machdep.c50
-rw-r--r--sys/riscv/riscv/pmap.c10
4 files changed, 43 insertions, 23 deletions
diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c
index d164ef8d3263..fa5ca242102a 100644
--- a/sys/riscv/riscv/genassym.c
+++ b/sys/riscv/riscv/genassym.c
@@ -56,10 +56,12 @@ __FBSDID("$FreeBSD$");
#include <machine/pte.h>
#include <machine/intr.h>
#include <machine/machdep.h>
+#include <machine/vmparam.h>
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 a794851bcb6b..0f4a84260c43 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 8dc05a70e28b..872d64060778 100644
--- a/sys/riscv/riscv/machdep.c
+++ b/sys/riscv/riscv/machdep.c
@@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/kdb.h>
#include <machine/machdep.h>
+#include <machine/metadata.h>
#include <machine/pcb.h>
#include <machine/reg.h>
#include <machine/riscvreg.h>
@@ -93,6 +94,7 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef FDT
+#include <contrib/libfdt/libfdt.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#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 86b10cc9c034..9a8a83906a2f 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) \