aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2016-03-12 17:50:32 -0800
committerTim Newsome <tim@sifive.com>2016-05-23 12:12:10 -0700
commit824689f929a4148668aaab2b31fa87bf16e8c804 (patch)
treeede985e3e63e5f81b70c59f3a0d08a15b6d5ef19
parent3fc2f3d5435f6eddaa0670f5ab3c555508bca5bb (diff)
downloadspike-824689f929a4148668aaab2b31fa87bf16e8c804.zip
spike-824689f929a4148668aaab2b31fa87bf16e8c804.tar.gz
spike-824689f929a4148668aaab2b31fa87bf16e8c804.tar.bz2
Flush icache when using swbps and report to gdb.
-rw-r--r--Makefile.in7
-rw-r--r--riscv/execute.cc4
-rw-r--r--riscv/gdbserver.cc73
-rw-r--r--riscv/gdbserver.h1
-rw-r--r--riscv/processor.cc5
-rw-r--r--riscv/processor.h12
-rw-r--r--riscv/sim.cc2
7 files changed, 89 insertions, 15 deletions
diff --git a/Makefile.in b/Makefile.in
index d6b0496..1e353ab 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -121,7 +121,7 @@ INSTALL_EXE := $(INSTALL) -m 555
STOW := @stow@
# Tests
-bintests =
+bintests = tests/gdbserver-smoke.py
#-------------------------------------------------------------------------
# Include subproject makefile fragments
@@ -333,8 +333,9 @@ deps : $(deps)
#-------------------------------------------------------------------------
bintest_outs = $(bintests:=.out)
-%.out: %
- $^ < /dev/null > $@ 2>&1
+junk += $(bintest_outs)
+%.out: % all
+ ./$^ < /dev/null 2>&1 | tee $@
check-cpp : $(test_outs)
echo; grep -h -e'Unit Tests' -e'FAILED' -e'Segmentation' $^ < /dev/null; echo
diff --git a/riscv/execute.cc b/riscv/execute.cc
index 4bfaf4a..c36cb4f 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -56,7 +56,7 @@ void processor_t::step(size_t n)
// TODO: We should really not call this function at all when halted, to avoid
// burning CPU.
if (single_step) {
- halted = false;
+ set_halted(false, HR_NONE);
n = 1;
}
@@ -136,6 +136,6 @@ miss:
if (single_step) {
single_step = false;
- halted = true;
+ set_halted(true, HR_STEPPED);
}
}
diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc
index 83bc013..70dac13 100644
--- a/riscv/gdbserver.cc
+++ b/riscv/gdbserver.cc
@@ -142,7 +142,7 @@ void gdbserver_t::accept()
// gdb wants the core to be halted when it attaches.
processor_t *p = sim->get_core(0);
- p->set_halted(true);
+ p->set_halted(true, HR_ATTACHED);
}
}
@@ -165,7 +165,7 @@ void gdbserver_t::read()
// The remote disconnected.
client_fd = 0;
processor_t *p = sim->get_core(0);
- p->set_halted(false);
+ p->set_halted(false, HR_NONE);
recv_buf.reset();
send_buf.reset();
} else {
@@ -260,7 +260,8 @@ void gdbserver_t::process_requests()
if (b == '$') {
// Start of new packet.
if (!packet.empty()) {
- fprintf(stderr, "Received malformed %ld-byte packet from debug client: ", packet.size());
+ fprintf(stderr, "Received malformed %ld-byte packet from debug client: ",
+ packet.size());
print_packet(packet);
recv_buf.consume(i);
break;
@@ -337,6 +338,16 @@ uint64_t consume_hex_number(std::vector<uint8_t>::const_iterator &iter,
return value;
}
+void consume_string(std::string &str, std::vector<uint8_t>::const_iterator &iter,
+ std::vector<uint8_t>::const_iterator end, uint8_t separator)
+{
+ while (iter != end && *iter != separator) {
+ str.append(1, (char) *iter);
+ iter++;
+ }
+}
+
+
void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
{
// p n
@@ -436,7 +447,7 @@ void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
return send_packet("E30");
}
- p->set_halted(false);
+ p->set_halted(false, HR_NONE);
running = true;
}
@@ -480,10 +491,12 @@ void software_breakpoint_t::insert(mmu_t* mmu)
instruction = mmu->load_uint32(address);
mmu->store_uint32(address, EBREAK);
}
+ printf(">>> Read %x from %lx\n", instruction, address);
}
void software_breakpoint_t::remove(mmu_t* mmu)
{
+ printf(">>> write %x to %lx\n", instruction, address);
if (size == 2) {
mmu->store_uint16(address, instruction);
} else {
@@ -516,7 +529,6 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
return send_packet("E53");
}
- processor_t *p = sim->get_core(0);
mmu_t* mmu = sim->debug_mmu;
if (insert) {
bp.insert(mmu);
@@ -527,9 +539,40 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
bp.remove(mmu);
breakpoints.erase(bp.address);
}
+ mmu->flush_icache();
+ processor_t *p = sim->get_core(0);
+ p->mmu->flush_icache();
return send_packet("OK");
}
+void gdbserver_t::handle_query(const std::vector<uint8_t> &packet)
+{
+ std::string name;
+ std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
+
+ consume_string(name, iter, packet.end(), ':');
+ if (iter != packet.end())
+ iter++;
+ if (name == "Supported") {
+ send("$");
+ running_checksum = 0;
+ while (iter != packet.end()) {
+ std::string feature;
+ consume_string(feature, iter, packet.end(), ';');
+ if (iter != packet.end())
+ iter++;
+ printf("is %s supported?\n", feature.c_str());
+ if (feature == "swbreak+") {
+ send("swbreak+;");
+ }
+ }
+ return send_running_checksum();
+ }
+
+ printf("Unsupported query %s\n", name.c_str());
+ return send_packet("");
+}
+
void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
{
if (compute_checksum(packet) != extract_checksum(packet)) {
@@ -568,6 +611,9 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
case 'z':
case 'Z':
return handle_breakpoint(packet);
+ case 'q':
+ case 'Q':
+ return handle_query(packet);
}
// Not supported.
@@ -579,7 +625,7 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
void gdbserver_t::handle_interrupt()
{
processor_t *p = sim->get_core(0);
- p->set_halted(true);
+ p->set_halted(true, HR_INTERRUPT);
send_packet("S02"); // Pretend program received SIGINT.
running = false;
}
@@ -589,6 +635,21 @@ void gdbserver_t::handle()
processor_t *p = sim->get_core(0);
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;
diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h
index 67ae6d0..8f52a92 100644
--- a/riscv/gdbserver.h
+++ b/riscv/gdbserver.h
@@ -75,6 +75,7 @@ public:
void handle_kill(const std::vector<uint8_t> &packet);
void handle_memory_binary_write(const std::vector<uint8_t> &packet);
void handle_memory_read(const std::vector<uint8_t> &packet);
+ void handle_query(const std::vector<uint8_t> &packet);
void handle_register_read(const std::vector<uint8_t> &packet);
void handle_step(const std::vector<uint8_t> &packet);
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 1c53986..4537c18 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -126,9 +126,10 @@ void processor_t::set_debug(bool value)
ext->set_debug(value);
}
-void processor_t::set_halted(bool value)
+void processor_t::set_halted(bool value, halt_reason_t reason)
{
halted = value;
+ halt_reason = reason;
}
void processor_t::set_single_step(bool value)
@@ -210,7 +211,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
if (t.cause() == CAUSE_BREAKPOINT) {
// TODO: Only do this if there is a debugger attached.
- halted = true;
+ set_halted(true, HR_SWBP);
return;
}
diff --git a/riscv/processor.h b/riscv/processor.h
index e654c0f..869873f 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -73,6 +73,15 @@ struct state_t
#endif
};
+typedef enum {
+ HR_NONE,
+ HR_STEPPED, // A single step was completed
+ HR_SWBP, // sbreak was executed
+ HR_INTERRUPT, // Execution interrupted by debugger
+ HR_CMDLINE, // Command line requested that the processor start halted
+ HR_ATTACHED // Halted because a debugger attached
+} halt_reason_t;
+
// this class represents one processor in a RISC-V machine.
class processor_t : public abstract_device_t
{
@@ -81,7 +90,7 @@ public:
~processor_t();
void set_debug(bool value);
- void set_halted(bool value);
+ void set_halted(bool value, halt_reason_t reason);
void set_single_step(bool value);
void set_histogram(bool value);
void reset(bool value);
@@ -124,6 +133,7 @@ private:
bool debug;
// TODO: Should this just be rolled into `run`?
bool halted; // When true, no instructions are executed.
+ halt_reason_t halt_reason; // Why is halted true?
// When true, execute exactly one instruction (even if halted is true), then
// set halted to true and single_step to false.
bool single_step;
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 09c8b44..19d3d84 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -45,7 +45,7 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
for (size_t i = 0; i < procs.size(); i++) {
procs[i] = new processor_t(isa, this, i);
- procs[i]->set_halted(halted);
+ procs[i]->set_halted(halted, HR_CMDLINE);
}
rtc.reset(new rtc_t(procs));