RISC-V: Check that the DTB doesn't overlap with kernel
This can happen with very large kernels (e.g. ones embedding a root filesystem). The DTB written by OpenSBI/BBL is quite small so this is unlikely to hit important data, but if it does this can result in very confusing and hard-to-debug crashes. Add a KASSERT() and a verbose print to catch this problem with debug kernels. While this will not print any output by default if it fails (that would depend on EARLY_PRINTF), at least the kernel now halts reliably instead of randomly crashing. Reviewed By: mhorne Differential Revision: https://reviews.freebsd.org/D25153
This commit is contained in:
parent
f7910a3df9
commit
c98013c0b1
@ -42,6 +42,7 @@ struct riscv_bootparams {
|
|||||||
vm_offset_t kern_phys; /* Kernel base (physical) addr */
|
vm_offset_t kern_phys; /* Kernel base (physical) addr */
|
||||||
vm_offset_t kern_stack;
|
vm_offset_t kern_stack;
|
||||||
vm_offset_t dtbp_virt; /* Device tree blob virtual addr */
|
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[PHYS_AVAIL_ENTRIES];
|
extern vm_paddr_t physmap[PHYS_AVAIL_ENTRIES];
|
||||||
|
@ -106,3 +106,4 @@ ASSYM(RISCV_BOOTPARAMS_KERN_PHYS, offsetof(struct riscv_bootparams, kern_phys));
|
|||||||
ASSYM(RISCV_BOOTPARAMS_KERN_STACK, offsetof(struct riscv_bootparams,
|
ASSYM(RISCV_BOOTPARAMS_KERN_STACK, offsetof(struct riscv_bootparams,
|
||||||
kern_stack));
|
kern_stack));
|
||||||
ASSYM(RISCV_BOOTPARAMS_DTBP_VIRT, offsetof(struct riscv_bootparams, dtbp_virt));
|
ASSYM(RISCV_BOOTPARAMS_DTBP_VIRT, offsetof(struct riscv_bootparams, dtbp_virt));
|
||||||
|
ASSYM(RISCV_BOOTPARAMS_DTBP_PHYS, offsetof(struct riscv_bootparams, dtbp_phys));
|
||||||
|
@ -221,6 +221,7 @@ va:
|
|||||||
and t1, a1, t1
|
and t1, a1, t1
|
||||||
add t0, t0, t1
|
add t0, t0, t1
|
||||||
sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp)
|
sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp)
|
||||||
|
sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp)
|
||||||
|
|
||||||
mv a0, sp
|
mv a0, sp
|
||||||
call _C_LABEL(initriscv) /* Off we go */
|
call _C_LABEL(initriscv) /* Off we go */
|
||||||
|
@ -776,9 +776,20 @@ fake_preload_metadata(struct riscv_bootparams *rvbp)
|
|||||||
PRELOAD_PUSH_VALUE(uint32_t, 0);
|
PRELOAD_PUSH_VALUE(uint32_t, 0);
|
||||||
preload_metadata = (caddr_t)fake_preload;
|
preload_metadata = (caddr_t)fake_preload;
|
||||||
|
|
||||||
|
/* Check if bootloader clobbered part of the kernel with the DTB. */
|
||||||
|
KASSERT(rvbp->dtbp_phys + dtb_size <= rvbp->kern_phys ||
|
||||||
|
rvbp->dtbp_phys >= rvbp->kern_phys + (lastaddr - KERNBASE),
|
||||||
|
("FDT (%lx-%lx) and kernel (%lx-%lx) overlap", rvbp->dtbp_phys,
|
||||||
|
rvbp->dtbp_phys + dtb_size, rvbp->kern_phys,
|
||||||
|
rvbp->kern_phys + (lastaddr - KERNBASE)));
|
||||||
KASSERT(fake_size < sizeof(fake_preload),
|
KASSERT(fake_size < sizeof(fake_preload),
|
||||||
("Too many fake_preload items"));
|
("Too many fake_preload items"));
|
||||||
|
|
||||||
|
if (boothowto & RB_VERBOSE)
|
||||||
|
printf("FDT phys (%lx-%lx), kernel phys (%lx-%lx)\n",
|
||||||
|
rvbp->dtbp_phys, rvbp->dtbp_phys + dtb_size,
|
||||||
|
rvbp->kern_phys, rvbp->kern_phys + (lastaddr - KERNBASE));
|
||||||
|
|
||||||
return (lastaddr);
|
return (lastaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user