The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=ddab534cd6f6557740c24ff2019642880ad8bef6
commit ddab534cd6f6557740c24ff2019642880ad8bef6 Author: Konstantin Belousov <k...@freebsd.org> AuthorDate: 2025-05-19 01:30:14 +0000 Commit: Konstantin Belousov <k...@freebsd.org> CommitDate: 2025-05-28 11:11:23 +0000 amd64: do not handle fs/gs bases conditionally on the selector For machines with RDFSBASE support, we only saved and restored fs and gs base registers when corresponding segment register contained the predefined value. This breaks some valid uses of the LDT together with WR{F,G}SBASE. Unconditionally save bases, and restore them on return to usermode. The PCB_FULL_IRET optimization is still in place. Reviewed by: markj, olce Reported and tested: Alex S <iwt...@gmail.com> Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D50414 --- sys/amd64/amd64/cpu_switch.S | 6 ------ sys/amd64/amd64/exception.S | 29 ----------------------------- sys/amd64/amd64/machdep.c | 6 ++---- sys/amd64/ia32/ia32_exception.S | 3 +-- 4 files changed, 3 insertions(+), 41 deletions(-) diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index 32d1b91d50b4..a053f6c70af1 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -91,14 +91,8 @@ ENTRY(cpu_switch) jnz 2f testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip) jz 2f - movl %fs,%eax - cmpl $KUF32SEL,%eax - jne 1f rdfsbase %rax movq %rax,PCB_FSBASE(%r8) -1: movl %gs,%eax - cmpl $KUG32SEL,%eax - jne 2f movq %rdx,%r12 movl $MSR_KGSBASE,%ecx /* Read user gs base */ rdmsr diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index c3d5819378d1..babfbacf92ef 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -479,22 +479,14 @@ prot_addrf: jz 6f /* already running with kernel GS.base */ testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip) jz 2f - cmpw $KUF32SEL,TF_FS(%rsp) - jne 1f rdfsbase %rax -1: cmpw $KUG32SEL,TF_GS(%rsp) - jne 2f rdgsbase %rdx 2: swapgs lfence movq PCPU(CURPCB),%rdi testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip) jz 4f - cmpw $KUF32SEL,TF_FS(%rsp) - jne 3f movq %rax,PCB_FSBASE(%rdi) -3: cmpw $KUG32SEL,TF_GS(%rsp) - jne 4f movq %rdx,PCB_GSBASE(%rdi) orl $PCB_FULL_IRET,PCB_FLAGS(%rdi) /* full iret from user #gp */ 4: call handle_ibrs_entry @@ -730,12 +722,8 @@ dbg_fromuserspace: orl $PCB_FULL_IRET,PCB_FLAGS(%rdi) testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip) jz 3f - cmpw $KUF32SEL,TF_FS(%rsp) - jne 2f rdfsbase %rax movq %rax,PCB_FSBASE(%rdi) -2: cmpw $KUG32SEL,TF_GS(%rsp) - jne 3f movl $MSR_KGSBASE,%ecx rdmsr shlq $32,%rdx @@ -842,12 +830,8 @@ nmi_fromuserspace: orl $PCB_FULL_IRET,PCB_FLAGS(%rdi) testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip) jz 3f - cmpw $KUF32SEL,TF_FS(%rsp) - jne 2f rdfsbase %rax movq %rax,PCB_FSBASE(%rdi) -2: cmpw $KUG32SEL,TF_GS(%rsp) - jne 3f movl $MSR_KGSBASE,%ecx rdmsr shlq $32,%rdx @@ -1177,15 +1161,12 @@ do_segs: .globl ld_fs ld_fs: movw %ax,%fs - cmpw $KUF32SEL,%ax - jne 1f movl $MSR_FSBASE,%ecx movl PCB_FSBASE(%r8),%eax movl PCB_FSBASE+4(%r8),%edx .globl ld_fsbase ld_fsbase: wrmsr -1: /* Restore %gs and gsbase */ movw TF_GS(%rsp),%si pushfq @@ -1198,10 +1179,6 @@ ld_fsbase: .globl ld_gs ld_gs: movw %si,%gs - /* Save user %gs base into %r14d:%r15d */ - rdmsr - movl %eax,%r14d - movl %edx,%r15d /* Restore kernel %gs base */ movl %r12d,%eax movl %r13d,%edx @@ -1212,14 +1189,8 @@ ld_gs: * from the previously saved msr read. */ movl $MSR_KGSBASE,%ecx - cmpw $KUG32SEL,%si - jne 1f movl PCB_GSBASE(%r8),%eax movl PCB_GSBASE+4(%r8),%edx - jmp ld_gsbase -1: - movl %r14d,%eax - movl %r15d,%edx .globl ld_gsbase ld_gsbase: wrmsr /* May trap if non-canonical, but only for TLS. */ diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 6d9bc8b7c573..032a134bbd4b 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1789,10 +1789,8 @@ set_pcb_flags_fsgsbase(struct pcb *pcb, const u_int flags) (pcb->pcb_flags & PCB_FULL_IRET) == 0) { r = intr_disable(); if ((pcb->pcb_flags & PCB_FULL_IRET) == 0) { - if (rfs() == _ufssel) - pcb->pcb_fsbase = rdfsbase(); - if (rgs() == _ugssel) - pcb->pcb_gsbase = rdmsr(MSR_KGSBASE); + pcb->pcb_fsbase = rdfsbase(); + pcb->pcb_gsbase = rdmsr(MSR_KGSBASE); } set_pcb_flags_raw(pcb, flags); intr_restore(r); diff --git a/sys/amd64/ia32/ia32_exception.S b/sys/amd64/ia32/ia32_exception.S index 42d0ff6c638b..ef1a2c59a0af 100644 --- a/sys/amd64/ia32/ia32_exception.S +++ b/sys/amd64/ia32/ia32_exception.S @@ -54,10 +54,10 @@ int0x80_syscall_common: movq %rax,TF_RAX(%rsp) movq %rdx,TF_RDX(%rsp) movq %rcx,TF_RCX(%rsp) + movq %r15,TF_R15(%rsp) call handle_ibrs_entry sti movq %rsi,TF_RSI(%rsp) - movq %r8,TF_R8(%rsp) movq %r9,TF_R9(%rsp) movq %rbx,TF_RBX(%rsp) movq %rbp,TF_RBP(%rsp) @@ -66,7 +66,6 @@ int0x80_syscall_common: movq %r12,TF_R12(%rsp) movq %r13,TF_R13(%rsp) movq %r14,TF_R14(%rsp) - movq %r15,TF_R15(%rsp) movl $TF_HASSEGS,TF_FLAGS(%rsp) pushfq andq $~(PSL_D | PSL_AC),(%rsp)