[PATCH] lockdep: irqtrace subsystem, s390 support

irqtrace support for s390.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Arjan van de Ven <arjan@infradead.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Heiko Carstens 2006-07-03 00:24:46 -07:00 committed by Linus Torvalds
parent 6375e2b74c
commit 1f194a4c39
9 changed files with 113 additions and 38 deletions

View file

@ -1,5 +1,9 @@
menu "Kernel hacking" menu "Kernel hacking"
config TRACE_IRQFLAGS_SUPPORT
bool
default y
source "lib/Kconfig.debug" source "lib/Kconfig.debug"
endmenu endmenu

View file

@ -58,6 +58,21 @@ STACK_SIZE = 1 << STACK_SHIFT
#define BASED(name) name-system_call(%r13) #define BASED(name) name-system_call(%r13)
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
l %r1,BASED(.Ltrace_irq_on)
basr %r14,%r1
.endm
.macro TRACE_IRQS_OFF
l %r1,BASED(.Ltrace_irq_off)
basr %r14,%r1
.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
#endif
/* /*
* Register usage in interrupt handlers: * Register usage in interrupt handlers:
* R9 - pointer to current task structure * R9 - pointer to current task structure
@ -361,6 +376,7 @@ ret_from_fork:
st %r15,SP_R15(%r15) # store stack pointer for new kthread st %r15,SP_R15(%r15) # store stack pointer for new kthread
0: l %r1,BASED(.Lschedtail) 0: l %r1,BASED(.Lschedtail)
basr %r14,%r1 basr %r14,%r1
TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
b BASED(sysc_return) b BASED(sysc_return)
@ -516,6 +532,7 @@ pgm_no_vtime3:
mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
b BASED(sysc_do_svc) b BASED(sysc_do_svc)
@ -539,9 +556,11 @@ io_int_handler:
io_no_vtime: io_no_vtime:
#endif #endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
la %r2,SP_PTREGS(%r15) # address of register-save area la %r2,SP_PTREGS(%r15) # address of register-save area
basr %r14,%r1 # branch to standard irq handler basr %r14,%r1 # branch to standard irq handler
TRACE_IRQS_ON
io_return: io_return:
tm SP_PSW+1(%r15),0x01 # returning to user ? tm SP_PSW+1(%r15),0x01 # returning to user ?
@ -651,10 +670,12 @@ ext_int_handler:
ext_no_vtime: ext_no_vtime:
#endif #endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
la %r2,SP_PTREGS(%r15) # address of register-save area la %r2,SP_PTREGS(%r15) # address of register-save area
lh %r3,__LC_EXT_INT_CODE # get interruption code lh %r3,__LC_EXT_INT_CODE # get interruption code
l %r1,BASED(.Ldo_extint) l %r1,BASED(.Ldo_extint)
basr %r14,%r1 basr %r14,%r1
TRACE_IRQS_ON
b BASED(io_return) b BASED(io_return)
__critical_end: __critical_end:
@ -731,8 +752,10 @@ mcck_no_vtime:
stosm __SF_EMPTY(%r15),0x04 # turn dat on stosm __SF_EMPTY(%r15),0x04 # turn dat on
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
bno BASED(mcck_return) bno BASED(mcck_return)
TRACE_IRQS_OFF
l %r1,BASED(.Ls390_handle_mcck) l %r1,BASED(.Ls390_handle_mcck)
basr %r14,%r1 # call machine check handler basr %r14,%r1 # call machine check handler
TRACE_IRQS_ON
mcck_return: mcck_return:
mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW
ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
@ -1012,7 +1035,11 @@ cleanup_io_leave_insn:
.Lvfork: .long sys_vfork .Lvfork: .long sys_vfork
.Lschedtail: .long schedule_tail .Lschedtail: .long schedule_tail
.Lsysc_table: .long sys_call_table .Lsysc_table: .long sys_call_table
#ifdef CONFIG_TRACE_IRQFLAGS
.Ltrace_irq_on:.long trace_hardirqs_on
.Ltrace_irq_off:
.long trace_hardirqs_off
#endif
.Lcritical_start: .Lcritical_start:
.long __critical_start + 0x80000000 .long __critical_start + 0x80000000
.Lcritical_end: .Lcritical_end:

View file

@ -58,6 +58,19 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
#define BASED(name) name-system_call(%r13) #define BASED(name) name-system_call(%r13)
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
brasl %r14,trace_hardirqs_on
.endm
.macro TRACE_IRQS_OFF
brasl %r14,trace_hardirqs_off
.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
#endif
.macro STORE_TIMER lc_offset .macro STORE_TIMER lc_offset
#ifdef CONFIG_VIRT_CPU_ACCOUNTING #ifdef CONFIG_VIRT_CPU_ACCOUNTING
stpt \lc_offset stpt \lc_offset
@ -354,6 +367,7 @@ ret_from_fork:
jo 0f jo 0f
stg %r15,SP_R15(%r15) # store stack pointer for new kthread stg %r15,SP_R15(%r15) # store stack pointer for new kthread
0: brasl %r14,schedule_tail 0: brasl %r14,schedule_tail
TRACE_IRQS_ON
stosm 24(%r15),0x03 # reenable interrupts stosm 24(%r15),0x03 # reenable interrupts
j sysc_return j sysc_return
@ -535,6 +549,7 @@ pgm_no_vtime3:
mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
j sysc_do_svc j sysc_do_svc
@ -557,8 +572,10 @@ io_int_handler:
io_no_vtime: io_no_vtime:
#endif #endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
la %r2,SP_PTREGS(%r15) # address of register-save area la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_IRQ # call standard irq handler brasl %r14,do_IRQ # call standard irq handler
TRACE_IRQS_ON
io_return: io_return:
tm SP_PSW+1(%r15),0x01 # returning to user ? tm SP_PSW+1(%r15),0x01 # returning to user ?
@ -665,9 +682,11 @@ ext_int_handler:
ext_no_vtime: ext_no_vtime:
#endif #endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
la %r2,SP_PTREGS(%r15) # address of register-save area la %r2,SP_PTREGS(%r15) # address of register-save area
llgh %r3,__LC_EXT_INT_CODE # get interruption code llgh %r3,__LC_EXT_INT_CODE # get interruption code
brasl %r14,do_extint brasl %r14,do_extint
TRACE_IRQS_ON
j io_return j io_return
__critical_end: __critical_end:
@ -743,7 +762,9 @@ mcck_no_vtime:
stosm __SF_EMPTY(%r15),0x04 # turn dat on stosm __SF_EMPTY(%r15),0x04 # turn dat on
tm __TI_flags+7(%r9),_TIF_MCCK_PENDING tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
jno mcck_return jno mcck_return
TRACE_IRQS_OFF
brasl %r14,s390_handle_mcck brasl %r14,s390_handle_mcck
TRACE_IRQS_ON
mcck_return: mcck_return:
mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW
ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit

View file

@ -97,7 +97,7 @@ asmlinkage void do_softirq(void)
account_system_vtime(current); account_system_vtime(current);
__local_bh_enable(); _local_bh_enable();
local_irq_restore(flags); local_irq_restore(flags);
} }

View file

@ -142,6 +142,7 @@ static void default_idle(void)
return; return;
} }
trace_hardirqs_on();
/* Wait for external, I/O or machine check interrupt. */ /* Wait for external, I/O or machine check interrupt. */
__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT); PSW_MASK_IO | PSW_MASK_EXT);

