All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Rutland <mark.rutland@arm.com>
To: linux-arm-kernel@lists.infradead.org
Cc: mark.rutland@arm.com, catalin.marinas@arm.com,
	robin.murphy@arm.com, james.morse@arm.com, will@kernel.org,
	hch@lst.de
Subject: [PATCHv2 07/17] arm64: sdei: explicitly simulate PAN/UAO entry
Date: Tue,  6 Oct 2020 15:46:32 +0100	[thread overview]
Message-ID: <20201006144642.12195-8-mark.rutland@arm.com> (raw)
In-Reply-To: <20201006144642.12195-1-mark.rutland@arm.com>

SDEI enters the kernel with a non-architectural exception which does not
manipulate PSTATE bits (e.g. PAN, UAO) in the same way as architectural
exceptions. We currently fix this up with a combination of
__uaccess_enable_hw_pan() and force_uaccess_access_begin(), but this has
a few problems:

* When set_fs() is removed, force_uaccess_begin() will have no HW
  side-effects, and UAO will need to be reset elsewhere.

* Kernels built without support for PAN or UAO will not reset these bits
  upon SDEI entry, and may inherit the values used by a VM, leading to
  unexpected behaviour.

* Kernels built *with* support for PAN or UAO, when run on systems with
  mismatched support across CPUs, will not reset these bits upon SDEI
  entry, and may inherit the values used by a VM, leading to unexpected
  behaviour.

To deal with all of these, let's always explicitly reset the PAN and UAO
bits when an SDEI event is delivered to the kernel. As above, we must do
so even when the kernel has chosen to not use PAN/UAO, or was not built
with support for PAN/UAO generally.

The existing system_uses_ttbr0_pan() is redefined in terms of
system_uses_hw_pan() both for clarity and as a minor optimization when
HW PAN is not selected.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will@kernel.org>
---
 arch/arm64/include/asm/cpufeature.h | 22 +++++++++++++++++++++-
 arch/arm64/kernel/sdei.c            | 19 ++++++++++++++-----
 2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 89b4f0142c287..6b10249304039 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -645,10 +645,16 @@ static __always_inline bool system_supports_fpsimd(void)
 	return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
 }
 
+static inline bool system_uses_hw_pan(void)
+{
+	return IS_ENABLED(CONFIG_ARM64_PAN) &&
+		cpus_have_const_cap(ARM64_HAS_PAN);
+}
+
 static inline bool system_uses_ttbr0_pan(void)
 {
 	return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
-		!cpus_have_const_cap(ARM64_HAS_PAN);
+		!system_uses_hw_pan();
 }
 
 static __always_inline bool system_supports_sve(void)
@@ -758,6 +764,20 @@ static inline bool cpu_has_hw_af(void)
 						ID_AA64MMFR1_HADBS_SHIFT);
 }
 
+static inline bool cpu_has_pan(void)
+{
+	u64 mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
+	return cpuid_feature_extract_unsigned_field(mmfr1,
+						    ID_AA64MMFR1_PAN_SHIFT);
+}
+
+static inline bool cpu_has_uao(void)
+{
+	u64 mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
+	return cpuid_feature_extract_unsigned_field(mmfr2,
+						    ID_AA64MMFR2_UAO_SHIFT);
+}
+
 #ifdef CONFIG_ARM64_AMU_EXTN
 /* Check whether the cpu supports the Activity Monitors Unit (AMU) */
 extern bool cpu_has_amu_feat(int cpu);
diff --git a/arch/arm64/kernel/sdei.c b/arch/arm64/kernel/sdei.c
index 4a5f24602aa0c..908d7be70eac0 100644
--- a/arch/arm64/kernel/sdei.c
+++ b/arch/arm64/kernel/sdei.c
@@ -216,6 +216,16 @@ static __kprobes unsigned long _sdei_handler(struct pt_regs *regs,
 	return vbar + 0x480;
 }
 
+static void __kprobes notrace __sdei_pstate_entry(void)
+{
+	if (system_uses_hw_pan())
+		set_pstate_pan(1);
+	else if (cpu_has_pan())
+		set_pstate_pan(0);
+
+	if (cpu_has_uao())
+		set_pstate_uao(0);
+}
 
 asmlinkage __kprobes notrace unsigned long
 __sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
@@ -224,12 +234,11 @@ __sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
 	mm_segment_t orig_addr_limit;
 
 	/*
-	 * We didn't take an exception to get here, so the HW hasn't set PAN or
-	 * cleared UAO, and the exception entry code hasn't reset addr_limit.
-	 * Set PAN, then use force_uaccess_begin() to clear UAO and reset
-	 * addr_limit.
+	 * We didn't take an exception to get here, so the HW hasn't
+	 * set/cleared bits in PSTATE that we may rely on. Intialize PAN/UAO,
+	 * then use force_uaccess_begin() to reset addr_limit.
 	 */
-	__uaccess_enable_hw_pan();
+	__sdei_pstate_entry();
 	orig_addr_limit = force_uaccess_begin();
 
 	nmi_enter();
-- 
2.11.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2020-10-06 14:49 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-06 14:46 [PATCHv2 00/17] arm64: remove set_fs() and friends Mark Rutland
2020-10-06 14:46 ` [PATCHv2 01/17] arm64: ensure ERET from kthread is illegal Mark Rutland
2020-10-06 14:46 ` [PATCHv2 02/17] arm64: add C wrappers for SET_PSTATE_*() Mark Rutland
2020-10-06 14:46 ` [PATCHv2 03/17] arm64: head.S: rename el2_setup -> init_kernel_el Mark Rutland
2020-10-06 14:46 ` [PATCHv2 04/17] arm64: head.S: cleanup SCTLR_ELx initialization Mark Rutland
2020-10-06 14:46 ` [PATCHv2 05/17] arm64: head.S: always initialize PSTATE Mark Rutland
2020-10-06 14:46 ` [PATCHv2 06/17] arm64: sdei: move uaccess logic to arch/arm64/ Mark Rutland
2020-10-06 14:46 ` Mark Rutland [this message]
2020-10-06 14:46 ` [PATCHv2 08/17] arm64: uaccess: move uao_* alternatives to asm-uaccess.h Mark Rutland
2020-10-06 14:46 ` [PATCHv2 09/17] arm64: uaccess: rename privileged uaccess routines Mark Rutland
2020-10-06 14:46 ` [PATCHv2 10/17] arm64: uaccess: simplify __copy_user_flushcache() Mark Rutland
2020-10-06 14:46 ` [PATCHv2 11/17] arm64: uaccess: refactor __{get,put}_user Mark Rutland
2020-10-06 14:46 ` [PATCHv2 12/17] arm64: uaccess: split user/kernel routines Mark Rutland
2020-10-06 14:46 ` [PATCHv2 13/17] arm64: uaccess cleanup macro naming Mark Rutland
2020-10-06 14:46 ` [PATCHv2 14/17] arm64: uaccess: remove set_fs() Mark Rutland
2020-10-06 14:46 ` [PATCHv2 15/17] arm64: uaccess: remove addr_limit_user_check() Mark Rutland
2020-10-06 14:46 ` [PATCHv2 16/17] arm64: uaccess: remove redundant PAN toggling Mark Rutland
2020-10-06 14:46 ` [PATCHv2 17/17] arm64: uaccess: remove vestigal UAO support Mark Rutland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201006144642.12195-8-mark.rutland@arm.com \
    --to=mark.rutland@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=hch@lst.de \
    --cc=james.morse@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=robin.murphy@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.