#ifndef _RISCV_GDBSERVER_H
#define _RISCV_GDBSERVER_H
+#include <map>
+#include <queue>
+
#include <stdint.h>
class sim_t;
public:
reg_t address;
unsigned int size;
- uint32_t instruction;
+ unsigned char instruction[4];
+};
+
+class gdbserver_t;
- void insert(mmu_t* mmu);
- void remove(mmu_t* mmu);
+class operation_t
+{
+ public:
+ operation_t(gdbserver_t& gdbserver) : gs(gdbserver), current_step(0) {}
+ virtual ~operation_t() {}
+
+ bool step() {
+ bool result = perform_step(current_step);
+ current_step++;
+ return result;
+ }
+
+ // Perform the next step of this operation (which is probably to write to
+ // Debug RAM and assert the debug interrupt).
+ // Return true if this operation is complete. In that case the object will
+ // be deleted.
+ // Return false if more steps are required the next time the debug
+ // interrupt is clear.
+ virtual bool perform_step(unsigned int step) = 0;
+
+ protected:
+ gdbserver_t& gs;
+ unsigned int current_step;
};
class gdbserver_t
bool connected() const { return client_fd > 0; }
- void halt();
+ // TODO: Move this into its own packet sending class?
+ // Add the given message to send_buf.
+ void send(const char* msg);
+ // Hex-encode a 64-bit value, and send it to gcc in target byte order (little
+ // endian).
+ void send(uint64_t value);
+ // Hex-encode a 32-bit value, and send it to gcc in target byte order (little
+ // endian).
+ void send(uint32_t value);
+ void send_packet(const char* data);
+ uint8_t running_checksum;
+ // Send "$" and clear running checksum.
+ void start_packet();
+ // Send "#" and checksum.
+ void end_packet(const char* data=NULL);
+
+ // Write value to the index'th word in Debug RAM.
+ void write_debug_ram(unsigned int index, uint32_t value);
+ uint32_t read_debug_ram(unsigned int index);
+
+ void set_interrupt(uint32_t hartid);
+
+ // Members that ought to be privated, but that we'd really like to access
+ // from operation classes.
+ reg_t saved_dpc;
+ reg_t saved_mbadaddr;
+ reg_t saved_mcause;
+ reg_t saved_mstatus;
+ reg_t dcsr;
+ reg_t sptbr;
+ bool sptbr_valid;
+
+ std::map<reg_t, reg_t> pte_cache;
+
+ reg_t translate(reg_t vaddr);
+ // Return the PRV_x that is used when the code under debug performs a memory
+ // access.
+ unsigned int privilege_mode();
+ // Return the VM_x that is used when the code under debug performs a memory
+ // access.
+ unsigned int virtual_memory();
private:
sim_t *sim;
// Used to track whether we think the target is running. If we think it is
// but it isn't, we need to tell gdb about it.
bool running;
- enum {
- STATE_UNKNOWN,
- STATE_RUNNING,
- STATE_HALTING,
- STATE_HALTED,
- STATE_CONT_GENERAL_REGISTERS,
- STATE_CONT_REGISTER_READ,
- } state;
- uint32_t state_argument;
-
- std::map <reg_t, software_breakpoint_t> breakpoints;
+
+ std::map <reg_t, software_breakpoint_t*> breakpoints;
// Read pending data from the client.
void read();
void accept();
// Process all complete requests in recv_buf.
void process_requests();
- // Add the given message to send_buf.
- void send(const char* msg);
- // Hex-encode a 64-bit value, and send it to gcc in target byte order (little
- // endian).
- void send(uint64_t value);
- // Hex-encode a 32-bit value, and send it to gcc in target byte order (little
- // endian).
- void send(uint32_t value);
- void send_packet(const char* data);
- uint8_t running_checksum;
- void send_running_checksum();
- // Write value to the index'th word in Debug RAM.
- void write_debug_ram(unsigned int index, uint32_t value);
- uint32_t read_debug_ram(unsigned int index);
+ std::queue<operation_t*> operation_queue;
+ void add_operation(operation_t* operation);
};
#endif