diff options
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 133 |
1 files changed, 83 insertions, 50 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index e99f8a5be2df..b5670564a1fb 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -99,22 +99,25 @@ ENDPROC(native_irq_enable_sysexit) | |||
99 | /* | 99 | /* |
100 | * 32bit SYSENTER instruction entry. | 100 | * 32bit SYSENTER instruction entry. |
101 | * | 101 | * |
102 | * SYSENTER loads ss, rsp, cs, and rip from previously programmed MSRs. | ||
103 | * IF and VM in rflags are cleared (IOW: interrupts are off). | ||
104 | * SYSENTER does not save anything on the stack, | ||
105 | * and does not save old rip (!!!) and rflags. | ||
106 | * | ||
102 | * Arguments: | 107 | * Arguments: |
103 | * %eax System call number. | 108 | * eax system call number |
104 | * %ebx Arg1 | 109 | * ebx arg1 |
105 | * %ecx Arg2 | 110 | * ecx arg2 |
106 | * %edx Arg3 | 111 | * edx arg3 |
107 | * %esi Arg4 | 112 | * esi arg4 |
108 | * %edi Arg5 | 113 | * edi arg5 |
109 | * %ebp user stack | 114 | * ebp user stack |
110 | * 0(%ebp) Arg6 | 115 | * 0(%ebp) arg6 |
111 | * | 116 | * |
112 | * Interrupts off. | ||
113 | * | ||
114 | * This is purely a fast path. For anything complicated we use the int 0x80 | 117 | * This is purely a fast path. For anything complicated we use the int 0x80 |
115 | * path below. Set up a complete hardware stack frame to share code | 118 | * path below. We set up a complete hardware stack frame to share code |
116 | * with the int 0x80 path. | 119 | * with the int 0x80 path. |
117 | */ | 120 | */ |
118 | ENTRY(ia32_sysenter_target) | 121 | ENTRY(ia32_sysenter_target) |
119 | CFI_STARTPROC32 simple | 122 | CFI_STARTPROC32 simple |
120 | CFI_SIGNAL_FRAME | 123 | CFI_SIGNAL_FRAME |
@@ -128,6 +131,7 @@ ENTRY(ia32_sysenter_target) | |||
128 | * disabled irqs, here we enable it straight after entry: | 131 | * disabled irqs, here we enable it straight after entry: |
129 | */ | 132 | */ |
130 | ENABLE_INTERRUPTS(CLBR_NONE) | 133 | ENABLE_INTERRUPTS(CLBR_NONE) |
134 | /* Construct iret frame (ss,rsp,rflags,cs,rip) */ | ||
131 | movl %ebp,%ebp /* zero extension */ | 135 | movl %ebp,%ebp /* zero extension */ |
132 | pushq_cfi $__USER32_DS | 136 | pushq_cfi $__USER32_DS |
133 | /*CFI_REL_OFFSET ss,0*/ | 137 | /*CFI_REL_OFFSET ss,0*/ |
@@ -140,14 +144,19 @@ ENTRY(ia32_sysenter_target) | |||
140 | pushq_cfi $__USER32_CS | 144 | pushq_cfi $__USER32_CS |
141 | /*CFI_REL_OFFSET cs,0*/ | 145 | /*CFI_REL_OFFSET cs,0*/ |
142 | movl %eax, %eax | 146 | movl %eax, %eax |
147 | /* Store thread_info->sysenter_return in rip stack slot */ | ||
143 | pushq_cfi %r10 | 148 | pushq_cfi %r10 |
144 | CFI_REL_OFFSET rip,0 | 149 | CFI_REL_OFFSET rip,0 |
150 | /* Store orig_ax */ | ||
145 | pushq_cfi %rax | 151 | pushq_cfi %rax |
152 | /* Construct the rest of "struct pt_regs" */ | ||
146 | cld | 153 | cld |
147 | ALLOC_PT_GPREGS_ON_STACK | 154 | ALLOC_PT_GPREGS_ON_STACK |
148 | SAVE_C_REGS_EXCEPT_R891011 | 155 | SAVE_C_REGS_EXCEPT_R891011 |
149 | /* no need to do an access_ok check here because rbp has been | 156 | /* |
150 | 32bit zero extended */ | 157 | * no need to do an access_ok check here because rbp has been |
158 | * 32bit zero extended | ||
159 | */ | ||
151 | ASM_STAC | 160 | ASM_STAC |
152 | 1: movl (%rbp),%ebp | 161 | 1: movl (%rbp),%ebp |
153 | _ASM_EXTABLE(1b,ia32_badarg) | 162 | _ASM_EXTABLE(1b,ia32_badarg) |
@@ -184,6 +193,7 @@ sysexit_from_sys_call: | |||
184 | movl RIP(%rsp),%edx /* User %eip */ | 193 | movl RIP(%rsp),%edx /* User %eip */ |
185 | CFI_REGISTER rip,rdx | 194 | CFI_REGISTER rip,rdx |
186 | RESTORE_RSI_RDI | 195 | RESTORE_RSI_RDI |
196 | /* pop everything except ss,rsp,rflags slots */ | ||
187 | REMOVE_PT_GPREGS_FROM_STACK 3*8 | 197 | REMOVE_PT_GPREGS_FROM_STACK 3*8 |
188 | xorq %r8,%r8 | 198 | xorq %r8,%r8 |
189 | xorq %r9,%r9 | 199 | xorq %r9,%r9 |
@@ -194,6 +204,10 @@ sysexit_from_sys_call: | |||
194 | popq_cfi %rcx /* User %esp */ | 204 | popq_cfi %rcx /* User %esp */ |
195 | CFI_REGISTER rsp,rcx | 205 | CFI_REGISTER rsp,rcx |
196 | TRACE_IRQS_ON | 206 | TRACE_IRQS_ON |
207 | /* | ||
208 | * 32bit SYSEXIT restores eip from edx, esp from ecx. | ||
209 | * cs and ss are loaded from MSRs. | ||
210 | */ | ||
197 | ENABLE_INTERRUPTS_SYSEXIT32 | 211 | ENABLE_INTERRUPTS_SYSEXIT32 |
198 | 212 | ||
199 | CFI_RESTORE_STATE | 213 | CFI_RESTORE_STATE |
@@ -274,23 +288,33 @@ ENDPROC(ia32_sysenter_target) | |||
274 | /* | 288 | /* |
275 | * 32bit SYSCALL instruction entry. | 289 | * 32bit SYSCALL instruction entry. |
276 | * | 290 | * |
291 | * 32bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11, | ||
292 | * then loads new ss, cs, and rip from previously programmed MSRs. | ||
293 | * rflags gets masked by a value from another MSR (so CLD and CLAC | ||
294 | * are not needed). SYSCALL does not save anything on the stack | ||
295 | * and does not change rsp. | ||
296 | * | ||
297 | * Note: rflags saving+masking-with-MSR happens only in Long mode | ||
298 | * (in legacy 32bit mode, IF, RF and VM bits are cleared and that's it). | ||
299 | * Don't get confused: rflags saving+masking depends on Long Mode Active bit | ||
300 | * (EFER.LMA=1), NOT on bitness of userspace where SYSCALL executes | ||
301 | * or target CS descriptor's L bit (SYSCALL does not read segment descriptors). | ||
302 | * | ||
277 | * Arguments: | 303 | * Arguments: |
278 | * %eax System call number. | 304 | * eax system call number |
279 | * %ebx Arg1 | 305 | * ecx return address |
280 | * %ecx return EIP | 306 | * ebx arg1 |
281 | * %edx Arg3 | 307 | * ebp arg2 (note: not saved in the stack frame, should not be touched) |
282 | * %esi Arg4 | 308 | * edx arg3 |
283 | * %edi Arg5 | 309 | * esi arg4 |
284 | * %ebp Arg2 [note: not saved in the stack frame, should not be touched] | 310 | * edi arg5 |
285 | * %esp user stack | 311 | * esp user stack |
286 | * 0(%esp) Arg6 | 312 | * 0(%esp) arg6 |
287 | * | 313 | * |
288 | * Interrupts off. | ||
289 | * | ||
290 | * This is purely a fast path. For anything complicated we use the int 0x80 | 314 | * This is purely a fast path. For anything complicated we use the int 0x80 |
291 | * path below. Set up a complete hardware stack frame to share code | 315 | * path below. We set up a complete hardware stack frame to share code |
292 | * with the int 0x80 path. | 316 | * with the int 0x80 path. |
293 | */ | 317 | */ |
294 | ENTRY(ia32_cstar_target) | 318 | ENTRY(ia32_cstar_target) |
295 | CFI_STARTPROC32 simple | 319 | CFI_STARTPROC32 simple |
296 | CFI_SIGNAL_FRAME | 320 | CFI_SIGNAL_FRAME |
@@ -306,7 +330,7 @@ ENTRY(ia32_cstar_target) | |||
306 | * disabled irqs and here we enable it straight after entry: | 330 | * disabled irqs and here we enable it straight after entry: |
307 | */ | 331 | */ |
308 | ENABLE_INTERRUPTS(CLBR_NONE) | 332 | ENABLE_INTERRUPTS(CLBR_NONE) |
309 | ALLOC_PT_GPREGS_ON_STACK 8 | 333 | ALLOC_PT_GPREGS_ON_STACK 8 /* +8: space for orig_ax */ |
310 | SAVE_C_REGS_EXCEPT_RCX_R891011 | 334 | SAVE_C_REGS_EXCEPT_RCX_R891011 |
311 | movl %eax,%eax /* zero extension */ | 335 | movl %eax,%eax /* zero extension */ |
312 | movq %rax,ORIG_RAX(%rsp) | 336 | movq %rax,ORIG_RAX(%rsp) |
@@ -320,9 +344,11 @@ ENTRY(ia32_cstar_target) | |||
320 | /*CFI_REL_OFFSET rflags,EFLAGS*/ | 344 | /*CFI_REL_OFFSET rflags,EFLAGS*/ |
321 | movq %r8,RSP(%rsp) | 345 | movq %r8,RSP(%rsp) |
322 | CFI_REL_OFFSET rsp,RSP | 346 | CFI_REL_OFFSET rsp,RSP |
323 | /* no need to do an access_ok check here because r8 has been | 347 | /* iret stack frame is complete now */ |
324 | 32bit zero extended */ | 348 | /* |
325 | /* hardware stack frame is complete now */ | 349 | * no need to do an access_ok check here because r8 has been |
350 | * 32bit zero extended | ||
351 | */ | ||
326 | ASM_STAC | 352 | ASM_STAC |
327 | 1: movl (%r8),%r9d | 353 | 1: movl (%r8),%r9d |
328 | _ASM_EXTABLE(1b,ia32_badarg) | 354 | _ASM_EXTABLE(1b,ia32_badarg) |
@@ -355,8 +381,15 @@ sysretl_from_sys_call: | |||
355 | TRACE_IRQS_ON | 381 | TRACE_IRQS_ON |
356 | movl RSP(%rsp),%esp | 382 | movl RSP(%rsp),%esp |
357 | CFI_RESTORE rsp | 383 | CFI_RESTORE rsp |
384 | /* | ||
385 | * 64bit->32bit SYSRET restores eip from ecx, | ||
386 | * eflags from r11 (but RF and VM bits are forced to 0), | ||
387 | * cs and ss are loaded from MSRs. | ||
388 | * (Note: 32bit->32bit SYSRET is different: since r11 | ||
389 | * does not exist, it merely sets eflags.IF=1). | ||
390 | */ | ||
358 | USERGS_SYSRET32 | 391 | USERGS_SYSRET32 |
359 | 392 | ||
360 | #ifdef CONFIG_AUDITSYSCALL | 393 | #ifdef CONFIG_AUDITSYSCALL |
361 | cstar_auditsys: | 394 | cstar_auditsys: |
362 | CFI_RESTORE_STATE | 395 | CFI_RESTORE_STATE |
@@ -394,26 +427,26 @@ ia32_badarg: | |||
394 | jmp ia32_sysret | 427 | jmp ia32_sysret |
395 | CFI_ENDPROC | 428 | CFI_ENDPROC |
396 | 429 | ||
397 | /* | 430 | /* |
398 | * Emulated IA32 system calls via int 0x80. | 431 | * Emulated IA32 system calls via int 0x80. |
399 | * | 432 | * |
400 | * Arguments: | 433 | * Arguments: |
401 | * %eax System call number. | 434 | * eax system call number |
402 | * %ebx Arg1 | 435 | * ebx arg1 |
403 | * %ecx Arg2 | 436 | * ecx arg2 |
404 | * %edx Arg3 | 437 | * edx arg3 |
405 | * %esi Arg4 | 438 | * esi arg4 |
406 | * %edi Arg5 | 439 | * edi arg5 |
407 | * %ebp Arg6 [note: not saved in the stack frame, should not be touched] | 440 | * ebp arg6 (note: not saved in the stack frame, should not be touched) |
408 | * | 441 | * |
409 | * Notes: | 442 | * Notes: |
410 | * Uses the same stack frame as the x86-64 version. | 443 | * Uses the same stack frame as the x86-64 version. |
411 | * All registers except %eax must be saved (but ptrace may violate that) | 444 | * All registers except eax must be saved (but ptrace may violate that). |
412 | * Arguments are zero extended. For system calls that want sign extension and | 445 | * Arguments are zero extended. For system calls that want sign extension and |
413 | * take long arguments a wrapper is needed. Most calls can just be called | 446 | * take long arguments a wrapper is needed. Most calls can just be called |
414 | * directly. | 447 | * directly. |
415 | * Assumes it is only called from user space and entered with interrupts off. | 448 | * Assumes it is only called from user space and entered with interrupts off. |
416 | */ | 449 | */ |
417 | 450 | ||
418 | ENTRY(ia32_syscall) | 451 | ENTRY(ia32_syscall) |
419 | CFI_STARTPROC32 simple | 452 | CFI_STARTPROC32 simple |
@@ -432,7 +465,7 @@ ENTRY(ia32_syscall) | |||
432 | */ | 465 | */ |
433 | ENABLE_INTERRUPTS(CLBR_NONE) | 466 | ENABLE_INTERRUPTS(CLBR_NONE) |
434 | movl %eax,%eax | 467 | movl %eax,%eax |
435 | pushq_cfi %rax | 468 | pushq_cfi %rax /* store orig_ax */ |
436 | cld | 469 | cld |
437 | /* note the registers are not zero extended to the sf. | 470 | /* note the registers are not zero extended to the sf. |
438 | this could be a problem. */ | 471 | this could be a problem. */ |