Commit 78e42911 authored by Linus Torvalds's avatar Linus Torvalds Committed by Linus Torvalds

x86: regparm calling convention for exceptions and interrupts.

This clarifies more of the x86 caller/callee stack ownership
issues by making the exception and interrupt handler assembler
interfaces use register calling conventions.

System calls still use the stack.

Tested with "crashme" on UP/SMP.
parent 0b3e8d29
...@@ -70,10 +70,10 @@ static void intel_thermal_interrupt(struct pt_regs *regs) ...@@ -70,10 +70,10 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
/* Thermal interrupt handler for this CPU setup */ /* Thermal interrupt handler for this CPU setup */
static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
asmlinkage void smp_thermal_interrupt(struct pt_regs regs) fastcall void smp_thermal_interrupt(struct pt_regs *regs)
{ {
irq_enter(); irq_enter();
vendor_thermal_interrupt(&regs); vendor_thermal_interrupt(regs);
irq_exit(); irq_exit();
} }
......
...@@ -131,7 +131,7 @@ VM_MASK = 0x00020000 ...@@ -131,7 +131,7 @@ VM_MASK = 0x00020000
movl $(__USER_DS), %edx; \ movl $(__USER_DS), %edx; \
movl %edx, %ds; \ movl %edx, %ds; \
movl %edx, %es; \ movl %edx, %es; \
pushl $11; \ movl $11,%eax; \
call do_exit; \ call do_exit; \
.previous; \ .previous; \
.section __ex_table,"a";\ .section __ex_table,"a";\
...@@ -291,8 +291,8 @@ work_notifysig: # deal with pending signals and ...@@ -291,8 +291,8 @@ work_notifysig: # deal with pending signals and
ALIGN ALIGN
work_notifysig_v86: work_notifysig_v86:
pushl %ecx pushl %ecx # save ti_flags for do_notify_resume
call save_v86_state call save_v86_state # %eax contains pt_regs pointer
popl %ecx popl %ecx
movl %eax, %esp movl %eax, %esp
xorl %edx, %edx xorl %edx, %edx
...@@ -359,6 +359,7 @@ vector=vector+1 ...@@ -359,6 +359,7 @@ vector=vector+1
ALIGN ALIGN
common_interrupt: common_interrupt:
SAVE_ALL SAVE_ALL
movl %esp,%eax
call do_IRQ call do_IRQ
jmp ret_from_intr jmp ret_from_intr
...@@ -366,7 +367,8 @@ common_interrupt: ...@@ -366,7 +367,8 @@ common_interrupt:
ENTRY(name) \ ENTRY(name) \
pushl $nr-256; \ pushl $nr-256; \
SAVE_ALL \ SAVE_ALL \
call smp_/**/name; \ movl %esp,%eax; \
call smp_/**/name; \
jmp ret_from_intr; jmp ret_from_intr;
/* The include is where all of the SMP etc. interrupts come from */ /* The include is where all of the SMP etc. interrupts come from */
...@@ -389,18 +391,15 @@ error_code: ...@@ -389,18 +391,15 @@ error_code:
pushl %ebx pushl %ebx
cld cld
movl %es, %ecx movl %es, %ecx
movl ORIG_EAX(%esp), %esi # get the error code
movl ES(%esp), %edi # get the function address movl ES(%esp), %edi # get the function address
movl ORIG_EAX(%esp), %edx # get the error code
movl %eax, ORIG_EAX(%esp) movl %eax, ORIG_EAX(%esp)
movl %ecx, ES(%esp) movl %ecx, ES(%esp)
movl %esp, %edx movl $(__USER_DS), %ecx
pushl %esi # push the error code movl %ecx, %ds
pushl %edx # push the pt_regs pointer movl %ecx, %es
movl $(__USER_DS), %edx movl %esp,%eax # pt_regs pointer
movl %edx, %ds
movl %edx, %es
call *%edi call *%edi
addl $8, %esp
jmp ret_from_exception jmp ret_from_exception
ENTRY(coprocessor_error) ENTRY(coprocessor_error)
...@@ -457,11 +456,9 @@ ENTRY(debug) ...@@ -457,11 +456,9 @@ ENTRY(debug)
debug_stack_correct: debug_stack_correct:
pushl $-1 # mark this as an int pushl $-1 # mark this as an int
SAVE_ALL SAVE_ALL
movl %esp,%edx xorl %edx,%edx # error code 0
pushl $0 movl %esp,%eax # pt_regs pointer
pushl %edx
call do_debug call do_debug
addl $8,%esp
testl %eax,%eax testl %eax,%eax
jnz restore_all jnz restore_all
jmp ret_from_exception jmp ret_from_exception
...@@ -491,11 +488,9 @@ ENTRY(nmi) ...@@ -491,11 +488,9 @@ ENTRY(nmi)
nmi_stack_correct: nmi_stack_correct:
pushl %eax pushl %eax
SAVE_ALL SAVE_ALL
movl %esp, %edx xorl %edx,%edx # zero error code
pushl $0 movl %esp,%eax # pt_regs pointer
pushl %edx
call do_nmi call do_nmi
addl $8, %esp
RESTORE_ALL RESTORE_ALL
nmi_stack_fixup: nmi_stack_fixup:
...@@ -515,11 +510,9 @@ nmi_debug_stack_fixup: ...@@ -515,11 +510,9 @@ nmi_debug_stack_fixup:
ENTRY(int3) ENTRY(int3)
pushl $-1 # mark this as an int pushl $-1 # mark this as an int
SAVE_ALL SAVE_ALL
movl %esp,%edx xorl %edx,%edx # zero error code
pushl $0 movl %esp,%eax # pt_regs pointer
pushl %edx
call do_int3 call do_int3
addl $8,%esp
testl %eax,%eax testl %eax,%eax
jnz restore_all jnz restore_all
jmp ret_from_exception jmp ret_from_exception
......
...@@ -45,10 +45,10 @@ static union irq_ctx *softirq_ctx[NR_CPUS]; ...@@ -45,10 +45,10 @@ static union irq_ctx *softirq_ctx[NR_CPUS];
* SMP cross-CPU interrupts have their own specific * SMP cross-CPU interrupts have their own specific
* handlers). * handlers).
*/ */
asmlinkage unsigned int do_IRQ(struct pt_regs regs) fastcall unsigned int do_IRQ(struct pt_regs *regs)
{ {
/* high bits used in ret_from_ code */ /* high bits used in ret_from_ code */
int irq = regs.orig_eax & 0xff; int irq = regs->orig_eax & 0xff;
#ifdef CONFIG_4KSTACKS #ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx; union irq_ctx *curctx, *irqctx;
u32 *isp; u32 *isp;
...@@ -82,24 +82,24 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs) ...@@ -82,24 +82,24 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
* current stack (which is the irq stack already after all) * current stack (which is the irq stack already after all)
*/ */
if (curctx != irqctx) { if (curctx != irqctx) {
int arg1, arg2, ebx;
/* build the stack frame on the IRQ stack */ /* build the stack frame on the IRQ stack */
isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_esp = current_stack_pointer(); irqctx->tinfo.previous_esp = current_stack_pointer();
*--isp = (u32) &regs;
*--isp = (u32) irq;
asm volatile( asm volatile(
" xchgl %%ebx,%%esp \n" " xchgl %%ebx,%%esp \n"
" call __do_IRQ \n" " call __do_IRQ \n"
" xchgl %%ebx,%%esp \n" " movl %%ebx,%%esp \n"
: : "b"(isp) : "=a" (arg1), "=d" (arg2), "=b" (ebx)
: "memory", "cc", "eax", "edx", "ecx" : "0" (irq), "1" (regs), "2" (isp)
: "memory", "cc", "ecx"
); );
} else } else
#endif #endif
__do_IRQ(irq, &regs); __do_IRQ(irq, regs);
irq_exit(); irq_exit();
......
...@@ -404,7 +404,7 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86, ...@@ -404,7 +404,7 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
} }
#define DO_ERROR(trapnr, signr, str, name) \ #define DO_ERROR(trapnr, signr, str, name) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \ == NOTIFY_STOP) \
...@@ -413,7 +413,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ ...@@ -413,7 +413,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
} }
#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
siginfo_t info; \ siginfo_t info; \
info.si_signo = signr; \ info.si_signo = signr; \
...@@ -427,7 +427,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ ...@@ -427,7 +427,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
} }
#define DO_VM86_ERROR(trapnr, signr, str, name) \ #define DO_VM86_ERROR(trapnr, signr, str, name) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \ == NOTIFY_STOP) \
...@@ -436,7 +436,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ ...@@ -436,7 +436,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
} }
#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ fastcall void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
siginfo_t info; \ siginfo_t info; \
info.si_signo = signr; \ info.si_signo = signr; \
...@@ -462,7 +462,7 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) ...@@ -462,7 +462,7 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) fastcall void do_general_protection(struct pt_regs * regs, long error_code)
{ {
int cpu = get_cpu(); int cpu = get_cpu();
struct tss_struct *tss = &per_cpu(init_tss, cpu); struct tss_struct *tss = &per_cpu(init_tss, cpu);
...@@ -622,7 +622,7 @@ static int dummy_nmi_callback(struct pt_regs * regs, int cpu) ...@@ -622,7 +622,7 @@ static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
static nmi_callback_t nmi_callback = dummy_nmi_callback; static nmi_callback_t nmi_callback = dummy_nmi_callback;
asmlinkage void do_nmi(struct pt_regs * regs, long error_code) fastcall void do_nmi(struct pt_regs * regs, long error_code)
{ {
int cpu; int cpu;
...@@ -648,7 +648,7 @@ void unset_nmi_callback(void) ...@@ -648,7 +648,7 @@ void unset_nmi_callback(void)
} }
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
asmlinkage int do_int3(struct pt_regs *regs, long error_code) fastcall int do_int3(struct pt_regs *regs, long error_code)
{ {
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
== NOTIFY_STOP) == NOTIFY_STOP)
...@@ -683,7 +683,7 @@ asmlinkage int do_int3(struct pt_regs *regs, long error_code) ...@@ -683,7 +683,7 @@ asmlinkage int do_int3(struct pt_regs *regs, long error_code)
* find every occurrence of the TF bit that could be saved away even * find every occurrence of the TF bit that could be saved away even
* by user code) * by user code)
*/ */
asmlinkage void do_debug(struct pt_regs * regs, long error_code) fastcall void do_debug(struct pt_regs * regs, long error_code)
{ {
unsigned int condition; unsigned int condition;
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -822,7 +822,7 @@ void math_error(void __user *eip) ...@@ -822,7 +822,7 @@ void math_error(void __user *eip)
force_sig_info(SIGFPE, &info, task); force_sig_info(SIGFPE, &info, task);
} }
asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code)
{ {
ignore_fpu_irq = 1; ignore_fpu_irq = 1;
math_error((void __user *)regs->eip); math_error((void __user *)regs->eip);
...@@ -876,7 +876,7 @@ void simd_math_error(void __user *eip) ...@@ -876,7 +876,7 @@ void simd_math_error(void __user *eip)
force_sig_info(SIGFPE, &info, task); force_sig_info(SIGFPE, &info, task);
} }
asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs, fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
long error_code) long error_code)
{ {
if (cpu_has_xmm) { if (cpu_has_xmm) {
...@@ -900,7 +900,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs, ...@@ -900,7 +900,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs,
} }
} }
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
long error_code) long error_code)
{ {
#if 0 #if 0
......
...@@ -201,7 +201,7 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr, ...@@ -201,7 +201,7 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
return 0; return 0;
} }
asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); fastcall void do_invalid_op(struct pt_regs *, unsigned long);
/* /*
* This routine handles page faults. It determines the address, * This routine handles page faults. It determines the address,
...@@ -213,7 +213,7 @@ asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); ...@@ -213,7 +213,7 @@ asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
* bit 1 == 0 means read, 1 means write * bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode * bit 2 == 0 means kernel, 1 means user-mode
*/ */
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
{ {
struct task_struct *tsk; struct task_struct *tsk;
struct mm_struct *mm; struct mm_struct *mm;
......
...@@ -32,16 +32,16 @@ extern u8 irq_vector[NR_IRQ_VECTORS]; ...@@ -32,16 +32,16 @@ extern u8 irq_vector[NR_IRQ_VECTORS];
extern void (*interrupt[NR_IRQS])(void); extern void (*interrupt[NR_IRQS])(void);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
asmlinkage void reschedule_interrupt(void); fastcall void reschedule_interrupt(void);
asmlinkage void invalidate_interrupt(void); fastcall void invalidate_interrupt(void);
asmlinkage void call_function_interrupt(void); fastcall void call_function_interrupt(void);
#endif #endif
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
asmlinkage void apic_timer_interrupt(void); fastcall void apic_timer_interrupt(void);
asmlinkage void error_interrupt(void); fastcall void error_interrupt(void);
asmlinkage void spurious_interrupt(void); fastcall void spurious_interrupt(void);
asmlinkage void thermal_interrupt(struct pt_regs); fastcall void thermal_interrupt(struct pt_regs *);
#define platform_legacy_irq(irq) ((irq) < 16) #define platform_legacy_irq(irq) ((irq) < 16)
#endif #endif
......
...@@ -79,9 +79,9 @@ extern cpumask_t irq_affinity[NR_IRQS]; ...@@ -79,9 +79,9 @@ extern cpumask_t irq_affinity[NR_IRQS];
extern int no_irq_affinity; extern int no_irq_affinity;
extern int noirqdebug_setup(char *str); extern int noirqdebug_setup(char *str);
extern asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
struct irqaction *action); struct irqaction *action);
extern asmlinkage unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret); extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret);
extern void report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret); extern void report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret);
extern int can_request_irq(unsigned int irq, unsigned long irqflags); extern int can_request_irq(unsigned int irq, unsigned long irqflags);
......
...@@ -69,7 +69,7 @@ extern struct notifier_block *panic_notifier_list; ...@@ -69,7 +69,7 @@ extern struct notifier_block *panic_notifier_list;
extern long (*panic_blink)(long time); extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...) NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2))); __attribute__ ((NORET_AND format (printf, 1, 2)));
asmlinkage NORET_TYPE void do_exit(long error_code) fastcall NORET_TYPE void do_exit(long error_code)
ATTRIB_NORET; ATTRIB_NORET;
NORET_TYPE void complete_and_exit(struct completion *, long) NORET_TYPE void complete_and_exit(struct completion *, long)
ATTRIB_NORET; ATTRIB_NORET;
......
...@@ -780,7 +780,7 @@ static void exit_notify(struct task_struct *tsk) ...@@ -780,7 +780,7 @@ static void exit_notify(struct task_struct *tsk)
tsk->flags |= PF_DEAD; tsk->flags |= PF_DEAD;
} }
asmlinkage NORET_TYPE void do_exit(long code) fastcall NORET_TYPE void do_exit(long code)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
int group_dead; int group_dead;
......
...@@ -86,7 +86,7 @@ void irq_exit(void) ...@@ -86,7 +86,7 @@ void irq_exit(void)
/* /*
* Have got an event to handle: * Have got an event to handle:
*/ */
asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
struct irqaction *action) struct irqaction *action)
{ {
int ret, retval = 0, status = 0; int ret, retval = 0, status = 0;
...@@ -114,7 +114,7 @@ asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, ...@@ -114,7 +114,7 @@ asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
* SMP cross-CPU interrupts have their own specific * SMP cross-CPU interrupts have their own specific
* handlers). * handlers).
*/ */
asmlinkage unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
{ {
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = irq_desc + irq;
struct irqaction * action; struct irqaction * action;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment