diff options
author | Roland McGrath <roland@redhat.com> | 2008-01-30 07:30:43 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:30:43 -0500 |
commit | 36197c92a20c142fc2a068e0366053d770fa0096 (patch) | |
tree | 796f377cadc86bb9cad36090698f6bbaec0ca0f1 /arch/x86 | |
parent | 0aa97fb22624f18e5925d702ab0364d3838cfd91 (diff) |
x86 vDSO: ia32 sysenter_return
This changes the 64-bit kernel's support for the 32-bit sysenter
instruction to use stored fields rather than constants for the
user-mode return address, as the 32-bit kernel does. This adds a
sysenter_return field to struct thread_info, as 32-bit has. There
is no observable effect from this yet. It makes the assembly code
independent of the 32-bit vDSO mapping address, paving the way for
making the vDSO address vary as it does on the 32-bit kernel.
[ akpm@linux-foundation.org: build fix on !CONFIG_IA32_EMULATION ]
Signed-off-by: Roland McGrath <roland@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 7 | ||||
-rw-r--r-- | arch/x86/ia32/syscall32.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/asm-offsets_64.c | 3 |
3 files changed, 10 insertions, 4 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index df588f0f76e1..2499a324feaa 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <asm/ia32_unistd.h> | 12 | #include <asm/ia32_unistd.h> |
13 | #include <asm/thread_info.h> | 13 | #include <asm/thread_info.h> |
14 | #include <asm/segment.h> | 14 | #include <asm/segment.h> |
15 | #include <asm/vsyscall32.h> | ||
16 | #include <asm/irqflags.h> | 15 | #include <asm/irqflags.h> |
17 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
18 | 17 | ||
@@ -104,7 +103,7 @@ ENTRY(ia32_sysenter_target) | |||
104 | pushfq | 103 | pushfq |
105 | CFI_ADJUST_CFA_OFFSET 8 | 104 | CFI_ADJUST_CFA_OFFSET 8 |
106 | /*CFI_REL_OFFSET rflags,0*/ | 105 | /*CFI_REL_OFFSET rflags,0*/ |
107 | movl $VSYSCALL32_SYSEXIT, %r10d | 106 | movl 8*3-THREAD_SIZE+threadinfo_sysenter_return(%rsp), %r10d |
108 | CFI_REGISTER rip,r10 | 107 | CFI_REGISTER rip,r10 |
109 | pushq $__USER32_CS | 108 | pushq $__USER32_CS |
110 | CFI_ADJUST_CFA_OFFSET 8 | 109 | CFI_ADJUST_CFA_OFFSET 8 |
@@ -142,6 +141,8 @@ sysenter_do_call: | |||
142 | andl $~TS_COMPAT,threadinfo_status(%r10) | 141 | andl $~TS_COMPAT,threadinfo_status(%r10) |
143 | /* clear IF, that popfq doesn't enable interrupts early */ | 142 | /* clear IF, that popfq doesn't enable interrupts early */ |
144 | andl $~0x200,EFLAGS-R11(%rsp) | 143 | andl $~0x200,EFLAGS-R11(%rsp) |
144 | movl RIP-R11(%rsp),%edx /* User %eip */ | ||
145 | CFI_REGISTER rip,rdx | ||
145 | RESTORE_ARGS 1,24,1,1,1,1 | 146 | RESTORE_ARGS 1,24,1,1,1,1 |
146 | popfq | 147 | popfq |
147 | CFI_ADJUST_CFA_OFFSET -8 | 148 | CFI_ADJUST_CFA_OFFSET -8 |
@@ -149,8 +150,6 @@ sysenter_do_call: | |||
149 | popq %rcx /* User %esp */ | 150 | popq %rcx /* User %esp */ |
150 | CFI_ADJUST_CFA_OFFSET -8 | 151 | CFI_ADJUST_CFA_OFFSET -8 |
151 | CFI_REGISTER rsp,rcx | 152 | CFI_REGISTER rsp,rcx |
152 | movl $VSYSCALL32_SYSEXIT,%edx /* User %eip */ | ||
153 | CFI_REGISTER rip,rdx | ||
154 | TRACE_IRQS_ON | 153 | TRACE_IRQS_ON |
155 | swapgs | 154 | swapgs |
156 | sti /* sti only takes effect after the next instruction */ | 155 | sti /* sti only takes effect after the next instruction */ |
diff --git a/arch/x86/ia32/syscall32.c b/arch/x86/ia32/syscall32.c index d751d96c2ef2..98ff99f5b59a 100644 --- a/arch/x86/ia32/syscall32.c +++ b/arch/x86/ia32/syscall32.c | |||
@@ -46,6 +46,10 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) | |||
46 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| | 46 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| |
47 | VM_ALWAYSDUMP, | 47 | VM_ALWAYSDUMP, |
48 | syscall32_pages); | 48 | syscall32_pages); |
49 | if (ret == 0) { | ||
50 | current->mm->context.vdso = (void __user *)VSYSCALL32_BASE; | ||
51 | current_thread_info()->sysenter_return = VSYSCALL32_SYSEXIT; | ||
52 | } | ||
49 | up_write(&mm->mmap_sem); | 53 | up_write(&mm->mmap_sem); |
50 | return ret; | 54 | return ret; |
51 | } | 55 | } |
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 40f41752c1df..c27c646214f4 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
@@ -46,6 +46,9 @@ int main(void) | |||
46 | ENTRY(addr_limit); | 46 | ENTRY(addr_limit); |
47 | ENTRY(preempt_count); | 47 | ENTRY(preempt_count); |
48 | ENTRY(status); | 48 | ENTRY(status); |
49 | #ifdef CONFIG_IA32_EMULATION | ||
50 | ENTRY(sysenter_return); | ||
51 | #endif | ||
49 | BLANK(); | 52 | BLANK(); |
50 | #undef ENTRY | 53 | #undef ENTRY |
51 | #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) | 54 | #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) |