Fix stack overflow and support --rbb-port=0
[riscv-isa-sim.git] / riscv / debug_module.cc
1 #include <cassert>
2
3 #include "debug_module.h"
4 #include "debug_defines.h"
5 #include "opcodes.h"
6 #include "mmu.h"
7
8 #include "debug_rom/debug_rom.h"
9
10 #if 1
11 # define D(x) x
12 #else
13 # define D(x)
14 #endif
15
16 debug_module_t::debug_module_t(sim_t *sim) : sim(sim)
17 {
18 dmcontrol = {0};
19 dmcontrol.version = 1;
20
21 for (unsigned i = 0; i < 1024; i++) {
22 write32(debug_rom_entry, i, jal(0, 0));
23 halted[i] = false;
24 }
25
26 for (unsigned i = 0; i < datacount; i++) {
27 data[i] = 0;
28 }
29
30 for (unsigned i = 0; i < progsize; i++) {
31 ibuf[i] = 0;
32 }
33
34 }
35
36 void debug_module_t::reset()
37 {
38 for (unsigned i = 0; i < sim->nprocs(); i++) {
39 processor_t *proc = sim->get_core(i);
40 if (proc)
41 proc->halt_request = false;
42 }
43
44 dmcontrol.haltreq = 0;
45 dmcontrol.reset = 0;
46 dmcontrol.dmactive = 0;
47 dmcontrol.hartsel = 0;
48 dmcontrol.authenticated = 1;
49 dmcontrol.version = 1;
50 dmcontrol.authbusy = 0;
51 dmcontrol.authtype = dmcontrol.AUTHTYPE_NOAUTH;
52 abstractcs = datacount << DMI_ABSTRACTCS_DATACOUNT_OFFSET;
53 }
54
55 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
56 {
57 addr = DEBUG_START + addr;
58
59 if (addr >= DEBUG_ROM_ENTRY && addr <= DEBUG_ROM_CODE) {
60 halted[(addr - DEBUG_ROM_ENTRY) / 4] = true;
61 memcpy(bytes, debug_rom_entry + addr - DEBUG_ROM_ENTRY, len);
62 return true;
63 }
64
65 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
66 PRIx64 "\n", len, addr);
67
68 return false;
69 }
70
71 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
72 {
73 addr = DEBUG_START + addr;
74
75 if (addr & (len-1)) {
76 fprintf(stderr, "ERROR: unaligned store to debug module: %zd bytes at 0x%016"
77 PRIx64 "\n", len, addr);
78 return false;
79 }
80
81 // memcpy(debug_ram + addr - DEBUG_RAM_START, bytes, len);
82
83 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
84 PRIx64 "\n", len, addr);
85 return false;
86 }
87
88 void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
89 {
90 uint8_t* base = memory + index * 4;
91 base[0] = value & 0xff;
92 base[1] = (value >> 8) & 0xff;
93 base[2] = (value >> 16) & 0xff;
94 base[3] = (value >> 24) & 0xff;
95 }
96
97 uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
98 {
99 uint8_t* base = memory + index * 4;
100 uint32_t value = ((uint32_t) base[0]) |
101 (((uint32_t) base[1]) << 8) |
102 (((uint32_t) base[2]) << 16) |
103 (((uint32_t) base[3]) << 24);
104 return value;
105 }
106
107 processor_t *debug_module_t::current_proc() const
108 {
109 processor_t *proc = NULL;
110 try {
111 proc = sim->get_core(dmcontrol.hartsel);
112 } catch (const std::out_of_range&) {
113 }
114 return proc;
115 }
116
117 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
118 {
119 uint32_t result = 0;
120 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
121 if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
122 result = data[address - DMI_DATA0];
123 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
124 result = ibuf[address - DMI_IBUF0];
125 } else {
126 switch (address) {
127 case DMI_DMCONTROL:
128 {
129 processor_t *proc = current_proc();
130 if (proc) {
131 if (halted[dmcontrol.hartsel]) {
132 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_HALTED;
133 } else {
134 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_RUNNING;
135 }
136 dmcontrol.haltreq = proc->halt_request;
137 } else {
138 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_NOTEXIST;
139 }
140 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
141 result = set_field(result, DMI_DMCONTROL_RESET, dmcontrol.reset);
142 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
143 result = set_field(result, DMI_DMCONTROL_HARTSTATUS, dmcontrol.hartstatus);
144 result = set_field(result, DMI_DMCONTROL_HARTSEL, dmcontrol.hartsel);
145 result = set_field(result, DMI_DMCONTROL_AUTHENTICATED, dmcontrol.authenticated);
146 result = set_field(result, DMI_DMCONTROL_AUTHBUSY, dmcontrol.authbusy);
147 result = set_field(result, DMI_DMCONTROL_AUTHTYPE, dmcontrol.authtype);
148 result = set_field(result, DMI_DMCONTROL_VERSION, dmcontrol.version);
149 }
150 break;
151 case DMI_ABSTRACTCS:
152 result = abstractcs;
153 break;
154 case DMI_ACCESSCS:
155 result = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
156 break;
157 default:
158 D(fprintf(stderr, "error\n"));
159 return false;
160 }
161 }
162 D(fprintf(stderr, "0x%x\n", result));
163 *value = result;
164 return true;
165 }
166
167 bool debug_module_t::perform_abstract_command(uint32_t command)
168 {
169 return false;
170 }
171
172 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
173 {
174 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
175 if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
176 data[address - DMI_DATA0] = value;
177 return true;
178 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
179 ibuf[address - DMI_IBUF0] = value;
180 return true;
181 } else {
182 switch (address) {
183 case DMI_DMCONTROL:
184 {
185 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
186 if (dmcontrol.dmactive) {
187 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
188 dmcontrol.reset = get_field(value, DMI_DMCONTROL_RESET);
189 dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
190 } else {
191 reset();
192 }
193 processor_t *proc = current_proc();
194 if (proc) {
195 proc->halt_request = dmcontrol.haltreq;
196 }
197 }
198 return true;
199
200 case DMI_ABSTRACTCS:
201 return perform_abstract_command(value);
202 }
203 }
204 return false;
205 }