Commit 0fbeb318 authored by James Morse's avatar James Morse Committed by Will Deacon
Browse files

arm64: explicitly mask all exceptions



There are a few places where we want to mask all exceptions. Today we
do this in a piecemeal fashion, typically we expect the caller to
have masked irqs and the arch code masks debug exceptions, ignoring
serror which is probably masked.

Make it clear that 'mask all exceptions' is the intention by adding
helpers to do exactly that.

This will let us unmask SError without having to add 'oh and SError'
to these paths.

Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Reviewed-by: default avatarJulien Thierry <julien.thierry@arm.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent c10f0d06
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -32,6 +32,23 @@
#include <asm/ptrace.h>
#include <asm/thread_info.h>

	.macro save_and_disable_daif, flags
	mrs	\flags, daif
	msr	daifset, #0xf
	.endm

	.macro disable_daif
	msr	daifset, #0xf
	.endm

	.macro enable_daif
	msr	daifclr, #0xf
	.endm

	.macro	restore_daif, flags:req
	msr	daif, \flags
	.endm

/*
 * Enable and disable interrupts.
 */
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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_DAIFFLAGS_H
#define __ASM_DAIFFLAGS_H

#include <linux/irqflags.h>

/* mask/save/unmask/restore all exceptions, including interrupts. */
static inline void local_daif_mask(void)
{
	asm volatile(
		"msr	daifset, #0xf		// local_daif_mask\n"
		:
		:
		: "memory");
	trace_hardirqs_off();
}

static inline unsigned long local_daif_save(void)
{
	unsigned long flags;

	asm volatile(
		"mrs	%0, daif		// local_daif_save\n"
		: "=r" (flags)
		:
		: "memory");
	local_daif_mask();

	return flags;
}

static inline void local_daif_unmask(void)
{
	trace_hardirqs_on();
	asm volatile(
		"msr	daifclr, #0xf		// local_daif_unmask"
		:
		:
		: "memory");
}

static inline void local_daif_restore(unsigned long flags)
{
	if (!arch_irqs_disabled_flags(flags))
		trace_hardirqs_on();
	asm volatile(
		"msr	daif, %0		// local_daif_restore"
		:
		: "r" (flags)
		: "memory");
	if (arch_irqs_disabled_flags(flags))
		trace_hardirqs_off();
}

#endif
+3 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <asm/barrier.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
#include <asm/daifflags.h>
#include <asm/irqflags.h>
#include <asm/kexec.h>
#include <asm/memory.h>
@@ -285,7 +286,7 @@ int swsusp_arch_suspend(void)
		return -EBUSY;
	}

	local_dbg_save(flags);
	flags = local_daif_save();

	if (__cpu_suspend_enter(&state)) {
		/* make the crash dump kernel image visible/saveable */
@@ -315,7 +316,7 @@ int swsusp_arch_suspend(void)
		__cpu_suspend_exit();
	}

	local_dbg_restore(flags);
	local_daif_restore(flags);

	return ret;
}
+2 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <asm/cacheflush.h>
#include <asm/cpu_ops.h>
#include <asm/daifflags.h>
#include <asm/memory.h>
#include <asm/mmu.h>
#include <asm/mmu_context.h>
@@ -195,8 +196,7 @@ void machine_kexec(struct kimage *kimage)

	pr_info("Bye!\n");

	/* Disable all DAIF exceptions. */
	asm volatile ("msr daifset, #0xf" : : : "memory");
	local_daif_mask();

	/*
	 * cpu_soft_restart will shutdown the MMU, disable data caches, then
+3 −6
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include <asm/cpu.h>
#include <asm/cputype.h>
#include <asm/cpu_ops.h>
#include <asm/daifflags.h>
#include <asm/mmu_context.h>
#include <asm/numa.h>
#include <asm/pgtable.h>
@@ -370,10 +371,6 @@ void __cpu_die(unsigned int cpu)
/*
 * Called from the idle thread for the CPU which has been shutdown.
 *
 * Note that we disable IRQs here, but do not re-enable them
 * before returning to the caller. This is also the behaviour
 * of the other hotplug-cpu capable cores, so presumably coming
 * out of idle fixes this.
 */
void cpu_die(void)
{
@@ -381,7 +378,7 @@ void cpu_die(void)

	idle_task_exit();

	local_irq_disable();
	local_daif_mask();

	/* Tell __cpu_die() that this CPU is now safe to dispose of */
	(void)cpu_report_death();
@@ -839,7 +836,7 @@ static void ipi_cpu_stop(unsigned int cpu)
{
	set_cpu_online(cpu, false);

	local_irq_disable();
	local_daif_mask();

	while (1)
		cpu_relax();
Loading