Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
0007  * Copyright (C) 1996 by Paul M. Antoine
0008  * Copyright (C) 1999 Silicon Graphics
0009  * Copyright (C) 2000 MIPS Technologies, Inc.
0010  */
0011 #ifndef _ASM_IRQFLAGS_H
0012 #define _ASM_IRQFLAGS_H
0013 
0014 #ifndef __ASSEMBLY__
0015 
0016 #include <linux/compiler.h>
0017 #include <linux/stringify.h>
0018 #include <asm/compiler.h>
0019 #include <asm/hazards.h>
0020 
0021 #if defined(CONFIG_CPU_HAS_DIEI)
0022 
0023 static inline void arch_local_irq_disable(void)
0024 {
0025     __asm__ __volatile__(
0026     "   .set    push                        \n"
0027     "   .set    noat                        \n"
0028     "   di                          \n"
0029     "   " __stringify(__irq_disable_hazard) "           \n"
0030     "   .set    pop                     \n"
0031     : /* no outputs */
0032     : /* no inputs */
0033     : "memory");
0034 }
0035 
0036 static inline unsigned long arch_local_irq_save(void)
0037 {
0038     unsigned long flags;
0039 
0040     asm __volatile__(
0041     "   .set    push                        \n"
0042     "   .set    reorder                     \n"
0043     "   .set    noat                        \n"
0044 #if defined(CONFIG_CPU_LOONGSON64) || defined(CONFIG_CPU_LOONGSON32)
0045     "   mfc0    %[flags], $12                   \n"
0046     "   di                          \n"
0047 #else
0048     "   di  %[flags]                    \n"
0049 #endif
0050     "   andi    %[flags], 1                 \n"
0051     "   " __stringify(__irq_disable_hazard) "           \n"
0052     "   .set    pop                     \n"
0053     : [flags] "=r" (flags)
0054     : /* no inputs */
0055     : "memory");
0056 
0057     return flags;
0058 }
0059 
0060 static inline void arch_local_irq_restore(unsigned long flags)
0061 {
0062     unsigned long __tmp1;
0063 
0064     __asm__ __volatile__(
0065     "   .set    push                        \n"
0066     "   .set    noreorder                   \n"
0067     "   .set    noat                        \n"
0068 #if defined(CONFIG_IRQ_MIPS_CPU)
0069     /*
0070      * Slow, but doesn't suffer from a relatively unlikely race
0071      * condition we're having since days 1.
0072      */
0073     "   beqz    %[flags], 1f                    \n"
0074     "   di                          \n"
0075     "   ei                          \n"
0076     "1:                             \n"
0077 #else
0078     /*
0079      * Fast, dangerous.  Life is fun, life is good.
0080      */
0081     "   mfc0    $1, $12                     \n"
0082     "   ins $1, %[flags], 0, 1              \n"
0083     "   mtc0    $1, $12                     \n"
0084 #endif
0085     "   " __stringify(__irq_disable_hazard) "           \n"
0086     "   .set    pop                     \n"
0087     : [flags] "=r" (__tmp1)
0088     : "0" (flags)
0089     : "memory");
0090 }
0091 
0092 #else
0093 /* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
0094 void arch_local_irq_disable(void);
0095 unsigned long arch_local_irq_save(void);
0096 void arch_local_irq_restore(unsigned long flags);
0097 #endif /* CONFIG_CPU_HAS_DIEI */
0098 
0099 static inline void arch_local_irq_enable(void)
0100 {
0101     __asm__ __volatile__(
0102     "   .set    push                        \n"
0103     "   .set    reorder                     \n"
0104     "   .set    noat                        \n"
0105 #if defined(CONFIG_CPU_HAS_DIEI)
0106     "   ei                          \n"
0107 #else
0108     "   mfc0    $1,$12                      \n"
0109     "   ori $1,0x1f                     \n"
0110     "   xori    $1,0x1e                     \n"
0111     "   mtc0    $1,$12                      \n"
0112 #endif
0113     "   " __stringify(__irq_enable_hazard) "            \n"
0114     "   .set    pop                     \n"
0115     : /* no outputs */
0116     : /* no inputs */
0117     : "memory");
0118 }
0119 
0120 static inline unsigned long arch_local_save_flags(void)
0121 {
0122     unsigned long flags;
0123 
0124     asm __volatile__(
0125     "   .set    push                        \n"
0126     "   .set    reorder                     \n"
0127     "   mfc0    %[flags], $12                   \n"
0128     "   .set    pop                     \n"
0129     : [flags] "=r" (flags));
0130 
0131     return flags;
0132 }
0133 
0134 
0135 static inline int arch_irqs_disabled_flags(unsigned long flags)
0136 {
0137     return !(flags & 1);
0138 }
0139 
0140 static inline int arch_irqs_disabled(void)
0141 {
0142     return arch_irqs_disabled_flags(arch_local_save_flags());
0143 }
0144 
0145 #endif /* #ifndef __ASSEMBLY__ */
0146 
0147 /*
0148  * Do the CPU's IRQ-state tracing from assembly code.
0149  */
0150 #ifdef CONFIG_TRACE_IRQFLAGS
0151 /* Reload some registers clobbered by trace_hardirqs_on */
0152 #ifdef CONFIG_64BIT
0153 # define TRACE_IRQS_RELOAD_REGS                     \
0154     LONG_L  $11, PT_R11(sp);                    \
0155     LONG_L  $10, PT_R10(sp);                    \
0156     LONG_L  $9, PT_R9(sp);                      \
0157     LONG_L  $8, PT_R8(sp);                      \
0158     LONG_L  $7, PT_R7(sp);                      \
0159     LONG_L  $6, PT_R6(sp);                      \
0160     LONG_L  $5, PT_R5(sp);                      \
0161     LONG_L  $4, PT_R4(sp);                      \
0162     LONG_L  $2, PT_R2(sp)
0163 #else
0164 # define TRACE_IRQS_RELOAD_REGS                     \
0165     LONG_L  $7, PT_R7(sp);                      \
0166     LONG_L  $6, PT_R6(sp);                      \
0167     LONG_L  $5, PT_R5(sp);                      \
0168     LONG_L  $4, PT_R4(sp);                      \
0169     LONG_L  $2, PT_R2(sp)
0170 #endif
0171 # define TRACE_IRQS_ON                          \
0172     CLI;    /* make sure trace_hardirqs_on() is called in kernel level */ \
0173     jal trace_hardirqs_on
0174 # define TRACE_IRQS_ON_RELOAD                       \
0175     TRACE_IRQS_ON;                          \
0176     TRACE_IRQS_RELOAD_REGS
0177 # define TRACE_IRQS_OFF                         \
0178     jal trace_hardirqs_off
0179 #else
0180 # define TRACE_IRQS_ON
0181 # define TRACE_IRQS_ON_RELOAD
0182 # define TRACE_IRQS_OFF
0183 #endif
0184 
0185 #endif /* _ASM_IRQFLAGS_H */