mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 00:48:50 +00:00
bbeb920951
This patch adds imprecise abort enable/disable macros and uses them to enable imprecise aborts early when starting the kernel. This helps in tracking down the real cause for such imprecise abort, as they are handled as soon as they occur. Until now those aborts would only be enabled when entering the userspace and as a consequence crash the first userspace process if any abort had been raised during kernel startup. Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
186 lines
3.8 KiB
C
186 lines
3.8 KiB
C
#ifndef __ASM_ARM_IRQFLAGS_H
|
|
#define __ASM_ARM_IRQFLAGS_H
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#include <asm/ptrace.h>
|
|
|
|
/*
|
|
* CPU interrupt mask handling.
|
|
*/
|
|
#ifdef CONFIG_CPU_V7M
|
|
#define IRQMASK_REG_NAME_R "primask"
|
|
#define IRQMASK_REG_NAME_W "primask"
|
|
#define IRQMASK_I_BIT 1
|
|
#else
|
|
#define IRQMASK_REG_NAME_R "cpsr"
|
|
#define IRQMASK_REG_NAME_W "cpsr_c"
|
|
#define IRQMASK_I_BIT PSR_I_BIT
|
|
#endif
|
|
|
|
#if __LINUX_ARM_ARCH__ >= 6
|
|
|
|
#define arch_local_irq_save arch_local_irq_save
|
|
static inline unsigned long arch_local_irq_save(void)
|
|
{
|
|
unsigned long flags;
|
|
|
|
asm volatile(
|
|
" mrs %0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\n"
|
|
" cpsid i"
|
|
: "=r" (flags) : : "memory", "cc");
|
|
return flags;
|
|
}
|
|
|
|
#define arch_local_irq_enable arch_local_irq_enable
|
|
static inline void arch_local_irq_enable(void)
|
|
{
|
|
asm volatile(
|
|
" cpsie i @ arch_local_irq_enable"
|
|
:
|
|
:
|
|
: "memory", "cc");
|
|
}
|
|
|
|
#define arch_local_irq_disable arch_local_irq_disable
|
|
static inline void arch_local_irq_disable(void)
|
|
{
|
|
asm volatile(
|
|
" cpsid i @ arch_local_irq_disable"
|
|
:
|
|
:
|
|
: "memory", "cc");
|
|
}
|
|
|
|
#define local_fiq_enable() __asm__("cpsie f @ __stf" : : : "memory", "cc")
|
|
#define local_fiq_disable() __asm__("cpsid f @ __clf" : : : "memory", "cc")
|
|
|
|
#ifndef CONFIG_CPU_V7M
|
|
#define local_abt_enable() __asm__("cpsie a @ __sta" : : : "memory", "cc")
|
|
#define local_abt_disable() __asm__("cpsid a @ __cla" : : : "memory", "cc")
|
|
#else
|
|
#define local_abt_enable() do { } while (0)
|
|
#define local_abt_disable() do { } while (0)
|
|
#endif
|
|
#else
|
|
|
|
/*
|
|
* Save the current interrupt enable state & disable IRQs
|
|
*/
|
|
#define arch_local_irq_save arch_local_irq_save
|
|
static inline unsigned long arch_local_irq_save(void)
|
|
{
|
|
unsigned long flags, temp;
|
|
|
|
asm volatile(
|
|
" mrs %0, cpsr @ arch_local_irq_save\n"
|
|
" orr %1, %0, #128\n"
|
|
" msr cpsr_c, %1"
|
|
: "=r" (flags), "=r" (temp)
|
|
:
|
|
: "memory", "cc");
|
|
return flags;
|
|
}
|
|
|
|
/*
|
|
* Enable IRQs
|
|
*/
|
|
#define arch_local_irq_enable arch_local_irq_enable
|
|
static inline void arch_local_irq_enable(void)
|
|
{
|
|
unsigned long temp;
|
|
asm volatile(
|
|
" mrs %0, cpsr @ arch_local_irq_enable\n"
|
|
" bic %0, %0, #128\n"
|
|
" msr cpsr_c, %0"
|
|
: "=r" (temp)
|
|
:
|
|
: "memory", "cc");
|
|
}
|
|
|
|
/*
|
|
* Disable IRQs
|
|
*/
|
|
#define arch_local_irq_disable arch_local_irq_disable
|
|
static inline void arch_local_irq_disable(void)
|
|
{
|
|
unsigned long temp;
|
|
asm volatile(
|
|
" mrs %0, cpsr @ arch_local_irq_disable\n"
|
|
" orr %0, %0, #128\n"
|
|
" msr cpsr_c, %0"
|
|
: "=r" (temp)
|
|
:
|
|
: "memory", "cc");
|
|
}
|
|
|
|
/*
|
|
* Enable FIQs
|
|
*/
|
|
#define local_fiq_enable() \
|
|
({ \
|
|
unsigned long temp; \
|
|
__asm__ __volatile__( \
|
|
"mrs %0, cpsr @ stf\n" \
|
|
" bic %0, %0, #64\n" \
|
|
" msr cpsr_c, %0" \
|
|
: "=r" (temp) \
|
|
: \
|
|
: "memory", "cc"); \
|
|
})
|
|
|
|
/*
|
|
* Disable FIQs
|
|
*/
|
|
#define local_fiq_disable() \
|
|
({ \
|
|
unsigned long temp; \
|
|
__asm__ __volatile__( \
|
|
"mrs %0, cpsr @ clf\n" \
|
|
" orr %0, %0, #64\n" \
|
|
" msr cpsr_c, %0" \
|
|
: "=r" (temp) \
|
|
: \
|
|
: "memory", "cc"); \
|
|
})
|
|
|
|
#define local_abt_enable() do { } while (0)
|
|
#define local_abt_disable() do { } while (0)
|
|
#endif
|
|
|
|
/*
|
|
* Save the current interrupt enable state.
|
|
*/
|
|
#define arch_local_save_flags arch_local_save_flags
|
|
static inline unsigned long arch_local_save_flags(void)
|
|
{
|
|
unsigned long flags;
|
|
asm volatile(
|
|
" mrs %0, " IRQMASK_REG_NAME_R " @ local_save_flags"
|
|
: "=r" (flags) : : "memory", "cc");
|
|
return flags;
|
|
}
|
|
|
|
/*
|
|
* restore saved IRQ & FIQ state
|
|
*/
|
|
#define arch_local_irq_restore arch_local_irq_restore
|
|
static inline void arch_local_irq_restore(unsigned long flags)
|
|
{
|
|
asm volatile(
|
|
" msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
|
|
:
|
|
: "r" (flags)
|
|
: "memory", "cc");
|
|
}
|
|
|
|
#define arch_irqs_disabled_flags arch_irqs_disabled_flags
|
|
static inline int arch_irqs_disabled_flags(unsigned long flags)
|
|
{
|
|
return flags & IRQMASK_I_BIT;
|
|
}
|
|
|
|
#include <asm-generic/irqflags.h>
|
|
|
|
#endif /* ifdef __KERNEL__ */
|
|
#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
|