summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-14 17:37:39 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-14 17:37:39 +0300
commit424280953322cf66314f3ba5e2d1ef345f21c770 (patch)
treeb60272675976be52c6ae25c2eb688f4f24f49b9d
parente21ee273e6fa3879aec9a27251cfce98156e07c4 (diff)
parent009b6c6486b94a3aff566b017256b598dc96bf18 (diff)
downloadlinux-424280953322cf66314f3ba5e2d1ef345f21c770.tar.xz
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
Pull ARM fixes from Russell King: - Avoid KASAN instrumentation of half-word IO - Use a byte load for KASAN shadow stack - Fix kexec and hibernation with PAN * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux: ARM: 9476/1: mm: fix kexec and hibernation with CONFIG_CPU_TTBR0_PAN ARM: 9475/1: entry: use byte load for KASAN VMAP stack shadow ARM: 9474/1: io: avoid KASAN instrumentation of raw halfword I/O
-rw-r--r--arch/arm/include/asm/io.h15
-rw-r--r--arch/arm/kernel/entry-armv.S2
-rw-r--r--arch/arm/kernel/hibernate.c10
-rw-r--r--arch/arm/mm/idmap.c12
4 files changed, 36 insertions, 3 deletions
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index bae5edf348ef..e6bd9e79737c 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -56,8 +56,19 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
* the bus. Rather than special-case the machine, just let the compiler
* generate the access for CPUs prior to ARMv6.
*/
-#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
-#define __raw_writew(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
+#define __raw_writew __raw_writew
+static __no_kasan_or_inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+ __chk_io_ptr(addr);
+ *(volatile unsigned short __force *)addr = val;
+}
+
+#define __raw_readw __raw_readw
+static __no_kasan_or_inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+ __chk_io_ptr(addr);
+ return *(const volatile unsigned short __force *)addr;
+}
#else
/*
* When running under a hypervisor, we want to avoid I/O accesses with
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index ef6a657c8d13..a3d050ce9b79 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -567,7 +567,7 @@ ENTRY(__switch_to)
@ are using KASAN
mov_l r2, KASAN_SHADOW_OFFSET
add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
- ldr r2, [r2]
+ ldrb r2, [r2]
#endif
#endif
diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c
index 38a90a3d12b2..231a76af09a0 100644
--- a/arch/arm/kernel/hibernate.c
+++ b/arch/arm/kernel/hibernate.c
@@ -21,6 +21,7 @@
#include <asm/suspend.h>
#include <asm/page.h>
#include <asm/sections.h>
+#include <asm/uaccess.h>
#include "reboot.h"
int pfn_is_nosave(unsigned long pfn)
@@ -82,6 +83,15 @@ static void notrace arch_restore_image(void *unused)
{
struct pbe *pbe;
+ /*
+ * With CONFIG_CPU_TTBR0_PAN enabled, TTBCR.EPD0 is set to block
+ * TTBR0 page-table walks. The identity mapping used here lives at
+ * low (user-space) virtual addresses and is only reachable via
+ * TTBR0, so re-enable those walks before switching page tables.
+ * On non-PAN kernels this is a no-op.
+ */
+ if (IS_ENABLED(CONFIG_CPU_TTBR0_PAN))
+ uaccess_save_and_enable();
cpu_switch_mm(idmap_pgd, &init_mm);
for (pbe = restore_pblist; pbe; pbe = pbe->next)
copy_page(pbe->orig_address, pbe->address);
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index 4a833e89782a..70403e968d2a 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -11,6 +11,7 @@
#include <asm/pgalloc.h>
#include <asm/sections.h>
#include <asm/system_info.h>
+#include <asm/uaccess.h>
/*
* Note: accesses outside of the kernel image and the identity map area
@@ -133,6 +134,17 @@ early_initcall(init_static_idmap);
*/
void setup_mm_for_reboot(void)
{
+ /*
+ * With CONFIG_CPU_TTBR0_PAN enabled, TTBCR.EPD0 is set whenever
+ * user-space access is disabled in order to block TTBR0 page-table
+ * walks. The identity mapping lives at low (user-space) virtual
+ * addresses and can only be reached via TTBR0, so we must re-enable
+ * those walks before switching page tables. On non-PAN kernels this
+ * is a no-op.
+ */
+ if (IS_ENABLED(CONFIG_CPU_TTBR0_PAN))
+ uaccess_save_and_enable();
+
/* Switch to the identity mapping. */
cpu_switch_mm(idmap_pgd, &init_mm);
local_flush_bp_all();