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.