Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adf75899 authored by Mark Rutland's avatar Mark Rutland Committed by Will Deacon
Browse files

arm64: simplify sysreg manipulation



A while back we added {read,write}_sysreg accessors to handle accesses
to system registers, without the usual boilerplate asm volatile,
temporary variable, etc.

This patch makes use of these across arm64 to make code shorter and
clearer. For sequences with a trailing ISB, the existing isb() macro is
also used so that asm blocks can be removed entirely.

A few uses of inline assembly for msr/mrs are left as-is. Those
manipulating sp_el0 for the current thread_info value have special
clobber requiremends.

Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 1f3d8699
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <asm/cputype.h>
#include <asm/cpufeature.h>
#include <asm/sysreg.h>
#include <asm/virt.h>

#ifdef __KERNEL__
@@ -98,18 +99,18 @@ static inline void decode_ctrl_reg(u32 reg,
#define AARCH64_DBG_REG_WCR	(AARCH64_DBG_REG_WVR + ARM_MAX_WRP)

/* Debug register names. */
#define AARCH64_DBG_REG_NAME_BVR	"bvr"
#define AARCH64_DBG_REG_NAME_BCR	"bcr"
#define AARCH64_DBG_REG_NAME_WVR	"wvr"
#define AARCH64_DBG_REG_NAME_WCR	"wcr"
#define AARCH64_DBG_REG_NAME_BVR	bvr
#define AARCH64_DBG_REG_NAME_BCR	bcr
#define AARCH64_DBG_REG_NAME_WVR	wvr
#define AARCH64_DBG_REG_NAME_WCR	wcr

/* Accessor macros for the debug registers. */
#define AARCH64_DBG_READ(N, REG, VAL) do {\
	asm volatile("mrs %0, dbg" REG #N "_el1" : "=r" (VAL));\
	VAL = read_sysreg(dbg##REG##N##_el1);\
} while (0)

#define AARCH64_DBG_WRITE(N, REG, VAL) do {\
	asm volatile("msr dbg" REG #N "_el1, %0" :: "r" (VAL));\
	write_sysreg(VAL, dbg##REG##N##_el1);\
} while (0)

struct task_struct;
+10 −17
Original line number Diff line number Diff line
@@ -27,16 +27,14 @@
#include <asm-generic/mm_hooks.h>
#include <asm/cputype.h>
#include <asm/pgtable.h>
#include <asm/sysreg.h>
#include <asm/tlbflush.h>

#ifdef CONFIG_PID_IN_CONTEXTIDR
static inline void contextidr_thread_switch(struct task_struct *next)
{
	asm(
	"	msr	contextidr_el1, %0\n"
	"	isb"
	:
	: "r" (task_pid_nr(next)));
	write_sysreg(task_pid_nr(next), contextidr_el1);
	isb();
}
#else
static inline void contextidr_thread_switch(struct task_struct *next)
@@ -51,11 +49,8 @@ static inline void cpu_set_reserved_ttbr0(void)
{
	unsigned long ttbr = virt_to_phys(empty_zero_page);

	asm(
	"	msr	ttbr0_el1, %0			// set TTBR0\n"
	"	isb"
	:
	: "r" (ttbr));
	write_sysreg(ttbr, ttbr0_el1);
	isb();
}

/*
@@ -81,13 +76,11 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz)
	if (!__cpu_uses_extended_idmap())
		return;

	asm volatile (
	"	mrs	%0, tcr_el1	;"
	"	bfi	%0, %1, %2, %3	;"
	"	msr	tcr_el1, %0	;"
	"	isb"
	: "=&r" (tcr)
	: "r"(t0sz), "I"(TCR_T0SZ_OFFSET), "I"(TCR_TxSZ_WIDTH));
	tcr = read_sysreg(tcr_el1);
	tcr &= ~TCR_T0SZ_MASK;
	tcr |= t0sz << TCR_T0SZ_OFFSET;
	write_sysreg(tcr, tcr_el1);
	isb();
}

#define cpu_set_default_tcr_t0sz()	__cpu_set_tcr_t0sz(TCR_T0SZ(VA_BITS))
+1 −0
Original line number Diff line number Diff line
@@ -208,6 +208,7 @@
#define TCR_T1SZ(x)		((UL(64) - (x)) << TCR_T1SZ_OFFSET)
#define TCR_TxSZ(x)		(TCR_T0SZ(x) | TCR_T1SZ(x))
#define TCR_TxSZ_WIDTH		6
#define TCR_T0SZ_MASK		(((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T0SZ_OFFSET)

#define TCR_IRGN0_SHIFT		8
#define TCR_IRGN0_MASK		(UL(3) << TCR_IRGN0_SHIFT)
+10 −10
Original line number Diff line number Diff line
@@ -253,16 +253,6 @@ asm(
"	.endm\n"
);

static inline void config_sctlr_el1(u32 clear, u32 set)
{
	u32 val;

	asm volatile("mrs %0, sctlr_el1" : "=r" (val));
	val &= ~clear;
	val |= set;
	asm volatile("msr sctlr_el1, %0" : : "r" (val));
}

/*
 * Unlike read_cpuid, calls to read_sysreg are never expected to be
 * optimized away or replaced with synthetic values.
@@ -283,6 +273,16 @@ static inline void config_sctlr_el1(u32 clear, u32 set)
		     : : "rZ" (__val));				\
} while (0)

static inline void config_sctlr_el1(u32 clear, u32 set)
{
	u32 val;

	val = read_sysreg(sctlr_el1);
	val &= ~clear;
	val |= set;
	write_sysreg(val, sctlr_el1);
}

#endif

#endif	/* __ASM_SYSREG_H */
+3 −0
Original line number Diff line number Diff line
@@ -75,6 +75,9 @@ static inline struct thread_info *current_thread_info(void) __attribute_const__;

/*
 * struct thread_info can be accessed directly via sp_el0.
 *
 * We don't use read_sysreg() as we want the compiler to cache the value where
 * possible.
 */
static inline struct thread_info *current_thread_info(void)
{
Loading