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 #include <asm/irqflags.h>
0012 #include <asm/hazards.h>
0013 #include <linux/compiler.h>
0014 #include <linux/preempt.h>
0015 #include <linux/export.h>
0016 #include <linux/stringify.h>
0017 
0018 #if !defined(CONFIG_CPU_HAS_DIEI)
0019 
0020 /*
0021  * For cli() we have to insert nops to make sure that the new value
0022  * has actually arrived in the status register before the end of this
0023  * macro.
0024  * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
0025  * no nops at all.
0026  */
0027 /*
0028  * For TX49, operating only IE bit is not enough.
0029  *
0030  * If mfc0 $12 follows store and the mfc0 is last instruction of a
0031  * page and fetching the next instruction causes TLB miss, the result
0032  * of the mfc0 might wrongly contain EXL bit.
0033  *
0034  * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
0035  *
0036  * Workaround: mask EXL bit of the result or place a nop before mfc0.
0037  */
0038 notrace void arch_local_irq_disable(void)
0039 {
0040     preempt_disable_notrace();
0041 
0042     __asm__ __volatile__(
0043     "   .set    push                        \n"
0044     "   .set    noat                        \n"
0045     "   mfc0    $1,$12                      \n"
0046     "   ori $1,0x1f                     \n"
0047     "   xori    $1,0x1f                     \n"
0048     "   .set    noreorder                   \n"
0049     "   mtc0    $1,$12                      \n"
0050     "   " __stringify(__irq_disable_hazard) "           \n"
0051     "   .set    pop                     \n"
0052     : /* no outputs */
0053     : /* no inputs */
0054     : "memory");
0055 
0056     preempt_enable_notrace();
0057 }
0058 EXPORT_SYMBOL(arch_local_irq_disable);
0059 
0060 notrace unsigned long arch_local_irq_save(void)
0061 {
0062     unsigned long flags;
0063 
0064     preempt_disable_notrace();
0065 
0066     __asm__ __volatile__(
0067     "   .set    push                        \n"
0068     "   .set    reorder                     \n"
0069     "   .set    noat                        \n"
0070     "   mfc0    %[flags], $12                   \n"
0071     "   ori $1, %[flags], 0x1f              \n"
0072     "   xori    $1, 0x1f                    \n"
0073     "   .set    noreorder                   \n"
0074     "   mtc0    $1, $12                     \n"
0075     "   " __stringify(__irq_disable_hazard) "           \n"
0076     "   .set    pop                     \n"
0077     : [flags] "=r" (flags)
0078     : /* no inputs */
0079     : "memory");
0080 
0081     preempt_enable_notrace();
0082 
0083     return flags;
0084 }
0085 EXPORT_SYMBOL(arch_local_irq_save);
0086 
0087 notrace void arch_local_irq_restore(unsigned long flags)
0088 {
0089     unsigned long __tmp1;
0090 
0091     preempt_disable_notrace();
0092 
0093     __asm__ __volatile__(
0094     "   .set    push                        \n"
0095     "   .set    noreorder                   \n"
0096     "   .set    noat                        \n"
0097     "   mfc0    $1, $12                     \n"
0098     "   andi    %[flags], 1                 \n"
0099     "   ori $1, 0x1f                    \n"
0100     "   xori    $1, 0x1f                    \n"
0101     "   or  %[flags], $1                    \n"
0102     "   mtc0    %[flags], $12                   \n"
0103     "   " __stringify(__irq_disable_hazard) "           \n"
0104     "   .set    pop                     \n"
0105     : [flags] "=r" (__tmp1)
0106     : "0" (flags)
0107     : "memory");
0108 
0109     preempt_enable_notrace();
0110 }
0111 EXPORT_SYMBOL(arch_local_irq_restore);
0112 
0113 #endif /* !CONFIG_CPU_HAS_DIEI */