aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/unaligned.c
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>2022-02-22 16:53:44 +0100
committerArnd Bergmann <arnd@arndb.de>2022-02-25 09:36:05 +0100
commit429124d992648b924408a912dc939cdb42d870b2 (patch)
tree97805502b09108f77e25718b5238b32f63cf9996 /arch/mips/kernel/unaligned.c
parentuaccess: add generic __{get,put}_kernel_nofault (diff)
downloadlinux-dev-429124d992648b924408a912dc939cdb42d870b2.tar.xz
linux-dev-429124d992648b924408a912dc939cdb42d870b2.zip
MIPS: Handle address errors for accesses above CPU max virtual user address
Address errors have always been treated as unaliged accesses and handled as such. But address errors are also issued for illegal accesses like user to kernel space or accesses outside of implemented spaces. This change implements Linux exception handling for accesses to the illegal space above the CPU implemented maximum virtual user address and the MIPS 64bit architecture maximum. With this we can now use a fixed value for the maximum task size on every MIPS CPU and get a more optimized access_ok(). Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r--arch/mips/kernel/unaligned.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index df4b708c04a9..7b5aba5df02e 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -1480,6 +1480,23 @@ asmlinkage void do_ade(struct pt_regs *regs)
prev_state = exception_enter();
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
1, regs, regs->cp0_badvaddr);
+
+#ifdef CONFIG_64BIT
+ /*
+ * check, if we are hitting space between CPU implemented maximum
+ * virtual user address and 64bit maximum virtual user address
+ * and do exception handling to get EFAULTs for get_user/put_user
+ */
+ if ((regs->cp0_badvaddr >= (1UL << cpu_vmbits)) &&
+ (regs->cp0_badvaddr < XKSSEG)) {
+ if (fixup_exception(regs)) {
+ current->thread.cp0_baduaddr = regs->cp0_badvaddr;
+ return;
+ }
+ goto sigbus;
+ }
+#endif
+
/*
* Did we catch a fault trying to load an instruction?
*/