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)
/* Thermal interrupt handler for this CPU setup */
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();
vendor_thermal_interrupt(&regs);
vendor_thermal_interrupt(regs);
irq_exit();
}
......
......@@ -131,7 +131,7 @@ VM_MASK = 0x00020000
movl $(__USER_DS), %edx; \
movl %edx, %ds; \
movl %edx, %es; \
pushl $11; \
movl $11,%eax; \
call do_exit; \
.previous; \
.section __ex_table,"a";\
......@@ -291,8 +291,8 @@ work_notifysig: # deal with pending signals and
ALIGN
work_notifysig_v86:
pushl %ecx
call save_v86_state
pushl %ecx # save ti_flags for do_notify_resume
call save_v86_state # %eax contains pt_regs pointer
popl %ecx
movl %eax, %esp
xorl %edx, %edx
......@@ -359,6 +359,7 @@ vector=vector+1
ALIGN
common_interrupt:
SAVE_ALL
movl %esp,%eax
call do_IRQ
jmp ret_from_intr
......@@ -366,7 +367,8 @@ common_interrupt:
ENTRY(name) \
pushl $nr-256; \
SAVE_ALL \
call smp_/**/name; \
movl %esp,%eax; \
call smp_/**/name; \
jmp ret_from_intr;
/* The include is where all of the SMP etc. interrupts come from */
......@@ -389,18 +391,15 @@ error_code:
pushl %ebx
cld
movl %es, %ecx
movl ORIG_EAX(%esp), %esi # get the error code
movl ES(%esp), %edi # get the function address
movl ORIG_EAX(%esp), %edx # get the error code
movl %eax, ORIG_EAX(%esp)
movl %ecx, ES(%esp)
movl %esp, %edx
pushl %esi # push the error code
pushl %edx # push the pt_regs pointer
movl $(__USER_DS), %edx
movl %edx, %ds
movl %edx, %es
movl $(__USER_DS), %ecx
movl %ecx, %ds
movl %ecx, %es
movl %esp,%eax # pt_regs pointer
call *%edi
addl $8, %esp
jmp ret_from_exception
ENTRY(coprocessor_error)
......@@ -457,11 +456,9 @@ ENTRY(debug)
debug_stack_correct:
pushl $-1 # mark this as an int
SAVE_ALL
movl %esp,%edx
pushl $0
pushl %edx
xorl %edx,%edx # error code 0
movl %esp,%eax # pt_regs pointer
call do_debug
addl $8,%esp
testl %eax,%eax
jnz restore_all
jmp ret_from_exception
......@@ -491,11 +488,9 @@ ENTRY(nmi)
nmi_stack_correct:
pushl %eax
SAVE_ALL
movl %esp, %edx
pushl $0
pushl %edx
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
addl $8, %esp
RESTORE_ALL
nmi_stack_fixup:
......@@ -515,11 +510,9 @@ nmi_debug_stack_fixup:
ENTRY(int3)
pushl $-1 # mark this as an int
SAVE_ALL
movl %esp,%edx
pushl $0
pushl %edx
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_int3
addl $8,%esp
testl %eax,%eax
jnz restore_all
jmp ret_from_exception
......
......@@ -45,10 +45,10 @@ static union irq_ctx *softirq_ctx[NR_CPUS];
* SMP cross-CPU interrupts have their own specific
* 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 */
int irq = regs.orig_eax & 0xff;
int irq = regs->orig_eax & 0xff;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
u32 *isp;
......@@ -82,24 +82,24 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
* current stack (which is the irq stack already after all)
*/
if (curctx != irqctx) {
int arg1, arg2, ebx;
/* build the stack frame on the IRQ stack */
isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_esp = current_stack_pointer();
*--isp = (u32) &regs;
*--isp = (u32) irq;
asm volatile(
" xchgl %%ebx,%%esp \n"
" call __do_IRQ \n"
" xchgl %%ebx,%%esp \n"
: : "b"(isp)
: "memory", "cc", "eax", "edx", "ecx"
" movl %%ebx,%%esp \n"
: "=a" (arg1), "=d" (arg2), "=b" (ebx)
: "0" (irq), "1" (regs), "2" (isp)
: "memory", "cc", "ecx"
);
} else
#endif
__do_IRQ(irq, &regs);
__do_IRQ(irq, regs);
irq_exit();
......
......@@ -404,7 +404,7 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
}
#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) \
== NOTIFY_STOP) \
......@@ -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) \
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; \
info.si_signo = signr; \
......@@ -427,7 +427,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
}
#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) \
== NOTIFY_STOP) \
......@@ -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) \
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; \
info.si_signo = signr; \
......@@ -462,7 +462,7 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
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();
struct tss_struct *tss = &per_cpu(init_tss, 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;
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
fastcall void do_nmi(struct pt_regs * regs, long error_code)
{
int cpu;
......@@ -648,7 +648,7 @@ void unset_nmi_callback(void)
}
#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)
== NOTIFY_STOP)
......@@ -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
* 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;
struct task_struct *tsk = current;
......@@ -822,7 +822,7 @@ void math_error(void __user *eip)
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;
math_error((void __user *)regs->eip);
......@@ -876,7 +876,7 @@ void simd_math_error(void __user *eip)
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)
{
if (cpu_has_xmm) {
......@@ -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)
{
#if 0
......
......@@ -201,7 +201,7 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
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,
......@@ -213,7 +213,7 @@ asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
* bit 1 == 0 means read, 1 means write
* 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 mm_struct *mm;
......
......@@ -32,16 +32,16 @@ extern u8 irq_vector[NR_IRQ_VECTORS];
extern void (*interrupt[NR_IRQS])(void);
#ifdef CONFIG_SMP
asmlinkage void reschedule_interrupt(void);
asmlinkage void invalidate_interrupt(void);
asmlinkage void call_function_interrupt(void);
fastcall void reschedule_interrupt(void);
fastcall void invalidate_interrupt(void);
fastcall void call_function_interrupt(void);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
asmlinkage void apic_timer_interrupt(void);
asmlinkage void error_interrupt(void);
asmlinkage void spurious_interrupt(void);
asmlinkage void thermal_interrupt(struct pt_regs);
fastcall void apic_timer_interrupt(void);
fastcall void error_interrupt(void);
fastcall void spurious_interrupt(void);
fastcall void thermal_interrupt(struct pt_regs *);
#define platform_legacy_irq(irq) ((irq) < 16)
#endif
......
......@@ -79,9 +79,9 @@ extern cpumask_t irq_affinity[NR_IRQS];
extern int no_irq_affinity;
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);
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 report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret);
extern int can_request_irq(unsigned int irq, unsigned long irqflags);
......
......@@ -69,7 +69,7 @@ extern struct notifier_block *panic_notifier_list;
extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...)
__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;
NORET_TYPE void complete_and_exit(struct completion *, long)
ATTRIB_NORET;
......
......@@ -780,7 +780,7 @@ static void exit_notify(struct task_struct *tsk)
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;
int group_dead;
......
......@@ -86,7 +86,7 @@ void irq_exit(void)
/*
* 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)
{
int ret, retval = 0, status = 0;
......@@ -114,7 +114,7 @@ asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
* SMP cross-CPU interrupts have their own specific
* 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;
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