From 7baa7795ba6b878f1dc859f4d4ee239bb569c750 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 26 Apr 2016 14:32:08 -0700 Subject: [PATCH] gdb can attach and read the PC: (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x0000000000010178 in fib (n=0) at waste.c:1 1 unsigned int fib(unsigned int n) { (gdb) --- riscv/execute.cc | 2 +- riscv/gdbserver.cc | 109 ++++++++++++++++++++++++++++++++++++--------- riscv/gdbserver.h | 7 ++- riscv/mmu.h | 1 + 4 files changed, 95 insertions(+), 24 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index ae4c959..a1c2229 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -63,7 +63,7 @@ void processor_t::step(size_t n) if (state.dcsr.cause != DCSR_CAUSE_NONE) { // In Debug Mode, just do 10 steps at a time. Otherwise we're going to be // spinning the rest of the time anyway. - n = std::max(n, (size_t) 10); + n = std::min(n, (size_t) 10); } while (n > 0) { diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc index 0487939..a4f8c0b 100644 --- a/riscv/gdbserver.cc +++ b/riscv/gdbserver.cc @@ -63,6 +63,15 @@ static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) MATCH_SW; } +static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) +{ + return (bits(offset, 11, 5) << 25) | + (src << 20) | + (base << 15) | + (bits(offset, 4, 0) << 7) | + MATCH_SD; +} + template unsigned int circular_buffer_t::size() const { @@ -177,12 +186,12 @@ uint32_t gdbserver_t::read_debug_ram(unsigned int index) void gdbserver_t::halt() { - processor_t *p = sim->get_core(0); + // TODO: For now we just assume the target is 64-bit. write_debug_ram(0, csrsi(DCSR_ADDRESS, DCSR_HALT_MASK)); write_debug_ram(1, csrr(S0, DPC_ADDRESS)); - write_debug_ram(2, sw(S0, 0, (uint16_t) DEBUG_RAM_START)); + write_debug_ram(2, sd(S0, 0, (uint16_t) DEBUG_RAM_START)); write_debug_ram(3, csrr(S0, DCSR_ADDRESS)); - write_debug_ram(4, sw(S0, 0, (uint16_t) DEBUG_RAM_START + 8)); + write_debug_ram(4, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 8)); write_debug_ram(5, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*5)))); sim->debug_module.set_interrupt(0); state = STATE_HALTING; @@ -358,7 +367,7 @@ void gdbserver_t::handle_halt_reason(const std::vector &packet) void die(const char* msg) { - fprintf(stderr, "%s\n", msg); + fprintf(stderr, "gdbserver code died: %s\n", msg); abort(); } @@ -379,12 +388,36 @@ void gdbserver_t::handle_general_registers_read(const std::vector &pack send("$"); running_checksum = 0; processor_t *p = sim->get_core(0); - for (int r = 0; r < 32; r++) { - die("handle_general_registers_read"); - // send(p->state.XPR[r]); + + // x0 is always zero. + send((reg_t) 0); + + write_debug_ram(0, sd(1, 0, (uint16_t) DEBUG_RAM_START + 16)); + write_debug_ram(1, sd(2, 0, (uint16_t) DEBUG_RAM_START + 0)); + write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2)))); + sim->debug_module.set_interrupt(0); + state = STATE_CONT_GENERAL_REGISTERS; + state_argument = 1; +} + +void gdbserver_t::continue_general_registers_read() +{ + send(((uint64_t) read_debug_ram(5) << 32) | read_debug_ram(4)); + if (state_argument >= 31) { + send_running_checksum(); + expect_ack = true; + state = STATE_HALTED; + } else { + send(((uint64_t) read_debug_ram(1) << 32) | read_debug_ram(0)); + + state_argument += 2; + // TODO properly read s0 and s1 + write_debug_ram(0, sd(state_argument, 0, (uint16_t) DEBUG_RAM_START + 16)); + write_debug_ram(1, sd(state_argument+1, 0, (uint16_t) DEBUG_RAM_START + 0)); + write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2)))); + sim->debug_module.set_interrupt(0); + state = STATE_CONT_GENERAL_REGISTERS; } - send_running_checksum(); - expect_ack = true; } // First byte is the most-significant one. @@ -460,21 +493,24 @@ void gdbserver_t::handle_register_read(const std::vector &packet) if (*iter != '#') return send_packet("E01"); - processor_t *p = sim->get_core(0); - send("$"); - running_checksum = 0; + state = STATE_CONT_REGISTER_READ; + state_argument = n; - die("handle_register_read"); - /* if (n >= REG_XPR0 && n <= REG_XPR31) { - send(p->state.XPR[n - REG_XPR0]); + die("handle_register_read"); + // send(p->state.XPR[n - REG_XPR0]); } else if (n == REG_PC) { - send(p->state.pc); + write_debug_ram(0, csrr(S0, DPC_ADDRESS)); + write_debug_ram(1, sd(S0, 0, (uint16_t) DEBUG_RAM_START)); + write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2)))); + sim->debug_module.set_interrupt(0); } else if (n >= REG_FPR0 && n <= REG_FPR31) { - send(p->state.FPR[n - REG_FPR0]); + die("handle_register_read"); + // send(p->state.FPR[n - REG_FPR0]); } else if (n >= REG_CSR0 && n <= REG_CSR4095) { try { - send(p->get_csr(n - REG_CSR0)); + die("handle_register_read"); + // send(p->get_csr(n - REG_CSR0)); } catch(trap_t& t) { // It would be nicer to return an error here, but if you do that then gdb // exits out of 'info registers all' as soon as it encounters a register @@ -482,12 +518,21 @@ void gdbserver_t::handle_register_read(const std::vector &packet) send((reg_t) 0); } } else { + state = STATE_HALTED; return send_packet("E02"); } - */ +} + +void gdbserver_t::continue_register_read() +{ + send("$"); + running_checksum = 0; + + send(((uint64_t) read_debug_ram(1) << 32) | read_debug_ram(0)); send_running_checksum(); expect_ack = true; + state = STATE_HALTED; } void gdbserver_t::handle_register_write(const std::vector &packet) @@ -786,13 +831,27 @@ void gdbserver_t::handle() if (client_fd > 0) { processor_t *p = sim->get_core(0); - if (state == STATE_HALTING && sim->debug_module.get_interrupt(0) == 0) { + bool interrupt = sim->debug_module.get_interrupt(0); + + if (state == STATE_HALTING && !interrupt) { // gdb requested a halt and now it's done. send_packet("T05"); fprintf(stderr, "DPC: 0x%x\n", read_debug_ram(0)); fprintf(stderr, "DCSR: 0x%x\n", read_debug_ram(2)); state = STATE_HALTED; - p->debug = false; + } + + if (!interrupt) { + switch (state) { + case STATE_CONT_GENERAL_REGISTERS: + continue_general_registers_read(); + break; + case STATE_CONT_REGISTER_READ: + continue_register_read(); + break; + default: + break; + } } /* TODO @@ -819,7 +878,13 @@ void gdbserver_t::handle() } */ - this->read(); + if (state == STATE_HALTED) { + this->read(); + //p->debug = false; + } else { + //p->debug = true; + } + this->write(); } else { diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h index 5a7a102..156001d 100644 --- a/riscv/gdbserver.h +++ b/riscv/gdbserver.h @@ -71,12 +71,14 @@ public: void handle_continue(const std::vector &packet); void handle_extended(const std::vector &packet); void handle_general_registers_read(const std::vector &packet); + void continue_general_registers_read(); void handle_halt_reason(const std::vector &packet); 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 continue_register_read(); void handle_register_write(const std::vector &packet); void handle_step(const std::vector &packet); @@ -100,8 +102,11 @@ private: STATE_UNKNOWN, STATE_RUNNING, STATE_HALTING, - STATE_HALTED + STATE_HALTED, + STATE_CONT_GENERAL_REGISTERS, + STATE_CONT_REGISTER_READ, } state; + uint32_t state_argument; std::map breakpoints; diff --git a/riscv/mmu.h b/riscv/mmu.h index a87b6af..8fe3043 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -117,6 +117,7 @@ public: entry->tag = -1; tracer.trace(paddr, length, FETCH); } + entry->tag = -1; // TODO: this is hack to work around Debug RAM code being cached return entry; } -- 2.30.2