diff options
author | Luca Dariz <luca@orpolo.org> | 2023-04-19 21:47:03 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2023-05-01 03:30:18 +0200 |
commit | 31dd30a94a682955c3c9e2f42252b4a07687067a (patch) | |
tree | 66be830d547a1e9cbd1b9b7bbc0378398be089d8 /i386 | |
parent | 660bc8ab3813737b3857648b7ec60d88494aeed1 (diff) | |
download | gnumach-31dd30a94a682955c3c9e2f42252b4a07687067a.tar.gz gnumach-31dd30a94a682955c3c9e2f42252b4a07687067a.tar.bz2 gnumach-31dd30a94a682955c3c9e2f42252b4a07687067a.zip |
add setting gs/fsbase
* 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
Message-Id: <20230419194703.410575-5-luca@orpolo.org>
Diffstat (limited to 'i386')
-rw-r--r-- | i386/i386/i386asm.sym | 2 | ||||
-rw-r--r-- | i386/i386/pcb.c | 39 | ||||
-rw-r--r-- | i386/i386/thread.h | 4 |
3 files changed, 42 insertions, 3 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; |