Browse Source

Flush icache when using swbps and report to gdb.

pull/39/head
Tim Newsome 11 years ago
parent
commit
824689f929
  1. 7
      Makefile.in
  2. 4
      riscv/execute.cc
  3. 73
      riscv/gdbserver.cc
  4. 1
      riscv/gdbserver.h
  5. 5
      riscv/processor.cc
  6. 12
      riscv/processor.h
  7. 2
      riscv/sim.cc

7
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

4
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);
}
}

73
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;

1
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);

5
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;
}

12
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;

2
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));

Loading…
Cancel
Save