View file

@ -383,6 +383,7 @@ void
sclp_sync_wait(void) sclp_sync_wait(void)
{ {
unsigned long psw_mask; unsigned long psw_mask;
unsigned long flags;
unsigned long cr0, cr0_sync; unsigned long cr0, cr0_sync;
u64 timeout; u64 timeout;
@ -395,9 +396,11 @@ sclp_sync_wait(void)
sclp_tod_from_jiffies(sclp_request_timer.expires - sclp_tod_from_jiffies(sclp_request_timer.expires -
jiffies); jiffies);
} }
local_irq_save(flags);
/* Prevent bottom half from executing once we force interrupts open */ /* Prevent bottom half from executing once we force interrupts open */
local_bh_disable(); local_bh_disable();
/* Enable service-signal interruption, disable timer interrupts */ /* Enable service-signal interruption, disable timer interrupts */
trace_hardirqs_on();
__ctl_store(cr0, 0, 0); __ctl_store(cr0, 0, 0);
cr0_sync = cr0; cr0_sync = cr0;
cr0_sync |= 0x00000200; cr0_sync |= 0x00000200;
@ -415,11 +418,10 @@ sclp_sync_wait(void)
barrier(); barrier();
cpu_relax(); cpu_relax();
} }
/* Restore interrupt settings */ local_irq_disable();
asm volatile ("SSM 0(%0)"
: : "a" (&psw_mask) : "memory");
__ctl_load(cr0, 0, 0); __ctl_load(cr0, 0, 0);
__local_bh_enable(); _local_bh_enable();
local_irq_restore(flags);
} }
EXPORT_SYMBOL(sclp_sync_wait); EXPORT_SYMBOL(sclp_sync_wait);

