The branch main has been updated by kib:

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

commit c7e5802ab6e6230a5782a09c914585d055eb5223
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-06-16 21:44:00 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-06-21 12:17:11 +0000

    amd64: do not restore fsbase/gsbase for 32bit processes
    
    There is no WRFSBASE and WRGSBASE 32bit variants at all. As such, the
    fsbase and gsbase must always be equal to the bases in the corresponding
    segment descriptor, same as on real i386.
    
    If a 32bit program reloads either %fs or %gs using setcontext(9) or
    sigreturn(9), restoring bases from the syscall entry time is wrong.
    In all other cases, hardware already does the right action when the
    segment register is loaded, and the bases for the ufssel/ugssel in GDT
    are updated on the context switch.
    
    Reviewed by:    markj (previous version)
    Tested by:      [email protected]
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D57611
---
 sys/amd64/amd64/exception.S | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index 5ff75fb65740..4d58e07caf4b 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -1161,12 +1161,15 @@ do_segs:
        .globl  ld_fs
 ld_fs:
        movw    %ax,%fs
+       testl   $PCB_32BIT,PCB_FLAGS(%r8)
+       jnz     after_ld_fsbase
        movl    $MSR_FSBASE,%ecx
        movl    PCB_FSBASE(%r8),%eax
        movl    PCB_FSBASE+4(%r8),%edx
        .globl  ld_fsbase
 ld_fsbase:
        wrmsr
+after_ld_fsbase:
        /* Restore %gs and gsbase */
        movw    TF_GS(%rsp),%si
        pushfq
@@ -1179,6 +1182,8 @@ ld_fsbase:
        .globl  ld_gs
 ld_gs:
        movw    %si,%gs
+       testl   $PCB_32BIT,PCB_FLAGS(%r8)
+       jnz     ld_gsbase_32
        /* Restore kernel %gs base */
        movl    %r12d,%eax
        movl    %r13d,%edx
@@ -1194,6 +1199,8 @@ ld_gs:
        .globl  ld_gsbase
 ld_gsbase:
        wrmsr   /* May trap if non-canonical, but only for TLS. */
+
+after_ld_gsbase:
        .globl  ld_es
 ld_es:
        movw    TF_ES(%rsp),%es
@@ -1241,6 +1248,30 @@ ld_regs:
 doreti_iret:
        iretq
 
+       /*
+        * 32bit gsbase path.
+        * The KGSBASE is not loaded from the pcb_gsbase, instead we move
+        * the GSBASE value into KGSBASE right after loading user %gs, then
+        * restore kernel gsbase.
+        */
+ld_gsbase_32:
+       /* Read the user gsbase into %r14d:%r15d. */
+       movl    $MSR_GSBASE,%ecx
+       rdmsr
+       movl    %eax,%r14d
+       movl    %edx,%r15d
+       /* Restore kernel %gs base */
+       movl    %r12d,%eax
+       movl    %r13d,%edx
+       wrmsr
+       popfq
+       /* Load the user gsbase into KGSBASE. */
+       movl    $MSR_KGSBASE,%ecx
+       movl    %r14d,%eax
+       movl    %r15d,%edx
+       wrmsr
+       jmp     after_ld_gsbase
+
 set_segs:
        movw    $KUDSEL,%ax
        movw    %ax,TF_DS(%rsp)

Reply via email to