git: f1e18f331923 - main - riscv: Exclude OpenSBI memory regions when booting with EFI
Date: Wed, 16 Apr 2025 14:21:51 UTC
The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=f1e18f331923041980149fef46cdb2736e61debb commit f1e18f331923041980149fef46cdb2736e61debb Author: Bojan Novković <bnovkov@FreeBSD.org> AuthorDate: 2025-04-15 16:28:05 +0000 Commit: Bojan Novković <bnovkov@FreeBSD.org> CommitDate: 2025-04-16 14:20:13 +0000 riscv: Exclude OpenSBI memory regions when booting with EFI OpenSBI uses the first PMP entry to prevent buggy supervisor software from overwriting the firmware [1]. However, this region may not be properly marked as reserved in the EFI map, leading to an access violation exception whenever the kernel attempts to write to a page from that region. Fix this by preemptively excluding first EFI memory map entry if it is marked as "BootServicesData". [1] https://github.com/riscv-non-isa/riscv-sbi-doc/pull/37 Reported by: tuexen Tested by: tuexen Fixes: a2e2178402af Reviewed by: imp, jrtc27 Differential Revision: https://reviews.freebsd.org/D49839 --- sys/riscv/riscv/machdep.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 516dbde5ffaa..f253bc9a853b 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -541,6 +541,22 @@ fdt_physmem_exclude_region_cb(const struct mem_region *mr, void *arg __unused) } #endif +static void +efi_exclude_sbi_pmp_cb(struct efi_md *p, void *argp) +{ + bool *first = (bool *)argp; + + if (!*first) + return; + + *first = false; + if (p->md_type == EFI_MD_TYPE_BS_DATA) { + physmem_exclude_region(p->md_phys, + min(p->md_pages * EFI_PAGE_SIZE, L2_SIZE), + EXFLAG_NOALLOC); + } +} + void initriscv(struct riscv_bootparams *rvbp) { @@ -548,6 +564,7 @@ initriscv(struct riscv_bootparams *rvbp) struct pcpu *pcpup; vm_offset_t lastaddr; vm_size_t kernlen; + bool first; char *env; TSRAW(&thread0, TS_ENTER, __func__, NULL); @@ -577,11 +594,22 @@ initriscv(struct riscv_bootparams *rvbp) if (efihdr != NULL) { efi_map_add_entries(efihdr); efi_map_exclude_entries(efihdr); + + /* + * OpenSBI uses the first PMP entry to prevent buggy supervisor + * software from overwriting the firmware. However, this + * region may not be properly marked as reserved, leading + * to an access violation exception whenever the kernel + * attempts to write to a page from that region. + * + * Fix this by excluding first EFI memory map entry + * if it is marked as "BootServicesData". + */ + first = true; + efi_map_foreach_entry(efihdr, efi_exclude_sbi_pmp_cb, &first); } #ifdef FDT else { - bool first; - /* Exclude reserved memory specified by the device tree. */ fdt_foreach_reserved_mem(fdt_physmem_exclude_region_cb, NULL);