linux/arch/mips/include/asm/irqflags.h
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
   7 * Copyright (C) 1996 by Paul M. Antoine
   8 * Copyright (C) 1999 Silicon Graphics
   9 * Copyright (C) 2000 MIPS Technologies, Inc.
  10 */
  11#ifndef _ASM_IRQFLAGS_H
  12#define _ASM_IRQFLAGS_H
  13
  14#ifndef __ASSEMBLY__
  15
  16#include <linux/compiler.h>
  17#include <linux/stringify.h>
  18#include <asm/compiler.h>
  19#include <asm/hazards.h>
  20
  21#if defined(CONFIG_CPU_MIPSR2) || defined (CONFIG_CPU_MIPSR6)
  22
  23static inline void arch_local_irq_disable(void)
  24{
  25        __asm__ __volatile__(
  26        "       .set    push                                            \n"
  27        "       .set    noat                                            \n"
  28        "       di                                                      \n"
  29        "       " __stringify(__irq_disable_hazard) "                   \n"
  30        "       .set    pop                                             \n"
  31        : /* no outputs */
  32        : /* no inputs */
  33        : "memory");
  34}
  35
  36static inline unsigned long arch_local_irq_save(void)
  37{
  38        unsigned long flags;
  39
  40        asm __volatile__(
  41        "       .set    push                                            \n"
  42        "       .set    reorder                                         \n"
  43        "       .set    noat                                            \n"
  44#if defined(CONFIG_CPU_LOONGSON3) || defined (CONFIG_CPU_LOONGSON1)
  45        "       mfc0    %[flags], $12                                   \n"
  46        "       di                                                      \n"
  47#else
  48        "       di      %[flags]                                        \n"
  49#endif
  50        "       andi    %[flags], 1                                     \n"
  51        "       " __stringify(__irq_disable_hazard) "                   \n"
  52        "       .set    pop                                             \n"
  53        : [flags] "=r" (flags)
  54        : /* no inputs */
  55        : "memory");
  56
  57        return flags;
  58}
  59
  60static inline void arch_local_irq_restore(unsigned long flags)
  61{
  62        unsigned long __tmp1;
  63
  64        __asm__ __volatile__(
  65        "       .set    push                                            \n"
  66        "       .set    noreorder                                       \n"
  67        "       .set    noat                                            \n"
  68#if defined(CONFIG_IRQ_MIPS_CPU)
  69        /*
  70         * Slow, but doesn't suffer from a relatively unlikely race
  71         * condition we're having since days 1.
  72         */
  73        "       beqz    %[flags], 1f                                    \n"
  74        "       di                                                      \n"
  75        "       ei                                                      \n"
  76        "1:                                                             \n"
  77#else
  78        /*
  79         * Fast, dangerous.  Life is fun, life is good.
  80         */
  81        "       mfc0    $1, $12                                         \n"
  82        "       ins     $1, %[flags], 0, 1                              \n"
  83        "       mtc0    $1, $12                                         \n"
  84#endif
  85        "       " __stringify(__irq_disable_hazard) "                   \n"
  86        "       .set    pop                                             \n"
  87        : [flags] "=r" (__tmp1)
  88        : "0" (flags)
  89        : "memory");
  90}
  91
  92#else
  93/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
  94void arch_local_irq_disable(void);
  95unsigned long arch_local_irq_save(void);
  96void arch_local_irq_restore(unsigned long flags);
  97#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
  98
  99static inline void arch_local_irq_enable(void)
 100{
 101        __asm__ __volatile__(
 102        "       .set    push                                            \n"
 103        "       .set    reorder                                         \n"
 104        "       .set    noat                                            \n"
 105#if   defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 106        "       ei                                                      \n"
 107#else
 108        "       mfc0    $1,$12                                          \n"
 109        "       ori     $1,0x1f                                         \n"
 110        "       xori    $1,0x1e                                         \n"
 111        "       mtc0    $1,$12                                          \n"
 112#endif
 113        "       " __stringify(__irq_enable_hazard) "                    \n"
 114        "       .set    pop                                             \n"
 115        : /* no outputs */
 116        : /* no inputs */
 117        : "memory");
 118}
 119
 120static inline unsigned long arch_local_save_flags(void)
 121{
 122        unsigned long flags;
 123
 124        asm __volatile__(
 125        "       .set    push                                            \n"
 126        "       .set    reorder                                         \n"
 127        "       mfc0    %[flags], $12                                   \n"
 128        "       .set    pop                                             \n"
 129        : [flags] "=r" (flags));
 130
 131        return flags;
 132}
 133
 134
 135static inline int arch_irqs_disabled_flags(unsigned long flags)
 136{
 137        return !(flags & 1);
 138}
 139
 140#endif /* #ifndef __ASSEMBLY__ */
 141
 142/*
 143 * Do the CPU's IRQ-state tracing from assembly code.
 144 */
 145#ifdef CONFIG_TRACE_IRQFLAGS
 146/* Reload some registers clobbered by trace_hardirqs_on */
 147#ifdef CONFIG_64BIT
 148# define TRACE_IRQS_RELOAD_REGS                                         \
 149        LONG_L  $11, PT_R11(sp);                                        \
 150        LONG_L  $10, PT_R10(sp);                                        \
 151        LONG_L  $9, PT_R9(sp);                                          \
 152        LONG_L  $8, PT_R8(sp);                                          \
 153        LONG_L  $7, PT_R7(sp);                                          \
 154        LONG_L  $6, PT_R6(sp);                                          \
 155        LONG_L  $5, PT_R5(sp);                                          \
 156        LONG_L  $4, PT_R4(sp);                                          \
 157        LONG_L  $2, PT_R2(sp)
 158#else
 159# define TRACE_IRQS_RELOAD_REGS                                         \
 160        LONG_L  $7, PT_R7(sp);                                          \
 161        LONG_L  $6, PT_R6(sp);                                          \
 162        LONG_L  $5, PT_R5(sp);                                          \
 163        LONG_L  $4, PT_R4(sp);                                          \
 164        LONG_L  $2, PT_R2(sp)
 165#endif
 166# define TRACE_IRQS_ON                                                  \
 167        CLI;    /* make sure trace_hardirqs_on() is called in kernel level */ \
 168        jal     trace_hardirqs_on
 169# define TRACE_IRQS_ON_RELOAD                                           \
 170        TRACE_IRQS_ON;                                                  \
 171        TRACE_IRQS_RELOAD_REGS
 172# define TRACE_IRQS_OFF                                                 \
 173        jal     trace_hardirqs_off
 174#else
 175# define TRACE_IRQS_ON
 176# define TRACE_IRQS_ON_RELOAD
 177# define TRACE_IRQS_OFF
 178#endif
 179
 180#endif /* _ASM_IRQFLAGS_H */
 181