dbus -> dmi
[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_data_t
17
18 debug_module_data_t::debug_module_data_t()
19 {
20 memset(data, 0, sizeof(data));
21 }
22
23 bool debug_module_data_t::load(reg_t addr, size_t len, uint8_t* bytes)
24 {
25 D(fprintf(stderr, "debug_module_data_t load 0x%lx bytes at 0x%lx\n", len,
26 addr));
27
28 if (addr + len < sizeof(data)) {
29 memcpy(bytes, data + addr, len);
30 return true;
31 }
32
33 fprintf(stderr, "ERROR: invalid load from debug_module_data_t: %zd bytes at 0x%016"
34 PRIx64 "\n", len, addr);
35
36 return false;
37 }
38
39 bool debug_module_data_t::store(reg_t addr, size_t len, const uint8_t* bytes)
40 {
41 D(fprintf(stderr, "debug_module_data_t store 0x%lx bytes at 0x%lx\n", len,
42 addr));
43
44 if (addr + len < sizeof(data)) {
45 memcpy(data + addr, bytes, len);
46 return true;
47 }
48
49 fprintf(stderr, "ERROR: invalid store to debug_module_data_t: %zd bytes at 0x%016"
50 PRIx64 "\n", len, addr);
51 return false;
52 }
53
54 uint32_t debug_module_data_t::read32(reg_t addr) const
55 {
56 assert(addr + 4 <= sizeof(data));
57 return data[addr] |
58 (data[addr + 1] << 8) |
59 (data[addr + 2] << 16) |
60 (data[addr + 3] << 24);
61 }
62
63 void debug_module_data_t::write32(reg_t addr, uint32_t value)
64 {
65 fprintf(stderr, "debug_module_data_t::write32(0x%lx, 0x%x)\n", addr, value);
66 assert(addr + 4 <= sizeof(data));
67 data[addr] = value & 0xff;
68 data[addr + 1] = (value >> 8) & 0xff;
69 data[addr + 2] = (value >> 16) & 0xff;
70 data[addr + 3] = (value >> 24) & 0xff;
71 }
72
73 ///////////////////////// debug_module_t
74
75 debug_module_t::debug_module_t(sim_t *sim) : sim(sim)
76 {
77 dmcontrol = {0};
78 dmcontrol.version = 1;
79
80 for (unsigned i = 0; i < DEBUG_ROM_ENTRY_SIZE / 4; i++) {
81 write32(debug_rom_entry, i, jal(ZERO, 0));
82 halted[i] = false;
83 }
84
85 for (unsigned i = 0; i < progsize; i++) {
86 ibuf[i] = 0;
87 }
88
89 }
90
91 void debug_module_t::reset()
92 {
93 for (unsigned i = 0; i < sim->nprocs(); i++) {
94 processor_t *proc = sim->get_core(i);
95 if (proc)
96 proc->halt_request = false;
97 }
98
99 dmcontrol = {0};
100 dmcontrol.authenticated = 1;
101 dmcontrol.version = 1;
102 dmcontrol.authtype = dmcontrol.AUTHTYPE_NOAUTH;
103
104 abstractcs = {0};
105 abstractcs.datacount = sizeof(dmdata.data) / 4;
106 }
107
108 void debug_module_t::add_device(bus_t *bus) {
109 bus->add_device(DEBUG_START, this);
110 bus->add_device(DEBUG_EXCHANGE, &dmdata);
111 }
112
113 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
114 {
115 D(fprintf(stderr, "load 0x%lx bytes at 0x%lx\n",
116 len, addr));
117 addr = DEBUG_START + addr;
118
119 if (addr >= DEBUG_ROM_ENTRY &&
120 addr < DEBUG_ROM_ENTRY + DEBUG_ROM_ENTRY_SIZE) {
121 halted[(addr - DEBUG_ROM_ENTRY) / 4] = true;
122 memcpy(bytes, debug_rom_entry + addr - DEBUG_ROM_ENTRY, len);
123
124 if (read32(debug_rom_entry, dmcontrol.hartsel) == jal(ZERO, 0)) {
125 // We're here in an infinite loop. That means that whatever abstract
126 // command has complete.
127 abstractcs.busy = false;
128 }
129 return true;
130 }
131
132 // Restore the jump-to-self loop.
133 write32(debug_rom_entry, dmcontrol.hartsel, jal(ZERO, 0));
134
135 if (addr >= DEBUG_ROM_CODE &&
136 addr < DEBUG_ROM_CODE + DEBUG_ROM_CODE_SIZE) {
137 memcpy(bytes, debug_rom_code + addr - DEBUG_ROM_CODE, len);
138 return true;
139 }
140
141 if (addr >= DEBUG_ROM_EXCEPTION &&
142 addr < DEBUG_ROM_EXCEPTION + DEBUG_ROM_EXCEPTION_SIZE) {
143 memcpy(bytes, debug_rom_exception + addr - DEBUG_ROM_EXCEPTION, len);
144 if (abstractcs.cmderr == abstractcs.CMDERR_NONE) {
145 abstractcs.cmderr = abstractcs.CMDERR_EXCEPTION;
146 }
147 return true;
148 }
149
150 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
151 PRIx64 "\n", len, addr);
152
153 return false;
154 }
155
156 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
157 {
158 addr = DEBUG_START + addr;
159
160 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
161 PRIx64 "\n", len, addr);
162 return false;
163 }
164
165 void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
166 {
167 uint8_t* base = memory + index * 4;
168 base[0] = value & 0xff;
169 base[1] = (value >> 8) & 0xff;
170 base[2] = (value >> 16) & 0xff;
171 base[3] = (value >> 24) & 0xff;
172 }
173
174 uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
175 {
176 uint8_t* base = memory + index * 4;
177 uint32_t value = ((uint32_t) base[0]) |
178 (((uint32_t) base[1]) << 8) |
179 (((uint32_t) base[2]) << 16) |
180 (((uint32_t) base[3]) << 24);
181 return value;
182 }
183
184 processor_t *debug_module_t::current_proc() const
185 {
186 processor_t *proc = NULL;
187 try {
188 proc = sim->get_core(dmcontrol.hartsel);
189 } catch (const std::out_of_range&) {
190 }
191 return proc;
192 }
193
194 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
195 {
196 uint32_t result = 0;
197 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
198 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
199 result = dmdata.read32(4 * (address - DMI_DATA0));
200 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
201 result = ibuf[address - DMI_IBUF0];
202 } else {
203 switch (address) {
204 case DMI_DMCONTROL:
205 {
206 processor_t *proc = current_proc();
207 if (proc) {
208 if (halted[dmcontrol.hartsel]) {
209 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_HALTED;
210 } else {
211 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_RUNNING;
212 }
213 dmcontrol.haltreq = proc->halt_request;
214 } else {
215 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_NOTEXIST;
216 }
217 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
218 result = set_field(result, DMI_DMCONTROL_RESET, dmcontrol.reset);
219 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
220 result = set_field(result, DMI_DMCONTROL_HARTSTATUS, dmcontrol.hartstatus);
221 result = set_field(result, DMI_DMCONTROL_HARTSEL, dmcontrol.hartsel);
222 result = set_field(result, DMI_DMCONTROL_AUTHENTICATED, dmcontrol.authenticated);
223 result = set_field(result, DMI_DMCONTROL_AUTHBUSY, dmcontrol.authbusy);
224 result = set_field(result, DMI_DMCONTROL_AUTHTYPE, dmcontrol.authtype);
225 result = set_field(result, DMI_DMCONTROL_VERSION, dmcontrol.version);
226 }
227 break;
228 case DMI_ABSTRACTCS:
229 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC7, abstractcs.autoexec7);
230 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC6, abstractcs.autoexec6);
231 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC5, abstractcs.autoexec5);
232 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC4, abstractcs.autoexec4);
233 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC3, abstractcs.autoexec3);
234 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC2, abstractcs.autoexec2);
235 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC1, abstractcs.autoexec1);
236 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC0, abstractcs.autoexec0);
237 result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
238 result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
239 result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
240 break;
241 case DMI_ACCESSCS:
242 result = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
243 break;
244 case DMI_COMMAND:
245 result = 0;
246 break;
247 default:
248 D(fprintf(stderr, "error\n"));
249 return false;
250 }
251 }
252 D(fprintf(stderr, "0x%x\n", result));
253 *value = result;
254 return true;
255 }
256
257 bool debug_module_t::perform_abstract_command(uint32_t command)
258 {
259 if (abstractcs.cmderr != abstractcs.CMDERR_NONE)
260 return true;
261 if (abstractcs.busy) {
262 abstractcs.cmderr = abstractcs.CMDERR_BUSY;
263 return true;
264 }
265
266 if ((command >> 24) == 0) {
267 // register access
268 unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
269 bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
270 unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
271
272 if (regno < 0x1000 || regno >= 0x1020) {
273 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
274 return true;
275 }
276
277 unsigned regnum = regno - 0x1000;
278
279 if (!halted[dmcontrol.hartsel]) {
280 abstractcs.cmderr = abstractcs.CMDERR_HALTRESUME;
281 return true;
282 }
283
284 switch (size) {
285 case 2:
286 if (write)
287 write32(debug_rom_code, 0, lw(regnum, ZERO, DEBUG_EXCHANGE));
288 else
289 write32(debug_rom_code, 0, sw(regnum, ZERO, DEBUG_EXCHANGE));
290 break;
291 case 3:
292 if (write)
293 write32(debug_rom_code, 0, ld(regnum, ZERO, DEBUG_EXCHANGE));
294 else
295 write32(debug_rom_code, 0, sd(regnum, ZERO, DEBUG_EXCHANGE));
296 break;
297 /*
298 case 4:
299 if (write)
300 write32(debug_rom_code, 0, lq(regnum, ZERO, DEBUG_EXCHANGE));
301 else
302 write32(debug_rom_code, 0, sq(regnum, ZERO, DEBUG_EXCHANGE));
303 break;
304 */
305 default:
306 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
307 return true;
308 }
309 write32(debug_rom_code, 1, ebreak());
310
311 write32(debug_rom_entry, dmcontrol.hartsel,
312 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
313 write32(debug_rom_exception, dmcontrol.hartsel,
314 jal(ZERO, (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel) - DEBUG_ROM_EXCEPTION));
315 abstractcs.busy = true;
316 } else {
317 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
318 }
319 return true;
320 }
321
322 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
323 {
324 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
325 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
326 dmdata.write32(4 * (address - DMI_DATA0), value);
327 return true;
328 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
329 ibuf[address - DMI_IBUF0] = value;
330 return true;
331 } else {
332 switch (address) {
333 case DMI_DMCONTROL:
334 {
335 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
336 if (dmcontrol.dmactive) {
337 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
338 dmcontrol.reset = get_field(value, DMI_DMCONTROL_RESET);
339 dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
340 } else {
341 reset();
342 }
343 processor_t *proc = current_proc();
344 if (proc) {
345 proc->halt_request = dmcontrol.haltreq;
346 }
347 }
348 return true;
349
350 case DMI_COMMAND:
351 return perform_abstract_command(value);
352
353 case DMI_ABSTRACTCS:
354 abstractcs.autoexec7 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC7);
355 abstractcs.autoexec6 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC6);
356 abstractcs.autoexec5 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC5);
357 abstractcs.autoexec4 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC4);
358 abstractcs.autoexec3 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC3);
359 abstractcs.autoexec2 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC2);
360 abstractcs.autoexec1 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC1);
361 abstractcs.autoexec0 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC0);
362 if (get_field(value, DMI_ABSTRACTCS_CMDERR) == abstractcs.CMDERR_NONE) {
363 abstractcs.cmderr = abstractcs.CMDERR_NONE;
364 }
365 return true;
366 }
367 }
368 return false;
369 }