^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Routines providing a simple monitor for use on the PowerMac.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1996-2005 Paul Mackerras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001 PPC64 Team, IBM Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kmsg_dump.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/cpumask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sysrq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/nmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/xmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/mmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/plpar_wrappers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/cputable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <asm/rtas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <asm/sstep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <asm/irq_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <asm/spu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <asm/spu_priv1.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <asm/setjmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <asm/reg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <asm/hw_breakpoint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/xive.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <asm/opal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <asm/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <asm/code-patching.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <asm/hvcall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <asm/paca.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include "nonstdio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include "dis-asm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include "xmon_bpts.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static unsigned long xmon_taken = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int xmon_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int xmon_gate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define xmon_owner 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #endif /* CONFIG_SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int set_indicator_token = RTAS_UNKNOWN_SERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static unsigned long in_xmon __read_mostly = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static bool xmon_is_ro = IS_ENABLED(CONFIG_XMON_DEFAULT_RO_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static unsigned long adrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MAX_DUMP (64 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static unsigned long ndump = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MAX_IDUMP (MAX_DUMP >> 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static unsigned long nidump = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static unsigned long ncsum = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int termch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static char tmpstr[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int tracing_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static long bus_error_jmp[JMP_BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int catch_memory_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static int catch_spr_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static long *xmon_fault_jmp[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* Breakpoint stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct bpt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct ppc_inst *instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) atomic_t ref_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned long pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Bits in bpt.enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define BP_CIABR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define BP_TRAP 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define BP_DABR 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static struct bpt bpts[NBPTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static struct bpt dabr[HBP_NUM_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static struct bpt *iabr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static unsigned bpinstr = 0x7fe00008; /* trap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define BP_NUM(bp) ((bp) - bpts + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Prototypes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int cmds(struct pt_regs *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int mread(unsigned long, void *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int mwrite(unsigned long, void *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int mread_instr(unsigned long, struct ppc_inst *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int handle_fault(struct pt_regs *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void byterev(unsigned char *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void memex(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int bsesc(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static void dump(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static void show_pte(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void prdump(unsigned long, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int ppc_inst_dump(unsigned long, long, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void dump_log_buf(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void dump_opal_msglog(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static inline void dump_opal_msglog(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) printf("Machine is not running OPAL firmware.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static void backtrace(struct pt_regs *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void excprint(struct pt_regs *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void prregs(struct pt_regs *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void memops(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void memlocate(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void memzcan(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int skipbl(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int scanhex(unsigned long *valp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void scannl(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int hexdigit(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) void getstring(char *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void flush_input(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int inchar(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void take_input(char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int read_spr(int, unsigned long *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void write_spr(int, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static void super_regs(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static void remove_bpts(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void insert_bpts(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void remove_cpu_bpts(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void insert_cpu_bpts(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct bpt *at_breakpoint(unsigned long pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int do_step(struct pt_regs *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void bpt_cmds(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void cacheflush(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int cpu_cmd(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void csum(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void bootcmds(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void proccall(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void show_tasks(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) void dump_segments(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void symbol_lookup(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static void xmon_show_stack(unsigned long sp, unsigned long lr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned long pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static void xmon_print_symbol(unsigned long address, const char *mid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) const char *after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static const char *getvecname(unsigned long vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int do_spu_cmd(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #ifdef CONFIG_44x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static void dump_tlb_44x(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #ifdef CONFIG_PPC_BOOK3E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void dump_tlb_book3e(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static void clear_all_bpt(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define REG "%.16lx"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define REG "%.8lx"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #ifdef __LITTLE_ENDIAN__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static const char *xmon_ro_msg = "Operation disabled: xmon in read-only mode\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static char *help_string = "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) Commands:\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) b show breakpoints\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) bd set data breakpoint\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) bi set instruction breakpoint\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bc clear breakpoint\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) c print cpus stopped in xmon\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) c# try to switch to cpu number h (in hex)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) C checksum\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) d dump bytes\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) d1 dump 1 byte values\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) d2 dump 2 byte values\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) d4 dump 4 byte values\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) d8 dump 8 byte values\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) di dump instructions\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) df dump float values\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dd dump double values\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dl dump the kernel log buffer\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) do dump the OPAL message log\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dp[#] dump paca for current cpu, or cpu #\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dpa dump paca for all possible cpus\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dr dump stream of raw bytes\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dv dump virtual address translation \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dt dump the tracing buffers (uses printk)\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) dtc dump the tracing buffers for current CPU (uses printk)\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) " dx# dump xive on CPU #\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dxi# dump xive irq state #\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) dxa dump xive on all CPUs\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) " e print exception information\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) f flush cache\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) la lookup symbol+offset of specified address\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ls lookup address of specified symbol\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) lp s [#] lookup address of percpu symbol s for current cpu, or cpu #\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) m examine/change memory\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) mm move a block of memory\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ms set a block of memory\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) md compare two blocks of memory\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ml locate a block of memory\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mz zero a block of memory\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mi show information about memory allocation\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) p call a procedure\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) P list processes/tasks\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) r print registers\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) s single step\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #ifdef CONFIG_SPU_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) " ss stop execution on all spus\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sr restore execution on stopped spus\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) sf # dump spu fields for spu # (in hex)\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) sd # dump spu local store for spu # (in hex)\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) sdi # disassemble spu local store for spu # (in hex)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) " S print special registers\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) Sa print all SPRs\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) Sr # read SPR #\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) Sw #v write v to SPR #\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) t print backtrace\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) x exit monitor and recover\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) X exit monitor and don't recover\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) " u dump segment table or SLB\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #elif defined(CONFIG_PPC_BOOK3S_32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) " u dump segment registers\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) " u dump TLB\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) " U show uptime information\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) " ? help\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) " # n limit output to n lines per page (for dp, dpa, dl)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) " zr reboot\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) " zh halt\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #ifdef CONFIG_SECURITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static bool xmon_is_locked_down(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static bool lockdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!lockdown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) lockdown = !!security_locked_down(LOCKDOWN_XMON_RW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (lockdown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) printf("xmon: Disabled due to kernel lockdown\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) xmon_is_ro = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (xmon_is_ro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) printf("xmon: Read-only due to kernel lockdown\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return lockdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) #else /* CONFIG_SECURITY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static inline bool xmon_is_locked_down(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static struct pt_regs *xmon_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static inline void sync(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) asm volatile("sync; isync");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static inline void cflush(void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static inline void cinval(void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * write_ciabr() - write the CIABR SPR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * @ciabr: The value to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * This function writes a value to the CIARB register either directly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * through mtspr instruction if the kernel is in HV privilege mode or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * call a hypervisor function to achieve the same in case the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * is in supervisor privilege mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static void write_ciabr(unsigned long ciabr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!cpu_has_feature(CPU_FTR_ARCH_207S))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (cpu_has_feature(CPU_FTR_HVMODE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) mtspr(SPRN_CIABR, ciabr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) plpar_set_ciabr(ciabr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * set_ciabr() - set the CIABR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * @addr: The value to set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * This function sets the correct privilege value into the the HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * breakpoint address before writing it up in the CIABR register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static void set_ciabr(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) addr &= ~CIABR_PRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (cpu_has_feature(CPU_FTR_HVMODE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) addr |= CIABR_PRIV_HYPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) addr |= CIABR_PRIV_SUPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) write_ciabr(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Disable surveillance (the service processor watchdog function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * while we are in xmon.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * XXX we should re-enable it when we leave. :)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) #define SURVEILLANCE_TOKEN 9000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static inline void disable_surveillance(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* Since this can't be a module, args should end up below 4GB. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static struct rtas_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * At this point we have got all the cpus we can into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * xmon, so there is hopefully no other cpu calling RTAS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * at the moment, even though we don't take rtas.lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * If we did try to take rtas.lock there would be a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * real possibility of deadlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (set_indicator_token == RTAS_UNKNOWN_SERVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) rtas_call_unlocked(&args, set_indicator_token, 3, 1, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) SURVEILLANCE_TOKEN, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) #endif /* CONFIG_PPC_PSERIES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int xmon_speaker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void get_output_lock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int me = smp_processor_id() + 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int last_speaker = 0, prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (xmon_speaker == me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) last_speaker = cmpxchg(&xmon_speaker, 0, me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (last_speaker == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * Wait a full second for the lock, we might be on a slow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * console, but check every 100us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) timeout = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) while (xmon_speaker == last_speaker) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (--timeout > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* hostile takeover */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) prev = cmpxchg(&xmon_speaker, last_speaker, me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (prev == last_speaker)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void release_output_lock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) xmon_speaker = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) int cpus_are_in_xmon(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return !cpumask_empty(&cpus_in_xmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static bool wait_for_other_cpus(int ncpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* We wait for 2s, which is a metric "little while" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) for (timeout = 20000; timeout != 0; --timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (cpumask_weight(&cpus_in_xmon) >= ncpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) #else /* CONFIG_SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static inline void get_output_lock(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static inline void release_output_lock(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static inline int unrecoverable_excp(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) #if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return ((regs->msr & MSR_RI) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static void xmon_touch_watchdogs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) touch_softlockup_watchdog_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) rcu_cpu_stall_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) touch_nmi_watchdog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static int xmon_core(struct pt_regs *regs, int fromipi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int cmd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) long recurse_jmp[JMP_BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) bool locked_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int secondary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) hard_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) locked_down = xmon_is_locked_down();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!fromipi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) tracing_enabled = tracing_is_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) tracing_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) bp = in_breakpoint_table(regs->nip, &offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (bp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) regs->nip = bp->address + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) atomic_dec(&bp->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) remove_cpu_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * We catch SPR read/write faults here because the 0x700, 0xf60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * etc. handlers don't call debugger_fault_handler().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (catch_spr_faults)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) longjmp(bus_error_jmp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) get_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) excprint(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) printf("cpu 0x%x: Exception %lx %s in xmon, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) "returning to main loop\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) cpu, regs->trap, getvecname(TRAP(regs)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) release_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) longjmp(xmon_fault_jmp[cpu], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (setjmp(recurse_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (!in_xmon || !xmon_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) get_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) printf("xmon: WARNING: bad recursive fault "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) "on cpu 0x%x\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) release_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) goto waiting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) secondary = !(xmon_taken && cpu == xmon_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) goto cmdloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) xmon_fault_jmp[cpu] = recurse_jmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) bp = at_breakpoint(regs->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (bp || unrecoverable_excp(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) fromipi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (!fromipi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) get_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!locked_down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) excprint(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) printf("cpu 0x%x stopped at breakpoint 0x%tx (",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) cpu, BP_NUM(bp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) xmon_print_symbol(regs->nip, " ", ")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (unrecoverable_excp(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) printf("WARNING: exception is not recoverable, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) "can't continue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) release_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) cpumask_set_cpu(cpu, &cpus_in_xmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) waiting:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) secondary = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) spin_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) while (secondary && !xmon_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (in_xmon == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (fromipi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) spin_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) secondary = test_and_set_bit(0, &in_xmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) spin_cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) touch_nmi_watchdog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) spin_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (!secondary && !xmon_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* we are the first cpu to come in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* interrupt other cpu(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int ncpus = num_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) xmon_owner = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (ncpus > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * A system reset (trap == 0x100) can be triggered on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * all CPUs, so when we come in via 0x100 try waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * for the other CPUs to come in before we send the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * debugger break (IPI). This is similar to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * crash_kexec_secondary().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (TRAP(regs) != 0x100 || !wait_for_other_cpus(ncpus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) smp_send_debugger_break();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) wait_for_other_cpus(ncpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) remove_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) disable_surveillance();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!locked_down) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* for breakpoint or single step, print curr insn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (bp || TRAP(regs) == 0xd00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) ppc_inst_dump(regs->nip, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) printf("enter ? for help\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) xmon_gate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) touch_nmi_watchdog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) cmdloop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) while (in_xmon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (secondary) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) spin_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (cpu == xmon_owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!test_and_set_bit(0, &xmon_taken)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) secondary = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) spin_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* missed it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) while (cpu == xmon_owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) spin_cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) spin_cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) touch_nmi_watchdog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!locked_down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) cmd = cmds(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (locked_down || cmd != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* exiting xmon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) insert_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) xmon_gate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) in_xmon = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* have switched to some other cpu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) secondary = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) leave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) cpumask_clear_cpu(cpu, &cpus_in_xmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) xmon_fault_jmp[cpu] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* UP is simple... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (in_xmon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) printf("Exception %lx %s in xmon, returning to main loop\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) regs->trap, getvecname(TRAP(regs)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) longjmp(xmon_fault_jmp[0], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (setjmp(recurse_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) xmon_fault_jmp[0] = recurse_jmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) in_xmon = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) excprint(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) bp = at_breakpoint(regs->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) printf("Stopped at breakpoint %tx (", BP_NUM(bp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) xmon_print_symbol(regs->nip, " ", ")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (unrecoverable_excp(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) printf("WARNING: exception is not recoverable, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) "can't continue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) remove_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) disable_surveillance();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!locked_down) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* for breakpoint or single step, print current insn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (bp || TRAP(regs) == 0xd00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ppc_inst_dump(regs->nip, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) printf("enter ? for help\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!locked_down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) cmd = cmds(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) insert_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) in_xmon = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) #ifdef CONFIG_BOOKE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (regs->msr & MSR_DE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) bp = at_breakpoint(regs->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (bp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) regs->nip = (unsigned long) &bp->instr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) atomic_inc(&bp->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) bp = at_breakpoint(regs->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (bp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int stepped = emulate_step(regs, ppc_inst_read(bp->instr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (stepped == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) regs->nip = (unsigned long) &bp->instr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) atomic_inc(&bp->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) } else if (stepped < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) printf("Couldn't single-step %s instruction\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) IS_RFID(ppc_inst_read(bp->instr))? "rfid": "mtmsrd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (locked_down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) clear_all_bpt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) insert_cpu_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) xmon_touch_watchdogs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return cmd != 'X' && cmd != EOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) int xmon(struct pt_regs *excp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct pt_regs regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (excp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ppc_save_regs(®s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) excp = ®s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return xmon_core(excp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) EXPORT_SYMBOL(xmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) irqreturn_t xmon_irq(int irq, void *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) printf("Keyboard interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) xmon(get_irq_regs());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static int xmon_bpt(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Are we at the trap at bp->instr[1] for some bp? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) bp = in_breakpoint_table(regs->nip, &offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (bp != NULL && (offset == 4 || offset == 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) regs->nip = bp->address + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) atomic_dec(&bp->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* Are we at a breakpoint? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) bp = at_breakpoint(regs->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) xmon_core(regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int xmon_sstep(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (user_mode(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) xmon_core(regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) static int xmon_break_match(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) for (i = 0; i < nr_wp_slots(); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (dabr[i].enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) xmon_core(regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static int xmon_iabr_match(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (iabr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) xmon_core(regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static int xmon_ipi(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) xmon_core(regs, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static int xmon_fault_handler(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (in_xmon && catch_memory_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) handle_fault(regs); /* doesn't return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) bp = in_breakpoint_table(regs->nip, &offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (bp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) regs->nip = bp->address + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) atomic_dec(&bp->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Force enable xmon if not already enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static inline void force_enable_xmon(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* Enable xmon hooks if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (!xmon_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) printf("xmon: Enabling debugger hooks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) xmon_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static struct bpt *at_breakpoint(unsigned long pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) bp = bpts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) for (i = 0; i < NBPTS; ++i, ++bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (bp->enabled && pc == bp->address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) unsigned long off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) off = nip - (unsigned long)bpt_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (off >= sizeof(bpt_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) *offp = off & (BPT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (off & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return bpts + (off / BPT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static struct bpt *new_breakpoint(unsigned long a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) a &= ~3UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) bp = at_breakpoint(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) bp->address = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) bp->instr = (void *)(bpt_table + ((bp - bpts) * BPT_WORDS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) printf("Sorry, no free breakpoints. Please clear one first.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static void insert_bpts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct ppc_inst instr, instr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct bpt *bp, *bp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) bp = bpts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) for (i = 0; i < NBPTS; ++i, ++bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (!mread_instr(bp->address, &instr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) printf("Couldn't read instruction at %lx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) "disabling breakpoint there\n", bp->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) bp->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (IS_MTMSRD(instr) || IS_RFID(instr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) printf("Breakpoint at %lx is on an mtmsrd or rfid "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) "instruction, disabling it\n", bp->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) bp->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * Check the address is not a suffix by looking for a prefix in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * front of it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (mread_instr(bp->address - 4, &instr2) == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) bp->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) bp->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * We might still be a suffix - if the prefix has already been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) * replaced by a breakpoint we won't catch it with the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) bp2 = at_breakpoint(bp->address - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (bp2 && ppc_inst_prefixed(ppc_inst_read(bp2->instr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) printf("Breakpoint at %lx is on the second word of a prefixed instruction, disabling it\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) bp->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) bp->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) patch_instruction(bp->instr, instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) patch_instruction(ppc_inst_next(bp->instr, &instr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ppc_inst(bpinstr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (bp->enabled & BP_CIABR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (patch_instruction((struct ppc_inst *)bp->address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) ppc_inst(bpinstr)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) printf("Couldn't write instruction at %lx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) "disabling breakpoint there\n", bp->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) bp->enabled &= ~BP_TRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) static void insert_cpu_bpts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct arch_hw_breakpoint brk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) for (i = 0; i < nr_wp_slots(); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (dabr[i].enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) brk.address = dabr[i].address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) brk.len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) brk.hw_len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) __set_breakpoint(i, &brk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (iabr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) set_ciabr(iabr->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) static void remove_bpts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) struct ppc_inst instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) bp = bpts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) for (i = 0; i < NBPTS; ++i, ++bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (mread_instr(bp->address, &instr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) && ppc_inst_equal(instr, ppc_inst(bpinstr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) && patch_instruction(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) (struct ppc_inst *)bp->address, ppc_inst_read(bp->instr)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) printf("Couldn't remove breakpoint at %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) bp->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static void remove_cpu_bpts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) hw_breakpoint_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) write_ciabr(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* Based on uptime_proc_show(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) show_uptime(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct timespec64 uptime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ktime_get_coarse_boottime_ts64(&uptime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) printf("Uptime: %lu.%.2lu seconds\n", (unsigned long)uptime.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ((unsigned long)uptime.tv_nsec / (NSEC_PER_SEC/100)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) __delay(200); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static void set_lpp_cmd(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) unsigned long lpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (!scanhex(&lpp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) printf("Invalid number.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) lpp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) xmon_set_pagination_lpp(lpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* Command interpreting routine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) static char *last_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) cmds(struct pt_regs *excp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) int cmd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) last_cmd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) xmon_regs = excp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) for(;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) printf("%x:", smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) #endif /* CONFIG_SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) printf("mon> ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) flush_input();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) cmd = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if( cmd == '\n' ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) if (last_cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) take_input(last_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) last_cmd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) memops(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) memlocate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case 'z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) memzcan();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) show_mem(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) termch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) memex();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) dump();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) symbol_lookup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) prregs(excp); /* print regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) excprint(excp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) super_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) backtrace(excp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) cacheflush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (do_spu_cmd() == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (do_step(excp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) case 'X':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (tracing_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) tracing_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) case EOF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) printf(" <no input ...>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) mdelay(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) case '?':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) xmon_puts(help_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) case '#':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) set_lpp_cmd();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) bpt_cmds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) case 'C':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) csum();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (cpu_cmd())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) case 'z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) bootcmds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) proccall();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) case 'P':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) show_tasks();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) #ifdef CONFIG_PPC_BOOK3S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) dump_segments();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) #elif defined(CONFIG_44x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) dump_tlb_44x();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) #elif defined(CONFIG_PPC_BOOK3E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) dump_tlb_book3e();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) case 'U':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) show_uptime();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) printf("Unrecognized command: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (' ' < cmd && cmd <= '~')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) putchar(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) printf("\\x%x", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) } while (cmd != '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) printf(" (type ? for help)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) #ifdef CONFIG_BOOKE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static int do_step(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) * Step a single instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) * Some instructions we emulate, others we execute with MSR_SE set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static int do_step(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) struct ppc_inst instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) int stepped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) force_enable_xmon();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* check we are in 64-bit kernel mode, translation enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (mread_instr(regs->nip, &instr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) stepped = emulate_step(regs, instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (stepped < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) printf("Couldn't single-step %s instruction\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) (IS_RFID(instr)? "rfid": "mtmsrd"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (stepped > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) set_trap(regs, 0xd00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) printf("stepped to ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) xmon_print_symbol(regs->nip, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ppc_inst_dump(regs->nip, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) regs->msr |= MSR_SE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) static void bootcmds(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) char tmp[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (cmd == 'r') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) getstring(tmp, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) ppc_md.restart(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) } else if (cmd == 'h') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) ppc_md.halt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) } else if (cmd == 'p') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (pm_power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) pm_power_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static int cpu_cmd(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) unsigned long cpu, first_cpu, last_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (!scanhex(&cpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) /* print cpus waiting or in xmon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) printf("cpus stopped:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) last_cpu = first_cpu = NR_CPUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (cpu == last_cpu + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) last_cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (last_cpu != first_cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) printf("-0x%lx", last_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) last_cpu = first_cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) printf(" 0x%lx", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (last_cpu != first_cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) printf("-0x%lx", last_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) /* try to switch to cpu specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) printf("cpu 0x%lx isn't in xmon\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) printf("backtrace of paca[0x%lx].saved_r1 (possibly stale):\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) xmon_show_stack(paca_ptrs[cpu]->saved_r1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) xmon_taken = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) xmon_owner = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) timeout = 10000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) while (!xmon_taken) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (--timeout == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (test_and_set_bit(0, &xmon_taken))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) /* take control back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) xmon_owner = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) printf("cpu 0x%lx didn't take control\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) #endif /* CONFIG_SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) static unsigned short fcstab[256] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) csum(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) unsigned short fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) unsigned char v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (!scanhex(&adrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (!scanhex(&ncsum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) fcs = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) for (i = 0; i < ncsum; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (mread(adrs+i, &v, 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) printf("csum stopped at "REG"\n", adrs+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) fcs = FCS(fcs, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) printf("%x\n", fcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * Check if this is a suitable place to put a breakpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) static long check_bp_loc(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) struct ppc_inst instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) addr &= ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if (!is_kernel_addr(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) printf("Breakpoints may only be placed at kernel addresses\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (!mread_instr(addr, &instr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) printf("Can't read instruction at address %lx\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (IS_MTMSRD(instr) || IS_RFID(instr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) printf("Breakpoints may not be placed on mtmsrd or rfid "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) "instructions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) #ifndef CONFIG_PPC_8xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) static int find_free_data_bpt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) for (i = 0; i < nr_wp_slots(); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (!dabr[i].enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) printf("Couldn't find free breakpoint register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) static void print_data_bpts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) for (i = 0; i < nr_wp_slots(); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (!dabr[i].enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) printf(" data "REG" [", dabr[i].address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (dabr[i].enabled & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) printf("r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (dabr[i].enabled & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) printf("w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) printf("]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) static char *breakpoint_help_string =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) "Breakpoint command usage:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) "b show breakpoints\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) "b <addr> [cnt] set breakpoint at given instr addr\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) "bc clear all breakpoints\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) "bc <n/addr> clear breakpoint number n or at addr\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) "bi <addr> [cnt] set hardware instr breakpoint (POWER8 only)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) "bd <addr> [cnt] set hardware data breakpoint\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) bpt_cmds(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) unsigned long a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) struct bpt *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) #ifndef CONFIG_PPC_8xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) case 'd': /* bd - hardware data breakpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (!ppc_breakpoint_available()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) printf("Hardware data breakpoint not supported on this cpu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) i = find_free_data_bpt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) mode = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (cmd == 'r')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) mode = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) else if (cmd == 'w')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) mode = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) termch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) dabr[i].address = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) dabr[i].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (scanhex(&dabr[i].address)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (!is_kernel_addr(dabr[i].address)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) printf(badaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) dabr[i].address &= ~HW_BRK_TYPE_DABR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) dabr[i].enabled = mode | BP_DABR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) force_enable_xmon();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) case 'i': /* bi - hardware instr breakpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) printf("Hardware instruction breakpoint "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) "not supported on this cpu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (iabr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) iabr->enabled &= ~BP_CIABR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) iabr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) if (!scanhex(&a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (!check_bp_loc(a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) bp = new_breakpoint(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (bp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) bp->enabled |= BP_CIABR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) iabr = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) force_enable_xmon();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (!scanhex(&a)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) /* clear all breakpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) for (i = 0; i < NBPTS; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) bpts[i].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) iabr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) for (i = 0; i < nr_wp_slots(); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) dabr[i].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) printf("All breakpoints cleared\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (a <= NBPTS && a >= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) /* assume a breakpoint number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) bp = &bpts[a-1]; /* bp nums are 1 based */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) /* assume a breakpoint address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) bp = at_breakpoint(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) if (bp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) printf("No breakpoint at %lx\n", a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) printf("Cleared breakpoint %tx (", BP_NUM(bp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) xmon_print_symbol(bp->address, " ", ")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) bp->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) termch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) cmd = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (cmd == '?') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) printf(breakpoint_help_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) termch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if (xmon_is_ro || !scanhex(&a)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) /* print all breakpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) printf(" type address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) print_data_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (!bp->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) printf("%tx %s ", BP_NUM(bp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) (bp->enabled & BP_CIABR) ? "inst": "trap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) xmon_print_symbol(bp->address, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (!check_bp_loc(a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) bp = new_breakpoint(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (bp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) bp->enabled |= BP_TRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) force_enable_xmon();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) /* Very cheap human name for vector lookup. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) const char *getvecname(unsigned long vec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) char *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) switch (vec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) case 0x100: ret = "(System Reset)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) case 0x200: ret = "(Machine Check)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) case 0x300: ret = "(Data Access)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) case 0x380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) if (radix_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) ret = "(Data Access Out of Range)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) ret = "(Data SLB Access)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) case 0x400: ret = "(Instruction Access)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) case 0x480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (radix_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) ret = "(Instruction Access Out of Range)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) ret = "(Instruction SLB Access)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) case 0x500: ret = "(Hardware Interrupt)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) case 0x600: ret = "(Alignment)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) case 0x700: ret = "(Program Check)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) case 0x800: ret = "(FPU Unavailable)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) case 0x900: ret = "(Decrementer)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) case 0x980: ret = "(Hypervisor Decrementer)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) case 0xa00: ret = "(Doorbell)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) case 0xc00: ret = "(System Call)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) case 0xd00: ret = "(Single Step)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) case 0xe40: ret = "(Emulation Assist)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) case 0xe60: ret = "(HMI)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) case 0xe80: ret = "(Hypervisor Doorbell)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) case 0xf00: ret = "(Performance Monitor)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) case 0xf20: ret = "(Altivec Unavailable)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) case 0x1300: ret = "(Instruction Breakpoint)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) case 0x1500: ret = "(Denormalisation)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) case 0x1700: ret = "(Altivec Assist)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) case 0x3000: ret = "(System Call Vectored)"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) default: ret = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) static void get_function_bounds(unsigned long pc, unsigned long *startp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) unsigned long *endp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) unsigned long size, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) *startp = *endp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (pc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (name != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) *startp = pc - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) *endp = pc - offset + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) static void xmon_show_stack(unsigned long sp, unsigned long lr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) unsigned long pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) int max_to_print = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) unsigned long ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) unsigned long newsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) unsigned long marker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) struct pt_regs regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) while (max_to_print--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) if (!is_kernel_addr(sp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) if (sp != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) printf("SP (%lx) is in userspace\n", sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) || !mread(sp, &newsp, sizeof(unsigned long))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) printf("Couldn't read stack frame at %lx\n", sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * For the first stack frame, try to work out if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * LR and/or the saved LR value in the bottommost
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) * stack frame are valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if ((pc | lr) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) unsigned long fnstart, fnend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) unsigned long nextip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) int printip = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) get_function_bounds(pc, &fnstart, &fnend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) nextip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (newsp > sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) mread(newsp + LRSAVE_OFFSET, &nextip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (lr == ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) if (!is_kernel_addr(lr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) || (fnstart <= lr && lr < fnend))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) printip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) } else if (lr == nextip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) printip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) } else if (is_kernel_addr(lr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) && !(fnstart <= lr && lr < fnend)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) printf("[link register ] ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) xmon_print_symbol(lr, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (printip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) printf("["REG"] ", sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) xmon_print_symbol(ip, " ", " (unreliable)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) pc = lr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) printf("["REG"] ", sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) xmon_print_symbol(ip, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) /* Look for "regshere" marker to see if this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) an exception frame. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) && marker == STACK_FRAME_REGS_MARKER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (mread(sp + STACK_FRAME_OVERHEAD, ®s, sizeof(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) != sizeof(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) printf("Couldn't read registers at %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) sp + STACK_FRAME_OVERHEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) printf("--- Exception: %lx %s at ", regs.trap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) getvecname(TRAP(®s)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) pc = regs.nip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) lr = regs.link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) xmon_print_symbol(pc, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) if (newsp == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) sp = newsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) static void backtrace(struct pt_regs *excp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) unsigned long sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (scanhex(&sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) xmon_show_stack(sp, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) scannl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) static void print_bug_trap(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) #ifdef CONFIG_BUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) const struct bug_entry *bug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) if (regs->msr & MSR_PR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return; /* not in kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) addr = regs->nip; /* address of trap instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (!is_kernel_addr(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) bug = find_bug(regs->nip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) if (bug == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (is_warning_bug(bug))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) #ifdef CONFIG_DEBUG_BUGVERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) printf("kernel BUG at %s:%u!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) bug->file, bug->line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) printf("kernel BUG at %px!\n", (void *)bug->bug_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) #endif /* CONFIG_BUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) static void excprint(struct pt_regs *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) unsigned long trap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) printf("cpu 0x%x: ", smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) #endif /* CONFIG_SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) trap = TRAP(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) printf("Vector: %lx %s at [%px]\n", fp->trap, getvecname(trap), fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) printf(" pc: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) xmon_print_symbol(fp->nip, ": ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) printf(" lr: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) xmon_print_symbol(fp->link, ": ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) printf(" sp: %lx\n", fp->gpr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) printf(" msr: %lx\n", fp->msr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) printf(" dar: %lx\n", fp->dar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (trap != 0x380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) printf(" dsisr: %lx\n", fp->dsisr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) printf(" current = 0x%px\n", current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) printf(" paca = 0x%px\t irqmask: 0x%02x\t irq_happened: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) local_paca, local_paca->irq_soft_mask, local_paca->irq_happened);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) if (current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) printf(" pid = %d, comm = %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) current->pid, current->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (trap == 0x700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) print_bug_trap(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) printf(linux_banner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) static void prregs(struct pt_regs *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) int n, trap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) struct pt_regs regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) if (scanhex(&base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) regs = *(struct pt_regs *)base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) printf("*** Error reading registers from "REG"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) fp = ®s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) if (FULL_REGS(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) for (n = 0; n < 16; ++n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) printf("R%.2d = "REG" R%.2d = "REG"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) n, fp->gpr[n], n+16, fp->gpr[n+16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) for (n = 0; n < 7; ++n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) printf("R%.2d = "REG" R%.2d = "REG"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) n, fp->gpr[n], n+7, fp->gpr[n+7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) for (n = 0; n < 32; ++n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) printf("R%.2d = %.8lx%s", n, fp->gpr[n],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) (n & 3) == 3? "\n": " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (n == 12 && !FULL_REGS(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) printf("pc = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) xmon_print_symbol(fp->nip, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if (!trap_is_syscall(fp) && cpu_has_feature(CPU_FTR_CFAR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) printf("cfar= ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) xmon_print_symbol(fp->orig_gpr3, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) printf("lr = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) xmon_print_symbol(fp->link, " ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) printf("ctr = "REG" xer = "REG" trap = %4lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) fp->ctr, fp->xer, fp->trap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) trap = TRAP(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (trap == 0x300 || trap == 0x380 || trap == 0x600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) static void cacheflush(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) unsigned long nflush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) if (cmd != 'i')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) termch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) scanhex((void *)&adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) if (termch != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) nflush = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) scanhex(&nflush);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) if (cmd != 'i' || IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) cflush((void *) adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) cinval((void *) adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) extern unsigned long xmon_mfspr(int spr, unsigned long default_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) extern void xmon_mtspr(int spr, unsigned long value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) read_spr(int n, unsigned long *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) unsigned long ret = -1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) int ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) catch_spr_faults = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) ret = xmon_mfspr(n, *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) *vp = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) catch_spr_faults = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) return ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) write_spr(int n, unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) catch_spr_faults = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) xmon_mtspr(n, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) printf("SPR 0x%03x (%4d) Faulted during write\n", n, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) catch_spr_faults = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) static void dump_206_sprs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (!cpu_has_feature(CPU_FTR_ARCH_206))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) /* Actually some of these pre-date 2.06, but whatevs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) printf("dscr = %.16lx ppr = %.16lx pir = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) mfspr(SPRN_DSCR), mfspr(SPRN_PPR), mfspr(SPRN_PIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) printf("amr = %.16lx uamor = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) mfspr(SPRN_AMR), mfspr(SPRN_UAMOR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) if (!(mfmsr() & MSR_HV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) printf("sdr1 = %.16lx hdar = %.16lx hdsisr = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) mfspr(SPRN_SDR1), mfspr(SPRN_HDAR), mfspr(SPRN_HDSISR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) printf("hsrr0 = %.16lx hsrr1 = %.16lx hdec = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) mfspr(SPRN_HSRR0), mfspr(SPRN_HSRR1), mfspr(SPRN_HDEC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) printf("lpcr = %.16lx pcr = %.16lx lpidr = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) mfspr(SPRN_LPCR), mfspr(SPRN_PCR), mfspr(SPRN_LPID));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) printf("hsprg0 = %.16lx hsprg1 = %.16lx amor = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) mfspr(SPRN_HSPRG0), mfspr(SPRN_HSPRG1), mfspr(SPRN_AMOR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) printf("dabr = %.16lx dabrx = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) mfspr(SPRN_DABR), mfspr(SPRN_DABRX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) static void dump_207_sprs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) unsigned long msr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) if (!cpu_has_feature(CPU_FTR_ARCH_207S))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) printf("dpdes = %.16lx tir = %.16lx cir = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) mfspr(SPRN_DPDES), mfspr(SPRN_TIR), mfspr(SPRN_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) printf("fscr = %.16lx tar = %.16lx pspb = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) mfspr(SPRN_FSCR), mfspr(SPRN_TAR), mfspr(SPRN_PSPB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) msr = mfmsr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (msr & MSR_TM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) /* Only if TM has been enabled in the kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) printf("tfhar = %.16lx tfiar = %.16lx texasr = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) mfspr(SPRN_TFHAR), mfspr(SPRN_TFIAR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) mfspr(SPRN_TEXASR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) printf("pmc1 = %.8lx pmc2 = %.8lx pmc3 = %.8lx pmc4 = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) mfspr(SPRN_PMC1), mfspr(SPRN_PMC2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) mfspr(SPRN_PMC3), mfspr(SPRN_PMC4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) printf("sdar = %.16lx sier = %.16lx pmc6 = %.8lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) printf("iamr = %.16lx\n", mfspr(SPRN_IAMR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if (!(msr & MSR_HV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) printf("dawr0 = %.16lx dawrx0 = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) mfspr(SPRN_DAWR0), mfspr(SPRN_DAWRX0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) if (nr_wp_slots() > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) printf("dawr1 = %.16lx dawrx1 = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) mfspr(SPRN_DAWR1), mfspr(SPRN_DAWRX1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) printf("ciabr = %.16lx\n", mfspr(SPRN_CIABR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) static void dump_300_sprs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) bool hv = mfmsr() & MSR_HV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if (!cpu_has_feature(CPU_FTR_ARCH_300))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) printf("pidr = %.16lx tidr = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) mfspr(SPRN_PID), mfspr(SPRN_TIDR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) printf("psscr = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) hv ? mfspr(SPRN_PSSCR) : mfspr(SPRN_PSSCR_PR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) if (!hv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) printf("ptcr = %.16lx asdr = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) mfspr(SPRN_PTCR), mfspr(SPRN_ASDR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) static void dump_310_sprs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) if (!cpu_has_feature(CPU_FTR_ARCH_31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) printf("mmcr3 = %.16lx, sier2 = %.16lx, sier3 = %.16lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) mfspr(SPRN_MMCR3), mfspr(SPRN_SIER2), mfspr(SPRN_SIER3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) static void dump_one_spr(int spr, bool show_unimplemented)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) val = 0xdeadbeef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) if (!read_spr(spr, &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (val == 0xdeadbeef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) /* Looks like read was a nop, confirm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) val = 0x0badcafe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) if (!read_spr(spr, &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (val == 0x0badcafe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) if (show_unimplemented)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) printf("SPR 0x%03x (%4d) Unimplemented\n", spr, spr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) printf("SPR 0x%03x (%4d) = 0x%lx\n", spr, spr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) static void super_regs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) static unsigned long regno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) int spr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) cmd = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) case '\n': {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) unsigned long sp, toc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) asm("mr %0,1" : "=r" (sp) :);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) asm("mr %0,2" : "=r" (toc) :);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) printf("msr = "REG" sprg0 = "REG"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) mfmsr(), mfspr(SPRN_SPRG0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) printf("pvr = "REG" sprg1 = "REG"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) printf("dec = "REG" sprg2 = "REG"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) printf("sp = "REG" sprg3 = "REG"\n", sp, mfspr(SPRN_SPRG3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) dump_206_sprs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) dump_207_sprs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) dump_300_sprs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) dump_310_sprs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) case 'w': {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) scanhex(®no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) read_spr(regno, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) scanhex(&val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) write_spr(regno, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) dump_one_spr(regno, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) scanhex(®no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) dump_one_spr(regno, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) /* dump ALL SPRs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) for (spr = 1; spr < 1024; ++spr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) dump_one_spr(spr, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) scannl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) * Stuff for reading and writing memory safely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) mread(unsigned long adrs, void *buf, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) volatile int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) char *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) p = (char *)adrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) q = (char *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) *(u16 *)q = *(u16 *)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) *(u32 *)q = *(u32 *)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) *(u64 *)q = *(u64 *)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) for( ; n < size; ++n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) *q++ = *p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) n = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) mwrite(unsigned long adrs, void *buf, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) volatile int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) char *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) p = (char *) adrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) q = (char *) buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) *(u16 *)p = *(u16 *)q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) *(u32 *)p = *(u32 *)q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) *(u64 *)p = *(u64 *)q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) for ( ; n < size; ++n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) *p++ = *q++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) n = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) printf("*** Error writing address "REG"\n", adrs + n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) mread_instr(unsigned long adrs, struct ppc_inst *instr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) volatile int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) *instr = ppc_inst_read((struct ppc_inst *)adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) n = ppc_inst_len(*instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) static int fault_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) static int fault_except;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) static char *fault_chars[] = { "--", "**", "##" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) static int handle_fault(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) fault_except = TRAP(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) switch (TRAP(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) case 0x200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) fault_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) case 0x300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) case 0x380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) fault_type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) fault_type = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) longjmp(bus_error_jmp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) byterev(unsigned char *val, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) int t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) SWAP(val[0], val[1], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) SWAP(val[0], val[3], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) SWAP(val[1], val[2], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) case 8: /* is there really any use for this? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) SWAP(val[0], val[7], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) SWAP(val[1], val[6], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) SWAP(val[2], val[5], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) SWAP(val[3], val[4], t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) static int brev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) static int mnoread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) static char *memex_help_string =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) "Memory examine command usage:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) "m [addr] [flags] examine/change memory\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) " addr is optional. will start where left off.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) " flags may include chars from this set:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) " b modify by bytes (default)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) " w modify by words (2 byte)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) " l modify by longs (4 byte)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) " d modify by doubleword (8 byte)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) " r toggle reverse byte order mode\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) " n do not read memory (for i/o spaces)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) " . ok to read (default)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) "NOTE: flags are saved as defaults\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) static char *memex_subcmd_help_string =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) "Memory examine subcommands:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) " hexval write this val to current location\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) " 'string' write chars from string to this location\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) " ' increment address\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) " ^ decrement address\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) " ` clear no-read flag\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) " ; stay at this addr\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) " v change to byte mode\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) " w change to word (2 byte) mode\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) " l change to long (4 byte) mode\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) " u change to doubleword (8 byte) mode\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) " m addr change current addr\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) " n toggle no-read flag\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) " r toggle byte reverse flag\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) " < count back up count bytes\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) " > count skip forward count bytes\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) " x exit this mode\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) memex(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) int cmd, inc, i, nslash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) unsigned long n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) unsigned char val[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) scanhex((void *)&adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) cmd = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (cmd == '?') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) printf(memex_help_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) termch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) last_cmd = "m\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) while ((cmd = skipbl()) != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) switch( cmd ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) case 'b': size = 1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) case 'w': size = 2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) case 'l': size = 4; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) case 'd': size = 8; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) case 'r': brev = !brev; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) case 'n': mnoread = 1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) case '.': mnoread = 0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) if( size <= 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) else if( size > 8 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) size = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) for(;;){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) if (!mnoread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) n = mread(adrs, val, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) printf(REG"%c", adrs, brev? 'r': ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) if (!mnoread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) if (brev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) byterev(val, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) for (i = 0; i < n; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) printf("%.2x", val[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) for (; i < size; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) printf("%s", fault_chars[fault_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) inc = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) nslash = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) for(;;){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) if( scanhex(&n) ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) for (i = 0; i < size; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) val[i] = n >> (i * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) if (!brev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) byterev(val, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) mwrite(adrs, val, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) inc = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) cmd = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) if (cmd == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) inc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) case '\'':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) for(;;){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) n = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) if( n == '\\' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) n = bsesc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) else if( n == '\'' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) for (i = 0; i < size; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) val[i] = n >> (i * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) if (!brev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) byterev(val, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) mwrite(adrs, val, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) adrs += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) adrs -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) inc = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) case ',':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) adrs += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) case '.':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) mnoread = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) case ';':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) case EOF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) scannl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) case 'v':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) case 'w':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) size = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) size = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) case '^':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) adrs -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) case '/':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) if (nslash > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) adrs -= 1 << nslash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) nslash = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) nslash += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) adrs += 1 << nslash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) case '\\':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) if (nslash < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) adrs += 1 << -nslash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) nslash = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) nslash -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) adrs -= 1 << -nslash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) scanhex((void *)&adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) mnoread = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) brev = !brev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) case '<':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) n = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) scanhex(&n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) adrs -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) case '>':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) n = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) scanhex(&n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) adrs += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) case '?':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) printf(memex_subcmd_help_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) adrs += inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) bsesc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) switch( c ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) case 'n': c = '\n'; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) case 'r': c = '\r'; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) case 'b': c = '\b'; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) case 't': c = '\t'; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) static void xmon_rawdump (unsigned long adrs, long ndump)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) long n, m, r, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) unsigned char temp[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) for (n = ndump; n > 0;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) r = n < 16? n: 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) nr = mread(adrs, temp, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) adrs += nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) for (m = 0; m < r; ++m) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) if (m < nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) printf("%.2x", temp[m]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) printf("%s", fault_chars[fault_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) n -= r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) if (nr < r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) static void dump_tracing(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) if (c == 'c')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) ftrace_dump(DUMP_ORIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) ftrace_dump(DUMP_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) static void dump_one_paca(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) struct paca_struct *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) if (setjmp(bus_error_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) p = paca_ptrs[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) printf("paca for cpu 0x%x @ %px:\n", cpu, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) printf(" %-*s = %s\n", 25, "possible", cpu_possible(cpu) ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) printf(" %-*s = %s\n", 25, "present", cpu_present(cpu) ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) printf(" %-*s = %s\n", 25, "online", cpu_online(cpu) ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) #define DUMP(paca, name, format) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) printf(" %-*s = "format"\t(0x%lx)\n", 25, #name, 18, paca->name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) offsetof(struct paca_struct, name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) DUMP(p, lock_token, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) DUMP(p, paca_index, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) DUMP(p, kernel_toc, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) DUMP(p, kernelbase, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) DUMP(p, kernel_msr, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) DUMP(p, emergency_sp, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) DUMP(p, nmi_emergency_sp, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) DUMP(p, mc_emergency_sp, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) DUMP(p, in_nmi, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) DUMP(p, in_mce, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) DUMP(p, hmi_event_available, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) DUMP(p, data_offset, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) DUMP(p, hw_cpu_id, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) DUMP(p, cpu_start, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) DUMP(p, kexec_state, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) if (!early_radix_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) for (i = 0; i < SLB_NUM_BOLTED; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) u64 esid, vsid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) if (!p->slb_shadow_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) if (esid || vsid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) printf(" %-*s[%d] = 0x%016llx 0x%016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 22, "slb_shadow", i, esid, vsid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) DUMP(p, vmalloc_sllp, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) DUMP(p, stab_rr, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) DUMP(p, slb_used_bitmap, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) DUMP(p, slb_kern_bitmap, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) DUMP(p, slb_cache_ptr, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) for (i = 0; i < SLB_CACHE_ENTRIES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) printf(" %-*s[%d] = 0x%016x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) 22, "slb_cache", i, p->slb_cache[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) DUMP(p, rfi_flush_fallback_area, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) DUMP(p, dscr_default, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) #ifdef CONFIG_PPC_BOOK3E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) DUMP(p, pgd, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) DUMP(p, kernel_pgd, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) DUMP(p, tcd_ptr, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) DUMP(p, mc_kstack, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) DUMP(p, crit_kstack, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) DUMP(p, dbg_kstack, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) DUMP(p, __current, "%-*px");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) DUMP(p, kstack, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) #ifdef CONFIG_STACKPROTECTOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) DUMP(p, canary, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) DUMP(p, saved_r1, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) #ifdef CONFIG_PPC_BOOK3E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) DUMP(p, trap_save, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) DUMP(p, irq_soft_mask, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) DUMP(p, irq_happened, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) #ifdef CONFIG_MMIOWB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) DUMP(p, mmiowb_state.nesting_count, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) DUMP(p, mmiowb_state.mmiowb_pending, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) DUMP(p, irq_work_pending, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) DUMP(p, sprg_vdso, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) DUMP(p, tm_scratch, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) DUMP(p, idle_state, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) DUMP(p, thread_idle_state, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) DUMP(p, subcore_sibling_mask, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) DUMP(p, requested_psscr, "%#-*llx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) DUMP(p, dont_stop.counter, "%#-*x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) DUMP(p, accounting.utime, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) DUMP(p, accounting.stime, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) DUMP(p, accounting.utime_scaled, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) DUMP(p, accounting.starttime, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) DUMP(p, accounting.starttime_user, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) DUMP(p, accounting.startspurr, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) DUMP(p, accounting.utime_sspurr, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) DUMP(p, accounting.steal_time, "%#-*lx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) #undef DUMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) static void dump_all_pacas(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) if (num_possible_cpus() == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) printf("No possible cpus, use 'dp #' to dump individual cpus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) for_each_possible_cpu(cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) dump_one_paca(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) static void dump_pacas(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) unsigned long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) if (c == 'a') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) dump_all_pacas();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) termch = c; /* Put c back, it wasn't 'a' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) if (scanhex(&num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) dump_one_paca(num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) dump_one_paca(xmon_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) static void dump_one_xive(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) unsigned int hwid = get_hard_smp_processor_id(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) bool hv = cpu_has_feature(CPU_FTR_HVMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) if (hv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) opal_xive_dump(XIVE_DUMP_TM_HYP, hwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) opal_xive_dump(XIVE_DUMP_TM_POOL, hwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) opal_xive_dump(XIVE_DUMP_TM_OS, hwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) opal_xive_dump(XIVE_DUMP_TM_USER, hwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) opal_xive_dump(XIVE_DUMP_VP, hwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) opal_xive_dump(XIVE_DUMP_EMU_STATE, hwid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) if (setjmp(bus_error_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) printf("*** Error dumping xive on cpu %d\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) xmon_xive_do_dump(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) static void dump_all_xives(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) if (num_possible_cpus() == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) printf("No possible cpus, use 'dx #' to dump individual cpus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) for_each_possible_cpu(cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) dump_one_xive(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) static void dump_one_xive_irq(u32 num, struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) xmon_xive_get_irq_config(num, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) static void dump_all_xive_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) struct irq_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) for_each_irq_desc(i, desc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) struct irq_data *d = irq_desc_get_irq_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) unsigned int hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) hwirq = (unsigned int)irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) /* IPIs are special (HW number 0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) if (hwirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) dump_one_xive_irq(hwirq, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) static void dump_xives(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) unsigned long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) if (!xive_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) printf("Xive disabled on this system\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) if (c == 'a') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) dump_all_xives();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) } else if (c == 'i') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) if (scanhex(&num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) dump_one_xive_irq(num, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) dump_all_xive_irq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) termch = c; /* Put c back, it wasn't 'a' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) if (scanhex(&num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) dump_one_xive(num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) dump_one_xive(xmon_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) #endif /* CONFIG_PPC_POWERNV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) static void dump_by_size(unsigned long addr, long count, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) unsigned char temp[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) count = ALIGN(count, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) for (i = 0; i < count; i += 16, addr += 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) printf(REG, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) if (mread(addr, temp, 16) != 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) printf("\nFaulted reading %d bytes from 0x"REG"\n", 16, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) for (j = 0; j < 16; j += size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) case 1: val = temp[j]; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) case 2: val = *(u16 *)&temp[j]; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) case 4: val = *(u32 *)&temp[j]; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) case 8: val = *(u64 *)&temp[j]; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) default: val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) printf("%0*llx", size * 2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) printf(" |");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) for (j = 0; j < 16; ++j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) val = temp[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) putchar(' ' <= val && val <= '~' ? val : '.');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) printf("|\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) dump(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) static char last[] = { "d?\n" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) if (c == 'p') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) xmon_start_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) dump_pacas();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) xmon_end_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) if (c == 'x') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) xmon_start_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) dump_xives();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) xmon_end_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) if (c == 't') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) dump_tracing();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) if (c == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) scanhex((void *)&adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) if (termch != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) if (c == 'i') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) scanhex(&nidump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) if (nidump == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) nidump = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) else if (nidump > MAX_IDUMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) nidump = MAX_IDUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) adrs += ppc_inst_dump(adrs, nidump, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) last_cmd = "di\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) } else if (c == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) dump_log_buf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) } else if (c == 'o') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) dump_opal_msglog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) } else if (c == 'v') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) /* dump virtual to physical translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) show_pte(adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) } else if (c == 'r') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) scanhex(&ndump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) if (ndump == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) ndump = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) xmon_rawdump(adrs, ndump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) adrs += ndump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) last_cmd = "dr\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) scanhex(&ndump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) if (ndump == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) ndump = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) else if (ndump > MAX_DUMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) ndump = MAX_DUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) case '8':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) case '4':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) case '2':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) ndump = ALIGN(ndump, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) dump_by_size(adrs, ndump, c - '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) last[1] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) last_cmd = last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) prdump(adrs, ndump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) last_cmd = "d\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) adrs += ndump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) prdump(unsigned long adrs, long ndump)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) long n, m, c, r, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) unsigned char temp[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) for (n = ndump; n > 0;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) printf(REG, adrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) r = n < 16? n: 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) nr = mread(adrs, temp, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) adrs += nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) for (m = 0; m < r; ++m) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) if ((m & (sizeof(long) - 1)) == 0 && m > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) if (m < nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) printf("%.2x", temp[m]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) printf("%s", fault_chars[fault_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) for (; m < 16; ++m) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) if ((m & (sizeof(long) - 1)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) printf(" ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) printf(" |");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) for (m = 0; m < r; ++m) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) if (m < nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) c = temp[m];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) putchar(' ' <= c && c <= '~'? c: '.');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) n -= r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) for (; m < 16; ++m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) putchar(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) printf("|\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) if (nr < r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) generic_inst_dump(unsigned long adr, long count, int praddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) instruction_dump_func dump_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) int nr, dotted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) unsigned long first_adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) struct ppc_inst inst, last_inst = ppc_inst(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) dotted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) for (first_adr = adr; count > 0; --count, adr += ppc_inst_len(inst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) nr = mread_instr(adr, &inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) if (nr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) if (praddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) const char *x = fault_chars[fault_type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) printf(REG" %s%s%s%s\n", adr, x, x, x, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) if (adr > first_adr && ppc_inst_equal(inst, last_inst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) if (!dotted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) printf(" ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) dotted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) dotted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) last_inst = inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) if (praddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) printf(REG" %s", adr, ppc_inst_as_str(inst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) printf("\t");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) if (!ppc_inst_prefixed(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) dump_func(ppc_inst_val(inst), adr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) dump_func(ppc_inst_as_u64(inst), adr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) return adr - first_adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) ppc_inst_dump(unsigned long adr, long count, int praddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) print_address(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) xmon_print_symbol(addr, "\t# ", "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) dump_log_buf(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) struct kmsg_dumper dumper = { .active = 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) unsigned char buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) if (setjmp(bus_error_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) printf("Error dumping printk buffer!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) kmsg_dump_rewind_nolock(&dumper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) xmon_start_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) buf[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) printf("%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) xmon_end_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) static void dump_opal_msglog(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) unsigned char buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) ssize_t res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) loff_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) if (!firmware_has_feature(FW_FEATURE_OPAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) printf("Machine is not running OPAL firmware.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) if (setjmp(bus_error_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) printf("Error dumping OPAL msglog!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) xmon_start_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) if (res < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) printf("Error dumping OPAL msglog! Error: %zd\n", res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) buf[res] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) printf("%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) pos += res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) xmon_end_pagination();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) * Memory operations - move, set, print differences
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) static unsigned long mdest; /* destination address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) static unsigned long msrc; /* source address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) static unsigned long mval; /* byte value to set memory to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) static unsigned long mcount; /* # bytes to affect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) static unsigned long mdiffs; /* max # differences to print */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) memops(int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) scanhex((void *)&mdest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) if( termch != '\n' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) scanhex((void *)(cmd == 's'? &mval: &msrc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) if( termch != '\n' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) scanhex((void *)&mcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) switch( cmd ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) memmove((void *)mdest, (void *)msrc, mcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) if (xmon_is_ro) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) printf(xmon_ro_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) memset((void *)mdest, mval, mcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) if( termch != '\n' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) scanhex((void *)&mdiffs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) unsigned n, prt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) prt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) for( n = nb; n > 0; --n )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) if( *p1++ != *p2++ )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) if( ++prt <= maxpr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) printf("%px %.2x # %px %.2x\n", p1 - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) p1[-1], p2 - 1, p2[-1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) if( prt > maxpr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) printf("Total of %d differences\n", prt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) static unsigned mend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) static unsigned mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) memlocate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) unsigned a, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) unsigned char val[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) last_cmd = "ml";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) scanhex((void *)&mdest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) if (termch != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) scanhex((void *)&mend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) if (termch != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) scanhex((void *)&mval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) mask = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) if (termch != '\n') termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) scanhex((void *)&mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) for (a = mdest; a < mend; a += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) if (mread(a, val, 4) == 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) && ((GETWORD(val) ^ mval) & mask) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) printf("%.16x: %.16x\n", a, GETWORD(val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) if (++n >= 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) static unsigned long mskip = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) static unsigned long mlim = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) memzcan(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) unsigned char v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) unsigned a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) int ok, ook;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) scanhex(&mdest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) if (termch != '\n') termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) scanhex(&mskip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) if (termch != '\n') termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) scanhex(&mlim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) ook = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) for (a = mdest; a < mlim; a += mskip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) ok = mread(a, &v, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) if (ok && !ook) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) printf("%.8x .. ", a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) } else if (!ok && ook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) printf("%.8lx\n", a - mskip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) ook = ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) if (a + mskip < a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) if (ook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) printf("%.8lx\n", a - mskip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) static void show_task(struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) char state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) * Cloned from kdb_task_state_char(), which is not entirely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) * appropriate for calling from xmon. This could be moved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) * to a common, generic, routine used by both.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) state = (tsk->state == 0) ? 'R' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) (tsk->state < 0) ? 'U' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) (tsk->state & TASK_UNINTERRUPTIBLE) ? 'D' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) (tsk->state & TASK_STOPPED) ? 'T' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) (tsk->state & TASK_TRACED) ? 'C' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) (tsk->exit_state & EXIT_ZOMBIE) ? 'Z' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) (tsk->exit_state & EXIT_DEAD) ? 'E' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) printf("%16px %16lx %16px %6d %6d %c %2d %s\n", tsk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) tsk->thread.ksp, tsk->thread.regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) tsk->pid, rcu_dereference(tsk->parent)->pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) state, task_cpu(tsk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) tsk->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) static void format_pte(void *ptep, unsigned long pte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) pte_t entry = __pte(pte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) printf("Flags = %s%s%s%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) pte_young(entry) ? "Accessed " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) pte_dirty(entry) ? "Dirty " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) pte_read(entry) ? "Read " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) pte_write(entry) ? "Write " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) pte_exec(entry) ? "Exec " : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) static void show_pte(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) unsigned long tskv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) struct task_struct *tsk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) struct mm_struct *mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) pgd_t *pgdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) p4d_t *p4dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) pud_t *pudp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) pmd_t *pmdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) pte_t *ptep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) if (!scanhex(&tskv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) mm = &init_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) tsk = (struct task_struct *)tskv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) if (tsk == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) mm = &init_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) mm = tsk->active_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) if (setjmp(bus_error_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) printf("*** Error dumping pte for task %px\n", tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) if (mm == &init_mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) pgdp = pgd_offset_k(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) pgdp = pgd_offset(mm, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) p4dp = p4d_offset(pgdp, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) if (p4d_none(*p4dp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) printf("No valid P4D\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) if (p4d_is_leaf(*p4dp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) format_pte(p4dp, p4d_val(*p4dp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) printf("p4dp @ 0x%px = 0x%016lx\n", p4dp, p4d_val(*p4dp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) pudp = pud_offset(p4dp, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) if (pud_none(*pudp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) printf("No valid PUD\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) if (pud_is_leaf(*pudp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) format_pte(pudp, pud_val(*pudp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) printf("pudp @ 0x%px = 0x%016lx\n", pudp, pud_val(*pudp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) pmdp = pmd_offset(pudp, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) if (pmd_none(*pmdp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) printf("No valid PMD\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) if (pmd_is_leaf(*pmdp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) format_pte(pmdp, pmd_val(*pmdp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) printf("pmdp @ 0x%px = 0x%016lx\n", pmdp, pmd_val(*pmdp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) ptep = pte_offset_map(pmdp, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) if (pte_none(*ptep)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) printf("no valid PTE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) format_pte(ptep, pte_val(*ptep));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) static void show_pte(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) printf("show_pte not yet implemented\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) #endif /* CONFIG_PPC_BOOK3S_64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) static void show_tasks(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) unsigned long tskv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) struct task_struct *tsk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) printf(" task_struct ->thread.ksp ->thread.regs PID PPID S P CMD\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) if (scanhex(&tskv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) tsk = (struct task_struct *)tskv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) if (setjmp(bus_error_jmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) printf("*** Error dumping task %px\n", tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) if (tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) show_task(tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) for_each_process(tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) show_task(tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) static void proccall(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) unsigned long args[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) unsigned long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) unsigned long, unsigned long, unsigned long,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) unsigned long, unsigned long, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) callfunc_t func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) if (!scanhex(&adrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) if (termch != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) for (i = 0; i < 8; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) args[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) for (i = 0; i < 8; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) if (!scanhex(&args[i]) || termch == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) func = (callfunc_t) adrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) ret = func(args[0], args[1], args[2], args[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) args[4], args[5], args[6], args[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) printf("return value is 0x%lx\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) printf("*** %x exception occurred\n", fault_except);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) /* Input scanning routines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) skipbl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) if( termch != 0 ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) c = termch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) while( c == ' ' || c == '\t' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) #define N_PTREGS 44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) static const char *regnames[N_PTREGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) "softe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) "mq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) "trap", "dar", "dsisr", "res"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) scanhex(unsigned long *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) int c, d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) c = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) if (c == '%') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) /* parse register name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) char regname[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) for (i = 0; i < sizeof(regname) - 1; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) if (!isalnum(c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) regname[i] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) regname[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) i = match_string(regnames, N_PTREGS, regname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) if (i < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) printf("invalid register name '%%%s'\n", regname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) if (xmon_regs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) printf("regs not available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) *vp = ((unsigned long *)xmon_regs)[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) /* skip leading "0x" if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) if (c == '0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) if (c == 'x') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) d = hexdigit(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) if (d == EOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) *vp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) } else if (c == '$') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) for (i=0; i<63; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) if (isspace(c) || c == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) tmpstr[i] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) tmpstr[i++] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) *vp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) *vp = kallsyms_lookup_name(tmpstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) if (!(*vp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) printf("unknown symbol '%s'\n", tmpstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) d = hexdigit(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) if (d == EOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) v = (v << 4) + d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) d = hexdigit(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) } while (d != EOF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) *vp = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) scannl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) c = termch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) while( c != '\n' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) static int hexdigit(int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) if( '0' <= c && c <= '9' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) return c - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) if( 'A' <= c && c <= 'F' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) return c - ('A' - 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) if( 'a' <= c && c <= 'f' )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) return c - ('a' - 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) return EOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) getstring(char *s, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) c = skipbl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) if (c == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) *s = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) if( size > 1 ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) *s++ = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) --size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) c = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) } while( c != ' ' && c != '\t' && c != '\n' );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) termch = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) *s = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) static char line[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) static char *lineptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) flush_input(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) lineptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) inchar(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) if (lineptr == NULL || *lineptr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) if (xmon_gets(line, sizeof(line)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) lineptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) return EOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) lineptr = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) return *lineptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) take_input(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) lineptr = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) symbol_lookup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) int type = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) unsigned long addr, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) void __percpu *ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) static char tmp[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) if (scanhex(&addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) xmon_print_symbol(addr, ": ", "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) getstring(tmp, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) addr = kallsyms_lookup_name(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) if (addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) printf("%s: %lx\n", tmp, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) printf("Symbol '%s' not found.\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) getstring(tmp, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) ptr = (void __percpu *)kallsyms_lookup_name(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) if (ptr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) ptr >= (void __percpu *)__per_cpu_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) ptr < (void __percpu *)__per_cpu_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) if (scanhex(&cpu) && cpu < num_possible_cpus()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) addr = (unsigned long)per_cpu_ptr(ptr, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) cpu = raw_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) addr = (unsigned long)this_cpu_ptr(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) printf("%s for cpu 0x%lx: %lx\n", tmp, cpu, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) printf("Percpu symbol '%s' not found.\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) termch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) /* Print an address in numeric and symbolic form (if possible) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) static void xmon_print_symbol(unsigned long address, const char *mid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) const char *after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) char *modname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) const char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) unsigned long offset, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) printf(REG, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) name = kallsyms_lookup(address, &size, &offset, &modname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) tmpstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) /* wait a little while to see if we get a machine check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) printf("%s%s+%#lx/%#lx", mid, name, offset, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) if (modname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) printf(" [%s]", modname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) printf("%s", after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) void dump_segments(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) unsigned long esid,vsid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) unsigned long llp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) printf("SLB contents of cpu 0x%x\n", smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) for (i = 0; i < mmu_slb_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) if (!esid && !vsid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) printf("%02d %016lx %016lx", i, esid, vsid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) if (!(esid & SLB_ESID_V)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) llp = vsid & SLB_VSID_LLP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) if (vsid & SLB_VSID_B_1T) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) GET_ESID_1T(esid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) llp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) GET_ESID(esid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) llp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) #ifdef CONFIG_PPC_BOOK3S_32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) void dump_segments(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) printf("sr0-15 =");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) for (i = 0; i < 16; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) printf(" %x", mfsrin(i << 28));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) #ifdef CONFIG_44x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) static void dump_tlb_44x(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) for (i = 0; i < PPC44x_TLB_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) unsigned long w0,w1,w2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) printf("[%02x] %08lx %08lx %08lx ", i, w0, w1, w2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) if (w0 & PPC44x_TLB_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) printf("V %08lx -> %01lx%08lx %c%c%c%c%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) w0 & PPC44x_TLB_EPN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) w1 & PPC44x_TLB_ERPN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) w1 & PPC44x_TLB_RPN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) (w2 & PPC44x_TLB_W) ? 'W' : 'w',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) (w2 & PPC44x_TLB_I) ? 'I' : 'i',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) (w2 & PPC44x_TLB_M) ? 'M' : 'm',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) (w2 & PPC44x_TLB_G) ? 'G' : 'g',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) (w2 & PPC44x_TLB_E) ? 'E' : 'e');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) #endif /* CONFIG_44x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) #ifdef CONFIG_PPC_BOOK3E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) static void dump_tlb_book3e(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) u32 mmucfg, pidmask, lpidmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) u64 ramask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) int mmu_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) static const char *pgsz_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) " 1K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) " 2K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) " 4K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) " 8K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) " 16K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) " 32K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) " 64K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) "128K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) "256K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) "512K",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) " 1M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) " 2M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) " 4M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) " 8M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) " 16M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) " 32M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) " 64M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) "128M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) "256M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) "512M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) " 1G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) " 2G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) " 4G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) " 8G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) " 16G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) " 32G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) " 64G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) "128G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) "256G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) "512G",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) " 1T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) " 2T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) /* Gather some infos about the MMU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) mmucfg = mfspr(SPRN_MMUCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) mmu_version = (mmucfg & 3) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) ntlbs = ((mmucfg >> 2) & 3) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) pidsz = ((mmucfg >> 6) & 0x1f) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) lpidsz = (mmucfg >> 24) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) rasz = (mmucfg >> 16) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) if ((mmu_version > 1) && (mmucfg & 0x10000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) lrat = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) mmu_version, ntlbs, pidsz, lpidsz, rasz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) pidmask = (1ul << pidsz) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) lpidmask = (1ul << lpidsz) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) ramask = (1ull << rasz) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) for (tlb = 0; tlb < ntlbs; tlb++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) u32 tlbcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) int nent, assoc, new_cc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) printf("TLB %d:\n------\n", tlb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) switch(tlb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) tlbcfg = mfspr(SPRN_TLB0CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) tlbcfg = mfspr(SPRN_TLB1CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) tlbcfg = mfspr(SPRN_TLB2CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) tlbcfg = mfspr(SPRN_TLB3CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) printf("Unsupported TLB number !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) nent = tlbcfg & 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) assoc = (tlbcfg >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) for (i = 0; i < nent; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) u32 mas0 = MAS0_TLBSEL(tlb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) u64 mas2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) u64 mas7_mas3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) int esel = i, cc = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) if (assoc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) cc = i / assoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) esel = i % assoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) mas2 = cc * 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) mas0 |= MAS0_ESEL(esel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) mtspr(SPRN_MAS0, mas0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) mtspr(SPRN_MAS1, mas1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) mtspr(SPRN_MAS2, mas2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) asm volatile("tlbre 0,0,0" : : : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) mas1 = mfspr(SPRN_MAS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) mas2 = mfspr(SPRN_MAS2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) if (assoc && (i % assoc) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) new_cc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) if (!(mas1 & MAS1_VALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) if (assoc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) printf("%04x- ", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) else if (new_cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) printf("%04x-%c", cc, 'A' + esel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) printf(" |%c", 'A' + esel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) new_cc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) printf(" %016llx %04x %s %c%c AS%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) mas2 & ~0x3ffull,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) (mas1 >> 16) & 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) pgsz_names[(mas1 >> 7) & 0x1f],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) mas1 & MAS1_IND ? 'I' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) mas1 & MAS1_IPROT ? 'P' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) mas1 & MAS1_TS ? '1' : '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) printf(" %c%c%c%c%c%c%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) mas2 & MAS2_X0 ? 'a' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) mas2 & MAS2_X1 ? 'v' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) mas2 & MAS2_W ? 'w' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) mas2 & MAS2_I ? 'i' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) mas2 & MAS2_M ? 'm' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) mas2 & MAS2_G ? 'g' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) mas2 & MAS2_E ? 'e' : ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) if (mas1 & MAS1_IND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) printf(" %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) printf(" U%c%c%c S%c%c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) mas7_mas3 & MAS3_UX ? 'x' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) mas7_mas3 & MAS3_UW ? 'w' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) mas7_mas3 & MAS3_UR ? 'r' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) mas7_mas3 & MAS3_SX ? 'x' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) mas7_mas3 & MAS3_SW ? 'w' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) mas7_mas3 & MAS3_SR ? 'r' : ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) #endif /* CONFIG_PPC_BOOK3E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) static void xmon_init(int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) __debugger = xmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) __debugger_ipi = xmon_ipi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) __debugger_bpt = xmon_bpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) __debugger_sstep = xmon_sstep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) __debugger_iabr_match = xmon_iabr_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) __debugger_break_match = xmon_break_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) __debugger_fault_handler = xmon_fault_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) * Get the token here to avoid trying to get a lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) * during the crash, causing a deadlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) set_indicator_token = rtas_token("set-indicator");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) __debugger = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) __debugger_ipi = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) __debugger_bpt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) __debugger_sstep = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) __debugger_iabr_match = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) __debugger_break_match = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) __debugger_fault_handler = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) #ifdef CONFIG_MAGIC_SYSRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) static void sysrq_handle_xmon(int key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) if (xmon_is_locked_down()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) clear_all_bpt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) xmon_init(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) /* ensure xmon is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) xmon_init(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) debugger(get_irq_regs());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) if (!xmon_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) xmon_init(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) static const struct sysrq_key_op sysrq_xmon_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) .handler = sysrq_handle_xmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) .help_msg = "xmon(x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) .action_msg = "Entering xmon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) static int __init setup_xmon_sysrq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) register_sysrq_key('x', &sysrq_xmon_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) device_initcall(setup_xmon_sysrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) #endif /* CONFIG_MAGIC_SYSRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) static void clear_all_bpt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) /* clear/unpatch all breakpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) remove_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) remove_cpu_bpts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) /* Disable all breakpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) for (i = 0; i < NBPTS; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) bpts[i].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) /* Clear any data or iabr breakpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) iabr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) for (i = 0; i < nr_wp_slots(); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) dabr[i].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) static int xmon_dbgfs_set(void *data, u64 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) xmon_on = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) xmon_init(xmon_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) /* make sure all breakpoints removed when disabling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) if (!xmon_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) clear_all_bpt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) get_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) printf("xmon: All breakpoints cleared\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) release_output_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) static int xmon_dbgfs_get(void *data, u64 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) *val = xmon_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) DEFINE_SIMPLE_ATTRIBUTE(xmon_dbgfs_ops, xmon_dbgfs_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) xmon_dbgfs_set, "%llu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) static int __init setup_xmon_dbgfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) debugfs_create_file("xmon", 0600, powerpc_debugfs_root, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) &xmon_dbgfs_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) device_initcall(setup_xmon_dbgfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) #endif /* CONFIG_DEBUG_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) static int xmon_early __initdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) static int __init early_parse_xmon(char *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) if (xmon_is_locked_down()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) xmon_init(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) xmon_early = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) xmon_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) } else if (!p || strncmp(p, "early", 5) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) /* just "xmon" is equivalent to "xmon=early" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) xmon_init(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) xmon_early = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) xmon_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) } else if (strncmp(p, "on", 2) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) xmon_init(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) xmon_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) } else if (strncmp(p, "rw", 2) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) xmon_init(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) xmon_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) xmon_is_ro = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) } else if (strncmp(p, "ro", 2) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) xmon_init(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) xmon_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) xmon_is_ro = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) } else if (strncmp(p, "off", 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) xmon_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) early_param("xmon", early_parse_xmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) void __init xmon_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) if (xmon_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) xmon_init(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) if (xmon_early)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) debugger(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) #ifdef CONFIG_SPU_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) struct spu_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) struct spu *spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) u64 saved_mfc_sr1_RW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) u32 saved_spu_runcntl_RW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) unsigned long dump_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) u8 stopped_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) #define XMON_NUM_SPUS 16 /* Enough for current hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) static struct spu_info spu_info[XMON_NUM_SPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) void xmon_register_spus(struct list_head *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) struct spu *spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) list_for_each_entry(spu, list, full_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) if (spu->number >= XMON_NUM_SPUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) spu_info[spu->number].spu = spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) spu_info[spu->number].stopped_ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) spu_info[spu->number].dump_addr = (unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) spu_info[spu->number].spu->local_store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) static void stop_spus(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) struct spu *spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) for (i = 0; i < XMON_NUM_SPUS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) if (!spu_info[i].spu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) spu = spu_info[i].spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) spu_info[i].saved_spu_runcntl_RW =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) in_be32(&spu->problem->spu_runcntl_RW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) tmp = spu_mfc_sr1_get(spu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) spu_info[i].saved_mfc_sr1_RW = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) spu_mfc_sr1_set(spu, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) spu_info[i].stopped_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) printf("Stopped spu %.2d (was %s)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) spu_info[i].saved_spu_runcntl_RW ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) "running" : "stopped");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) printf("*** Error stopping spu %.2d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) static void restart_spus(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) struct spu *spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) for (i = 0; i < XMON_NUM_SPUS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) if (!spu_info[i].spu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) if (!spu_info[i].stopped_ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) printf("*** Error, spu %d was not successfully stopped"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) ", not restarting\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) spu = spu_info[i].spu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) out_be32(&spu->problem->spu_runcntl_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) spu_info[i].saved_spu_runcntl_RW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) printf("Restarted spu %.2d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) printf("*** Error restarting spu %.2d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) #define DUMP_WIDTH 23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) #define DUMP_VALUE(format, field, value) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) if (setjmp(bus_error_jmp) == 0) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) catch_memory_errors = 1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) sync(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) printf(" %-*s = "format"\n", DUMP_WIDTH, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) #field, value); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) sync(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) __delay(200); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) } else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) catch_memory_errors = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) printf(" %-*s = *** Error reading field.\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) DUMP_WIDTH, #field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) catch_memory_errors = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) #define DUMP_FIELD(obj, format, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) DUMP_VALUE(format, field, obj->field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) static void dump_spu_fields(struct spu *spu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) printf("Dumping spu fields at address %p:\n", spu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) DUMP_FIELD(spu, "0x%x", number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) DUMP_FIELD(spu, "%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) DUMP_FIELD(spu, "0x%lx", local_store_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) DUMP_FIELD(spu, "0x%p", local_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) DUMP_FIELD(spu, "0x%lx", ls_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) DUMP_FIELD(spu, "0x%x", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) DUMP_FIELD(spu, "0x%lx", flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) DUMP_FIELD(spu, "%llu", class_0_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) DUMP_FIELD(spu, "0x%llx", class_0_dar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) DUMP_FIELD(spu, "0x%llx", class_1_dar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) DUMP_FIELD(spu, "0x%llx", class_1_dsisr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) DUMP_FIELD(spu, "0x%x", irqs[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) DUMP_FIELD(spu, "0x%x", irqs[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) DUMP_FIELD(spu, "0x%x", irqs[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) DUMP_FIELD(spu, "0x%x", slb_replace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) DUMP_FIELD(spu, "%d", pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) DUMP_FIELD(spu, "0x%p", mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) DUMP_FIELD(spu, "0x%p", ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) DUMP_FIELD(spu, "0x%p", rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) DUMP_FIELD(spu, "0x%llx", timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) DUMP_FIELD(spu, "0x%lx", problem_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) DUMP_FIELD(spu, "0x%p", problem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) in_be32(&spu->problem->spu_runcntl_RW));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) DUMP_VALUE("0x%x", problem->spu_status_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) in_be32(&spu->problem->spu_status_R));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) DUMP_VALUE("0x%x", problem->spu_npc_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) in_be32(&spu->problem->spu_npc_RW));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) DUMP_FIELD(spu, "0x%p", priv2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) DUMP_FIELD(spu, "0x%p", pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) spu_inst_dump(unsigned long adr, long count, int praddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) return generic_inst_dump(adr, count, praddr, print_insn_spu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) static void dump_spu_ls(unsigned long num, int subcmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) unsigned long offset, addr, ls_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) if (setjmp(bus_error_jmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) catch_memory_errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) ls_addr = (unsigned long)spu_info[num].spu->local_store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) __delay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) printf("*** Error: accessing spu info for spu %ld\n", num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) catch_memory_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) if (scanhex(&offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) addr = ls_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) addr = spu_info[num].dump_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) if (addr >= ls_addr + LS_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) printf("*** Error: address outside of local store\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) switch (subcmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) addr += spu_inst_dump(addr, 16, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) last_cmd = "sdi\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) prdump(addr, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) addr += 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) last_cmd = "sd\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) spu_info[num].dump_addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) static int do_spu_cmd(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) static unsigned long num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) int cmd, subcmd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) cmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) stop_spus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) restart_spus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) subcmd = inchar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) if (isxdigit(subcmd) || subcmd == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) termch = subcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) scanhex(&num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) printf("*** Error: invalid spu number\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) dump_spu_fields(spu_info[num].spu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) dump_spu_ls(num, subcmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) #else /* ! CONFIG_SPU_BASE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) static int do_spu_cmd(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) #endif