bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 5/5] add setting gs/fsbase


From: Samuel Thibault
Subject: Re: [PATCH 5/5] add setting gs/fsbase
Date: Mon, 1 May 2023 03:30:33 +0200
User-agent: NeoMutt/20170609 (1.8.3)

Applied, thanks!

Luca Dariz, le mer. 19 avril 2023 21:47:03 +0200, a ecrit:
> * i386/i386/i386asm.sym: add offsets for asm
> * i386/i386/pcb.c: switch FSBASE/GSBASE on context switch and
>   implement accessors in thread setstatus/getstatus
> * i386/i386/thread.h: add new state to thread saved state
> * kern/thread.c: add i386_FSGS_BASE_STATE handler
> * x86_64/locore.S: fix fs/gs handling, skipping the base address and
>   avoid resetting it by manually re-loading fs/gs
> ---
>  i386/i386/i386asm.sym |  2 +
>  i386/i386/pcb.c       | 39 +++++++++++++++++--
>  i386/i386/thread.h    |  4 ++
>  kern/thread.c         |  3 ++
>  x86_64/locore.S       | 89 ++++++++++++++++++++++++++++++++++---------
>  5 files changed, 116 insertions(+), 21 deletions(-)
> 
> diff --git a/i386/i386/i386asm.sym b/i386/i386/i386asm.sym
> index 1b9b40bb..fd0be557 100644
> --- a/i386/i386/i386asm.sym
> +++ b/i386/i386/i386asm.sym
> @@ -108,6 +108,8 @@ offset    i386_saved_state        r       r12
>  offset       i386_saved_state        r       r13
>  offset       i386_saved_state        r       r14
>  offset       i386_saved_state        r       r15
> +offset       i386_saved_state        r       fsbase
> +offset       i386_saved_state        r       gsbase
>  #endif
>  
>  offset       i386_interrupt_state    i       eip
> diff --git a/i386/i386/pcb.c b/i386/i386/pcb.c
> index 61125fe8..8a9e3bf4 100644
> --- a/i386/i386/pcb.c
> +++ b/i386/i386/pcb.c
> @@ -51,6 +51,7 @@
>  #include "eflags.h"
>  #include "gdt.h"
>  #include "ldt.h"
> +#include "msr.h"
>  #include "ktss.h"
>  #include "pcb.h"
>  
> @@ -372,7 +373,10 @@ thread_t switch_context(
>        *      Load the rest of the user state for the new thread
>        */
>       switch_ktss(new->pcb);
> -
> +#if defined(__x86_64__) && !defined(USER32)
> +        wrmsr(MSR_REG_FSBASE, new->pcb->iss.fsbase);
> +        wrmsr(MSR_REG_GSBASE, new->pcb->iss.gsbase);
> +#endif
>       return Switch_context(old, continuation, new);
>  }
>  
> @@ -667,7 +671,23 @@ kern_return_t thread_setstatus(
>                       return ret;
>               break;
>           }
> -
> +#if defined(__x86_64__) && !defined(USER32)
> +         case i386_FSGS_BASE_STATE:
> +            {
> +                    struct i386_fsgs_base_state *state;
> +                    if (count < i386_FSGS_BASE_STATE_COUNT)
> +                            return KERN_INVALID_ARGUMENT;
> +
> +                    state = (struct i386_fsgs_base_state *) tstate;
> +                    thread->pcb->iss.fsbase = state->fs_base;
> +                    thread->pcb->iss.gsbase = state->gs_base;
> +                    if (thread == current_thread()) {
> +                            wrmsr(MSR_REG_FSBASE, state->fs_base);
> +                            wrmsr(MSR_REG_GSBASE, state->gs_base);
> +                    }
> +                    break;
> +            }
> +#endif
>           default:
>               return(KERN_INVALID_ARGUMENT);
>       }
> @@ -843,7 +863,20 @@ kern_return_t thread_getstatus(
>               *count = i386_DEBUG_STATE_COUNT;
>               break;
>           }
> -
> +#if defined(__x86_64__) && !defined(USER32)
> +         case i386_FSGS_BASE_STATE:
> +            {
> +                    struct i386_fsgs_base_state *state;
> +                    if (*count < i386_FSGS_BASE_STATE_COUNT)
> +                            return KERN_INVALID_ARGUMENT;
> +
> +                    state = (struct i386_fsgs_base_state *) tstate;
> +                    state->fs_base = thread->pcb->iss.fsbase;
> +                    state->fs_base = thread->pcb->iss.gsbase;
> +                    *count = i386_FSGS_BASE_STATE_COUNT;
> +                    break;
> +            }
> +#endif
>           default:
>               return(KERN_INVALID_ARGUMENT);
>       }
> diff --git a/i386/i386/thread.h b/i386/i386/thread.h
> index 933b43d8..b5fc5ffb 100644
> --- a/i386/i386/thread.h
> +++ b/i386/i386/thread.h
> @@ -51,6 +51,10 @@
>   */
>  
>  struct i386_saved_state {
> +#ifdef __x86_64__
> +     unsigned long   fsbase;
> +     unsigned long   gsbase;
> +#endif
>       unsigned long   gs;
>       unsigned long   fs;
>       unsigned long   es;
> diff --git a/kern/thread.c b/kern/thread.c
> index 392d38f8..f0cea804 100644
> --- a/kern/thread.c
> +++ b/kern/thread.c
> @@ -1472,6 +1472,9 @@ kern_return_t thread_set_state(
>       if (flavor == i386_DEBUG_STATE && thread == current_thread())
>               /* This state can be set directly for the curren thread.  */
>               return thread_setstatus(thread, flavor, new_state, 
> new_state_count);
> +     if (flavor == i386_FSGS_BASE_STATE && thread == current_thread())
> +             /* This state can be set directly for the curren thread.  */
> +             return thread_setstatus(thread, flavor, new_state, 
> new_state_count);
>  #endif
>  
>       if (thread == THREAD_NULL || thread == current_thread())
> diff --git a/x86_64/locore.S b/x86_64/locore.S
> index 1b17d921..ba0400a3 100644
> --- a/x86_64/locore.S
> +++ b/x86_64/locore.S
> @@ -34,6 +34,7 @@
>  #include <i386/i386/trap.h>
>  #include <i386/i386/seg.h>
>  #include <i386/i386/ldt.h>
> +#include <i386/i386/msr.h>
>  #include <i386/i386/i386asm.h>
>  #include <i386/i386/cpu_number.h>
>  #include <i386/i386/xen.h>
> @@ -41,6 +42,46 @@
>  #define pusha pushq %rax ; pushq %rcx ; pushq %rdx ; pushq %rbx ; subq 
> $8,%rsp ; pushq %rbp ; pushq %rsi ; pushq %rdi ; pushq %r8 ; pushq %r9 ; 
> pushq %r10 ; pushq %r11 ; pushq %r12 ; pushq %r13 ; pushq %r14 ; pushq %r15
>  #define popa popq %r15 ; popq %r14 ; popq %r13 ; popq %r12 ; popq %r11 ; 
> popq %r10 ; popq %r9 ; popq %r8 ; popq %rdi ; popq %rsi ; popq %rbp ; addq 
> $8,%rsp ; popq %rbx ; popq %rdx ; popq %rcx ; popq %rax
>  
> +#ifdef USER32
> +#define PUSH_FSGS            \
> +     pushq   %fs             ;\
> +     pushq   %gs             ;\
> +     subq    $16,%rsp
> +#else
> +#define PUSH_FSGS            \
> +     subq    $32,%rsp
> +#endif
> +
> +#ifdef USER32
> +#define POP_FSGS             \
> +     popq    %gs             ;\
> +     popq    %fs             ;\
> +     addq    $16,%rsp
> +#else
> +#define POP_FSGS             \
> +     addq    $32,%rsp
> +#endif
> +
> +#ifdef USER32
> +#define PUSH_FSGS_ISR                \
> +     pushq   %fs             ;\
> +     pushq   %gs
> +#else
> +#define PUSH_FSGS_ISR                \
> +     subq    $16,%rsp
> +#endif
> +
> +#ifdef USER32
> +#define POP_FSGS_ISR         \
> +     popq    %gs             ;\
> +     popq    %fs
> +#else
> +#define POP_FSGS_ISR         \
> +     addq    $16,%rsp
> +#endif
> +
> +
> +
>  /*
>   * Fault recovery.
>   */
> @@ -405,6 +446,11 @@ push_fs:
>       pushq   %fs                     /* restore fs, */
>  push_gs:
>       pushq   %gs                     /* restore gs. */
> +#ifdef USER32
> +push_gsbase:
> +     pushq   $0
> +     pushq   $0
> +#endif
>  push_segregs:
>       movq    %rax,R_TRAPNO(%rsp)     /* set trap number */
>       movq    %rdx,R_ERR(%rsp)        /* set error code */
> @@ -470,8 +516,7 @@ trap_push_segs:
>       pushq   %rax
>       movq    %es,%rax                        /* and the segment registers */
>       pushq   %rax
> -     pushq   %fs
> -     pushq   %gs
> +     PUSH_FSGS
>  
>       /* Note that we have to load the segment registers
>          even if this is a trap from the kernel,
> @@ -480,9 +525,10 @@ trap_push_segs:
>       mov     %ss,%ax                 /* switch to kernel data segment */
>       mov     %ax,%ds                 /* (same as kernel stack segment) */
>       mov     %ax,%es
> +#ifdef USER32
>       mov     %ax,%fs
>       mov     %ax,%gs
> -
> +#endif
>  trap_set_segs:
>       cld                             /* clear direction flag */
>       testl   $(EFL_VM),R_EFLAGS(%rsp) /* in V86 mode? */
> @@ -536,10 +582,17 @@ _return_to_user:
>   */
>  
>  _return_from_kernel:
> +     addq    $16,%rsp                /* skip FS/GS base */
> +#ifndef USER32
> +_kret_popl_gs:
> +_kret_popl_fs:
> +     addq    $16,%rsp                /* skip FS/GS selector */
> +#else
>  _kret_popl_gs:
>       popq    %gs                     /* restore segment registers */
>  _kret_popl_fs:
>       popq    %fs
> +#endif
>  _kret_popl_es:
>       popq    %rax
>       movq    %rax,%es
> @@ -695,14 +748,15 @@ ENTRY(all_intrs)
>       pushq   %rdx
>       movq    %es,%rdx
>       pushq   %rdx
> -     pushq   %fs
> -     pushq   %gs
> +     PUSH_FSGS_ISR
> +
>       mov     %ss,%dx                 /* switch to kernel segments */
>       mov     %dx,%ds
>       mov     %dx,%es
> +#ifdef USER32
>       mov     %dx,%fs
>       mov     %dx,%gs
> -
> +#endif
>       CPU_NUMBER(%edx)
>  
>       movq    CX(EXT(int_stack_top),%edx),%rcx
> @@ -741,8 +795,7 @@ LEXT(return_to_iret)                      /* ( label for 
> kdb_kintr and hardclock) */
>       cmpq    $0,CX(EXT(need_ast),%edx)
>       jnz     ast_from_interrupt      /* take it if so */
>  1:
> -     pop     %gs                     /* restore segment regs */
> -     pop     %fs
> +     POP_FSGS_ISR
>       pop     %rdx
>       mov     %rdx,%es
>       pop     %rdx
> @@ -796,9 +849,7 @@ stack_overflowed:
>   *   ss
>   */
>  ast_from_interrupt:
> -     pop     %gs                     /* restore all registers ... */
> -     pop     %fs
> -     pop     %rdx
> +     POP_FSGS
>       mov     %rdx,%es
>       pop     %rdx
>       mov     %rdx,%ds
> @@ -818,14 +869,15 @@ ast_from_interrupt:
>       push    %rdx
>       mov     %es,%rdx
>       push    %rdx
> -     push    %fs
> -     push    %gs
> +     PUSH_FSGS
> +
>       mov     %ss,%dx                 /* switch to kernel segments */
>       mov     %dx,%ds
>       mov     %dx,%es
> +#ifdef USER32
>       mov     %dx,%fs
>       mov     %dx,%gs
> -
> +#endif
>       CPU_NUMBER(%edx)
>       TIME_TRAP_UENTRY
>  
> @@ -947,14 +999,12 @@ kdb_from_iret_i:                        /* on interrupt 
> stack */
>       push    %rdx
>       mov     %es,%rdx
>       push    %rdx
> -     push    %fs
> -     push    %gs
> +     PUSH_FSGS
>       movq    %rsp,%rdx               /* pass regs, */
>       movq    $0,%rsi                 /* code, */
>       movq    $-1,%rdi                /* type to kdb */
>       call    EXT(kdb_trap)
> -     pop     %gs                     /* restore segment registers */
> -     pop     %fs
> +     POP_FSGS
>       pop     %rdx
>       mov     %rdx,%es
>       pop     %rdx
> @@ -1039,6 +1089,7 @@ ttd_from_iret_i:                        /* on interrupt 
> stack */
>       push    %rdx
>       push    %fs
>       push    %gs
> +     ud2     // TEST it
>       movq    %rsp,%rdx               /* pass regs, */
>       movq    $0,%rsi                 /* code, */
>       movq    $-1,%rdi                /* type to kdb */
> @@ -1087,6 +1138,8 @@ syscall_entry_2:
>       pushq   %rdx
>       pushq   %fs
>       pushq   %gs
> +     pushq   $0      // gsbase
> +     pushq   $0      // fsbase
>  
>       mov     %ss,%dx                 /* switch to kernel data segment */
>       mov     %dx,%ds
> -- 
> 2.30.2
> 
> 

-- 
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]