View file

@ -147,7 +147,7 @@ cio_tpi(void)
sch->driver->irq(&sch->dev); sch->driver->irq(&sch->dev);
spin_unlock(&sch->lock); spin_unlock(&sch->lock);
irq_exit (); irq_exit ();
__local_bh_enable(); _local_bh_enable();
return 1; return 1;
} }

View file

@ -0,0 +1,50 @@
/*
* include/asm-s390/irqflags.h
*
* Copyright (C) IBM Corp. 2006
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
*/
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H
#ifdef __KERNEL__
/* interrupt control.. */
#define raw_local_irq_enable() ({ \
unsigned long __dummy; \
__asm__ __volatile__ ( \
"stosm 0(%1),0x03" \
: "=m" (__dummy) : "a" (&__dummy) : "memory" ); \
})
#define raw_local_irq_disable() ({ \
unsigned long __flags; \
__asm__ __volatile__ ( \
"stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \
__flags; \
})
#define raw_local_save_flags(x) \
__asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) )
#define raw_local_irq_restore(x) \
__asm__ __volatile__("ssm 0(%0)" : : "a" (&x), "m" (x) : "memory")
#define raw_irqs_disabled() \
({ \
unsigned long flags; \
local_save_flags(flags); \
!((flags >> __FLAG_SHIFT) & 3); \
})
static inline int raw_irqs_disabled_flags(unsigned long flags)
{
return !((flags >> __FLAG_SHIFT) & 3);
}
/* For spinlocks etc */
#define raw_local_irq_save(x) ((x) = raw_local_irq_disable())
#endif /* __KERNEL__ */
#endif /* __ASM_IRQFLAGS_H */

View file

@ -301,34 +301,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#define set_mb(var, value) do { var = value; mb(); } while (0) #define set_mb(var, value) do { var = value; mb(); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0) #define set_wmb(var, value) do { var = value; wmb(); } while (0)
/* interrupt control.. */
#define local_irq_enable() ({ \
unsigned long __dummy; \
__asm__ __volatile__ ( \
"stosm 0(%1),0x03" \
: "=m" (__dummy) : "a" (&__dummy) : "memory" ); \
})
#define local_irq_disable() ({ \
unsigned long __flags; \
__asm__ __volatile__ ( \
"stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \
__flags; \
})
#define local_save_flags(x) \
__asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) )
#define local_irq_restore(x) \
__asm__ __volatile__("ssm 0(%0)" : : "a" (&x), "m" (x) : "memory")
#define irqs_disabled() \
({ \
unsigned long flags; \
local_save_flags(flags); \
!((flags >> __FLAG_SHIFT) & 3); \
})
#ifdef __s390x__ #ifdef __s390x__
#define __ctl_load(array, low, high) ({ \ #define __ctl_load(array, low, high) ({ \
@ -442,8 +414,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
}) })
#endif /* __s390x__ */ #endif /* __s390x__ */
/* For spinlocks etc */ #include <linux/irqflags.h>
#define local_irq_save(x) ((x) = local_irq_disable())
/* /*
* Use to set psw mask except for the first byte which * Use to set psw mask except for the first byte which
@ -482,4 +453,3 @@ extern void (*_machine_power_off)(void);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif