From 824689f929a4148668aaab2b31fa87bf16e8c804 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 12 Mar 2016 17:50:32 -0800 Subject: [PATCH] Flush icache when using swbps and report to gdb. --- Makefile.in | 7 +++-- riscv/execute.cc | 4 +-- riscv/gdbserver.cc | 73 ++++++++++++++++++++++++++++++++++++++++++---- riscv/gdbserver.h | 1 + riscv/processor.cc | 5 ++-- riscv/processor.h | 12 +++++++- riscv/sim.cc | 2 +- 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::const_iterator &iter, return value; } +void consume_string(std::string &str, std::vector::const_iterator &iter, + std::vector::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 &packet) { // p n @@ -436,7 +447,7 @@ void gdbserver_t::handle_continue(const std::vector &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 &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 &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 &packet) +{ + std::string name; + std::vector::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 &packet) { if (compute_checksum(packet) != extract_checksum(packet)) { @@ -568,6 +611,9 @@ void gdbserver_t::handle_packet(const std::vector &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 &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 &packet); void handle_memory_binary_write(const std::vector &packet); void handle_memory_read(const std::vector &packet); + void handle_query(const std::vector &packet); void handle_register_read(const std::vector &packet); void handle_step(const std::vector &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)); -- 2.30.2