forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/powerpc/xmon/xmon.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Routines providing a simple monitor for use on the PowerMac.
34 *
45 * Copyright (C) 1996-2005 Paul Mackerras.
56 * Copyright (C) 2001 PPC64 Team, IBM Corp
67 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
7
- *
8
- * This program is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License
10
- * as published by the Free Software Foundation; either version
11
- * 2 of the License, or (at your option) any later version.
128 */
139
1410 #include <linux/kernel.h>
....@@ -29,6 +25,7 @@
2925 #include <linux/nmi.h>
3026 #include <linux/ctype.h>
3127 #include <linux/highmem.h>
28
+#include <linux/security.h>
3229
3330 #include <asm/debugfs.h>
3431 #include <asm/ptrace.h>
....@@ -38,7 +35,6 @@
3835 #include <asm/machdep.h>
3936 #include <asm/xmon.h>
4037 #include <asm/processor.h>
41
-#include <asm/pgtable.h>
4238 #include <asm/mmu.h>
4339 #include <asm/mmu_context.h>
4440 #include <asm/plpar_wrappers.h>
....@@ -57,14 +53,17 @@
5753 #include <asm/firmware.h>
5854 #include <asm/code-patching.h>
5955 #include <asm/sections.h>
56
+#include <asm/inst.h>
6057
6158 #ifdef CONFIG_PPC64
6259 #include <asm/hvcall.h>
6360 #include <asm/paca.h>
61
+#include <asm/lppaca.h>
6462 #endif
6563
6664 #include "nonstdio.h"
6765 #include "dis-asm.h"
66
+#include "xmon_bpts.h"
6867
6968 #ifdef CONFIG_SMP
7069 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
....@@ -80,11 +79,13 @@
8079 #endif
8180 static unsigned long in_xmon __read_mostly = 0;
8281 static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
82
+static bool xmon_is_ro = IS_ENABLED(CONFIG_XMON_DEFAULT_RO_MODE);
8383
8484 static unsigned long adrs;
8585 static int size = 1;
86
-#define MAX_DUMP (128 * 1024)
86
+#define MAX_DUMP (64 * 1024)
8787 static unsigned long ndump = 64;
88
+#define MAX_IDUMP (MAX_DUMP >> 2)
8889 static unsigned long nidump = 16;
8990 static unsigned long ncsum = 4096;
9091 static int termch;
....@@ -99,7 +100,7 @@
99100 /* Breakpoint stuff */
100101 struct bpt {
101102 unsigned long address;
102
- unsigned int instr[2];
103
+ struct ppc_inst *instr;
103104 atomic_t ref_count;
104105 int enabled;
105106 unsigned long pad;
....@@ -110,9 +111,8 @@
110111 #define BP_TRAP 2
111112 #define BP_DABR 4
112113
113
-#define NBPTS 256
114114 static struct bpt bpts[NBPTS];
115
-static struct bpt dabr;
115
+static struct bpt dabr[HBP_NUM_MAX];
116116 static struct bpt *iabr;
117117 static unsigned bpinstr = 0x7fe00008; /* trap */
118118
....@@ -122,6 +122,7 @@
122122 static int cmds(struct pt_regs *);
123123 static int mread(unsigned long, void *, int);
124124 static int mwrite(unsigned long, void *, int);
125
+static int mread_instr(unsigned long, struct ppc_inst *);
125126 static int handle_fault(struct pt_regs *);
126127 static void byterev(unsigned char *, int);
127128 static void memex(void);
....@@ -190,6 +191,8 @@
190191 static void dump_tlb_book3e(void);
191192 #endif
192193
194
+static void clear_all_bpt(void);
195
+
193196 #ifdef CONFIG_PPC64
194197 #define REG "%.16lx"
195198 #else
....@@ -201,6 +204,8 @@
201204 #else
202205 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
203206 #endif
207
+
208
+static const char *xmon_ro_msg = "Operation disabled: xmon in read-only mode\n";
204209
205210 static char *help_string = "\
206211 Commands:\n\
....@@ -276,7 +281,7 @@
276281 X exit monitor and don't recover\n"
277282 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
278283 " u dump segment table or SLB\n"
279
-#elif defined(CONFIG_PPC_STD_MMU_32)
284
+#elif defined(CONFIG_PPC_BOOK3S_32)
280285 " u dump segment registers\n"
281286 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
282287 " u dump TLB\n"
....@@ -284,20 +289,43 @@
284289 " U show uptime information\n"
285290 " ? help\n"
286291 " # n limit output to n lines per page (for dp, dpa, dl)\n"
287
-" zr reboot\n\
288
- zh halt\n"
292
+" zr reboot\n"
293
+" zh halt\n"
289294 ;
295
+
296
+#ifdef CONFIG_SECURITY
297
+static bool xmon_is_locked_down(void)
298
+{
299
+ static bool lockdown;
300
+
301
+ if (!lockdown) {
302
+ lockdown = !!security_locked_down(LOCKDOWN_XMON_RW);
303
+ if (lockdown) {
304
+ printf("xmon: Disabled due to kernel lockdown\n");
305
+ xmon_is_ro = true;
306
+ }
307
+ }
308
+
309
+ if (!xmon_is_ro) {
310
+ xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR);
311
+ if (xmon_is_ro)
312
+ printf("xmon: Read-only due to kernel lockdown\n");
313
+ }
314
+
315
+ return lockdown;
316
+}
317
+#else /* CONFIG_SECURITY */
318
+static inline bool xmon_is_locked_down(void)
319
+{
320
+ return false;
321
+}
322
+#endif
290323
291324 static struct pt_regs *xmon_regs;
292325
293326 static inline void sync(void)
294327 {
295328 asm volatile("sync; isync");
296
-}
297
-
298
-static inline void store_inst(void *p)
299
-{
300
- asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
301329 }
302330
303331 static inline void cflush(void *p)
....@@ -439,7 +467,10 @@
439467
440468 return false;
441469 }
442
-#endif /* CONFIG_SMP */
470
+#else /* CONFIG_SMP */
471
+static inline void get_output_lock(void) {}
472
+static inline void release_output_lock(void) {}
473
+#endif
443474
444475 static inline int unrecoverable_excp(struct pt_regs *regs)
445476 {
....@@ -451,11 +482,19 @@
451482 #endif
452483 }
453484
485
+static void xmon_touch_watchdogs(void)
486
+{
487
+ touch_softlockup_watchdog_sync();
488
+ rcu_cpu_stall_reset();
489
+ touch_nmi_watchdog();
490
+}
491
+
454492 static int xmon_core(struct pt_regs *regs, int fromipi)
455493 {
456494 int cmd = 0;
457495 struct bpt *bp;
458496 long recurse_jmp[JMP_BUF_LEN];
497
+ bool locked_down;
459498 unsigned long offset;
460499 unsigned long flags;
461500 #ifdef CONFIG_SMP
....@@ -465,6 +504,8 @@
465504
466505 local_irq_save(flags);
467506 hard_irq_disable();
507
+
508
+ locked_down = xmon_is_locked_down();
468509
469510 if (!fromipi) {
470511 tracing_enabled = tracing_is_on();
....@@ -519,7 +560,8 @@
519560
520561 if (!fromipi) {
521562 get_output_lock();
522
- excprint(regs);
563
+ if (!locked_down)
564
+ excprint(regs);
523565 if (bp) {
524566 printf("cpu 0x%x stopped at breakpoint 0x%tx (",
525567 cpu, BP_NUM(bp));
....@@ -571,10 +613,14 @@
571613 }
572614 remove_bpts();
573615 disable_surveillance();
574
- /* for breakpoint or single step, print the current instr. */
575
- if (bp || TRAP(regs) == 0xd00)
576
- ppc_inst_dump(regs->nip, 1, 0);
577
- printf("enter ? for help\n");
616
+
617
+ if (!locked_down) {
618
+ /* for breakpoint or single step, print curr insn */
619
+ if (bp || TRAP(regs) == 0xd00)
620
+ ppc_inst_dump(regs->nip, 1, 0);
621
+ printf("enter ? for help\n");
622
+ }
623
+
578624 mb();
579625 xmon_gate = 1;
580626 barrier();
....@@ -598,8 +644,9 @@
598644 spin_cpu_relax();
599645 touch_nmi_watchdog();
600646 } else {
601
- cmd = cmds(regs);
602
- if (cmd != 0) {
647
+ if (!locked_down)
648
+ cmd = cmds(regs);
649
+ if (locked_down || cmd != 0) {
603650 /* exiting xmon */
604651 insert_bpts();
605652 xmon_gate = 0;
....@@ -636,13 +683,16 @@
636683 "can't continue\n");
637684 remove_bpts();
638685 disable_surveillance();
639
- /* for breakpoint or single step, print the current instr. */
640
- if (bp || TRAP(regs) == 0xd00)
641
- ppc_inst_dump(regs->nip, 1, 0);
642
- printf("enter ? for help\n");
686
+ if (!locked_down) {
687
+ /* for breakpoint or single step, print current insn */
688
+ if (bp || TRAP(regs) == 0xd00)
689
+ ppc_inst_dump(regs->nip, 1, 0);
690
+ printf("enter ? for help\n");
691
+ }
643692 }
644693
645
- cmd = cmds(regs);
694
+ if (!locked_down)
695
+ cmd = cmds(regs);
646696
647697 insert_bpts();
648698 in_xmon = 0;
....@@ -660,20 +710,23 @@
660710 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
661711 bp = at_breakpoint(regs->nip);
662712 if (bp != NULL) {
663
- int stepped = emulate_step(regs, bp->instr[0]);
713
+ int stepped = emulate_step(regs, ppc_inst_read(bp->instr));
664714 if (stepped == 0) {
665715 regs->nip = (unsigned long) &bp->instr[0];
666716 atomic_inc(&bp->ref_count);
667717 } else if (stepped < 0) {
668718 printf("Couldn't single-step %s instruction\n",
669
- (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
719
+ IS_RFID(ppc_inst_read(bp->instr))? "rfid": "mtmsrd");
670720 }
671721 }
672722 }
673723 #endif
674
- insert_cpu_bpts();
724
+ if (locked_down)
725
+ clear_all_bpt();
726
+ else
727
+ insert_cpu_bpts();
675728
676
- touch_nmi_watchdog();
729
+ xmon_touch_watchdogs();
677730 local_irq_restore(flags);
678731
679732 return cmd != 'X' && cmd != EOF;
....@@ -712,8 +765,8 @@
712765
713766 /* Are we at the trap at bp->instr[1] for some bp? */
714767 bp = in_breakpoint_table(regs->nip, &offset);
715
- if (bp != NULL && offset == 4) {
716
- regs->nip = bp->address + 4;
768
+ if (bp != NULL && (offset == 4 || offset == 8)) {
769
+ regs->nip = bp->address + offset;
717770 atomic_dec(&bp->ref_count);
718771 return 1;
719772 }
....@@ -738,10 +791,17 @@
738791
739792 static int xmon_break_match(struct pt_regs *regs)
740793 {
794
+ int i;
795
+
741796 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
742797 return 0;
743
- if (dabr.enabled == 0)
744
- return 0;
798
+ for (i = 0; i < nr_wp_slots(); i++) {
799
+ if (dabr[i].enabled)
800
+ goto found;
801
+ }
802
+ return 0;
803
+
804
+found:
745805 xmon_core(regs, 0);
746806 return 1;
747807 }
....@@ -810,15 +870,13 @@
810870 {
811871 unsigned long off;
812872
813
- off = nip - (unsigned long) bpts;
814
- if (off >= sizeof(bpts))
873
+ off = nip - (unsigned long)bpt_table;
874
+ if (off >= sizeof(bpt_table))
815875 return NULL;
816
- off %= sizeof(struct bpt);
817
- if (off != offsetof(struct bpt, instr[0])
818
- && off != offsetof(struct bpt, instr[1]))
876
+ *offp = off & (BPT_SIZE - 1);
877
+ if (off & 3)
819878 return NULL;
820
- *offp = off - offsetof(struct bpt, instr[0]);
821
- return (struct bpt *) (nip - off);
879
+ return bpts + (off / BPT_SIZE);
822880 }
823881
824882 static struct bpt *new_breakpoint(unsigned long a)
....@@ -833,8 +891,7 @@
833891 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
834892 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
835893 bp->address = a;
836
- bp->instr[1] = bpinstr;
837
- store_inst(&bp->instr[1]);
894
+ bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS));
838895 return bp;
839896 }
840897 }
....@@ -846,47 +903,76 @@
846903 static void insert_bpts(void)
847904 {
848905 int i;
849
- struct bpt *bp;
906
+ struct ppc_inst instr, instr2;
907
+ struct bpt *bp, *bp2;
850908
851909 bp = bpts;
852910 for (i = 0; i < NBPTS; ++i, ++bp) {
853911 if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
854912 continue;
855
- if (mread(bp->address, &bp->instr[0], 4) != 4) {
913
+ if (!mread_instr(bp->address, &instr)) {
856914 printf("Couldn't read instruction at %lx, "
857915 "disabling breakpoint there\n", bp->address);
858916 bp->enabled = 0;
859917 continue;
860918 }
861
- if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
919
+ if (IS_MTMSRD(instr) || IS_RFID(instr)) {
862920 printf("Breakpoint at %lx is on an mtmsrd or rfid "
863921 "instruction, disabling it\n", bp->address);
864922 bp->enabled = 0;
865923 continue;
866924 }
867
- store_inst(&bp->instr[0]);
925
+ /*
926
+ * Check the address is not a suffix by looking for a prefix in
927
+ * front of it.
928
+ */
929
+ if (mread_instr(bp->address - 4, &instr2) == 8) {
930
+ printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n",
931
+ bp->address);
932
+ bp->enabled = 0;
933
+ continue;
934
+ }
935
+ /*
936
+ * We might still be a suffix - if the prefix has already been
937
+ * replaced by a breakpoint we won't catch it with the above
938
+ * test.
939
+ */
940
+ bp2 = at_breakpoint(bp->address - 4);
941
+ if (bp2 && ppc_inst_prefixed(ppc_inst_read(bp2->instr))) {
942
+ printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n",
943
+ bp->address);
944
+ bp->enabled = 0;
945
+ continue;
946
+ }
947
+
948
+ patch_instruction(bp->instr, instr);
949
+ patch_instruction(ppc_inst_next(bp->instr, &instr),
950
+ ppc_inst(bpinstr));
868951 if (bp->enabled & BP_CIABR)
869952 continue;
870
- if (patch_instruction((unsigned int *)bp->address,
871
- bpinstr) != 0) {
953
+ if (patch_instruction((struct ppc_inst *)bp->address,
954
+ ppc_inst(bpinstr)) != 0) {
872955 printf("Couldn't write instruction at %lx, "
873956 "disabling breakpoint there\n", bp->address);
874957 bp->enabled &= ~BP_TRAP;
875958 continue;
876959 }
877
- store_inst((void *)bp->address);
878960 }
879961 }
880962
881963 static void insert_cpu_bpts(void)
882964 {
965
+ int i;
883966 struct arch_hw_breakpoint brk;
884967
885
- if (dabr.enabled) {
886
- brk.address = dabr.address;
887
- brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
888
- brk.len = 8;
889
- __set_breakpoint(&brk);
968
+ for (i = 0; i < nr_wp_slots(); i++) {
969
+ if (dabr[i].enabled) {
970
+ brk.address = dabr[i].address;
971
+ brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
972
+ brk.len = 8;
973
+ brk.hw_len = 8;
974
+ __set_breakpoint(i, &brk);
975
+ }
890976 }
891977
892978 if (iabr)
....@@ -897,20 +983,18 @@
897983 {
898984 int i;
899985 struct bpt *bp;
900
- unsigned instr;
986
+ struct ppc_inst instr;
901987
902988 bp = bpts;
903989 for (i = 0; i < NBPTS; ++i, ++bp) {
904990 if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
905991 continue;
906
- if (mread(bp->address, &instr, 4) == 4
907
- && instr == bpinstr
992
+ if (mread_instr(bp->address, &instr)
993
+ && ppc_inst_equal(instr, ppc_inst(bpinstr))
908994 && patch_instruction(
909
- (unsigned int *)bp->address, bp->instr[0]) != 0)
995
+ (struct ppc_inst *)bp->address, ppc_inst_read(bp->instr)) != 0)
910996 printf("Couldn't remove breakpoint at %lx\n",
911997 bp->address);
912
- else
913
- store_inst((void *)bp->address);
914998 }
915999 }
9161000
....@@ -991,6 +1075,10 @@
9911075 memlocate();
9921076 break;
9931077 case 'z':
1078
+ if (xmon_is_ro) {
1079
+ printf(xmon_ro_msg);
1080
+ break;
1081
+ }
9941082 memzcan();
9951083 break;
9961084 case 'i':
....@@ -1057,12 +1145,16 @@
10571145 bootcmds();
10581146 break;
10591147 case 'p':
1148
+ if (xmon_is_ro) {
1149
+ printf(xmon_ro_msg);
1150
+ break;
1151
+ }
10601152 proccall();
10611153 break;
10621154 case 'P':
10631155 show_tasks();
10641156 break;
1065
-#ifdef CONFIG_PPC_STD_MMU
1157
+#ifdef CONFIG_PPC_BOOK3S
10661158 case 'u':
10671159 dump_segments();
10681160 break;
....@@ -1107,13 +1199,13 @@
11071199 */
11081200 static int do_step(struct pt_regs *regs)
11091201 {
1110
- unsigned int instr;
1202
+ struct ppc_inst instr;
11111203 int stepped;
11121204
11131205 force_enable_xmon();
11141206 /* check we are in 64-bit kernel mode, translation enabled */
11151207 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
1116
- if (mread(regs->nip, &instr, 4) == 4) {
1208
+ if (mread_instr(regs->nip, &instr)) {
11171209 stepped = emulate_step(regs, instr);
11181210 if (stepped < 0) {
11191211 printf("Couldn't single-step %s instruction\n",
....@@ -1121,7 +1213,7 @@
11211213 return 0;
11221214 }
11231215 if (stepped > 0) {
1124
- regs->trap = 0xd00 | (regs->trap & 1);
1216
+ set_trap(regs, 0xd00);
11251217 printf("stepped to ");
11261218 xmon_print_symbol(regs->nip, " ", "\n");
11271219 ppc_inst_dump(regs->nip, 1, 0);
....@@ -1136,16 +1228,19 @@
11361228
11371229 static void bootcmds(void)
11381230 {
1231
+ char tmp[64];
11391232 int cmd;
11401233
11411234 cmd = inchar();
1142
- if (cmd == 'r')
1143
- ppc_md.restart(NULL);
1144
- else if (cmd == 'h')
1235
+ if (cmd == 'r') {
1236
+ getstring(tmp, 64);
1237
+ ppc_md.restart(tmp);
1238
+ } else if (cmd == 'h') {
11451239 ppc_md.halt();
1146
- else if (cmd == 'p')
1240
+ } else if (cmd == 'p') {
11471241 if (pm_power_off)
11481242 pm_power_off();
1243
+ }
11491244 }
11501245
11511246 static int cpu_cmd(void)
....@@ -1270,14 +1365,14 @@
12701365 */
12711366 static long check_bp_loc(unsigned long addr)
12721367 {
1273
- unsigned int instr;
1368
+ struct ppc_inst instr;
12741369
12751370 addr &= ~3;
12761371 if (!is_kernel_addr(addr)) {
12771372 printf("Breakpoints may only be placed at kernel addresses\n");
12781373 return 0;
12791374 }
1280
- if (!mread(addr, &instr, sizeof(instr))) {
1375
+ if (!mread_instr(addr, &instr)) {
12811376 printf("Can't read instruction at address %lx\n", addr);
12821377 return 0;
12831378 }
....@@ -1287,6 +1382,35 @@
12871382 return 0;
12881383 }
12891384 return 1;
1385
+}
1386
+
1387
+static int find_free_data_bpt(void)
1388
+{
1389
+ int i;
1390
+
1391
+ for (i = 0; i < nr_wp_slots(); i++) {
1392
+ if (!dabr[i].enabled)
1393
+ return i;
1394
+ }
1395
+ printf("Couldn't find free breakpoint register\n");
1396
+ return -1;
1397
+}
1398
+
1399
+static void print_data_bpts(void)
1400
+{
1401
+ int i;
1402
+
1403
+ for (i = 0; i < nr_wp_slots(); i++) {
1404
+ if (!dabr[i].enabled)
1405
+ continue;
1406
+
1407
+ printf(" data "REG" [", dabr[i].address);
1408
+ if (dabr[i].enabled & 1)
1409
+ printf("r");
1410
+ if (dabr[i].enabled & 2)
1411
+ printf("w");
1412
+ printf("]\n");
1413
+ }
12901414 }
12911415
12921416 static char *breakpoint_help_string =
....@@ -1308,15 +1432,22 @@
13081432 struct bpt *bp;
13091433
13101434 cmd = inchar();
1435
+
13111436 switch (cmd) {
1312
-#ifndef CONFIG_PPC_8xx
1313
- static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
1314
- int mode;
1315
- case 'd': /* bd - hardware data breakpoint */
1437
+ case 'd': { /* bd - hardware data breakpoint */
1438
+ static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
1439
+ int mode;
1440
+ if (xmon_is_ro) {
1441
+ printf(xmon_ro_msg);
1442
+ break;
1443
+ }
13161444 if (!ppc_breakpoint_available()) {
13171445 printf("Hardware data breakpoint not supported on this cpu\n");
13181446 break;
13191447 }
1448
+ i = find_free_data_bpt();
1449
+ if (i < 0)
1450
+ break;
13201451 mode = 7;
13211452 cmd = inchar();
13221453 if (cmd == 'r')
....@@ -1325,21 +1456,26 @@
13251456 mode = 6;
13261457 else
13271458 termch = cmd;
1328
- dabr.address = 0;
1329
- dabr.enabled = 0;
1330
- if (scanhex(&dabr.address)) {
1331
- if (!is_kernel_addr(dabr.address)) {
1459
+ dabr[i].address = 0;
1460
+ dabr[i].enabled = 0;
1461
+ if (scanhex(&dabr[i].address)) {
1462
+ if (!is_kernel_addr(dabr[i].address)) {
13321463 printf(badaddr);
13331464 break;
13341465 }
1335
- dabr.address &= ~HW_BRK_TYPE_DABR;
1336
- dabr.enabled = mode | BP_DABR;
1466
+ dabr[i].address &= ~HW_BRK_TYPE_DABR;
1467
+ dabr[i].enabled = mode | BP_DABR;
13371468 }
13381469
13391470 force_enable_xmon();
13401471 break;
1472
+ }
13411473
13421474 case 'i': /* bi - hardware instr breakpoint */
1475
+ if (xmon_is_ro) {
1476
+ printf(xmon_ro_msg);
1477
+ break;
1478
+ }
13431479 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
13441480 printf("Hardware instruction breakpoint "
13451481 "not supported on this cpu\n");
....@@ -1360,7 +1496,6 @@
13601496 force_enable_xmon();
13611497 }
13621498 break;
1363
-#endif
13641499
13651500 case 'c':
13661501 if (!scanhex(&a)) {
....@@ -1368,7 +1503,9 @@
13681503 for (i = 0; i < NBPTS; ++i)
13691504 bpts[i].enabled = 0;
13701505 iabr = NULL;
1371
- dabr.enabled = 0;
1506
+ for (i = 0; i < nr_wp_slots(); i++)
1507
+ dabr[i].enabled = 0;
1508
+
13721509 printf("All breakpoints cleared\n");
13731510 break;
13741511 }
....@@ -1398,17 +1535,11 @@
13981535 break;
13991536 }
14001537 termch = cmd;
1401
- if (!scanhex(&a)) {
1538
+
1539
+ if (xmon_is_ro || !scanhex(&a)) {
14021540 /* print all breakpoints */
14031541 printf(" type address\n");
1404
- if (dabr.enabled) {
1405
- printf(" data "REG" [", dabr.address);
1406
- if (dabr.enabled & 1)
1407
- printf("r");
1408
- if (dabr.enabled & 2)
1409
- printf("w");
1410
- printf("]\n");
1411
- }
1542
+ print_data_bpts();
14121543 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
14131544 if (!bp->enabled)
14141545 continue;
....@@ -1470,6 +1601,7 @@
14701601 case 0x1300: ret = "(Instruction Breakpoint)"; break;
14711602 case 0x1500: ret = "(Denormalisation)"; break;
14721603 case 0x1700: ret = "(Altivec Assist)"; break;
1604
+ case 0x3000: ret = "(System Call Vectored)"; break;
14731605 default: ret = "";
14741606 }
14751607 return ret;
....@@ -1706,7 +1838,7 @@
17061838 #endif
17071839 printf("pc = ");
17081840 xmon_print_symbol(fp->nip, " ", "\n");
1709
- if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1841
+ if (!trap_is_syscall(fp) && cpu_has_feature(CPU_FTR_CFAR)) {
17101842 printf("cfar= ");
17111843 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
17121844 }
....@@ -1738,7 +1870,7 @@
17381870 catch_memory_errors = 1;
17391871 sync();
17401872
1741
- if (cmd != 'i') {
1873
+ if (cmd != 'i' || IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
17421874 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
17431875 cflush((void *) adrs);
17441876 } else {
....@@ -1779,6 +1911,11 @@
17791911 static void
17801912 write_spr(int n, unsigned long val)
17811913 {
1914
+ if (xmon_is_ro) {
1915
+ printf(xmon_ro_msg);
1916
+ return;
1917
+ }
1918
+
17821919 if (setjmp(bus_error_jmp) == 0) {
17831920 catch_spr_faults = 1;
17841921 sync();
....@@ -1863,8 +2000,13 @@
18632000
18642001 printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
18652002 mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
1866
- printf("dawr = %.16lx dawrx = %.16lx ciabr = %.16lx\n",
1867
- mfspr(SPRN_DAWR), mfspr(SPRN_DAWRX), mfspr(SPRN_CIABR));
2003
+ printf("dawr0 = %.16lx dawrx0 = %.16lx\n",
2004
+ mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0));
2005
+ if (nr_wp_slots() > 1) {
2006
+ printf("dawr1 = %.16lx dawrx1 = %.16lx\n",
2007
+ mfspr(SPRN_DAWR1), mfspr(SPRN_DAWRX1));
2008
+ }
2009
+ printf("ciabr = %.16lx\n", mfspr(SPRN_CIABR));
18682010 #endif
18692011 }
18702012
....@@ -1886,6 +2028,18 @@
18862028
18872029 printf("ptcr = %.16lx asdr = %.16lx\n",
18882030 mfspr(SPRN_PTCR), mfspr(SPRN_ASDR));
2031
+#endif
2032
+}
2033
+
2034
+static void dump_310_sprs(void)
2035
+{
2036
+#ifdef CONFIG_PPC64
2037
+ if (!cpu_has_feature(CPU_FTR_ARCH_31))
2038
+ return;
2039
+
2040
+ printf("mmcr3 = %.16lx, sier2 = %.16lx, sier3 = %.16lx\n",
2041
+ mfspr(SPRN_MMCR3), mfspr(SPRN_SIER2), mfspr(SPRN_SIER3));
2042
+
18892043 #endif
18902044 }
18912045
....@@ -1943,6 +2097,7 @@
19432097 dump_206_sprs();
19442098 dump_207_sprs();
19452099 dump_300_sprs();
2100
+ dump_310_sprs();
19462101
19472102 return;
19482103 }
....@@ -2017,6 +2172,12 @@
20172172 char *p, *q;
20182173
20192174 n = 0;
2175
+
2176
+ if (xmon_is_ro) {
2177
+ printf(xmon_ro_msg);
2178
+ return n;
2179
+ }
2180
+
20202181 if (setjmp(bus_error_jmp) == 0) {
20212182 catch_memory_errors = 1;
20222183 sync();
....@@ -2044,6 +2205,25 @@
20442205 n = size;
20452206 } else {
20462207 printf("*** Error writing address "REG"\n", adrs + n);
2208
+ }
2209
+ catch_memory_errors = 0;
2210
+ return n;
2211
+}
2212
+
2213
+static int
2214
+mread_instr(unsigned long adrs, struct ppc_inst *instr)
2215
+{
2216
+ volatile int n;
2217
+
2218
+ n = 0;
2219
+ if (setjmp(bus_error_jmp) == 0) {
2220
+ catch_memory_errors = 1;
2221
+ sync();
2222
+ *instr = ppc_inst_read((struct ppc_inst *)adrs);
2223
+ sync();
2224
+ /* wait a little while to see if we get a machine check */
2225
+ __delay(200);
2226
+ n = ppc_inst_len(*instr);
20472227 }
20482228 catch_memory_errors = 0;
20492229 return n;
....@@ -2381,25 +2561,33 @@
23812561 DUMP(p, cpu_start, "%#-*x");
23822562 DUMP(p, kexec_state, "%#-*x");
23832563 #ifdef CONFIG_PPC_BOOK3S_64
2384
- for (i = 0; i < SLB_NUM_BOLTED; i++) {
2385
- u64 esid, vsid;
2564
+ if (!early_radix_enabled()) {
2565
+ for (i = 0; i < SLB_NUM_BOLTED; i++) {
2566
+ u64 esid, vsid;
23862567
2387
- if (!p->slb_shadow_ptr)
2388
- continue;
2568
+ if (!p->slb_shadow_ptr)
2569
+ continue;
23892570
2390
- esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
2391
- vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
2571
+ esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
2572
+ vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
23922573
2393
- if (esid || vsid) {
2394
- printf(" %-*s[%d] = 0x%016llx 0x%016llx\n",
2395
- 22, "slb_shadow", i, esid, vsid);
2574
+ if (esid || vsid) {
2575
+ printf(" %-*s[%d] = 0x%016llx 0x%016llx\n",
2576
+ 22, "slb_shadow", i, esid, vsid);
2577
+ }
2578
+ }
2579
+ DUMP(p, vmalloc_sllp, "%#-*x");
2580
+ DUMP(p, stab_rr, "%#-*x");
2581
+ DUMP(p, slb_used_bitmap, "%#-*x");
2582
+ DUMP(p, slb_kern_bitmap, "%#-*x");
2583
+
2584
+ if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
2585
+ DUMP(p, slb_cache_ptr, "%#-*x");
2586
+ for (i = 0; i < SLB_CACHE_ENTRIES; i++)
2587
+ printf(" %-*s[%d] = 0x%016x\n",
2588
+ 22, "slb_cache", i, p->slb_cache[i]);
23962589 }
23972590 }
2398
- DUMP(p, vmalloc_sllp, "%#-*x");
2399
- DUMP(p, slb_cache_ptr, "%#-*x");
2400
- for (i = 0; i < SLB_CACHE_ENTRIES; i++)
2401
- printf(" %-*s[%d] = 0x%016x\n",
2402
- 22, "slb_cache", i, p->slb_cache[i]);
24032591
24042592 DUMP(p, rfi_flush_fallback_area, "%-*px");
24052593 #endif
....@@ -2415,14 +2603,20 @@
24152603 DUMP(p, __current, "%-*px");
24162604 DUMP(p, kstack, "%#-*llx");
24172605 printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1));
2418
- DUMP(p, stab_rr, "%#-*llx");
2606
+#ifdef CONFIG_STACKPROTECTOR
2607
+ DUMP(p, canary, "%#-*lx");
2608
+#endif
24192609 DUMP(p, saved_r1, "%#-*llx");
2610
+#ifdef CONFIG_PPC_BOOK3E
24202611 DUMP(p, trap_save, "%#-*x");
2612
+#endif
24212613 DUMP(p, irq_soft_mask, "%#-*x");
24222614 DUMP(p, irq_happened, "%#-*x");
2423
- DUMP(p, io_sync, "%#-*x");
2615
+#ifdef CONFIG_MMIOWB
2616
+ DUMP(p, mmiowb_state.nesting_count, "%#-*x");
2617
+ DUMP(p, mmiowb_state.mmiowb_pending, "%#-*x");
2618
+#endif
24242619 DUMP(p, irq_work_pending, "%#-*x");
2425
- DUMP(p, nap_state_lost, "%#-*x");
24262620 DUMP(p, sprg_vdso, "%#-*llx");
24272621
24282622 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
....@@ -2430,28 +2624,29 @@
24302624 #endif
24312625
24322626 #ifdef CONFIG_PPC_POWERNV
2433
- DUMP(p, core_idle_state_ptr, "%-*px");
2434
- DUMP(p, thread_idle_state, "%#-*x");
2435
- DUMP(p, thread_mask, "%#-*x");
2436
- DUMP(p, subcore_sibling_mask, "%#-*x");
2437
- DUMP(p, requested_psscr, "%#-*llx");
2438
- DUMP(p, stop_sprs.pid, "%#-*llx");
2439
- DUMP(p, stop_sprs.ldbar, "%#-*llx");
2440
- DUMP(p, stop_sprs.fscr, "%#-*llx");
2441
- DUMP(p, stop_sprs.hfscr, "%#-*llx");
2442
- DUMP(p, stop_sprs.mmcr1, "%#-*llx");
2443
- DUMP(p, stop_sprs.mmcr2, "%#-*llx");
2444
- DUMP(p, stop_sprs.mmcra, "%#-*llx");
2445
- DUMP(p, dont_stop.counter, "%#-*x");
2627
+ DUMP(p, idle_state, "%#-*lx");
2628
+ if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
2629
+ DUMP(p, thread_idle_state, "%#-*x");
2630
+ DUMP(p, subcore_sibling_mask, "%#-*x");
2631
+ } else {
2632
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
2633
+ DUMP(p, requested_psscr, "%#-*llx");
2634
+ DUMP(p, dont_stop.counter, "%#-*x");
2635
+#endif
2636
+ }
24462637 #endif
24472638
24482639 DUMP(p, accounting.utime, "%#-*lx");
24492640 DUMP(p, accounting.stime, "%#-*lx");
2641
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
24502642 DUMP(p, accounting.utime_scaled, "%#-*lx");
2643
+#endif
24512644 DUMP(p, accounting.starttime, "%#-*lx");
24522645 DUMP(p, accounting.starttime_user, "%#-*lx");
2646
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
24532647 DUMP(p, accounting.startspurr, "%#-*lx");
24542648 DUMP(p, accounting.utime_sspurr, "%#-*lx");
2649
+#endif
24552650 DUMP(p, accounting.steal_time, "%#-*lx");
24562651 #undef DUMP
24572652
....@@ -2534,16 +2729,28 @@
25342729 dump_one_xive(cpu);
25352730 }
25362731
2537
-static void dump_one_xive_irq(u32 num)
2732
+static void dump_one_xive_irq(u32 num, struct irq_data *d)
25382733 {
2539
- s64 rc;
2540
- __be64 vp;
2541
- u8 prio;
2542
- __be32 lirq;
2734
+ xmon_xive_get_irq_config(num, d);
2735
+}
25432736
2544
- rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq);
2545
- xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n",
2546
- num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc);
2737
+static void dump_all_xive_irq(void)
2738
+{
2739
+ unsigned int i;
2740
+ struct irq_desc *desc;
2741
+
2742
+ for_each_irq_desc(i, desc) {
2743
+ struct irq_data *d = irq_desc_get_irq_data(desc);
2744
+ unsigned int hwirq;
2745
+
2746
+ if (!d)
2747
+ continue;
2748
+
2749
+ hwirq = (unsigned int)irqd_to_hwirq(d);
2750
+ /* IPIs are special (HW number 0) */
2751
+ if (hwirq)
2752
+ dump_one_xive_irq(hwirq, d);
2753
+ }
25472754 }
25482755
25492756 static void dump_xives(void)
....@@ -2562,7 +2769,9 @@
25622769 return;
25632770 } else if (c == 'i') {
25642771 if (scanhex(&num))
2565
- dump_one_xive_irq(num);
2772
+ dump_one_xive_irq(num, NULL);
2773
+ else
2774
+ dump_all_xive_irq();
25662775 return;
25672776 }
25682777
....@@ -2603,7 +2812,12 @@
26032812
26042813 printf("%0*llx", size * 2, val);
26052814 }
2606
- printf("\n");
2815
+ printf(" |");
2816
+ for (j = 0; j < 16; ++j) {
2817
+ val = temp[j];
2818
+ putchar(' ' <= val && val <= '~' ? val : '.');
2819
+ }
2820
+ printf("|\n");
26072821 }
26082822 }
26092823
....@@ -2647,8 +2861,8 @@
26472861 scanhex(&nidump);
26482862 if (nidump == 0)
26492863 nidump = 16;
2650
- else if (nidump > MAX_DUMP)
2651
- nidump = MAX_DUMP;
2864
+ else if (nidump > MAX_IDUMP)
2865
+ nidump = MAX_IDUMP;
26522866 adrs += ppc_inst_dump(adrs, nidump, 1);
26532867 last_cmd = "di\n";
26542868 } else if (c == 'l') {
....@@ -2741,12 +2955,11 @@
27412955 {
27422956 int nr, dotted;
27432957 unsigned long first_adr;
2744
- unsigned int inst, last_inst = 0;
2745
- unsigned char val[4];
2958
+ struct ppc_inst inst, last_inst = ppc_inst(0);
27462959
27472960 dotted = 0;
2748
- for (first_adr = adr; count > 0; --count, adr += 4) {
2749
- nr = mread(adr, val, 4);
2961
+ for (first_adr = adr; count > 0; --count, adr += ppc_inst_len(inst)) {
2962
+ nr = mread_instr(adr, &inst);
27502963 if (nr == 0) {
27512964 if (praddr) {
27522965 const char *x = fault_chars[fault_type];
....@@ -2754,8 +2967,7 @@
27542967 }
27552968 break;
27562969 }
2757
- inst = GETWORD(val);
2758
- if (adr > first_adr && inst == last_inst) {
2970
+ if (adr > first_adr && ppc_inst_equal(inst, last_inst)) {
27592971 if (!dotted) {
27602972 printf(" ...\n");
27612973 dotted = 1;
....@@ -2765,9 +2977,12 @@
27652977 dotted = 0;
27662978 last_inst = inst;
27672979 if (praddr)
2768
- printf(REG" %.8x", adr, inst);
2980
+ printf(REG" %s", adr, ppc_inst_as_str(inst));
27692981 printf("\t");
2770
- dump_func(inst, adr);
2982
+ if (!ppc_inst_prefixed(inst))
2983
+ dump_func(ppc_inst_val(inst), adr);
2984
+ else
2985
+ dump_func(ppc_inst_as_u64(inst), adr);
27712986 printf("\n");
27722987 }
27732988 return adr - first_adr;
....@@ -2785,7 +3000,7 @@
27853000 xmon_print_symbol(addr, "\t# ", "");
27863001 }
27873002
2788
-void
3003
+static void
27893004 dump_log_buf(void)
27903005 {
27913006 struct kmsg_dumper dumper = { .active = 1 };
....@@ -2874,9 +3089,17 @@
28743089 scanhex((void *)&mcount);
28753090 switch( cmd ){
28763091 case 'm':
3092
+ if (xmon_is_ro) {
3093
+ printf(xmon_ro_msg);
3094
+ break;
3095
+ }
28773096 memmove((void *)mdest, (void *)msrc, mcount);
28783097 break;
28793098 case 's':
3099
+ if (xmon_is_ro) {
3100
+ printf(xmon_ro_msg);
3101
+ break;
3102
+ }
28803103 memset((void *)mdest, mval, mcount);
28813104 break;
28823105 case 'd':
....@@ -2984,25 +3207,27 @@
29843207 (tsk->exit_state & EXIT_DEAD) ? 'E' :
29853208 (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
29863209
2987
- printf("%px %016lx %6d %6d %c %2d %s\n", tsk,
2988
- tsk->thread.ksp,
2989
- tsk->pid, tsk->parent->pid,
2990
- state, task_thread_info(tsk)->cpu,
3210
+ printf("%16px %16lx %16px %6d %6d %c %2d %s\n", tsk,
3211
+ tsk->thread.ksp, tsk->thread.regs,
3212
+ tsk->pid, rcu_dereference(tsk->parent)->pid,
3213
+ state, task_cpu(tsk),
29913214 tsk->comm);
29923215 }
29933216
29943217 #ifdef CONFIG_PPC_BOOK3S_64
2995
-void format_pte(void *ptep, unsigned long pte)
3218
+static void format_pte(void *ptep, unsigned long pte)
29963219 {
3220
+ pte_t entry = __pte(pte);
3221
+
29973222 printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);
29983223 printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK);
29993224
30003225 printf("Flags = %s%s%s%s%s\n",
3001
- (pte & _PAGE_ACCESSED) ? "Accessed " : "",
3002
- (pte & _PAGE_DIRTY) ? "Dirty " : "",
3003
- (pte & _PAGE_READ) ? "Read " : "",
3004
- (pte & _PAGE_WRITE) ? "Write " : "",
3005
- (pte & _PAGE_EXEC) ? "Exec " : "");
3226
+ pte_young(entry) ? "Accessed " : "",
3227
+ pte_dirty(entry) ? "Dirty " : "",
3228
+ pte_read(entry) ? "Read " : "",
3229
+ pte_write(entry) ? "Write " : "",
3230
+ pte_exec(entry) ? "Exec " : "");
30063231 }
30073232
30083233 static void show_pte(unsigned long addr)
....@@ -3010,7 +3235,8 @@
30103235 unsigned long tskv = 0;
30113236 struct task_struct *tsk = NULL;
30123237 struct mm_struct *mm;
3013
- pgd_t *pgdp, *pgdir;
3238
+ pgd_t *pgdp;
3239
+ p4d_t *p4dp;
30143240 pud_t *pudp;
30153241 pmd_t *pmdp;
30163242 pte_t *ptep;
....@@ -3034,35 +3260,33 @@
30343260 catch_memory_errors = 1;
30353261 sync();
30363262
3037
- if (mm == &init_mm) {
3263
+ if (mm == &init_mm)
30383264 pgdp = pgd_offset_k(addr);
3039
- pgdir = pgd_offset_k(0);
3040
- } else {
3265
+ else
30413266 pgdp = pgd_offset(mm, addr);
3042
- pgdir = pgd_offset(mm, 0);
3043
- }
30443267
3045
- if (pgd_none(*pgdp)) {
3046
- printf("no linux page table for address\n");
3268
+ p4dp = p4d_offset(pgdp, addr);
3269
+
3270
+ if (p4d_none(*p4dp)) {
3271
+ printf("No valid P4D\n");
30473272 return;
30483273 }
30493274
3050
- printf("pgd @ 0x%px\n", pgdir);
3051
-
3052
- if (pgd_huge(*pgdp)) {
3053
- format_pte(pgdp, pgd_val(*pgdp));
3275
+ if (p4d_is_leaf(*p4dp)) {
3276
+ format_pte(p4dp, p4d_val(*p4dp));
30543277 return;
30553278 }
3056
- printf("pgdp @ 0x%px = 0x%016lx\n", pgdp, pgd_val(*pgdp));
30573279
3058
- pudp = pud_offset(pgdp, addr);
3280
+ printf("p4dp @ 0x%px = 0x%016lx\n", p4dp, p4d_val(*p4dp));
3281
+
3282
+ pudp = pud_offset(p4dp, addr);
30593283
30603284 if (pud_none(*pudp)) {
30613285 printf("No valid PUD\n");
30623286 return;
30633287 }
30643288
3065
- if (pud_huge(*pudp)) {
3289
+ if (pud_is_leaf(*pudp)) {
30663290 format_pte(pudp, pud_val(*pudp));
30673291 return;
30683292 }
....@@ -3076,7 +3300,7 @@
30763300 return;
30773301 }
30783302
3079
- if (pmd_huge(*pmdp)) {
3303
+ if (pmd_is_leaf(*pmdp)) {
30803304 format_pte(pmdp, pmd_val(*pmdp));
30813305 return;
30823306 }
....@@ -3106,7 +3330,7 @@
31063330 unsigned long tskv;
31073331 struct task_struct *tsk = NULL;
31083332
3109
- printf(" task_struct ->thread.ksp PID PPID S P CMD\n");
3333
+ printf(" task_struct ->thread.ksp ->thread.regs PID PPID S P CMD\n");
31103334
31113335 if (scanhex(&tskv))
31123336 tsk = (struct task_struct *)tskv;
....@@ -3316,6 +3540,11 @@
33163540 int c;
33173541
33183542 c = skipbl();
3543
+ if (c == '\n') {
3544
+ *s = 0;
3545
+ return;
3546
+ }
3547
+
33193548 do {
33203549 if( size > 1 ){
33213550 *s++ = c;
....@@ -3485,7 +3714,7 @@
34853714 }
34863715 #endif
34873716
3488
-#ifdef CONFIG_PPC_STD_MMU_32
3717
+#ifdef CONFIG_PPC_BOOK3S_32
34893718 void dump_segments(void)
34903719 {
34913720 int i;
....@@ -3700,6 +3929,11 @@
37003929 #ifdef CONFIG_MAGIC_SYSRQ
37013930 static void sysrq_handle_xmon(int key)
37023931 {
3932
+ if (xmon_is_locked_down()) {
3933
+ clear_all_bpt();
3934
+ xmon_init(0);
3935
+ return;
3936
+ }
37033937 /* ensure xmon is enabled */
37043938 xmon_init(1);
37053939 debugger(get_irq_regs());
....@@ -3707,7 +3941,7 @@
37073941 xmon_init(0);
37083942 }
37093943
3710
-static struct sysrq_key_op sysrq_xmon_op = {
3944
+static const struct sysrq_key_op sysrq_xmon_op = {
37113945 .handler = sysrq_handle_xmon,
37123946 .help_msg = "xmon(x)",
37133947 .action_msg = "Entering xmon",
....@@ -3721,7 +3955,6 @@
37213955 device_initcall(setup_xmon_sysrq);
37223956 #endif /* CONFIG_MAGIC_SYSRQ */
37233957
3724
-#ifdef CONFIG_DEBUG_FS
37253958 static void clear_all_bpt(void)
37263959 {
37273960 int i;
....@@ -3735,22 +3968,25 @@
37353968 bpts[i].enabled = 0;
37363969
37373970 /* Clear any data or iabr breakpoints */
3738
- if (iabr || dabr.enabled) {
3739
- iabr = NULL;
3740
- dabr.enabled = 0;
3741
- }
3742
-
3743
- printf("xmon: All breakpoints cleared\n");
3971
+ iabr = NULL;
3972
+ for (i = 0; i < nr_wp_slots(); i++)
3973
+ dabr[i].enabled = 0;
37443974 }
37453975
3976
+#ifdef CONFIG_DEBUG_FS
37463977 static int xmon_dbgfs_set(void *data, u64 val)
37473978 {
37483979 xmon_on = !!val;
37493980 xmon_init(xmon_on);
37503981
37513982 /* make sure all breakpoints removed when disabling */
3752
- if (!xmon_on)
3983
+ if (!xmon_on) {
37533984 clear_all_bpt();
3985
+ get_output_lock();
3986
+ printf("xmon: All breakpoints cleared\n");
3987
+ release_output_lock();
3988
+ }
3989
+
37543990 return 0;
37553991 }
37563992
....@@ -3776,7 +4012,11 @@
37764012
37774013 static int __init early_parse_xmon(char *p)
37784014 {
3779
- if (!p || strncmp(p, "early", 5) == 0) {
4015
+ if (xmon_is_locked_down()) {
4016
+ xmon_init(0);
4017
+ xmon_early = 0;
4018
+ xmon_on = 0;
4019
+ } else if (!p || strncmp(p, "early", 5) == 0) {
37804020 /* just "xmon" is equivalent to "xmon=early" */
37814021 xmon_init(1);
37824022 xmon_early = 1;
....@@ -3784,6 +4024,14 @@
37844024 } else if (strncmp(p, "on", 2) == 0) {
37854025 xmon_init(1);
37864026 xmon_on = 1;
4027
+ } else if (strncmp(p, "rw", 2) == 0) {
4028
+ xmon_init(1);
4029
+ xmon_on = 1;
4030
+ xmon_is_ro = false;
4031
+ } else if (strncmp(p, "ro", 2) == 0) {
4032
+ xmon_init(1);
4033
+ xmon_on = 1;
4034
+ xmon_is_ro = true;
37874035 } else if (strncmp(p, "off", 3) == 0)
37884036 xmon_on = 0;
37894037 else
....@@ -4031,6 +4279,7 @@
40314279 subcmd = inchar();
40324280 if (isxdigit(subcmd) || subcmd == '\n')
40334281 termch = subcmd;
4282
+ fallthrough;
40344283 case 'f':
40354284 scanhex(&num);
40364285 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {