Browse Source

Implement single memory read access.

Prevent unaligned accesses in memory read.

Also change how exceptions in Debug Mode are signaled.
pull/39/head
Tim Newsome 10 years ago
parent
commit
8e418f9e54
  1. 20
      debug_rom/debug_rom.S
  2. 33
      debug_rom/debug_rom.h
  3. 113
      riscv/gdbserver.cc
  4. 6
      riscv/processor.cc

20
debug_rom/debug_rom.S

@ -29,15 +29,14 @@ entry: j _entry
resume:
j _resume
exception:
# Flip the LSB of the first word in Debug RAM so the debugger can know
# that we hit an exception.
lw s1, (DEBUG_RAM)(zero)
xori s1, s1, 1
sw s1, (DEBUG_RAM)(zero)
# Fall through to resume.
# Set the last word of Debug RAM to all ones, to indicate that we hit
# an exception.
li s0, ~0
j _resume2
_resume:
li s0, 0
_resume2:
# Clear debug interrupt.
csrr s1, CSR_MHARTID
sw s1, CLEARDEBINT(zero)
@ -58,6 +57,11 @@ restore_64:
restore_128:
nop #lq s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
# s0 contains ~0 if we got here through an exception, and 0 otherwise.
# Store this to the last word in Debug RAM so the debugger can tell if
# an exception occurred.
sw s0, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
check_halt:
csrr s0, DCSR
andi s0, s0, (1<<DCSR_HALT_OFFSET)
@ -68,7 +72,7 @@ exit:
# Restore s0.
csrr s0, DSCRATCH
# TODO: dret?
mret
sret
_entry:

33
debug_rom/debug_rom.h

@ -1,18 +1,19 @@
static const unsigned char debug_rom_raw[] = {
0x6f, 0x00, 0xc0, 0x05, 0x6f, 0x00, 0x00, 0x01, 0x83, 0x24, 0x00, 0xc0,
0x93, 0xc4, 0x14, 0x00, 0x23, 0x20, 0x90, 0xc0, 0xf3, 0x24, 0x50, 0xf1,
0x23, 0x2c, 0x90, 0xee, 0x0f, 0x00, 0xf0, 0x0f, 0xf3, 0x24, 0x00, 0xf1,
0x63, 0xc6, 0x04, 0x00, 0x83, 0x24, 0xc0, 0xc3, 0x6f, 0x00, 0x80, 0x01,
0x93, 0x94, 0x14, 0x00, 0x63, 0xc6, 0x04, 0x00, 0x83, 0x34, 0x80, 0xc3,
0x6f, 0x00, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00, 0x73, 0x24, 0x00, 0x79,
0x13, 0x74, 0x84, 0x00, 0x63, 0x04, 0x04, 0x00, 0x6f, 0x00, 0x40, 0x05,
0x73, 0x24, 0x20, 0x79, 0x73, 0x00, 0x20, 0x10, 0x73, 0x10, 0x24, 0x79,
0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x74, 0x00, 0x13, 0x04, 0xd4, 0xff,
0x63, 0x16, 0x04, 0x02, 0x73, 0x24, 0x00, 0xf1, 0x63, 0x46, 0x04, 0x00,
0x23, 0x2e, 0x90, 0xc2, 0x67, 0x00, 0x00, 0xc0, 0x13, 0x14, 0x14, 0x00,
0x63, 0x46, 0x04, 0x00, 0x23, 0x3c, 0x90, 0xc2, 0x67, 0x00, 0x00, 0xc0,
0x13, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0xc0, 0x73, 0x24, 0x50, 0xf1,
0x23, 0x20, 0x80, 0xf0, 0x73, 0x60, 0x04, 0x79, 0x73, 0x24, 0x00, 0x79,
0x13, 0x74, 0x04, 0x40, 0xe3, 0x0c, 0x04, 0xfe, 0x6f, 0xf0, 0x1f, 0xfc
0x6f, 0x00, 0x00, 0x06, 0x6f, 0x00, 0xc0, 0x00, 0x13, 0x04, 0xf0, 0xff,
0x6f, 0x00, 0x80, 0x00, 0x13, 0x04, 0x00, 0x00, 0xf3, 0x24, 0x40, 0xf1,
0x23, 0x24, 0x90, 0x10, 0x0f, 0x00, 0xf0, 0x0f, 0xf3, 0x24, 0x00, 0xf1,
0x63, 0xc6, 0x04, 0x00, 0x83, 0x24, 0xc0, 0x43, 0x6f, 0x00, 0xc0, 0x01,
0x93, 0x94, 0x14, 0x00, 0x63, 0xc6, 0x04, 0x00, 0x83, 0x34, 0x80, 0x43,
0x6f, 0x00, 0xc0, 0x00, 0x13, 0x00, 0x00, 0x00, 0x23, 0x2e, 0x80, 0x42,
0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x84, 0x00, 0x63, 0x04, 0x04, 0x00,
0x6f, 0x00, 0x40, 0x05, 0x73, 0x24, 0x20, 0x79, 0x73, 0x00, 0x00, 0x10,
0x73, 0x10, 0x24, 0x79, 0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x74, 0x00,
0x13, 0x04, 0xd4, 0xff, 0x63, 0x16, 0x04, 0x02, 0x73, 0x24, 0x00, 0xf1,
0x63, 0x46, 0x04, 0x00, 0x23, 0x2e, 0x90, 0x42, 0x67, 0x00, 0x00, 0x40,
0x13, 0x14, 0x14, 0x00, 0x63, 0x46, 0x04, 0x00, 0x23, 0x3c, 0x90, 0x42,
0x67, 0x00, 0x00, 0x40, 0x13, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x40,
0x73, 0x24, 0x40, 0xf1, 0x23, 0x20, 0x80, 0x10, 0x73, 0x60, 0x04, 0x79,
0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x04, 0x40, 0xe3, 0x0c, 0x04, 0xfe,
0x6f, 0xf0, 0x1f, 0xfc
};
static const unsigned int debug_rom_raw_len = 180;
static const unsigned int debug_rom_raw_len = 184;

