x86: rename the struct pt_regs members for 32/64-bit consistency
[deliverable/linux.git] / arch / x86 / ia32 / ia32_binfmt.c
1 /*
2 * Written 2000,2002 by Andi Kleen.
3 *
4 * Loosely based on the sparc64 and IA64 32bit emulation loaders.
5 * This tricks binfmt_elf.c into loading 32bit binaries using lots
6 * of ugly preprocessor tricks. Talk about very very poor man's inheritance.
7 */
8
9 #include <linux/types.h>
10 #include <linux/stddef.h>
11 #include <linux/rwsem.h>
12 #include <linux/sched.h>
13 #include <linux/compat.h>
14 #include <linux/string.h>
15 #include <linux/binfmts.h>
16 #include <linux/mm.h>
17 #include <linux/security.h>
18 #include <linux/elfcore-compat.h>
19
20 #include <asm/segment.h>
21 #include <asm/ptrace.h>
22 #include <asm/processor.h>
23 #include <asm/user32.h>
24 #include <asm/sigcontext32.h>
25 #include <asm/fpu32.h>
26 #include <asm/i387.h>
27 #include <asm/uaccess.h>
28 #include <asm/ia32.h>
29 #include <asm/vdso.h>
30
31 #undef ELF_ARCH
32 #undef ELF_CLASS
33 #define ELF_CLASS ELFCLASS32
34 #define ELF_ARCH EM_386
35
36 #undef elfhdr
37 #undef elf_phdr
38 #undef elf_note
39 #undef elf_addr_t
40 #define elfhdr elf32_hdr
41 #define elf_phdr elf32_phdr
42 #define elf_note elf32_note
43 #define elf_addr_t Elf32_Off
44
45 #define ELF_NAME "elf/i386"
46
47 #define AT_SYSINFO 32
48 #define AT_SYSINFO_EHDR 33
49
50 extern int sysctl_vsyscall32;
51
52 #undef ARCH_DLINFO
53 #define ARCH_DLINFO do { \
54 if (sysctl_vsyscall32) { \
55 NEW_AUX_ENT(AT_SYSINFO, (u32)VDSO_ENTRY); \
56 NEW_AUX_ENT(AT_SYSINFO_EHDR, (u32)VDSO_CURRENT_BASE); \
57 } \
58 } while(0)
59
60 struct file;
61
62 #define IA32_EMULATOR 1
63
64 #undef ELF_ET_DYN_BASE
65
66 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
67
68 #define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0)
69
70 #define _GET_SEG(x) \
71 ({ __u32 seg; asm("movl %%" __stringify(x) ",%0" : "=r"(seg)); seg; })
72
73 /* Assumes current==process to be dumped */
74 #undef ELF_CORE_COPY_REGS
75 #define ELF_CORE_COPY_REGS(pr_reg, regs) \
76 pr_reg[0] = regs->bx; \
77 pr_reg[1] = regs->cx; \
78 pr_reg[2] = regs->dx; \
79 pr_reg[3] = regs->si; \
80 pr_reg[4] = regs->di; \
81 pr_reg[5] = regs->bp; \
82 pr_reg[6] = regs->ax; \
83 pr_reg[7] = _GET_SEG(ds); \
84 pr_reg[8] = _GET_SEG(es); \
85 pr_reg[9] = _GET_SEG(fs); \
86 pr_reg[10] = _GET_SEG(gs); \
87 pr_reg[11] = regs->orig_ax; \
88 pr_reg[12] = regs->ip; \
89 pr_reg[13] = regs->cs; \
90 pr_reg[14] = regs->flags; \
91 pr_reg[15] = regs->sp; \
92 pr_reg[16] = regs->ss;
93
94
95 #define elf_prstatus compat_elf_prstatus
96 #define elf_prpsinfo compat_elf_prpsinfo
97 #define elf_fpregset_t struct user_i387_ia32_struct
98 #define elf_fpxregset_t struct user32_fxsr_struct
99 #define user user32
100
101 #undef elf_read_implies_exec
102 #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)
103
104 #define elf_core_copy_regs elf32_core_copy_regs
105 static inline void elf32_core_copy_regs(compat_elf_gregset_t *elfregs,
106 struct pt_regs *regs)
107 {
108 ELF_CORE_COPY_REGS((&elfregs->ebx), regs)
109 }
110
111 #define elf_core_copy_task_regs elf32_core_copy_task_regs
112 static inline int elf32_core_copy_task_regs(struct task_struct *t,
113 compat_elf_gregset_t* elfregs)
114 {
115 struct pt_regs *pp = task_pt_regs(t);
116 ELF_CORE_COPY_REGS((&elfregs->ebx), pp);
117 /* fix wrong segments */
118 elfregs->ds = t->thread.ds;
119 elfregs->fs = t->thread.fsindex;
120 elfregs->gs = t->thread.gsindex;
121 elfregs->es = t->thread.es;
122 return 1;
123 }
124
125 #define elf_core_copy_task_fpregs elf32_core_copy_task_fpregs
126 static inline int
127 elf32_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs,
128 elf_fpregset_t *fpu)
129 {
130 struct _fpstate_ia32 *fpstate = (void*)fpu;
131 mm_segment_t oldfs = get_fs();
132
133 if (!tsk_used_math(tsk))
134 return 0;
135 if (!regs)
136 regs = task_pt_regs(tsk);
137 if (tsk == current)
138 unlazy_fpu(tsk);
139 set_fs(KERNEL_DS);
140 save_i387_ia32(tsk, fpstate, regs, 1);
141 /* Correct for i386 bug. It puts the fop into the upper 16bits of
142 the tag word (like FXSAVE), not into the fcs*/
143 fpstate->cssel |= fpstate->tag & 0xffff0000;
144 set_fs(oldfs);
145 return 1;
146 }
147
148 #define ELF_CORE_COPY_XFPREGS 1
149 #define ELF_CORE_XFPREG_TYPE NT_PRXFPREG
150 #define elf_core_copy_task_xfpregs elf32_core_copy_task_xfpregs
151 static inline int
152 elf32_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
153 {
154 struct pt_regs *regs = task_pt_regs(t);
155 if (!tsk_used_math(t))
156 return 0;
157 if (t == current)
158 unlazy_fpu(t);
159 memcpy(xfpu, &t->thread.i387.fxsave, sizeof(elf_fpxregset_t));
160 xfpu->fcs = regs->cs;
161 xfpu->fos = t->thread.ds; /* right? */
162 return 1;
163 }
164
165 #undef elf_check_arch
166 #define elf_check_arch(x) \
167 ((x)->e_machine == EM_386)
168
169 extern int force_personality32;
170
171 #undef ELF_EXEC_PAGESIZE
172 #undef ELF_HWCAP
173 #undef ELF_PLATFORM
174 #undef SET_PERSONALITY
175 #define ELF_EXEC_PAGESIZE PAGE_SIZE
176 #define ELF_HWCAP (boot_cpu_data.x86_capability[0])
177 #define ELF_PLATFORM ("i686")
178 #define SET_PERSONALITY(ex, ibcs2) \
179 do { \
180 unsigned long new_flags = 0; \
181 if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
182 new_flags = _TIF_IA32; \
183 if ((current_thread_info()->flags & _TIF_IA32) \
184 != new_flags) \
185 set_thread_flag(TIF_ABI_PENDING); \
186 else \
187 clear_thread_flag(TIF_ABI_PENDING); \
188 /* XXX This overwrites the user set personality */ \
189 current->personality |= force_personality32; \
190 } while (0)
191
192 /* Override some function names */
193 #define elf_format elf32_format
194
195 #define init_elf_binfmt init_elf32_binfmt
196 #define exit_elf_binfmt exit_elf32_binfmt
197
198 #define load_elf_binary load_elf32_binary
199
200 #undef ELF_PLAT_INIT
201 #define ELF_PLAT_INIT(r, load_addr) elf32_init(r)
202
203 #undef start_thread
204 #define start_thread(regs,new_rip,new_rsp) do { \
205 asm volatile("movl %0,%%fs" :: "r" (0)); \
206 asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); \
207 load_gs_index(0); \
208 (regs)->ip = (new_rip); \
209 (regs)->sp = (new_rsp); \
210 (regs)->flags = X86_EFLAGS_IF; \
211 (regs)->cs = __USER32_CS; \
212 (regs)->ss = __USER32_DS; \
213 set_fs(USER_DS); \
214 } while(0)
215
216
217 #include <linux/module.h>
218
219 MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries.");
220 MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
221
222 #undef MODULE_DESCRIPTION
223 #undef MODULE_AUTHOR
224
225 static void elf32_init(struct pt_regs *);
226
227 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
228 #define arch_setup_additional_pages syscall32_setup_pages
229 extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
230
231 #include "../../../fs/binfmt_elf.c"
232
233 static void elf32_init(struct pt_regs *regs)
234 {
235 struct task_struct *me = current;
236 regs->di = 0;
237 regs->si = 0;
238 regs->dx = 0;
239 regs->cx = 0;
240 regs->ax = 0;
241 regs->bx = 0;
242 regs->bp = 0;
243 regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
244 regs->r13 = regs->r14 = regs->r15 = 0;
245 me->thread.fs = 0;
246 me->thread.gs = 0;
247 me->thread.fsindex = 0;
248 me->thread.gsindex = 0;
249 me->thread.ds = __USER_DS;
250 me->thread.es = __USER_DS;
251 }
252
253 #ifdef CONFIG_SYSCTL
254 /* Register vsyscall32 into the ABI table */
255 #include <linux/sysctl.h>
256
257 static ctl_table abi_table2[] = {
258 {
259 .procname = "vsyscall32",
260 .data = &sysctl_vsyscall32,
261 .maxlen = sizeof(int),
262 .mode = 0644,
263 .proc_handler = proc_dointvec
264 },
265 {}
266 };
267
268 static ctl_table abi_root_table2[] = {
269 {
270 .ctl_name = CTL_ABI,
271 .procname = "abi",
272 .mode = 0555,
273 .child = abi_table2
274 },
275 {}
276 };
277
278 static __init int ia32_binfmt_init(void)
279 {
280 register_sysctl_table(abi_root_table2);
281 return 0;
282 }
283 __initcall(ia32_binfmt_init);
284 #endif
This page took 0.045402 seconds and 5 git commands to generate.