diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-14 19:56:02 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-14 19:56:02 -0800 |
commit | 4060994c3e337b40e0f6fa8ce2cc178e021baf3d (patch) | |
tree | 980297c1747ca89354bc879cc5d17903eacb19e2 /arch/x86_64/kernel/signal.c | |
parent | 0174f72f848dfe7dc7488799776303c81b181b16 (diff) | |
parent | d3ee871e63d0a0c70413dc0aa5534b8d6cd6ec37 (diff) | |
download | op-kernel-dev-4060994c3e337b40e0f6fa8ce2cc178e021baf3d.zip op-kernel-dev-4060994c3e337b40e0f6fa8ce2cc178e021baf3d.tar.gz |
Merge x86-64 update from Andi
Diffstat (limited to 'arch/x86_64/kernel/signal.c')
-rw-r--r-- | arch/x86_64/kernel/signal.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index d642fbf..5876df1 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -110,6 +110,15 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned COPY(r14); COPY(r15); + /* Kernel saves and restores only the CS segment register on signals, + * which is the bare minimum needed to allow mixed 32/64-bit code. + * App's signal handler can save/restore other segments if needed. */ + { + unsigned cs; + err |= __get_user(cs, &sc->cs); + regs->cs = cs | 3; /* Force into user mode */ + } + { unsigned int tmpflags; err |= __get_user(tmpflags, &sc->eflags); @@ -187,6 +196,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo { int err = 0; + err |= __put_user(regs->cs, &sc->cs); err |= __put_user(0, &sc->gs); err |= __put_user(0, &sc->fs); @@ -318,7 +328,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->rsp = (unsigned long)frame; + /* Set up the CS register to run signal handlers in 64-bit mode, + even if the handler happens to be interrupting 32-bit code. */ + regs->cs = __USER_CS; + + /* This, by contrast, has nothing to do with segment registers - + see include/asm-x86_64/uaccess.h for details. */ set_fs(USER_DS); + regs->eflags &= ~TF_MASK; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); |