113
riscv/gdbserver.cc

@ -104,15 +104,38 @@ static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
MATCH_SD;
}
static uint32_t ld(unsigned int src, unsigned int base, uint16_t offset)
static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
{
return (bits(offset, 11, 5) << 25) |
(bits(src, 4, 0) << 20) |
return (bits(offset, 11, 0) << 20) |
(base << 15) |
(bits(offset, 4, 0) << 7) |
(bits(rd, 4, 0) << 7) |
MATCH_LD;
}
static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
{
return (bits(offset, 11, 0) << 20) |
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LW;
}
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
{
return (bits(offset, 11, 0) << 20) |
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LH;
}
static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
{
return (bits(offset, 11, 0) << 20) |
(base << 15) |
(bits(rd, 4, 0) << 7) |
MATCH_LB;
}
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
{
return (bits(offset, 11, 5) << 25) |
@ -415,6 +438,77 @@ class register_read_op_t : public operation_t
unsigned int reg;
};
class memory_read_op_t : public operation_t
{
public:
memory_read_op_t(gdbserver_t& gdbserver, reg_t addr, unsigned int length) :
operation_t(gdbserver), addr(addr), length(length) {};
bool start()
{
// address goes in S0
access_size = (addr % length);
if (access_size == 0)
access_size = length;
gs.write_debug_ram(0, ld(S0, 0, (uint16_t) DEBUG_RAM_START + 16));
switch (access_size) {
case 1:
gs.write_debug_ram(1, lb(S1, S0, 0));
break;
case 2:
gs.write_debug_ram(1, lh(S1, S0, 0));
break;
case 4:
gs.write_debug_ram(1, lw(S1, S0, 0));
break;
case 8:
gs.write_debug_ram(1, ld(S1, S0, 0));
break;
default:
gs.send_packet("E12");
return true;
}
gs.write_debug_ram(2, sd(S1, 0, (uint16_t) DEBUG_RAM_START + 24));
gs.write_debug_ram(3, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*3))));
gs.write_debug_ram(4, addr);
gs.write_debug_ram(5, addr >> 32);
gs.set_interrupt(0);
gs.start_packet();
return false;
}
bool step()
{
char buffer[3];
reg_t value = ((uint64_t) gs.read_debug_ram(7) << 32) | gs.read_debug_ram(6);
for (unsigned int i = 0; i < access_size; i++) {
sprintf(buffer, "%02x", (unsigned int) (value & 0xff));
gs.send(buffer);
value >>= 8;
}
length -= access_size;
addr += access_size;
if (length == 0) {
gs.end_packet();
return true;
} else {
gs.write_debug_ram(4, addr);
gs.write_debug_ram(5, addr >> 32);
gs.set_interrupt(0);
return false;
}
}
private:
reg_t addr;
unsigned int length;
unsigned int access_size;
};
////////////////////////////// gdbserver itself
gdbserver_t::gdbserver_t(uint16_t port, sim_t *sim) :
@ -764,16 +858,7 @@ void gdbserver_t::handle_memory_read(const std::vector<uint8_t> &packet)
if (*iter != '#')
return send_packet("E11");
start_packet();
char buffer[3];
processor_t *p = sim->get_core(0);
mmu_t* mmu = sim->debug_mmu;
for (reg_t i = 0; i < length; i++) {
sprintf(buffer, "%02x", mmu->load_uint8(address + i));
send(buffer);
}
end_packet();
set_operation(new memory_read_op_t(*this, address, length));
}
void gdbserver_t::handle_memory_binary_write(const std::vector<uint8_t> &packet)

6
riscv/processor.cc

@ -206,9 +206,13 @@ void processor_t::enter_debug_mode(uint8_t cause)
void processor_t::take_trap(trap_t& t, reg_t epc)
{
if (debug)
if (debug) {
fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
id, t.name(), epc);
if (t.has_badaddr())
fprintf(stderr, "core %3d: badaddr 0x%016" PRIx64 "\n", id,
t.get_badaddr());
}
if (t.cause() == CAUSE_BREAKPOINT &&
sim->gdbserver && sim->gdbserver->connected()) {

Loading…
Cancel
Save