The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=83d98828867591b5d842573ed6edcec7392f82df

commit 83d98828867591b5d842573ed6edcec7392f82df
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-01-18 21:14:59 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-01-19 16:20:36 +0000

    sys: do not allow entering vm_fault() on boot until VM is initialized
    
    On amd64, a hack sets td_critnest to 1 in hammer_time(), and then clear
    it before returning from hammer_time(), which is too early.  Instead,
    set TDP_NOFAULTING for thread0, and clear the flag after vm_init() finished.
    
    Noted by:       adrian
    Reviewed by:    adrian (previous version), markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D54768
---
 sys/amd64/amd64/machdep.c |  5 +----
 sys/kern/init_main.c      | 12 +++++++++++-
 sys/vm/vm_init.c          |  8 ++++++++
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 2fce1a7e64b6..cae58181000f 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1518,13 +1518,11 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
 
        /*
         * We initialize the PCB pointer early so that exception
-        * handlers will work.  Also set up td_critnest to short-cut
-        * the page fault handler.
+        * handlers will work.
         */
        cpu_max_ext_state_size = sizeof(struct savefpu);
        set_top_of_stack_td(&thread0);
        thread0.td_pcb = get_pcb_td(&thread0);
-       thread0.td_critnest = 1;
 
        /*
         * The console and kdb should be initialized even earlier than here,
@@ -1615,7 +1613,6 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
 #ifdef FDT
        x86_init_fdt();
 #endif
-       thread0.td_critnest = 0;
 
        kasan_init();
        kmsan_init();
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 4144297d674c..39357b8d4440 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -104,7 +104,17 @@ void mi_startup(void);                             /* 
Should be elsewhere */
 static struct session session0;
 static struct pgrp pgrp0;
 struct proc proc0;
-struct thread0_storage thread0_st __aligned(32);
+struct thread0_storage thread0_st __aligned(32) = {
+       .t0st_thread = {
+               /*
+                * thread0.td_pflags is set with TDP_NOFAULTING to
+                * short-cut the vm page fault handler until it is
+                * ready.  It is cleared in vm_init() after VM
+                * initialization.
+                */
+               .td_pflags = TDP_NOFAULTING,
+       },
+};
 struct vmspace vmspace0;
 struct proc *initproc;
 
diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c
index a0d3651ba266..2764b438d27b 100644
--- a/sys/vm/vm_init.c
+++ b/sys/vm/vm_init.c
@@ -159,6 +159,14 @@ vm_mem_init(void *dummy)
        pmap_init();
        vm_pager_init();
 
+       /*
+        * Now we can properly handle calls into vm_fault() from
+        * kernel page faults during initialization, typically to
+        * panic.  Clear the nofaulting flag set for thread0 in the
+        * image, see kern/init_main.c
+        */
+       curthread->td_pflags &= ~TDP_NOFAULTING;
+
 #ifdef INVARIANTS
        vm_check_pagesizes();
 #endif

Reply via email to