1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2019 Intel Corporation. All rights reserved.
4 //
5 // Author: Marcin Rajwa <marcin.rajwa@linux.intel.com>
6
7 /*
8 * Xtensa related functions for GDB.
9 *
10 */
11 #define GDB_DISABLE_LOWER_INTERRUPTS_MASK ~0x1F
12
13 #include <arch/debug/gdb/utilities.h>
14 #include <xtensa/config/core-isa.h>
15 #include <xtensa/specreg.h>
16
arch_gdb_read_sr(int sr)17 void arch_gdb_read_sr(int sr)
18 {
19 int val;
20
21 asm volatile ("movi a3, 1f + 1\n"
22 "s8i %1, a3, 0\n"
23 "dhwb a3, 0\n"
24 "ihi a3, 0\n"
25 "isync\n"
26 "1:\n"
27 "rsr %0, lbeg\n"
28 : "=r"(val)
29 : "r"(sr)
30 : "a3", "memory");
31 }
32
arch_gdb_write_sr(int sr,int * sregs)33 void arch_gdb_write_sr(int sr, int *sregs)
34 {
35 asm volatile ("movi a3, 1f + 1\n"
36 "s8i %1, a3, 0\n"
37 "dhwb a3, 0\n"
38 "ihi a3, 0\n"
39 "isync\n"
40 "1:\n"
41 "wsr %0, lbeg\n"
42 :
43 : "r"(sregs[sr]), "r"(sr)
44 : "a3", "memory");
45 }
46
arch_gdb_load_from_memory(void * mem)47 unsigned char arch_gdb_load_from_memory(void *mem)
48 {
49 unsigned long v;
50 unsigned long addr = (unsigned long)mem;
51 unsigned char ch;
52
53 asm volatile ("_l32i %0, %1, 0\n"
54 : "=r"(v)
55 : "r"(addr & ~3)
56 : "memory");
57 ch = v >> (addr & 3) * 8;
58
59 return ch;
60 }
61
arch_gdb_memory_load_and_store(void * mem,unsigned char ch)62 void arch_gdb_memory_load_and_store(void *mem, unsigned char ch)
63 {
64 unsigned long tmp;
65 unsigned long addr = (unsigned long)mem;
66
67 asm volatile ("_l32i %0, %1, 0\n"
68 "and %0, %0, %2\n"
69 "or %0, %0, %3\n"
70 "_s32i %0, %1, 0\n"
71 "dhwb %1, 0\n"
72 "ihi %1, 0\n"
73 : "=&r"(tmp)
74 : "r"(addr & ~3), "r"(0xffffffff ^ (0xff <<
75 (addr & 3) * 8)),
76 "r"(ch << (addr & 3) * 8)
77 : "memory");
78 }
79
arch_gdb_single_step(int * sregs)80 void arch_gdb_single_step(int *sregs)
81 {
82 /* leave debug just for one instruction */
83 sregs[ICOUNT] = 0xfffffffe;
84 sregs[ICOUNTLEVEL] = XCHAL_DEBUGLEVEL;
85 /* disable low level interrupts */
86 sregs[INTENABLE] &= ~GDB_DISABLE_LOWER_INTERRUPTS_MASK;
87 arch_gdb_write_sr(ICOUNTLEVEL, sregs);
88 arch_gdb_write_sr(ICOUNT, sregs);
89 arch_gdb_write_sr(INTENABLE, sregs);
90 }
91