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_HAS_DIEI)
  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_LOONGSON64) || defined(CONFIG_CPU_LOONGSON32)
  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_HAS_DIEI */
  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_HAS_DIEI)
 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
 140static inline int arch_irqs_disabled(void)
 141{
 142        return arch_irqs_disabled_flags(arch_local_save_flags());
 143}
 144
 145#endif /* #ifndef __ASSEMBLY__ */
 146
 147/*
 148 * Do the CPU's IRQ-state tracing from assembly code.
 149 */
 150#ifdef CONFIG_TRACE_IRQFLAGS
 151/* Reload some registers clobbered by trace_hardirqs_on */
 152#ifdef CONFIG_64BIT
 153# define TRACE_IRQS_RELOAD_REGS                                         \
 154        LONG_L  $11, PT_R11(sp);                                        \
 155        LONG_L  $10, PT_R10(sp);                                        \
 156        LONG_L  $9, PT_R9(sp);                                          \
 157        LONG_L  $8, PT_R8(sp);                                          \
 158        LONG_L  $7, PT_R7(sp);                                          \
 159        LONG_L  $6, PT_R6(sp);                                          \
 160        LONG_L  $5, PT_R5(sp);                                          \
 161        LONG_L  $4, PT_R4(sp);                                          \
 162        LONG_L  $2, PT_R2(sp)
 163#else
 164# define TRACE_IRQS_RELOAD_REGS                                         \
 165        LONG_L  $7, PT_R7(sp);                                          \
 166        LONG_L  $6, PT_R6(sp);                                          \
 167        LONG_L  $5, PT_R5(sp);                                          \
 168        LONG_L  $4, PT_R4(sp);                                          \
 169        LONG_L  $2, PT_R2(sp)
 170#endif
 171# define TRACE_IRQS_ON                                                  \
 172        CLI;    /* make sure trace_hardirqs_on() is called in kernel level */ \
 173        jal     trace_hardirqs_on
 174# define TRACE_IRQS_ON_RELOAD                                           \
 175        TRACE_IRQS_ON;                                                  \
 176        TRACE_IRQS_RELOAD_REGS
 177# define TRACE_IRQS_OFF                                                 \
 178        jal     trace_hardirqs_off
 179#else
 180# define TRACE_IRQS_ON
 181# define TRACE_IRQS_ON_RELOAD
 182# define TRACE_IRQS_OFF
 183#endif
 184
 185#endif /* _ASM_IRQFLAGS_H */
 186