From 64f57718a840888fd2ba944316576c5a35f7a7a8 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 8 Mar 2016 21:56:31 -0800 Subject: [PATCH] Now you can halt/continue from gdb. --- riscv/execute.cc | 4 +++- riscv/gdbserver.cc | 45 +++++++++++++++++++++++++++++++++++++++++++-- riscv/gdbserver.h | 5 ++++- riscv/processor.cc | 7 ++++++- riscv/processor.h | 4 ++++ 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index 5c3fdf7..45205b3 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -53,7 +53,9 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch) // fetch/decode/execute loop void processor_t::step(size_t n) { - while (run && n > 0) { + // TODO: We should really not call this function at all when halted, to avoid + // burning CPU. + while (run && !halted && n > 0) { size_t instret = 0; reg_t pc = state.pc; mmu_t* _mmu = mmu; diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc index fe553dc..a3663c9 100644 --- a/riscv/gdbserver.cc +++ b/riscv/gdbserver.cc @@ -145,6 +145,10 @@ void gdbserver_t::accept() int oldopts = fcntl(client_fd, F_GETFL, 0); fcntl(client_fd, F_SETFL, oldopts | O_NONBLOCK); expect_ack = false; + + // gdb wants the core to be halted when it attaches. + processor_t *p = sim->get_core(0); + p->set_halted(true); } } @@ -170,6 +174,7 @@ void gdbserver_t::read() send_buf.reset(); } else { recv_buf.data_added(bytes); + printf("Read %d bytes.\n", bytes); } } @@ -202,7 +207,10 @@ void gdbserver_t::write() void print_packet(const std::vector &packet) { for (uint8_t c : packet) { - fprintf(stderr, "%c", c); + if (c >= ' ' and c <= '~') + fprintf(stderr, "%c", c); + else + fprintf(stderr, "\\x%x", c); } fprintf(stderr, "\n"); } @@ -248,6 +256,13 @@ void gdbserver_t::process_requests() break; } + if (packet.empty() && b == 3) { + fprintf(stderr, "Received interrupt\n"); + recv_buf.consume(1); + handle_interrupt(); + break; + } + if (b == '$') { // Start of new packet. if (!packet.empty()) { @@ -271,8 +286,11 @@ void gdbserver_t::process_requests() } // There's a partial packet in the buffer. Wait until we get more data to // process it. - if (packet.size()) + if (packet.size()) { + fprintf(stderr, "Partial packet: "); + print_packet(packet); break; + } } } @@ -412,12 +430,35 @@ void gdbserver_t::handle_packet(const std::vector &packet) return handle_read_memory(packet); case 'p': return handle_read_register(packet); + case 'c': + return handle_continue(packet); } // Not supported. send_packet(""); } +void gdbserver_t::handle_interrupt() +{ + processor_t *p = sim->get_core(0); + p->set_halted(true); + send_packet("S02"); // Pretend program received SIGINT. +} + +void gdbserver_t::handle_continue(const std::vector &packet) +{ + // c [addr] + processor_t *p = sim->get_core(0); + if (packet[2] != '#') { + std::vector::const_iterator iter = packet.begin() + 2; + p->state.pc = consume_hex_number(iter, packet.end()); + if (*iter != '#') + return send_packet("E16"); // EINVAL + } + + p->set_halted(false); +} + void gdbserver_t::handle() { if (client_fd > 0) { diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h index 58bebf5..8add2ad 100644 --- a/riscv/gdbserver.h +++ b/riscv/gdbserver.h @@ -52,11 +52,14 @@ public: // Process all pending messages from a client. void handle(); - void handle_halt_reason(const std::vector &packet); void handle_packet(const std::vector &packet); + void handle_interrupt(); + + void handle_halt_reason(const std::vector &packet); void handle_read_general_registers(const std::vector &packet); void handle_read_memory(const std::vector &packet); void handle_read_register(const std::vector &packet); + void handle_continue(const std::vector &packet); private: sim_t *sim; diff --git a/riscv/processor.cc b/riscv/processor.cc index 63339b1..26a91db 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -22,7 +22,7 @@ processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id) : sim(sim), ext(NULL), disassembler(new disassembler_t), - id(id), run(false), debug(false) + id(id), run(false), debug(false), halted(false) { parse_isa_string(isa); @@ -126,6 +126,11 @@ void processor_t::set_debug(bool value) ext->set_debug(value); } +void processor_t::set_halted(bool value) +{ + halted = value; +} + void processor_t::set_histogram(bool value) { histogram_enabled = value; diff --git a/riscv/processor.h b/riscv/processor.h index 3adf990..94e9593 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -81,6 +81,7 @@ public: ~processor_t(); void set_debug(bool value); + void set_halted(bool value); void set_histogram(bool value); void reset(bool value); void step(size_t n); // run for n cycles @@ -118,7 +119,10 @@ private: reg_t isa; std::string isa_string; bool run; // !reset + // When true, display disassembly of each instruction that's executed. bool debug; + // TODO: Should this just be rolled into `run`? + bool halted; // When true, no instructions are executed. bool histogram_enabled; std::vector instructions; -- 2.30.2