irqflags.h 3.4 KB
Newer Older
M
Marc Zyngier 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Copyright (C) 2012 ARM Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H

#ifdef __KERNEL__

21
#include <asm/alternative.h>
22
#include <asm/barrier.h>
M
Marc Zyngier 已提交
23
#include <asm/ptrace.h>
24
#include <asm/sysreg.h>
M
Marc Zyngier 已提交
25

26 27 28 29 30 31 32 33 34 35 36 37 38
/*
 * Aarch64 has flags for masking: Debug, Asynchronous (serror), Interrupts and
 * FIQ exceptions, in the 'daif' register. We mask and unmask them in 'dai'
 * order:
 * Masking debug exceptions causes all other exceptions to be masked too/
 * Masking SError masks irq, but not debug exceptions. Masking irqs has no
 * side effects for other flags. Keeping to this order makes it easier for
 * entry.S to know which exceptions should be unmasked.
 *
 * FIQ is never expected, but we mask it when we disable debug exceptions, and
 * unmask it at all other times.
 */

M
Marc Zyngier 已提交
39 40 41 42 43
/*
 * CPU interrupt mask handling.
 */
static inline void arch_local_irq_enable(void)
{
44 45 46 47 48 49
	if (system_has_prio_mask_debugging()) {
		u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);

		WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
	}

50
	asm volatile(ALTERNATIVE(
51 52
		"msr	daifclr, #2		// arch_local_irq_enable",
		__msr_s(SYS_ICC_PMR_EL1, "%0"),
53
		ARM64_HAS_IRQ_PRIO_MASKING)
M
Marc Zyngier 已提交
54
		:
55
		: "r" ((unsigned long) GIC_PRIO_IRQON)
M
Marc Zyngier 已提交
56
		: "memory");
57 58

	pmr_sync();
M
Marc Zyngier 已提交
59 60 61 62
}

static inline void arch_local_irq_disable(void)
{
63 64 65 66 67 68
	if (system_has_prio_mask_debugging()) {
		u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);

		WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
	}

69 70
	asm volatile(ALTERNATIVE(
		"msr	daifset, #2		// arch_local_irq_disable",
71
		__msr_s(SYS_ICC_PMR_EL1, "%0"),
72
		ARM64_HAS_IRQ_PRIO_MASKING)
M
Marc Zyngier 已提交
73
		:
74
		: "r" ((unsigned long) GIC_PRIO_IRQOFF)
M
Marc Zyngier 已提交
75 76 77 78 79 80 81 82 83
		: "memory");
}

/*
 * Save the current interrupt enable state.
 */
static inline unsigned long arch_local_save_flags(void)
{
	unsigned long flags;
84 85

	asm volatile(ALTERNATIVE(
86 87 88 89 90 91
		"mrs	%0, daif",
		__mrs_s("%0", SYS_ICC_PMR_EL1),
		ARM64_HAS_IRQ_PRIO_MASKING)
		: "=&r" (flags)
		:
		: "memory");
92 93 94 95

	return flags;
}

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
	int res;

	asm volatile(ALTERNATIVE(
		"and	%w0, %w1, #" __stringify(PSR_I_BIT),
		"eor	%w0, %w1, #" __stringify(GIC_PRIO_IRQON),
		ARM64_HAS_IRQ_PRIO_MASKING)
		: "=&r" (res)
		: "r" ((int) flags)
		: "memory");

	return res;
}

111 112 113 114 115 116
static inline unsigned long arch_local_irq_save(void)
{
	unsigned long flags;

	flags = arch_local_save_flags();

117 118 119 120 121 122
	/*
	 * There are too many states with IRQs disabled, just keep the current
	 * state if interrupts are already disabled/masked.
	 */
	if (!arch_irqs_disabled_flags(flags))
		arch_local_irq_disable();
123

M
Marc Zyngier 已提交
124 125 126 127 128 129 130 131
	return flags;
}

/*
 * restore saved IRQ state
 */
static inline void arch_local_irq_restore(unsigned long flags)
{
132
	asm volatile(ALTERNATIVE(
133 134 135
		"msr	daif, %0",
		__msr_s(SYS_ICC_PMR_EL1, "%0"),
		ARM64_HAS_IRQ_PRIO_MASKING)
136
		:
137
		: "r" (flags)
138
		: "memory");
139 140

	pmr_sync();
M
Marc Zyngier 已提交
141 142 143 144
}

#endif
#endif