aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/debug_module.cc4
-rw-r--r--riscv/debug_module.h14
-rw-r--r--riscv/decode.h6
-rw-r--r--riscv/encoding.h8
-rw-r--r--riscv/gdbserver.cc137
-rw-r--r--riscv/gdbserver.h5
6 files changed, 100 insertions, 74 deletions
diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc
index e3eb16b..8ad9513 100644
--- a/riscv/debug_module.cc
+++ b/riscv/debug_module.cc
@@ -41,6 +41,10 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
clear_interrupt(bytes[0] | (bytes[1] << 8) |
(bytes[2] << 16) | (bytes[3] << 24));
return true;
+ } else if (len == 4 && addr == DEBUG_SETHALTNOT) {
+ set_halt_notification(bytes[0] | (bytes[1] << 8) |
+ (bytes[2] << 16) | (bytes[3] << 24));
+ return true;
}
fprintf(stderr, "ERROR: invalid store to debug module: %ld bytes at 0x%lx\n",
diff --git a/riscv/debug_module.h b/riscv/debug_module.h
index d7c1a87..7a78ad3 100644
--- a/riscv/debug_module.h
+++ b/riscv/debug_module.h
@@ -27,9 +27,23 @@ class debug_module_t : public abstract_device_t
return interrupt.find(hartid) != interrupt.end();
}
+ void set_halt_notification(uint32_t hartid) {
+ fprintf(stderr, "set debug halt_notification 0x%x\n", hartid);
+ halt_notification.insert(hartid);
+ }
+ void clear_halt_notification(uint32_t hartid) {
+ fprintf(stderr, "clear debug halt_notification 0x%x\n", hartid);
+ halt_notification.erase(hartid);
+ }
+ bool get_halt_notification(uint32_t hartid) const {
+ return halt_notification.find(hartid) != halt_notification.end();
+ }
+
private:
// Track which interrupts from module to debugger are set.
std::set<uint32_t> interrupt;
+ // Track which halt notifications from debugger to module are set.
+ std::set<uint32_t> halt_notification;
char debug_ram[DEBUG_RAM_SIZE];
};
diff --git a/riscv/decode.h b/riscv/decode.h
index 067d426..1625398 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -229,12 +229,6 @@ private:
* automatically generated. */
/* TODO */
#include "/media/sf_tnewsome/Synced/SiFive/debug-spec/core_registers.tex.h"
-#define DCSR_CAUSE_NONE 0
-#define DCSR_CAUSE_SWBP 1
-#define DCSR_CAUSE_HWBP 2
-#define DCSR_CAUSE_DEBUGINT 3
-#define DCSR_CAUSE_STEPPED 4
-#define DCSR_CAUSE_HALT 5
#define DEBUG_START 0x100
#define DEBUG_ROM_START 0x800
diff --git a/riscv/encoding.h b/riscv/encoding.h
index 11aa518..fcc0a8a 100644
--- a/riscv/encoding.h
+++ b/riscv/encoding.h
@@ -34,6 +34,14 @@
#define SSTATUS64_SD 0x8000000000000000
#define DCSR_PRV (3<<14)
+#define DCSR_CAUSE 7
+
+#define DCSR_CAUSE_NONE 0
+#define DCSR_CAUSE_SWBP 1
+#define DCSR_CAUSE_HWBP 2
+#define DCSR_CAUSE_DEBUGINT 3
+#define DCSR_CAUSE_STEP 4
+#define DCSR_CAUSE_HALT 5
#define MIP_SSIP (1 << IRQ_S_SOFT)
#define MIP_HSIP (1 << IRQ_H_SOFT)
diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc
index d3f2d4d..0cccf3d 100644
--- a/riscv/gdbserver.cc
+++ b/riscv/gdbserver.cc
@@ -247,7 +247,8 @@ void circular_buffer_t<T>::append(const T *src, unsigned int count)
class halt_op_t : public operation_t
{
public:
- halt_op_t(gdbserver_t& gdbserver) : operation_t(gdbserver) {};
+ halt_op_t(gdbserver_t& gdbserver, bool send_status=false) :
+ operation_t(gdbserver), send_status(send_status) {};
bool perform_step(unsigned int step) {
switch (step) {
@@ -287,10 +288,33 @@ class halt_op_t : public operation_t
gs.sptbr_valid = false;
gs.pte_cache.clear();
+
+ if (send_status) {
+ switch (get_field(gs.dcsr, DCSR_CAUSE)) {
+ case DCSR_CAUSE_NONE:
+ fprintf(stderr, "Internal error. Processor halted without reason.\n");
+ abort();
+
+ case DCSR_CAUSE_HWBP:
+ case DCSR_CAUSE_DEBUGINT:
+ case DCSR_CAUSE_STEP:
+ case DCSR_CAUSE_HALT:
+ // There's no gdb code for this.
+ gs.send_packet("T05");
+ break;
+ case DCSR_CAUSE_SWBP:
+ gs.send_packet("T05swbreak:;");
+ break;
+ }
+ }
+
return true;
}
return false;
}
+
+ private:
+ bool send_status;
};
class continue_op_t : public operation_t
@@ -461,8 +485,11 @@ class register_read_op_t : public operation_t
class memory_read_op_t : public operation_t
{
public:
- memory_read_op_t(gdbserver_t& gdbserver, reg_t vaddr, unsigned int length) :
- operation_t(gdbserver), vaddr(vaddr), length(length) {};
+ // Read length bytes from vaddr, storing the result into data.
+ // If data is NULL, send the result straight to gdb.
+ memory_read_op_t(gdbserver_t& gdbserver, reg_t vaddr, unsigned int length,
+ unsigned char *data=NULL) :
+ operation_t(gdbserver), vaddr(vaddr), length(length), data(data) {};
bool perform_step(unsigned int step)
{
@@ -472,6 +499,8 @@ class memory_read_op_t : public operation_t
access_size = (paddr % length);
if (access_size == 0)
access_size = length;
+ if (access_size > 8)
+ access_size = 8;
gs.write_debug_ram(0, ld(S0, 0, (uint16_t) DEBUG_RAM_START + 16));
switch (access_size) {
@@ -487,9 +516,6 @@ class memory_read_op_t : public operation_t
case 8:
gs.write_debug_ram(1, ld(S1, S0, 0));
break;
- default:
- gs.send_packet("E12");
- return true;
}
gs.write_debug_ram(2, sd(S1, 0, (uint16_t) DEBUG_RAM_START + 24));
gs.write_debug_ram(3, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*3))));
@@ -497,22 +523,30 @@ class memory_read_op_t : public operation_t
gs.write_debug_ram(5, paddr >> 32);
gs.set_interrupt(0);
- gs.start_packet();
+ if (!data) {
+ gs.start_packet();
+ }
return false;
}
char buffer[3];
reg_t value = ((uint64_t) gs.read_debug_ram(7) << 32) | gs.read_debug_ram(6);
for (unsigned int i = 0; i < access_size; i++) {
- sprintf(buffer, "%02x", (unsigned int) (value & 0xff));
- gs.send(buffer);
+ if (data) {
+ *(data++) = value & 0xff;
+ } else {
+ sprintf(buffer, "%02x", (unsigned int) (value & 0xff));
+ gs.send(buffer);
+ }
value >>= 8;
}
length -= access_size;
paddr += access_size;
if (length == 0) {
- gs.end_packet();
+ if (!data) {
+ gs.end_packet();
+ }
return true;
} else {
gs.write_debug_ram(4, paddr);
@@ -523,8 +557,10 @@ class memory_read_op_t : public operation_t
}
private:
- reg_t vaddr, paddr;
+ reg_t vaddr;
unsigned int length;
+ unsigned char* data;
+ reg_t paddr;
unsigned int access_size;
};
@@ -1265,28 +1301,6 @@ void gdbserver_t::handle_extended(const std::vector<uint8_t> &packet)
extended_mode = true;
}
-void software_breakpoint_t::insert(mmu_t* mmu)
-{
- if (size == 2) {
- instruction = mmu->load_uint16(address);
- mmu->store_uint16(address, C_EBREAK);
- } else {
- instruction = mmu->load_uint32(address);
- mmu->store_uint32(address, EBREAK);
- }
- fprintf(stderr, ">>> Read %x from %lx\n", instruction, address);
-}
-
-void software_breakpoint_t::remove(mmu_t* mmu)
-{
- fprintf(stderr, ">>> write %x to %lx\n", instruction, address);
- if (size == 2) {
- mmu->store_uint16(address, instruction);
- } else {
- mmu->store_uint32(address, instruction);
- }
-}
-
void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
{
// insert: Z type,addr,kind
@@ -1312,22 +1326,35 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
return send_packet("E53");
}
- processor_t *p = sim->get_core(0);
- die("handle_breakpoint");
- /*
- mmu_t* mmu = p->mmu;
+ add_operation(new collect_translation_info_op_t(*this, bp.address, bp.size));
if (insert) {
- bp.insert(mmu);
+ // TODO: this only works on little-endian hosts.
+ unsigned char* swbp = new unsigned char[4];
+ if (bp.size == 2) {
+ swbp[0] = C_EBREAK & 0xff;
+ swbp[1] = (C_EBREAK >> 8) & 0xff;
+ } else {
+ swbp[0] = EBREAK & 0xff;
+ swbp[1] = (EBREAK >> 8) & 0xff;
+ swbp[2] = (EBREAK >> 16) & 0xff;
+ swbp[3] = (EBREAK >> 24) & 0xff;
+ }
+
+ add_operation(new memory_read_op_t(*this, bp.address, bp.size, bp.instruction));
+ add_operation(new memory_write_op_t(*this, bp.address, bp.size, swbp));
breakpoints[bp.address] = bp;
} else {
bp = breakpoints[bp.address];
- bp.remove(mmu);
+ unsigned char* instruction = new unsigned char[4];
+ memcpy(instruction, bp.instruction, 4);
+ add_operation(new memory_write_op_t(*this, bp.address, bp.size, instruction));
breakpoints.erase(bp.address);
}
- mmu->flush_icache();
- sim->debug_mmu->flush_icache();
- */
+
+ // TODO mmu->flush_icache();
+ // TODO sim->debug_mmu->flush_icache();
+
return send_packet("OK");
}
@@ -1431,29 +1458,11 @@ void gdbserver_t::handle()
}
}
- /* TODO
- if (running && p->halted) {
- // The core was running, but now it's halted. Better tell gdb.
- switch (p->halt_reason) {
- case HR_NONE:
- fprintf(stderr, "Internal error. Processor halted without reason.\n");
- abort();
- case HR_STEPPED:
- case HR_INTERRUPT:
- case HR_CMDLINE:
- case HR_ATTACHED:
- // There's no gdb code for this.
- send_packet("T05");
- break;
- case HR_SWBP:
- send_packet("T05swbreak:;");
- break;
- }
- send_packet("T00");
- // TODO: Actually include register values here
- running = false;
+ bool halt_notification = sim->debug_module.get_halt_notification(0);
+ if (halt_notification) {
+ sim->debug_module.clear_halt_notification(0);
+ add_operation(new halt_op_t(*this, true));
}
- */
this->read();
this->write();
diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h
index 9b39450..f91498a 100644
--- a/riscv/gdbserver.h
+++ b/riscv/gdbserver.h
@@ -51,10 +51,7 @@ class software_breakpoint_t
public:
reg_t address;
unsigned int size;
- uint32_t instruction;
-
- void insert(mmu_t* mmu);
- void remove(mmu_t* mmu);
+ unsigned char instruction[4];
};
class gdbserver_t;