root/arch/arm64/include/asm/irqflags.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. arch_local_irq_enable
  2. arch_local_irq_disable
  3. arch_local_save_flags
  4. arch_irqs_disabled_flags
  5. arch_local_irq_save
  6. arch_local_irq_restore

   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * Copyright (C) 2012 ARM Ltd.
   4  */
   5 #ifndef __ASM_IRQFLAGS_H
   6 #define __ASM_IRQFLAGS_H
   7 
   8 #include <asm/alternative.h>
   9 #include <asm/ptrace.h>
  10 #include <asm/sysreg.h>
  11 
  12 /*
  13  * Aarch64 has flags for masking: Debug, Asynchronous (serror), Interrupts and
  14  * FIQ exceptions, in the 'daif' register. We mask and unmask them in 'dai'
  15  * order:
  16  * Masking debug exceptions causes all other exceptions to be masked too/
  17  * Masking SError masks irq, but not debug exceptions. Masking irqs has no
  18  * side effects for other flags. Keeping to this order makes it easier for
  19  * entry.S to know which exceptions should be unmasked.
  20  *
  21  * FIQ is never expected, but we mask it when we disable debug exceptions, and
  22  * unmask it at all other times.
  23  */
  24 
  25 /*
  26  * CPU interrupt mask handling.
  27  */
  28 static inline void arch_local_irq_enable(void)
  29 {
  30         if (system_has_prio_mask_debugging()) {
  31                 u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
  32 
  33                 WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
  34         }
  35 
  36         asm volatile(ALTERNATIVE(
  37                 "msr    daifclr, #2             // arch_local_irq_enable\n"
  38                 "nop",
  39                 __msr_s(SYS_ICC_PMR_EL1, "%0")
  40                 "dsb    sy",
  41                 ARM64_HAS_IRQ_PRIO_MASKING)
  42                 :
  43                 : "r" ((unsigned long) GIC_PRIO_IRQON)
  44                 : "memory");
  45 }
  46 
  47 static inline void arch_local_irq_disable(void)
  48 {
  49         if (system_has_prio_mask_debugging()) {
  50                 u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
  51 
  52                 WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
  53         }
  54 
  55         asm volatile(ALTERNATIVE(
  56                 "msr    daifset, #2             // arch_local_irq_disable",
  57                 __msr_s(SYS_ICC_PMR_EL1, "%0"),
  58                 ARM64_HAS_IRQ_PRIO_MASKING)
  59                 :
  60                 : "r" ((unsigned long) GIC_PRIO_IRQOFF)
  61                 : "memory");
  62 }
  63 
  64 /*
  65  * Save the current interrupt enable state.
  66  */
  67 static inline unsigned long arch_local_save_flags(void)
  68 {
  69         unsigned long flags;
  70 
  71         asm volatile(ALTERNATIVE(
  72                 "mrs    %0, daif",
  73                 __mrs_s("%0", SYS_ICC_PMR_EL1),
  74                 ARM64_HAS_IRQ_PRIO_MASKING)
  75                 : "=&r" (flags)
  76                 :
  77                 : "memory");
  78 
  79         return flags;
  80 }
  81 
  82 static inline int arch_irqs_disabled_flags(unsigned long flags)
  83 {
  84         int res;
  85 
  86         asm volatile(ALTERNATIVE(
  87                 "and    %w0, %w1, #" __stringify(PSR_I_BIT),
  88                 "eor    %w0, %w1, #" __stringify(GIC_PRIO_IRQON),
  89                 ARM64_HAS_IRQ_PRIO_MASKING)
  90                 : "=&r" (res)
  91                 : "r" ((int) flags)
  92                 : "memory");
  93 
  94         return res;
  95 }
  96 
  97 static inline unsigned long arch_local_irq_save(void)
  98 {
  99         unsigned long flags;
 100 
 101         flags = arch_local_save_flags();
 102 
 103         /*
 104          * There are too many states with IRQs disabled, just keep the current
 105          * state if interrupts are already disabled/masked.
 106          */
 107         if (!arch_irqs_disabled_flags(flags))
 108                 arch_local_irq_disable();
 109 
 110         return flags;
 111 }
 112 
 113 /*
 114  * restore saved IRQ state
 115  */
 116 static inline void arch_local_irq_restore(unsigned long flags)
 117 {
 118         asm volatile(ALTERNATIVE(
 119                         "msr    daif, %0\n"
 120                         "nop",
 121                         __msr_s(SYS_ICC_PMR_EL1, "%0")
 122                         "dsb    sy",
 123                         ARM64_HAS_IRQ_PRIO_MASKING)
 124                 :
 125                 : "r" (flags)
 126                 : "memory");
 127 }
 128 
 129 #endif /* __ASM_IRQFLAGS_H */

/* [<][>][^][v][top][bottom][index][help] */