Users can use this register to inspect and change the privilege level of
the core. It doesn't make any assumptions about the actual underlying
debug mechanism (as opposed to having the user change DCSR directly,
which may not exist in all debug implementations).
# define D(x)
#endif // DEBUG
# define D(x)
#endif // DEBUG
-const int debug_gdbserver = 0;
-
void die(const char* msg)
{
fprintf(stderr, "gdbserver code died: %s\n", msg);
void die(const char* msg)
{
fprintf(stderr, "gdbserver code died: %s\n", msg);
REG_FPR31 = 64,
REG_CSR0 = 65,
REG_CSR4095 = 4160,
REG_FPR31 = 64,
REG_CSR0 = 65,
REG_CSR4095 = 4160,
};
//////////////////////////////////////// Functions to generate RISC-V opcodes.
};
//////////////////////////////////////// Functions to generate RISC-V opcodes.
// If we hit an exception reading the CSR, we'll end up returning ~0 as
// the register's value, which is what we want. (Right?)
gs.dr_write(SLOT_DATA0, ~(uint64_t) 0);
// If we hit an exception reading the CSR, we'll end up returning ~0 as
// the register's value, which is what we want. (Right?)
gs.dr_write(SLOT_DATA0, ~(uint64_t) 0);
+ } else if (reg == REG_PRIV) {
+ gs.start_packet();
+ gs.send((uint8_t) get_field(gs.dcsr, DCSR_PRV));
+ gs.end_packet();
+ return true;
} else {
gs.send_packet("E02");
return true;
} else {
gs.send_packet("E02");
return true;
gs.sptbr = value;
gs.sptbr_valid = true;
}
gs.sptbr = value;
gs.sptbr_valid = true;
}
+ } else if (reg == REG_PRIV) {
+ gs.dcsr = set_field(gs.dcsr, DCSR_PRV, value);
+ return true;
} else {
gs.send_packet("E02");
return true;
} else {
gs.send_packet("E02");
return true;
- if (data && debug_gdbserver) {
D(fprintf(stderr, "\n"));
}
length -= access_size;
D(fprintf(stderr, "\n"));
}
length -= access_size;
+void gdbserver_t::send(uint8_t value)
+{
+ char buffer[3];
+ sprintf(buffer, "%02x", (int) value);
+ send(buffer);
+}
+
void gdbserver_t::send_packet(const char* data)
{
start_packet();
void gdbserver_t::send_packet(const char* data)
{
start_packet();
// Hex-encode a 32-bit value, and send it to gcc in target byte order (little
// endian).
void send(uint32_t value);
// Hex-encode a 32-bit value, and send it to gcc in target byte order (little
// endian).
void send(uint32_t value);
+ // Hex-encode an 8-bit value, and send it to gcc.
+ void send(uint8_t value);
void send_packet(const char* data);
uint8_t running_checksum;
// Send "$" and clear running checksum.
void send_packet(const char* data);
uint8_t running_checksum;
// Send "$" and clear running checksum.
require_privilege(PRV_M);
set_pc_and_serialize(STATE.dpc);
require_privilege(PRV_M);
set_pc_and_serialize(STATE.dpc);
-p->set_privilege(STATE.dcsr.prv);
+/* The debug spec says we can't crash when prv is set to an invalid value. */
+if (p->validate_priv(STATE.dcsr.prv)) {
+ p->set_privilege(STATE.dcsr.prv);
+}
/* We're not in Debug Mode anymore. */
STATE.dcsr.cause = 0;
/* We're not in Debug Mode anymore. */
STATE.dcsr.cause = 0;
raise_interrupt(ctz(enabled_interrupts));
}
raise_interrupt(ctz(enabled_interrupts));
}
-static bool validate_priv(reg_t priv)
+bool processor_t::validate_priv(reg_t priv)
{
return priv == PRV_U || priv == PRV_S || priv == PRV_M;
}
{
return priv == PRV_U || priv == PRV_S || priv == PRV_M;
}
if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
return ext >= 'A' && ext <= 'Z' && ((isa >> (ext - 'A')) & 1);
}
if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
return ext >= 'A' && ext <= 'Z' && ((isa >> (ext - 'A')) & 1);
}
+ bool validate_priv(reg_t priv);
void set_privilege(reg_t);
void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
void update_histogram(reg_t pc);
void set_privilege(reg_t);
void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
void update_histogram(reg_t pc);