hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/arch/arm/kernel/traps.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/arch/arm/kernel/traps.c
34 *
45 * Copyright (C) 1995-2009 Russell King
56 * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
107 *
118 * 'traps.c' handles hardware exceptions after we have saved some state in
129 * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably
....@@ -33,6 +30,7 @@
3330 #include <linux/atomic.h>
3431 #include <asm/cacheflush.h>
3532 #include <asm/exception.h>
33
+#include <asm/spectre.h>
3634 #include <asm/unistd.h>
3735 #include <asm/traps.h>
3836 #include <asm/ptrace.h>
....@@ -65,21 +63,24 @@
6563
6664 static void dump_mem(const char *, const char *, unsigned long, unsigned long);
6765
68
-void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
66
+void dump_backtrace_entry(unsigned long where, unsigned long from,
67
+ unsigned long frame, const char *loglvl)
6968 {
7069 unsigned long end = frame + 4 + sizeof(struct pt_regs);
7170
7271 #ifdef CONFIG_KALLSYMS
73
- printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from);
72
+ printk("%s[<%08lx>] (%ps) from [<%08lx>] (%pS)\n",
73
+ loglvl, where, (void *)where, from, (void *)from);
7474 #else
75
- printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
75
+ printk("%sFunction entered at [<%08lx>] from [<%08lx>]\n",
76
+ loglvl, where, from);
7677 #endif
7778
7879 if (in_entry_text(from) && end <= ALIGN(frame, THREAD_SIZE))
79
- dump_mem("", "Exception stack", frame + 4, end);
80
+ dump_mem(loglvl, "Exception stack", frame + 4, end);
8081 }
8182
82
-void dump_backtrace_stm(u32 *stack, u32 instruction)
83
+void dump_backtrace_stm(u32 *stack, u32 instruction, const char *loglvl)
8384 {
8485 char str[80], *p;
8586 unsigned int x;
....@@ -91,12 +92,12 @@
9192 if (++x == 6) {
9293 x = 0;
9394 p = str;
94
- printk("%s\n", str);
95
+ printk("%s%s\n", loglvl, str);
9596 }
9697 }
9798 }
9899 if (p != str)
99
- printk("%s\n", str);
100
+ printk("%s%s\n", loglvl, str);
100101 }
101102
102103 #ifndef CONFIG_ARM_UNWIND
....@@ -204,17 +205,19 @@
204205 }
205206
206207 #ifdef CONFIG_ARM_UNWIND
207
-static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
208
+static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
209
+ const char *loglvl)
208210 {
209
- unwind_backtrace(regs, tsk);
211
+ unwind_backtrace(regs, tsk, loglvl);
210212 }
211213 #else
212
-static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
214
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
215
+ const char *loglvl)
213216 {
214217 unsigned int fp, mode;
215218 int ok = 1;
216219
217
- printk("Backtrace: ");
220
+ printk("%sBacktrace: ", loglvl);
218221
219222 if (!tsk)
220223 tsk = current;
....@@ -241,18 +244,20 @@
241244 pr_cont("\n");
242245
243246 if (ok)
244
- c_backtrace(fp, mode);
247
+ c_backtrace(fp, mode, loglvl);
245248 }
246249 #endif
247250
248
-void show_stack(struct task_struct *tsk, unsigned long *sp)
251
+void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
249252 {
250
- dump_backtrace(NULL, tsk);
253
+ dump_backtrace(NULL, tsk, loglvl);
251254 barrier();
252255 }
253256
254257 #ifdef CONFIG_PREEMPT
255258 #define S_PREEMPT " PREEMPT"
259
+#elif defined(CONFIG_PREEMPT_RT)
260
+#define S_PREEMPT " PREEMPT_RT"
256261 #else
257262 #define S_PREEMPT ""
258263 #endif
....@@ -289,7 +294,7 @@
289294 if (!user_mode(regs) || in_interrupt()) {
290295 dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
291296 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
292
- dump_backtrace(regs, tsk);
297
+ dump_backtrace(regs, tsk, KERN_EMERG);
293298 dump_instr(KERN_EMERG, regs);
294299 }
295300
....@@ -343,7 +348,7 @@
343348 if (panic_on_oops)
344349 panic("Fatal exception");
345350 if (signr)
346
- do_exit(signr);
351
+ make_task_dead(signr);
347352 }
348353
349354 /*
....@@ -367,13 +372,14 @@
367372 }
368373
369374 void arm_notify_die(const char *str, struct pt_regs *regs,
370
- struct siginfo *info, unsigned long err, unsigned long trap)
375
+ int signo, int si_code, void __user *addr,
376
+ unsigned long err, unsigned long trap)
371377 {
372378 if (user_mode(regs)) {
373379 current->thread.error_code = err;
374380 current->thread.trap_no = trap;
375381
376
- force_sig_info(info->si_signo, info, current);
382
+ force_sig_fault(signo, si_code, addr);
377383 } else {
378384 die(str, regs, err);
379385 }
....@@ -391,7 +397,7 @@
391397 u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);
392398 #endif
393399
394
- if (probe_kernel_address((unsigned *)pc, bkpt))
400
+ if (get_kernel_nofault(bkpt, (void *)pc))
395401 return 0;
396402
397403 return bkpt == insn;
....@@ -440,10 +446,8 @@
440446 asmlinkage void do_undefinstr(struct pt_regs *regs)
441447 {
442448 unsigned int instr;
443
- siginfo_t info;
444449 void __user *pc;
445450
446
- clear_siginfo(&info);
447451 pc = (void __user *)instruction_pointer(regs);
448452
449453 if (processor_mode(regs) == SVC_MODE) {
....@@ -487,13 +491,8 @@
487491 dump_instr(KERN_INFO, regs);
488492 }
489493 #endif
490
-
491
- info.si_signo = SIGILL;
492
- info.si_errno = 0;
493
- info.si_code = ILL_ILLOPC;
494
- info.si_addr = pc;
495
-
496
- arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
494
+ arm_notify_die("Oops - undefined instruction", regs,
495
+ SIGILL, ILL_ILLOPC, pc, 0, 6);
497496 }
498497 NOKPROBE_SYMBOL(do_undefinstr)
499498
....@@ -541,9 +540,6 @@
541540
542541 static int bad_syscall(int n, struct pt_regs *regs)
543542 {
544
- siginfo_t info;
545
-
546
- clear_siginfo(&info);
547543 if ((current->personality & PER_MASK) != PER_LINUX) {
548544 send_sig(SIGSEGV, current, 1);
549545 return regs->ARM_r0;
....@@ -557,13 +553,10 @@
557553 }
558554 #endif
559555
560
- info.si_signo = SIGILL;
561
- info.si_errno = 0;
562
- info.si_code = ILL_ILLTRP;
563
- info.si_addr = (void __user *)instruction_pointer(regs) -
564
- (thumb_mode(regs) ? 2 : 4);
565
-
566
- arm_notify_die("Oops - bad syscall", regs, &info, n, 0);
556
+ arm_notify_die("Oops - bad syscall", regs, SIGILL, ILL_ILLTRP,
557
+ (void __user *)instruction_pointer(regs) -
558
+ (thumb_mode(regs) ? 2 : 4),
559
+ n, 0);
567560
568561 return regs->ARM_r0;
569562 }
....@@ -579,7 +572,7 @@
579572 if (fatal_signal_pending(current))
580573 return 0;
581574
582
- ret = flush_cache_user_range(start, start + chunk);
575
+ ret = flush_icache_user_range(start, start + chunk);
583576 if (ret)
584577 return ret;
585578
....@@ -596,7 +589,7 @@
596589 if (end < start || flags)
597590 return -EINVAL;
598591
599
- if (!access_ok(VERIFY_READ, start, end - start))
592
+ if (!access_ok((void __user *)start, end - start))
600593 return -EFAULT;
601594
602595 return __do_cache_op(start, end);
....@@ -609,25 +602,18 @@
609602 #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE)
610603 asmlinkage int arm_syscall(int no, struct pt_regs *regs)
611604 {
612
- siginfo_t info;
613
-
614
- clear_siginfo(&info);
615605 if ((no >> 16) != (__ARM_NR_BASE>> 16))
616606 return bad_syscall(no, regs);
617607
618608 switch (no & 0xffff) {
619609 case 0: /* branch through 0 */
620
- info.si_signo = SIGSEGV;
621
- info.si_errno = 0;
622
- info.si_code = SEGV_MAPERR;
623
- info.si_addr = NULL;
624
-
625
- arm_notify_die("branch through zero", regs, &info, 0, 0);
610
+ arm_notify_die("branch through zero", regs,
611
+ SIGSEGV, SEGV_MAPERR, NULL, 0, 0);
626612 return 0;
627613
628614 case NR(breakpoint): /* SWI BREAK_POINT */
629615 regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
630
- ptrace_break(current, regs);
616
+ ptrace_break(regs);
631617 return regs->ARM_r0;
632618
633619 /*
....@@ -683,20 +669,17 @@
683669 if (user_debug & UDBG_SYSCALL) {
684670 pr_err("[%d] %s: arm syscall %d\n",
685671 task_pid_nr(current), current->comm, no);
686
- dump_instr("", regs);
672
+ dump_instr(KERN_ERR, regs);
687673 if (user_mode(regs)) {
688674 __show_regs(regs);
689
- c_backtrace(frame_pointer(regs), processor_mode(regs));
675
+ c_backtrace(frame_pointer(regs), processor_mode(regs), KERN_ERR);
690676 }
691677 }
692678 #endif
693
- info.si_signo = SIGILL;
694
- info.si_errno = 0;
695
- info.si_code = ILL_ILLTRP;
696
- info.si_addr = (void __user *)instruction_pointer(regs) -
697
- (thumb_mode(regs) ? 2 : 4);
698
-
699
- arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0);
679
+ arm_notify_die("Oops - bad syscall(2)", regs, SIGILL, ILL_ILLTRP,
680
+ (void __user *)instruction_pointer(regs) -
681
+ (thumb_mode(regs) ? 2 : 4),
682
+ no, 0);
700683 return 0;
701684 }
702685
....@@ -746,25 +729,19 @@
746729 baddataabort(int code, unsigned long instr, struct pt_regs *regs)
747730 {
748731 unsigned long addr = instruction_pointer(regs);
749
- siginfo_t info;
750
-
751
- clear_siginfo(&info);
752732
753733 #ifdef CONFIG_DEBUG_USER
754734 if (user_debug & UDBG_BADABORT) {
735
+ pr_err("8<--- cut here ---\n");
755736 pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n",
756737 task_pid_nr(current), current->comm, code, instr);
757738 dump_instr(KERN_ERR, regs);
758
- show_pte(current->mm, addr);
739
+ show_pte(KERN_ERR, current->mm, addr);
759740 }
760741 #endif
761742
762
- info.si_signo = SIGILL;
763
- info.si_errno = 0;
764
- info.si_code = ILL_ILLOPC;
765
- info.si_addr = (void __user *)addr;
766
-
767
- arm_notify_die("unknown data abort code", regs, &info, instr, 0);
743
+ arm_notify_die("unknown data abort code", regs,
744
+ SIGILL, ILL_ILLOPC, (void __user *)addr, instr, 0);
768745 }
769746
770747 void __readwrite_bug(const char *fn)
....@@ -830,10 +807,59 @@
830807 }
831808 #endif
832809
810
+#ifndef CONFIG_CPU_V7M
811
+static void copy_from_lma(void *vma, void *lma_start, void *lma_end)
812
+{
813
+ memcpy(vma, lma_start, lma_end - lma_start);
814
+}
815
+
816
+static void flush_vectors(void *vma, size_t offset, size_t size)
817
+{
818
+ unsigned long start = (unsigned long)vma + offset;
819
+ unsigned long end = start + size;
820
+
821
+ flush_icache_range(start, end);
822
+}
823
+
824
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
825
+int spectre_bhb_update_vectors(unsigned int method)
826
+{
827
+ extern char __vectors_bhb_bpiall_start[], __vectors_bhb_bpiall_end[];
828
+ extern char __vectors_bhb_loop8_start[], __vectors_bhb_loop8_end[];
829
+ void *vec_start, *vec_end;
830
+
831
+ if (system_state > SYSTEM_SCHEDULING) {
832
+ pr_err("CPU%u: Spectre BHB workaround too late - system vulnerable\n",
833
+ smp_processor_id());
834
+ return SPECTRE_VULNERABLE;
835
+ }
836
+
837
+ switch (method) {
838
+ case SPECTRE_V2_METHOD_LOOP8:
839
+ vec_start = __vectors_bhb_loop8_start;
840
+ vec_end = __vectors_bhb_loop8_end;
841
+ break;
842
+
843
+ case SPECTRE_V2_METHOD_BPIALL:
844
+ vec_start = __vectors_bhb_bpiall_start;
845
+ vec_end = __vectors_bhb_bpiall_end;
846
+ break;
847
+
848
+ default:
849
+ pr_err("CPU%u: unknown Spectre BHB state %d\n",
850
+ smp_processor_id(), method);
851
+ return SPECTRE_VULNERABLE;
852
+ }
853
+
854
+ copy_from_lma(vectors_page, vec_start, vec_end);
855
+ flush_vectors(vectors_page, 0, vec_end - vec_start);
856
+
857
+ return SPECTRE_MITIGATED;
858
+}
859
+#endif
860
+
833861 void __init early_trap_init(void *vectors_base)
834862 {
835
-#ifndef CONFIG_CPU_V7M
836
- unsigned long vectors = (unsigned long)vectors_base;
837863 extern char __stubs_start[], __stubs_end[];
838864 extern char __vectors_start[], __vectors_end[];
839865 unsigned i;
....@@ -854,17 +880,20 @@
854880 * into the vector page, mapped at 0xffff0000, and ensure these
855881 * are visible to the instruction stream.
856882 */
857
- memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
858
- memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
883
+ copy_from_lma(vectors_base, __vectors_start, __vectors_end);
884
+ copy_from_lma(vectors_base + 0x1000, __stubs_start, __stubs_end);
859885
860886 kuser_init(vectors_base);
861887
862
- flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
888
+ flush_vectors(vectors_base, 0, PAGE_SIZE * 2);
889
+}
863890 #else /* ifndef CONFIG_CPU_V7M */
891
+void __init early_trap_init(void *vectors_base)
892
+{
864893 /*
865894 * on V7-M there is no need to copy the vector table to a dedicated
866895 * memory area. The address is configurable and so a table in the kernel
867896 * image can be used.
868897 */
869
-#endif
870898 }
899
+#endif