forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
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,6 +53,7 @@
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>
....@@ -65,6 +62,7 @@
6562
6663 #include "nonstdio.h"
6764 #include "dis-asm.h"
65
+#include "xmon_bpts.h"
6866
6967 #ifdef CONFIG_SMP
7068 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
....@@ -80,11 +78,13 @@
8078 #endif
8179 static unsigned long in_xmon __read_mostly = 0;
8280 static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
81
+static bool xmon_is_ro = IS_ENABLED(CONFIG_XMON_DEFAULT_RO_MODE);
8382
8483 static unsigned long adrs;
8584 static int size = 1;
86
-#define MAX_DUMP (128 * 1024)
85
+#define MAX_DUMP (64 * 1024)
8786 static unsigned long ndump = 64;
87
+#define MAX_IDUMP (MAX_DUMP >> 2)
8888 static unsigned long nidump = 16;
8989 static unsigned long ncsum = 4096;
9090 static int termch;
....@@ -99,7 +99,7 @@
9999 /* Breakpoint stuff */
100100 struct bpt {
101101 unsigned long address;
102
- unsigned int instr[2];
102
+ struct ppc_inst *instr;
103103 atomic_t ref_count;
104104 int enabled;
105105 unsigned long pad;
....@@ -110,9 +110,8 @@
110110 #define BP_TRAP 2
111111 #define BP_DABR 4
112112
113
-#define NBPTS 256
114113 static struct bpt bpts[NBPTS];
115
-static struct bpt dabr;
114
+static struct bpt dabr[HBP_NUM_MAX];
116115 static struct bpt *iabr;
117116 static unsigned bpinstr = 0x7fe00008; /* trap */
118117
....@@ -122,6 +121,7 @@
122121 static int cmds(struct pt_regs *);
123122 static int mread(unsigned long, void *, int);
124123 static int mwrite(unsigned long, void *, int);
124
+static int mread_instr(unsigned long, struct ppc_inst *);
125125 static int handle_fault(struct pt_regs *);
126126 static void byterev(unsigned char *, int);
127127 static void memex(void);
....@@ -190,6 +190,8 @@
190190 static void dump_tlb_book3e(void);
191191 #endif
192192
193
+static void clear_all_bpt(void);
194
+
193195 #ifdef CONFIG_PPC64
194196 #define REG "%.16lx"
195197 #else
....@@ -201,6 +203,8 @@
201203 #else
202204 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
203205 #endif
206
+
207
+static const char *xmon_ro_msg = "Operation disabled: xmon in read-only mode\n";
204208
205209 static char *help_string = "\
206210 Commands:\n\
....@@ -276,7 +280,7 @@
276280 X exit monitor and don't recover\n"
277281 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
278282 " u dump segment table or SLB\n"
279
-#elif defined(CONFIG_PPC_STD_MMU_32)
283
+#elif defined(CONFIG_PPC_BOOK3S_32)
280284 " u dump segment registers\n"
281285 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
282286 " u dump TLB\n"
....@@ -284,20 +288,43 @@
284288 " U show uptime information\n"
285289 " ? help\n"
286290 " # n limit output to n lines per page (for dp, dpa, dl)\n"
287
-" zr reboot\n\
288
- zh halt\n"
291
+" zr reboot\n"
292
+" zh halt\n"
289293 ;
294
+
295
+#ifdef CONFIG_SECURITY
296
+static bool xmon_is_locked_down(void)
297
+{
298
+ static bool lockdown;
299
+
300
+ if (!lockdown) {
301
+ lockdown = !!security_locked_down(LOCKDOWN_XMON_RW);
302
+ if (lockdown) {
303
+ printf("xmon: Disabled due to kernel lockdown\n");
304
+ xmon_is_ro = true;
305
+ }
306
+ }
307
+
308
+ if (!xmon_is_ro) {
309
+ xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR);
310
+ if (xmon_is_ro)
311
+ printf("xmon: Read-only due to kernel lockdown\n");
312
+ }
313
+
314
+ return lockdown;
315
+}
316
+#else /* CONFIG_SECURITY */
317
+static inline bool xmon_is_locked_down(void)
318
+{
319
+ return false;
320
+}
321
+#endif
290322
291323 static struct pt_regs *xmon_regs;
292324
293325 static inline void sync(void)
294326 {
295327 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));
301328 }
302329
303330 static inline void cflush(void *p)
....@@ -439,7 +466,10 @@
439466
440467 return false;
441468 }
442
-#endif /* CONFIG_SMP */
469
+#else /* CONFIG_SMP */
470
+static inline void get_output_lock(void) {}
471
+static inline void release_output_lock(void) {}
472
+#endif
443473
444474 static inline int unrecoverable_excp(struct pt_regs *regs)
445475 {
....@@ -451,11 +481,19 @@
451481 #endif
452482 }
453483
484
+static void xmon_touch_watchdogs(void)
485
+{
486
+ touch_softlockup_watchdog_sync();
487
+ rcu_cpu_stall_reset();
488
+ touch_nmi_watchdog();
489
+}
490
+
454491 static int xmon_core(struct pt_regs *regs, int fromipi)
455492 {
456493 int cmd = 0;
457494 struct bpt *bp;
458495 long recurse_jmp[JMP_BUF_LEN];
496
+ bool locked_down;
459497 unsigned long offset;
460498 unsigned long flags;
461499 #ifdef CONFIG_SMP
....@@ -465,6 +503,8 @@
465503
466504 local_irq_save(flags);
467505 hard_irq_disable();
506
+
507
+ locked_down = xmon_is_locked_down();
468508
469509 if (!fromipi) {
470510 tracing_enabled = tracing_is_on();
....@@ -519,7 +559,8 @@
519559
520560 if (!fromipi) {
521561 get_output_lock();
522
- excprint(regs);
562
+ if (!locked_down)
563
+ excprint(regs);
523564 if (bp) {
524565 printf("cpu 0x%x stopped at breakpoint 0x%tx (",
525566 cpu, BP_NUM(bp));
....@@ -571,10 +612,14 @@
571612 }
572613 remove_bpts();
573614 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");
615
+
616
+ if (!locked_down) {
617
+ /* for breakpoint or single step, print curr insn */
618
+ if (bp || TRAP(regs) == 0xd00)
619
+ ppc_inst_dump(regs->nip, 1, 0);
620
+ printf("enter ? for help\n");
621
+ }
622
+
578623 mb();
579624 xmon_gate = 1;
580625 barrier();
....@@ -598,8 +643,9 @@
598643 spin_cpu_relax();
599644 touch_nmi_watchdog();
600645 } else {
601
- cmd = cmds(regs);
602
- if (cmd != 0) {
646
+ if (!locked_down)
647
+ cmd = cmds(regs);
648
+ if (locked_down || cmd != 0) {
603649 /* exiting xmon */
604650 insert_bpts();
605651 xmon_gate = 0;
....@@ -636,13 +682,16 @@
636682 "can't continue\n");
637683 remove_bpts();
638684 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");
685
+ if (!locked_down) {
686
+ /* for breakpoint or single step, print current insn */
687
+ if (bp || TRAP(regs) == 0xd00)
688
+ ppc_inst_dump(regs->nip, 1, 0);
689
+ printf("enter ? for help\n");
690
+ }
643691 }
644692
645
- cmd = cmds(regs);
693
+ if (!locked_down)
694
+ cmd = cmds(regs);
646695
647696 insert_bpts();
648697 in_xmon = 0;
....@@ -660,20 +709,23 @@
660709 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
661710 bp = at_breakpoint(regs->nip);
662711 if (bp != NULL) {
663
- int stepped = emulate_step(regs, bp->instr[0]);
712
+ int stepped = emulate_step(regs, ppc_inst_read(bp->instr));
664713 if (stepped == 0) {
665714 regs->nip = (unsigned long) &bp->instr[0];
666715 atomic_inc(&bp->ref_count);
667716 } else if (stepped < 0) {
668717 printf("Couldn't single-step %s instruction\n",
669
- (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
718
+ IS_RFID(ppc_inst_read(bp->instr))? "rfid": "mtmsrd");
670719 }
671720 }
672721 }
673722 #endif
674
- insert_cpu_bpts();
723
+ if (locked_down)
724
+ clear_all_bpt();
725
+ else
726
+ insert_cpu_bpts();
675727
676
- touch_nmi_watchdog();
728
+ xmon_touch_watchdogs();
677729 local_irq_restore(flags);
678730
679731 return cmd != 'X' && cmd != EOF;
....@@ -712,8 +764,8 @@
712764
713765 /* Are we at the trap at bp->instr[1] for some bp? */
714766 bp = in_breakpoint_table(regs->nip, &offset);
715
- if (bp != NULL && offset == 4) {
716
- regs->nip = bp->address + 4;
767
+ if (bp != NULL && (offset == 4 || offset == 8)) {
768
+ regs->nip = bp->address + offset;
717769 atomic_dec(&bp->ref_count);
718770 return 1;
719771 }
....@@ -738,10 +790,17 @@
738790
739791 static int xmon_break_match(struct pt_regs *regs)
740792 {
793
+ int i;
794
+
741795 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
742796 return 0;
743
- if (dabr.enabled == 0)
744
- return 0;
797
+ for (i = 0; i < nr_wp_slots(); i++) {
798
+ if (dabr[i].enabled)
799
+ goto found;
800
+ }
801
+ return 0;
802
+
803
+found:
745804 xmon_core(regs, 0);
746805 return 1;
747806 }
....@@ -810,15 +869,13 @@
810869 {
811870 unsigned long off;
812871
813
- off = nip - (unsigned long) bpts;
814
- if (off >= sizeof(bpts))
872
+ off = nip - (unsigned long)bpt_table;
873
+ if (off >= sizeof(bpt_table))
815874 return NULL;
816
- off %= sizeof(struct bpt);
817
- if (off != offsetof(struct bpt, instr[0])
818
- && off != offsetof(struct bpt, instr[1]))
875
+ *offp = off & (BPT_SIZE - 1);
876
+ if (off & 3)
819877 return NULL;
820
- *offp = off - offsetof(struct bpt, instr[0]);
821
- return (struct bpt *) (nip - off);
878
+ return bpts + (off / BPT_SIZE);
822879 }
823880
824881 static struct bpt *new_breakpoint(unsigned long a)
....@@ -833,8 +890,7 @@
833890 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
834891 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
835892 bp->address = a;
836
- bp->instr[1] = bpinstr;
837
- store_inst(&bp->instr[1]);
893
+ bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS));
838894 return bp;
839895 }
840896 }
....@@ -846,47 +902,76 @@
846902 static void insert_bpts(void)
847903 {
848904 int i;
849
- struct bpt *bp;
905
+ struct ppc_inst instr, instr2;
906
+ struct bpt *bp, *bp2;
850907
851908 bp = bpts;
852909 for (i = 0; i < NBPTS; ++i, ++bp) {
853910 if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
854911 continue;
855
- if (mread(bp->address, &bp->instr[0], 4) != 4) {
912
+ if (!mread_instr(bp->address, &instr)) {
856913 printf("Couldn't read instruction at %lx, "
857914 "disabling breakpoint there\n", bp->address);
858915 bp->enabled = 0;
859916 continue;
860917 }
861
- if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
918
+ if (IS_MTMSRD(instr) || IS_RFID(instr)) {
862919 printf("Breakpoint at %lx is on an mtmsrd or rfid "
863920 "instruction, disabling it\n", bp->address);
864921 bp->enabled = 0;
865922 continue;
866923 }
867
- store_inst(&bp->instr[0]);
924
+ /*
925
+ * Check the address is not a suffix by looking for a prefix in
926
+ * front of it.
927
+ */
928
+ if (mread_instr(bp->address - 4, &instr2) == 8) {
929
+ printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n",
930
+ bp->address);
931
+ bp->enabled = 0;
932
+ continue;
933
+ }
934
+ /*
935
+ * We might still be a suffix - if the prefix has already been
936
+ * replaced by a breakpoint we won't catch it with the above
937
+ * test.
938
+ */
939
+ bp2 = at_breakpoint(bp->address - 4);
940
+ if (bp2 && ppc_inst_prefixed(ppc_inst_read(bp2->instr))) {
941
+ printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n",
942
+ bp->address);
943
+ bp->enabled = 0;
944
+ continue;
945
+ }
946
+
947
+ patch_instruction(bp->instr, instr);
948
+ patch_instruction(ppc_inst_next(bp->instr, &instr),
949
+ ppc_inst(bpinstr));
868950 if (bp->enabled & BP_CIABR)
869951 continue;
870
- if (patch_instruction((unsigned int *)bp->address,
871
- bpinstr) != 0) {
952
+ if (patch_instruction((struct ppc_inst *)bp->address,
953
+ ppc_inst(bpinstr)) != 0) {
872954 printf("Couldn't write instruction at %lx, "
873955 "disabling breakpoint there\n", bp->address);
874956 bp->enabled &= ~BP_TRAP;
875957 continue;
876958 }
877
- store_inst((void *)bp->address);
878959 }
879960 }
880961
881962 static void insert_cpu_bpts(void)
882963 {
964
+ int i;
883965 struct arch_hw_breakpoint brk;
884966
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);
967
+ for (i = 0; i < nr_wp_slots(); i++) {
968
+ if (dabr[i].enabled) {
969
+ brk.address = dabr[i].address;
970
+ brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
971
+ brk.len = 8;
972
+ brk.hw_len = 8;
973
+ __set_breakpoint(i, &brk);
974
+ }
890975 }
891976
892977 if (iabr)
....@@ -897,20 +982,18 @@
897982 {
898983 int i;
899984 struct bpt *bp;
900
- unsigned instr;
985
+ struct ppc_inst instr;
901986
902987 bp = bpts;
903988 for (i = 0; i < NBPTS; ++i, ++bp) {
904989 if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
905990 continue;
906
- if (mread(bp->address, &instr, 4) == 4
907
- && instr == bpinstr
991
+ if (mread_instr(bp->address, &instr)
992
+ && ppc_inst_equal(instr, ppc_inst(bpinstr))
908993 && patch_instruction(
909
- (unsigned int *)bp->address, bp->instr[0]) != 0)
994
+ (struct ppc_inst *)bp->address, ppc_inst_read(bp->instr)) != 0)
910995 printf("Couldn't remove breakpoint at %lx\n",
911996 bp->address);
912
- else
913
- store_inst((void *)bp->address);
914997 }
915998 }
916999
....@@ -991,6 +1074,10 @@
9911074 memlocate();
9921075 break;
9931076 case 'z':
1077
+ if (xmon_is_ro) {
1078
+ printf(xmon_ro_msg);
1079
+ break;
1080
+ }
9941081 memzcan();
9951082 break;
9961083 case 'i':
....@@ -1057,12 +1144,16 @@
10571144 bootcmds();
10581145 break;
10591146 case 'p':
1147
+ if (xmon_is_ro) {
1148
+ printf(xmon_ro_msg);
1149
+ break;
1150
+ }
10601151 proccall();
10611152 break;
10621153 case 'P':
10631154 show_tasks();
10641155 break;
1065
-#ifdef CONFIG_PPC_STD_MMU
1156
+#ifdef CONFIG_PPC_BOOK3S
10661157 case 'u':
10671158 dump_segments();
10681159 break;
....@@ -1107,13 +1198,13 @@
11071198 */
11081199 static int do_step(struct pt_regs *regs)
11091200 {
1110
- unsigned int instr;
1201
+ struct ppc_inst instr;
11111202 int stepped;
11121203
11131204 force_enable_xmon();
11141205 /* check we are in 64-bit kernel mode, translation enabled */
11151206 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
1116
- if (mread(regs->nip, &instr, 4) == 4) {
1207
+ if (mread_instr(regs->nip, &instr)) {
11171208 stepped = emulate_step(regs, instr);
11181209 if (stepped < 0) {
11191210 printf("Couldn't single-step %s instruction\n",
....@@ -1121,7 +1212,7 @@
11211212 return 0;
11221213 }
11231214 if (stepped > 0) {
1124
- regs->trap = 0xd00 | (regs->trap & 1);
1215
+ set_trap(regs, 0xd00);
11251216 printf("stepped to ");
11261217 xmon_print_symbol(regs->nip, " ", "\n");
11271218 ppc_inst_dump(regs->nip, 1, 0);
....@@ -1136,16 +1227,19 @@
11361227
11371228 static void bootcmds(void)
11381229 {
1230
+ char tmp[64];
11391231 int cmd;
11401232
11411233 cmd = inchar();
1142
- if (cmd == 'r')
1143
- ppc_md.restart(NULL);
1144
- else if (cmd == 'h')
1234
+ if (cmd == 'r') {
1235
+ getstring(tmp, 64);
1236
+ ppc_md.restart(tmp);
1237
+ } else if (cmd == 'h') {
11451238 ppc_md.halt();
1146
- else if (cmd == 'p')
1239
+ } else if (cmd == 'p') {
11471240 if (pm_power_off)
11481241 pm_power_off();
1242
+ }
11491243 }
11501244
11511245 static int cpu_cmd(void)
....@@ -1270,14 +1364,14 @@
12701364 */
12711365 static long check_bp_loc(unsigned long addr)
12721366 {
1273
- unsigned int instr;
1367
+ struct ppc_inst instr;
12741368
12751369 addr &= ~3;
12761370 if (!is_kernel_addr(addr)) {
12771371 printf("Breakpoints may only be placed at kernel addresses\n");
12781372 return 0;
12791373 }
1280
- if (!mread(addr, &instr, sizeof(instr))) {
1374
+ if (!mread_instr(addr, &instr)) {
12811375 printf("Can't read instruction at address %lx\n", addr);
12821376 return 0;
12831377 }
....@@ -1287,6 +1381,37 @@
12871381 return 0;
12881382 }
12891383 return 1;
1384
+}
1385
+
1386
+#ifndef CONFIG_PPC_8xx
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
+#endif
1399
+
1400
+static void print_data_bpts(void)
1401
+{
1402
+ int i;
1403
+
1404
+ for (i = 0; i < nr_wp_slots(); i++) {
1405
+ if (!dabr[i].enabled)
1406
+ continue;
1407
+
1408
+ printf(" data "REG" [", dabr[i].address);
1409
+ if (dabr[i].enabled & 1)
1410
+ printf("r");
1411
+ if (dabr[i].enabled & 2)
1412
+ printf("w");
1413
+ printf("]\n");
1414
+ }
12901415 }
12911416
12921417 static char *breakpoint_help_string =
....@@ -1308,15 +1433,23 @@
13081433 struct bpt *bp;
13091434
13101435 cmd = inchar();
1436
+
13111437 switch (cmd) {
13121438 #ifndef CONFIG_PPC_8xx
13131439 static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
13141440 int mode;
13151441 case 'd': /* bd - hardware data breakpoint */
1442
+ if (xmon_is_ro) {
1443
+ printf(xmon_ro_msg);
1444
+ break;
1445
+ }
13161446 if (!ppc_breakpoint_available()) {
13171447 printf("Hardware data breakpoint not supported on this cpu\n");
13181448 break;
13191449 }
1450
+ i = find_free_data_bpt();
1451
+ if (i < 0)
1452
+ break;
13201453 mode = 7;
13211454 cmd = inchar();
13221455 if (cmd == 'r')
....@@ -1325,21 +1458,25 @@
13251458 mode = 6;
13261459 else
13271460 termch = cmd;
1328
- dabr.address = 0;
1329
- dabr.enabled = 0;
1330
- if (scanhex(&dabr.address)) {
1331
- if (!is_kernel_addr(dabr.address)) {
1461
+ dabr[i].address = 0;
1462
+ dabr[i].enabled = 0;
1463
+ if (scanhex(&dabr[i].address)) {
1464
+ if (!is_kernel_addr(dabr[i].address)) {
13321465 printf(badaddr);
13331466 break;
13341467 }
1335
- dabr.address &= ~HW_BRK_TYPE_DABR;
1336
- dabr.enabled = mode | BP_DABR;
1468
+ dabr[i].address &= ~HW_BRK_TYPE_DABR;
1469
+ dabr[i].enabled = mode | BP_DABR;
13371470 }
13381471
13391472 force_enable_xmon();
13401473 break;
13411474
13421475 case 'i': /* bi - hardware instr breakpoint */
1476
+ if (xmon_is_ro) {
1477
+ printf(xmon_ro_msg);
1478
+ break;
1479
+ }
13431480 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
13441481 printf("Hardware instruction breakpoint "
13451482 "not supported on this cpu\n");
....@@ -1368,7 +1505,9 @@
13681505 for (i = 0; i < NBPTS; ++i)
13691506 bpts[i].enabled = 0;
13701507 iabr = NULL;
1371
- dabr.enabled = 0;
1508
+ for (i = 0; i < nr_wp_slots(); i++)
1509
+ dabr[i].enabled = 0;
1510
+
13721511 printf("All breakpoints cleared\n");
13731512 break;
13741513 }
....@@ -1398,17 +1537,11 @@
13981537 break;
13991538 }
14001539 termch = cmd;
1401
- if (!scanhex(&a)) {
1540
+
1541
+ if (xmon_is_ro || !scanhex(&a)) {
14021542 /* print all breakpoints */
14031543 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
- }
1544
+ print_data_bpts();
14121545 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
14131546 if (!bp->enabled)
14141547 continue;
....@@ -1470,6 +1603,7 @@
14701603 case 0x1300: ret = "(Instruction Breakpoint)"; break;
14711604 case 0x1500: ret = "(Denormalisation)"; break;
14721605 case 0x1700: ret = "(Altivec Assist)"; break;
1606
+ case 0x3000: ret = "(System Call Vectored)"; break;
14731607 default: ret = "";
14741608 }
14751609 return ret;
....@@ -1706,7 +1840,7 @@
17061840 #endif
17071841 printf("pc = ");
17081842 xmon_print_symbol(fp->nip, " ", "\n");
1709
- if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1843
+ if (!trap_is_syscall(fp) && cpu_has_feature(CPU_FTR_CFAR)) {
17101844 printf("cfar= ");
17111845 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
17121846 }
....@@ -1738,7 +1872,7 @@
17381872 catch_memory_errors = 1;
17391873 sync();
17401874
1741
- if (cmd != 'i') {
1875
+ if (cmd != 'i' || IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
17421876 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
17431877 cflush((void *) adrs);
17441878 } else {
....@@ -1779,6 +1913,11 @@
17791913 static void
17801914 write_spr(int n, unsigned long val)
17811915 {
1916
+ if (xmon_is_ro) {
1917
+ printf(xmon_ro_msg);
1918
+ return;
1919
+ }
1920
+
17821921 if (setjmp(bus_error_jmp) == 0) {
17831922 catch_spr_faults = 1;
17841923 sync();
....@@ -1863,8 +2002,13 @@
18632002
18642003 printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
18652004 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));
2005
+ printf("dawr0 = %.16lx dawrx0 = %.16lx\n",
2006
+ mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0));
2007
+ if (nr_wp_slots() > 1) {
2008
+ printf("dawr1 = %.16lx dawrx1 = %.16lx\n",
2009
+ mfspr(SPRN_DAWR1), mfspr(SPRN_DAWRX1));
2010
+ }
2011
+ printf("ciabr = %.16lx\n", mfspr(SPRN_CIABR));
18682012 #endif
18692013 }
18702014
....@@ -1886,6 +2030,18 @@
18862030
18872031 printf("ptcr = %.16lx asdr = %.16lx\n",
18882032 mfspr(SPRN_PTCR), mfspr(SPRN_ASDR));
2033
+#endif
2034
+}
2035
+
2036
+static void dump_310_sprs(void)
2037
+{
2038
+#ifdef CONFIG_PPC64
2039
+ if (!cpu_has_feature(CPU_FTR_ARCH_31))
2040
+ return;
2041
+
2042
+ printf("mmcr3 = %.16lx, sier2 = %.16lx, sier3 = %.16lx\n",
2043
+ mfspr(SPRN_MMCR3), mfspr(SPRN_SIER2), mfspr(SPRN_SIER3));
2044
+
18892045 #endif
18902046 }
18912047
....@@ -1943,6 +2099,7 @@
19432099 dump_206_sprs();
19442100 dump_207_sprs();
19452101 dump_300_sprs();
2102
+ dump_310_sprs();
19462103
19472104 return;
19482105 }
....@@ -2017,6 +2174,12 @@
20172174 char *p, *q;
20182175
20192176 n = 0;
2177
+
2178
+ if (xmon_is_ro) {
2179
+ printf(xmon_ro_msg);
2180
+ return n;
2181
+ }
2182
+
20202183 if (setjmp(bus_error_jmp) == 0) {
20212184 catch_memory_errors = 1;
20222185 sync();
....@@ -2044,6 +2207,25 @@
20442207 n = size;
20452208 } else {
20462209 printf("*** Error writing address "REG"\n", adrs + n);
2210
+ }
2211
+ catch_memory_errors = 0;
2212
+ return n;
2213
+}
2214
+
2215
+static int
2216
+mread_instr(unsigned long adrs, struct ppc_inst *instr)
2217
+{
2218
+ volatile int n;
2219
+
2220
+ n = 0;
2221
+ if (setjmp(bus_error_jmp) == 0) {
2222
+ catch_memory_errors = 1;
2223
+ sync();
2224
+ *instr = ppc_inst_read((struct ppc_inst *)adrs);
2225
+ sync();
2226
+ /* wait a little while to see if we get a machine check */
2227
+ __delay(200);
2228
+ n = ppc_inst_len(*instr);
20472229 }
20482230 catch_memory_errors = 0;
20492231 return n;
....@@ -2381,25 +2563,33 @@
23812563 DUMP(p, cpu_start, "%#-*x");
23822564 DUMP(p, kexec_state, "%#-*x");
23832565 #ifdef CONFIG_PPC_BOOK3S_64
2384
- for (i = 0; i < SLB_NUM_BOLTED; i++) {
2385
- u64 esid, vsid;
2566
+ if (!early_radix_enabled()) {
2567
+ for (i = 0; i < SLB_NUM_BOLTED; i++) {
2568
+ u64 esid, vsid;
23862569
2387
- if (!p->slb_shadow_ptr)
2388
- continue;
2570
+ if (!p->slb_shadow_ptr)
2571
+ continue;
23892572
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);
2573
+ esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
2574
+ vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
23922575
2393
- if (esid || vsid) {
2394
- printf(" %-*s[%d] = 0x%016llx 0x%016llx\n",
2395
- 22, "slb_shadow", i, esid, vsid);
2576
+ if (esid || vsid) {
2577
+ printf(" %-*s[%d] = 0x%016llx 0x%016llx\n",
2578
+ 22, "slb_shadow", i, esid, vsid);
2579
+ }
2580
+ }
2581
+ DUMP(p, vmalloc_sllp, "%#-*x");
2582
+ DUMP(p, stab_rr, "%#-*x");
2583
+ DUMP(p, slb_used_bitmap, "%#-*x");
2584
+ DUMP(p, slb_kern_bitmap, "%#-*x");
2585
+
2586
+ if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
2587
+ DUMP(p, slb_cache_ptr, "%#-*x");
2588
+ for (i = 0; i < SLB_CACHE_ENTRIES; i++)
2589
+ printf(" %-*s[%d] = 0x%016x\n",
2590
+ 22, "slb_cache", i, p->slb_cache[i]);
23962591 }
23972592 }
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]);
24032593
24042594 DUMP(p, rfi_flush_fallback_area, "%-*px");
24052595 #endif
....@@ -2415,14 +2605,20 @@
24152605 DUMP(p, __current, "%-*px");
24162606 DUMP(p, kstack, "%#-*llx");
24172607 printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1));
2418
- DUMP(p, stab_rr, "%#-*llx");
2608
+#ifdef CONFIG_STACKPROTECTOR
2609
+ DUMP(p, canary, "%#-*lx");
2610
+#endif
24192611 DUMP(p, saved_r1, "%#-*llx");
2612
+#ifdef CONFIG_PPC_BOOK3E
24202613 DUMP(p, trap_save, "%#-*x");
2614
+#endif
24212615 DUMP(p, irq_soft_mask, "%#-*x");
24222616 DUMP(p, irq_happened, "%#-*x");
2423
- DUMP(p, io_sync, "%#-*x");
2617
+#ifdef CONFIG_MMIOWB
2618
+ DUMP(p, mmiowb_state.nesting_count, "%#-*x");
2619
+ DUMP(p, mmiowb_state.mmiowb_pending, "%#-*x");
2620
+#endif
24242621 DUMP(p, irq_work_pending, "%#-*x");
2425
- DUMP(p, nap_state_lost, "%#-*x");
24262622 DUMP(p, sprg_vdso, "%#-*llx");
24272623
24282624 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
....@@ -2430,28 +2626,29 @@
24302626 #endif
24312627
24322628 #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");
2629
+ DUMP(p, idle_state, "%#-*lx");
2630
+ if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
2631
+ DUMP(p, thread_idle_state, "%#-*x");
2632
+ DUMP(p, subcore_sibling_mask, "%#-*x");
2633
+ } else {
2634
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
2635
+ DUMP(p, requested_psscr, "%#-*llx");
2636
+ DUMP(p, dont_stop.counter, "%#-*x");
2637
+#endif
2638
+ }
24462639 #endif
24472640
24482641 DUMP(p, accounting.utime, "%#-*lx");
24492642 DUMP(p, accounting.stime, "%#-*lx");
2643
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
24502644 DUMP(p, accounting.utime_scaled, "%#-*lx");
2645
+#endif
24512646 DUMP(p, accounting.starttime, "%#-*lx");
24522647 DUMP(p, accounting.starttime_user, "%#-*lx");
2648
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
24532649 DUMP(p, accounting.startspurr, "%#-*lx");
24542650 DUMP(p, accounting.utime_sspurr, "%#-*lx");
2651
+#endif
24552652 DUMP(p, accounting.steal_time, "%#-*lx");
24562653 #undef DUMP
24572654
....@@ -2534,16 +2731,28 @@
25342731 dump_one_xive(cpu);
25352732 }
25362733
2537
-static void dump_one_xive_irq(u32 num)
2734
+static void dump_one_xive_irq(u32 num, struct irq_data *d)
25382735 {
2539
- s64 rc;
2540
- __be64 vp;
2541
- u8 prio;
2542
- __be32 lirq;
2736
+ xmon_xive_get_irq_config(num, d);
2737
+}
25432738
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);
2739
+static void dump_all_xive_irq(void)
2740
+{
2741
+ unsigned int i;
2742
+ struct irq_desc *desc;
2743
+
2744
+ for_each_irq_desc(i, desc) {
2745
+ struct irq_data *d = irq_desc_get_irq_data(desc);
2746
+ unsigned int hwirq;
2747
+
2748
+ if (!d)
2749
+ continue;
2750
+
2751
+ hwirq = (unsigned int)irqd_to_hwirq(d);
2752
+ /* IPIs are special (HW number 0) */
2753
+ if (hwirq)
2754
+ dump_one_xive_irq(hwirq, d);
2755
+ }
25472756 }
25482757
25492758 static void dump_xives(void)
....@@ -2562,7 +2771,9 @@
25622771 return;
25632772 } else if (c == 'i') {
25642773 if (scanhex(&num))
2565
- dump_one_xive_irq(num);
2774
+ dump_one_xive_irq(num, NULL);
2775
+ else
2776
+ dump_all_xive_irq();
25662777 return;
25672778 }
25682779
....@@ -2603,7 +2814,12 @@
26032814
26042815 printf("%0*llx", size * 2, val);
26052816 }
2606
- printf("\n");
2817
+ printf(" |");
2818
+ for (j = 0; j < 16; ++j) {
2819
+ val = temp[j];
2820
+ putchar(' ' <= val && val <= '~' ? val : '.');
2821
+ }
2822
+ printf("|\n");
26072823 }
26082824 }
26092825
....@@ -2647,8 +2863,8 @@
26472863 scanhex(&nidump);
26482864 if (nidump == 0)
26492865 nidump = 16;
2650
- else if (nidump > MAX_DUMP)
2651
- nidump = MAX_DUMP;
2866
+ else if (nidump > MAX_IDUMP)
2867
+ nidump = MAX_IDUMP;
26522868 adrs += ppc_inst_dump(adrs, nidump, 1);
26532869 last_cmd = "di\n";
26542870 } else if (c == 'l') {
....@@ -2741,12 +2957,11 @@
27412957 {
27422958 int nr, dotted;
27432959 unsigned long first_adr;
2744
- unsigned int inst, last_inst = 0;
2745
- unsigned char val[4];
2960
+ struct ppc_inst inst, last_inst = ppc_inst(0);
27462961
27472962 dotted = 0;
2748
- for (first_adr = adr; count > 0; --count, adr += 4) {
2749
- nr = mread(adr, val, 4);
2963
+ for (first_adr = adr; count > 0; --count, adr += ppc_inst_len(inst)) {
2964
+ nr = mread_instr(adr, &inst);
27502965 if (nr == 0) {
27512966 if (praddr) {
27522967 const char *x = fault_chars[fault_type];
....@@ -2754,8 +2969,7 @@
27542969 }
27552970 break;
27562971 }
2757
- inst = GETWORD(val);
2758
- if (adr > first_adr && inst == last_inst) {
2972
+ if (adr > first_adr && ppc_inst_equal(inst, last_inst)) {
27592973 if (!dotted) {
27602974 printf(" ...\n");
27612975 dotted = 1;
....@@ -2765,9 +2979,12 @@
27652979 dotted = 0;
27662980 last_inst = inst;
27672981 if (praddr)
2768
- printf(REG" %.8x", adr, inst);
2982
+ printf(REG" %s", adr, ppc_inst_as_str(inst));
27692983 printf("\t");
2770
- dump_func(inst, adr);
2984
+ if (!ppc_inst_prefixed(inst))
2985
+ dump_func(ppc_inst_val(inst), adr);
2986
+ else
2987
+ dump_func(ppc_inst_as_u64(inst), adr);
27712988 printf("\n");
27722989 }
27732990 return adr - first_adr;
....@@ -2785,10 +3002,10 @@
27853002 xmon_print_symbol(addr, "\t# ", "");
27863003 }
27873004
2788
-void
3005
+static void
27893006 dump_log_buf(void)
27903007 {
2791
- struct kmsg_dumper dumper = { .active = 1 };
3008
+ struct kmsg_dumper_iter iter = { .active = 1 };
27923009 unsigned char buf[128];
27933010 size_t len;
27943011
....@@ -2800,9 +3017,9 @@
28003017 catch_memory_errors = 1;
28013018 sync();
28023019
2803
- kmsg_dump_rewind_nolock(&dumper);
3020
+ kmsg_dump_rewind(&iter);
28043021 xmon_start_pagination();
2805
- while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
3022
+ while (kmsg_dump_get_line(&iter, false, buf, sizeof(buf), &len)) {
28063023 buf[len] = '\0';
28073024 printf("%s", buf);
28083025 }
....@@ -2874,9 +3091,17 @@
28743091 scanhex((void *)&mcount);
28753092 switch( cmd ){
28763093 case 'm':
3094
+ if (xmon_is_ro) {
3095
+ printf(xmon_ro_msg);
3096
+ break;
3097
+ }
28773098 memmove((void *)mdest, (void *)msrc, mcount);
28783099 break;
28793100 case 's':
3101
+ if (xmon_is_ro) {
3102
+ printf(xmon_ro_msg);
3103
+ break;
3104
+ }
28803105 memset((void *)mdest, mval, mcount);
28813106 break;
28823107 case 'd':
....@@ -2984,25 +3209,27 @@
29843209 (tsk->exit_state & EXIT_DEAD) ? 'E' :
29853210 (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
29863211
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,
3212
+ printf("%16px %16lx %16px %6d %6d %c %2d %s\n", tsk,
3213
+ tsk->thread.ksp, tsk->thread.regs,
3214
+ tsk->pid, rcu_dereference(tsk->parent)->pid,
3215
+ state, task_cpu(tsk),
29913216 tsk->comm);
29923217 }
29933218
29943219 #ifdef CONFIG_PPC_BOOK3S_64
2995
-void format_pte(void *ptep, unsigned long pte)
3220
+static void format_pte(void *ptep, unsigned long pte)
29963221 {
3222
+ pte_t entry = __pte(pte);
3223
+
29973224 printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);
29983225 printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK);
29993226
30003227 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 " : "");
3228
+ pte_young(entry) ? "Accessed " : "",
3229
+ pte_dirty(entry) ? "Dirty " : "",
3230
+ pte_read(entry) ? "Read " : "",
3231
+ pte_write(entry) ? "Write " : "",
3232
+ pte_exec(entry) ? "Exec " : "");
30063233 }
30073234
30083235 static void show_pte(unsigned long addr)
....@@ -3010,7 +3237,8 @@
30103237 unsigned long tskv = 0;
30113238 struct task_struct *tsk = NULL;
30123239 struct mm_struct *mm;
3013
- pgd_t *pgdp, *pgdir;
3240
+ pgd_t *pgdp;
3241
+ p4d_t *p4dp;
30143242 pud_t *pudp;
30153243 pmd_t *pmdp;
30163244 pte_t *ptep;
....@@ -3034,35 +3262,33 @@
30343262 catch_memory_errors = 1;
30353263 sync();
30363264
3037
- if (mm == &init_mm) {
3265
+ if (mm == &init_mm)
30383266 pgdp = pgd_offset_k(addr);
3039
- pgdir = pgd_offset_k(0);
3040
- } else {
3267
+ else
30413268 pgdp = pgd_offset(mm, addr);
3042
- pgdir = pgd_offset(mm, 0);
3043
- }
30443269
3045
- if (pgd_none(*pgdp)) {
3046
- printf("no linux page table for address\n");
3270
+ p4dp = p4d_offset(pgdp, addr);
3271
+
3272
+ if (p4d_none(*p4dp)) {
3273
+ printf("No valid P4D\n");
30473274 return;
30483275 }
30493276
3050
- printf("pgd @ 0x%px\n", pgdir);
3051
-
3052
- if (pgd_huge(*pgdp)) {
3053
- format_pte(pgdp, pgd_val(*pgdp));
3277
+ if (p4d_is_leaf(*p4dp)) {
3278
+ format_pte(p4dp, p4d_val(*p4dp));
30543279 return;
30553280 }
3056
- printf("pgdp @ 0x%px = 0x%016lx\n", pgdp, pgd_val(*pgdp));
30573281
3058
- pudp = pud_offset(pgdp, addr);
3282
+ printf("p4dp @ 0x%px = 0x%016lx\n", p4dp, p4d_val(*p4dp));
3283
+
3284
+ pudp = pud_offset(p4dp, addr);
30593285
30603286 if (pud_none(*pudp)) {
30613287 printf("No valid PUD\n");
30623288 return;
30633289 }
30643290
3065
- if (pud_huge(*pudp)) {
3291
+ if (pud_is_leaf(*pudp)) {
30663292 format_pte(pudp, pud_val(*pudp));
30673293 return;
30683294 }
....@@ -3076,7 +3302,7 @@
30763302 return;
30773303 }
30783304
3079
- if (pmd_huge(*pmdp)) {
3305
+ if (pmd_is_leaf(*pmdp)) {
30803306 format_pte(pmdp, pmd_val(*pmdp));
30813307 return;
30823308 }
....@@ -3106,7 +3332,7 @@
31063332 unsigned long tskv;
31073333 struct task_struct *tsk = NULL;
31083334
3109
- printf(" task_struct ->thread.ksp PID PPID S P CMD\n");
3335
+ printf(" task_struct ->thread.ksp ->thread.regs PID PPID S P CMD\n");
31103336
31113337 if (scanhex(&tskv))
31123338 tsk = (struct task_struct *)tskv;
....@@ -3316,6 +3542,11 @@
33163542 int c;
33173543
33183544 c = skipbl();
3545
+ if (c == '\n') {
3546
+ *s = 0;
3547
+ return;
3548
+ }
3549
+
33193550 do {
33203551 if( size > 1 ){
33213552 *s++ = c;
....@@ -3485,7 +3716,7 @@
34853716 }
34863717 #endif
34873718
3488
-#ifdef CONFIG_PPC_STD_MMU_32
3719
+#ifdef CONFIG_PPC_BOOK3S_32
34893720 void dump_segments(void)
34903721 {
34913722 int i;
....@@ -3700,6 +3931,11 @@
37003931 #ifdef CONFIG_MAGIC_SYSRQ
37013932 static void sysrq_handle_xmon(int key)
37023933 {
3934
+ if (xmon_is_locked_down()) {
3935
+ clear_all_bpt();
3936
+ xmon_init(0);
3937
+ return;
3938
+ }
37033939 /* ensure xmon is enabled */
37043940 xmon_init(1);
37053941 debugger(get_irq_regs());
....@@ -3707,7 +3943,7 @@
37073943 xmon_init(0);
37083944 }
37093945
3710
-static struct sysrq_key_op sysrq_xmon_op = {
3946
+static const struct sysrq_key_op sysrq_xmon_op = {
37113947 .handler = sysrq_handle_xmon,
37123948 .help_msg = "xmon(x)",
37133949 .action_msg = "Entering xmon",
....@@ -3721,7 +3957,6 @@
37213957 device_initcall(setup_xmon_sysrq);
37223958 #endif /* CONFIG_MAGIC_SYSRQ */
37233959
3724
-#ifdef CONFIG_DEBUG_FS
37253960 static void clear_all_bpt(void)
37263961 {
37273962 int i;
....@@ -3735,22 +3970,25 @@
37353970 bpts[i].enabled = 0;
37363971
37373972 /* 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");
3973
+ iabr = NULL;
3974
+ for (i = 0; i < nr_wp_slots(); i++)
3975
+ dabr[i].enabled = 0;
37443976 }
37453977
3978
+#ifdef CONFIG_DEBUG_FS
37463979 static int xmon_dbgfs_set(void *data, u64 val)
37473980 {
37483981 xmon_on = !!val;
37493982 xmon_init(xmon_on);
37503983
37513984 /* make sure all breakpoints removed when disabling */
3752
- if (!xmon_on)
3985
+ if (!xmon_on) {
37533986 clear_all_bpt();
3987
+ get_output_lock();
3988
+ printf("xmon: All breakpoints cleared\n");
3989
+ release_output_lock();
3990
+ }
3991
+
37543992 return 0;
37553993 }
37563994
....@@ -3776,7 +4014,11 @@
37764014
37774015 static int __init early_parse_xmon(char *p)
37784016 {
3779
- if (!p || strncmp(p, "early", 5) == 0) {
4017
+ if (xmon_is_locked_down()) {
4018
+ xmon_init(0);
4019
+ xmon_early = 0;
4020
+ xmon_on = 0;
4021
+ } else if (!p || strncmp(p, "early", 5) == 0) {
37804022 /* just "xmon" is equivalent to "xmon=early" */
37814023 xmon_init(1);
37824024 xmon_early = 1;
....@@ -3784,6 +4026,14 @@
37844026 } else if (strncmp(p, "on", 2) == 0) {
37854027 xmon_init(1);
37864028 xmon_on = 1;
4029
+ } else if (strncmp(p, "rw", 2) == 0) {
4030
+ xmon_init(1);
4031
+ xmon_on = 1;
4032
+ xmon_is_ro = false;
4033
+ } else if (strncmp(p, "ro", 2) == 0) {
4034
+ xmon_init(1);
4035
+ xmon_on = 1;
4036
+ xmon_is_ro = true;
37874037 } else if (strncmp(p, "off", 3) == 0)
37884038 xmon_on = 0;
37894039 else
....@@ -4031,6 +4281,7 @@
40314281 subcmd = inchar();
40324282 if (isxdigit(subcmd) || subcmd == '\n')
40334283 termch = subcmd;
4284
+ fallthrough;
40344285 case 'f':
40354286 scanhex(&num);
40364287 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {