[Bug 298105] debug of TRAP 12 kernel 5k display issues (fixes provided) leads to pre-init pmap bug, stride/bpp bug and many outdated kernel constants on amd64 arm64 (and possibly others)
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 298105] debug of TRAP 12 kernel 5k display issues (fixes provided) leads to pre-init pmap bug, stride/bpp bug and many outdated kernel constants on amd64 arm64 (and possibly others)"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 298105] debug of TRAP 12 kernel 5k display issues (fixes provided) leads to pre-init pmap bug, stride/bpp bug and many outdated kernel constants on amd64 arm64 (and possibly others)"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 298105] debug of TRAP 12 kernel 5k display issues (fixes provided) leads to pre-init pmap bug, stride/bpp bug and many outdated kernel constants on amd64 arm64 (and possibly others)"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 01 Sep 2026 23:02:21 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=298105
Bug ID: 298105
Summary: debug of TRAP 12 kernel 5k display issues (fixes
provided) leads to pre-init pmap bug, stride/bpp bug
and many outdated kernel constants on amd64 arm64 (and
possibly others)
Product: Base System
Version: 15.1-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: bugs@FreeBSD.org
Reporter: tagoldth@gmail.com
Files involved/modified:
usr/src/sys/amd64/amd64/pmap.c
usr/src/sys/arm64/arm64/pmap.c
usr/src/sys/arm64/include/pte.h
usr/src/sys/dev/vt/hw/efifb/efifb.c (the caller that snowballs it all)
usr/src/sys/dev/vt/hw/fb/vt_early_fb.c (stride/bpp calculation error)
usr/src/sys/dev/vt/vt.h
It was assumed that https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=280597
had fixed 5k (5120x2880) screen issues at boot and was closed. A part of the
assumption that the bug was in the loader only was due to never seeing the
initial kernel banner. The crash/hang happened when printing the screen
configuration and calling the loaded kernel.
Replacing the loader with a custom one that purposely set things up revealed
that the crashes are happening pre-init in the kernel, specifically in
pmap_mapdev_internal() during a call to pmap_kenter_attr(), which is looped
many times with a small page size on the newly allocated pa to va range.
Though the crash is here, doing some pre-init debugging via some inserted
profiling code dumping to EARLY_PRINTF, the problem in pmap_kenter_attr() is
due to an invalid va being stumbled on part way through the execution of the
loop.
This invalid va comes from an allocation out of virtual_avail, with no bounds
check in place before doing the allocation.
The bounds comes from the outdated constants that make up how much
virtual_avail is allocated (via nkpt).
As I have amd64 and arm64, I did the trackdown on the amd64 and made a bounds
check for use in the pre-init case. Also updated the constants for amd64 and
arm64.
I did not bother writing a check for similar bounds problems in the arm code,
but did update the requisite constants there too to stop the crashes/hangs.
The problem:
The vitual_avail is set up and sized by way of code and constants that make
assumptions about the things encountered pre init. These include some slop as
well as the default framebuffer.
When the framebuffer is a large size modern one, the sizes compiled in do not
come close to matching what is requested of virtual_avail. This means it is
easy to be given a va which is past what is reserved for pre-init use.
A 5k display can easily be a stride of 8k with a 3k depth and 4 byte pixel. An
8k display can easily be 8k x 5k x 4. Just the 5k one is over twice the
available reserved space in the default kernel. My display, for example, needs
90 megabytes. An 8k display needs 130 megabytes.
Meanwhile, the kernel, with slop included, only has 64MBytes allocated.
Additionally, the VT sizings are not up to par for large displays either.
These are fixed below too.
To make it usable, all of the below are related and need to be done. The
history change is a nice to have because it affects debugging of things that
are printed (and 500 is just too small for a workable history).
TODO: All of the pre-init allocation for architectures other than amd64 (done
below) needs to be looked at for making a bounds check. The constants for the
sizing of the virtual_avail needs to be updated for architectures other than
amd64 and arm64 (which are done below) to allow for modern framebuffers without
hitting a pre init bounds.
All changes here are against 15.1p3
*** usr/src/sys/amd64/amd64/pmap.c Mon Aug 31 19:29:19 2026
--- usr/src/sys/amd64/amd64/pmap.c.orig Thu Aug 27 16:12:44 2026
***************
*** 1676,1695 ****
* before vm_mem_init() and pmap_init(). 20MB for a frame buffer
* is not uncommon.
*/
!
! /*
! * The 32 that was here was based on sizing of yesteryear. Thing
! * is, modern framebuffers can easily be 90MB for the efifb portion.
! * Lets be generous and give it twice that, or 192MB. I know I use
90MB
! * of it at boot on a 5120x2880 (90MB is 8192stride*2880line*4byte)
! * framebuffer. This has been manifesting as a trap 12 in early
! * boot below because of passing the limit of pages allocated here.
! * Those traps occur in the tmpsize/pmap_kenter_attr() loop when it
! * hits the invalid space provided above it in the code.
! *
! * There are places NKPT are discussed that need new updating too.
! */
! pt_pages += 96; /* 192MB additional slop. */
#endif
nkpt = pt_pages;
}
--- 1676,1682 ----
* before vm_mem_init() and pmap_init(). 20MB for a frame buffer
* is not uncommon.
*/
! pt_pages += 32; /* 64MB additional slop. */
#endif
nkpt = pt_pages;
}
***************
*** 9417,9437 ****
pa = trunc_page(pa);
if (!pmap_initialized) {
- printf("%s: avail: 0x%016lx end: 0x%016lx free: 0x%016lx
(%luMB) req-paddr: 0x%016lx req-size:
%lu\n",__func__,virtual_avail,MAX(KERNBASE + nkpt * NBPDR,
kernel_vm_end),MAX(KERNBASE + nkpt * NBPDR,
kernel_vm_end)-virtual_avail,(MAX(KERNBASE + nkpt * NBPDR,
kernel_vm_end)-virtual_avail)/1024L/1024L,pa,size);
va = 0;
for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
ppim = pmap_preinit_mapping + i;
if (ppim->va == 0) {
- /*
- * The code past this happily does the
erroneous allocation past virtual addresses
- * reserved. The trap 12 crashes in early boot
seen because of this manifest themselves
- * farther in the tmpsize loop doing
pmap_kenter_attr().
- *
- * Doing a panic() here, but, perhaps this
should return errors to the caller and
- * let them deal with it? That may require too
much other coding, however.
- */
- if((virtual_avail+size)>=(MAX(KERNBASE + nkpt *
NBPDR, kernel_vm_end)))
- panic("%s: passing end of kernel
virtual addresses allocated", __func__);
ppim->pa = pa;
ppim->sz = size;
ppim->mode = mode;
--- 9404,9413 ----
***************
*** 9474,9490 ****
if (va == 0)
panic("%s: Couldn't allocate KVA", __func__);
}
-
-
for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE)
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
-
pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
-
-
if ((flags & MAPDEV_FLUSHCACHE) != 0)
pmap_invalidate_cache_range(va, va + tmpsize);
-
return ((void *)(va + offset));
}
--- 9450,9460 ----
*** usr/src/sys/arm64/arm64/pmap.c Mon Aug 31 19:29:35 2026
--- usr/src/sys/arm64/arm64/pmap.c.orig Mon Aug 31 13:57:21 2026
***************
*** 303,309 ****
struct pmap kernel_pmap_store;
/* Used for mapping ACPI memory before VM is initialized */
! #define PMAP_PREINIT_MAPPING_COUNT 96
#define PMAP_PREINIT_MAPPING_SIZE (PMAP_PREINIT_MAPPING_COUNT *
L2_SIZE)
static vm_offset_t preinit_map_va; /* Start VA of pre-init mapping space
*/
static int vm_initialized = 0; /* No need to use pre-init maps
when set */
--- 303,309 ----
struct pmap kernel_pmap_store;
/* Used for mapping ACPI memory before VM is initialized */
! #define PMAP_PREINIT_MAPPING_COUNT 32
#define PMAP_PREINIT_MAPPING_SIZE (PMAP_PREINIT_MAPPING_COUNT *
L2_SIZE)
static vm_offset_t preinit_map_va; /* Start VA of pre-init mapping space
*/
static int vm_initialized = 0; /* No need to use pre-init maps
when set */
*** usr/src/sys/arm64/include/pte.h Mon Aug 31 19:29:46 2026
--- usr/src/sys/arm64/include/pte.h.orig Mon Aug 31 13:54:54 2026
***************
*** 211,221 ****
* A substantial portion of this is to make sure that we can cope with 4K
* framebuffers in early boot, assuming a common 4K resolution @ 32-bit
depth.
*/
! /*
! * Framebuffers of 5k and 8k now easily possible with 32 bit depth
! * Be sure these can work.
! */
! #define PMAP_MAPDEV_EARLY_SIZE (L2_SIZE * 60)
#if PAGE_SIZE == PAGE_SIZE_4K
#define L0_ENTRIES_SHIFT 9
--- 211,217 ----
* A substantial portion of this is to make sure that we can cope with 4K
* framebuffers in early boot, assuming a common 4K resolution @ 32-bit
depth.
*/
! #define PMAP_MAPDEV_EARLY_SIZE (L2_SIZE * 20)
#if PAGE_SIZE == PAGE_SIZE_4K
#define L0_ENTRIES_SHIFT 9
*** usr/src/sys/dev/vt/hw/fb/vt_early_fb.c Mon Aug 31 19:29:57 2026
--- usr/src/sys/dev/vt/hw/fb/vt_early_fb.c.orig Thu Aug 20 19:02:25 2026
***************
*** 282,295 ****
/* Get pixel storage size. */
info->fb_bpp = info->fb_stride / info->fb_width * 8;
-
- /*
- * XXX: above compuation fails with big strides on large framebuffers
- * an 8192 stride on 5120 line gives 32768/5120*8 => 5*8 => 40 bits
- */
-
- if((info->fb_bpp)>32
- info->fb_bpp = 32;
#ifdef FDT
vt_efb_initialize(info, node);
--- 282,287 ----
*** usr/src/sys/dev/vt/vt.h Tue Sep 1 16:31:04 2026
--- usr/src/sys/dev/vt/vt.h.orig Thu Aug 20 19:00:13 2026
***************
*** 222,236 ****
term_char_t **vb_rows; /* (u) Array of rows */
};
- /*
- * Modern machine console debugging has much more to scroll through, 500 ->
5000
- * covers most of it
- */
-
#ifdef SC_HISTORY_SIZE
#define VBF_DEFAULT_HISTORY_SIZE SC_HISTORY_SIZE
#else
! #define VBF_DEFAULT_HISTORY_SIZE 5000
#endif
void vtbuf_lock(struct vt_buf *);
--- 222,231 ----
term_char_t **vb_rows; /* (u) Array of rows */
};
#ifdef SC_HISTORY_SIZE
#define VBF_DEFAULT_HISTORY_SIZE SC_HISTORY_SIZE
#else
! #define VBF_DEFAULT_HISTORY_SIZE 500
#endif
void vtbuf_lock(struct vt_buf *);
***************
*** 418,432 ****
#define PIXEL_WIDTH(w) ((w) / 8)
#define PIXEL_HEIGHT(h) ((h) / 16)
- /*
- * Modern framebuffers are much larger than 4096x2048, they could be 8192
landscape or portrait
- */
-
#ifndef VT_FB_MAX_WIDTH
! #define VT_FB_MAX_WIDTH 8192
#endif
#ifndef VT_FB_MAX_HEIGHT
! #define VT_FB_MAX_HEIGHT 8192
#endif
/* name argument is not used yet. */
--- 413,423 ----
#define PIXEL_WIDTH(w) ((w) / 8)
#define PIXEL_HEIGHT(h) ((h) / 16)
#ifndef VT_FB_MAX_WIDTH
! #define VT_FB_MAX_WIDTH 4096
#endif
#ifndef VT_FB_MAX_HEIGHT
! #define VT_FB_MAX_HEIGHT 2400
#endif
/* name argument is not used yet. */
--
You are receiving this mail because:
You are the assignee for the bug.