fix elf loader and pmp check for debug accesses
This commit is contained in:
parent
e934049dd4
commit
2f05083cf0
|
@ -388,6 +388,7 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_fi
|
||||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
||||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
||||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
||||||
|
auto entry = reader.get_entry();
|
||||||
for (const auto pseg : reader.segments) {
|
for (const auto pseg : reader.segments) {
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
const auto seg_data = pseg->get_data();
|
const auto seg_data = pseg->get_data();
|
||||||
|
@ -400,14 +401,35 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_fi
|
||||||
<< pseg->get_physical_address();
|
<< pseg->get_physical_address();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if (sec->get_name() == ".tohost") {
|
if(sec->get_name() == ".symtab") {
|
||||||
|
if ( SHT_SYMTAB == sec->get_type() ||
|
||||||
|
SHT_DYNSYM == sec->get_type() ) {
|
||||||
|
ELFIO::symbol_section_accessor symbols( reader, sec );
|
||||||
|
auto sym_no = symbols.get_symbols_num();
|
||||||
|
std::string name;
|
||||||
|
ELFIO::Elf64_Addr value = 0;
|
||||||
|
ELFIO::Elf_Xword size = 0;
|
||||||
|
unsigned char bind = 0;
|
||||||
|
unsigned char type = 0;
|
||||||
|
ELFIO::Elf_Half section = 0;
|
||||||
|
unsigned char other = 0;
|
||||||
|
for ( auto i = 0U; i < sym_no; ++i ) {
|
||||||
|
symbols.get_symbol( i, name, value, size, bind, type, section, other );
|
||||||
|
if(name=="tohost") {
|
||||||
|
tohost = value;
|
||||||
|
} else if(name=="fromhost") {
|
||||||
|
fromhost = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sec->get_name() == ".tohost") {
|
||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(reader.get_entry(), true);
|
}
|
||||||
|
return std::make_pair(entry, true);
|
||||||
}
|
}
|
||||||
throw std::runtime_error("memory load file is not a valid elf file");
|
throw std::runtime_error("memory load file is not a valid elf file");
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,6 +531,7 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
||||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
||||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
||||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
||||||
|
auto entry = reader.get_entry();
|
||||||
for (const auto pseg : reader.segments) {
|
for (const auto pseg : reader.segments) {
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
const auto seg_data = pseg->get_data();
|
const auto seg_data = pseg->get_data();
|
||||||
|
@ -543,14 +544,35 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
||||||
<< pseg->get_physical_address();
|
<< pseg->get_physical_address();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if (sec->get_name() == ".tohost") {
|
if(sec->get_name() == ".symtab") {
|
||||||
|
if ( SHT_SYMTAB == sec->get_type() ||
|
||||||
|
SHT_DYNSYM == sec->get_type() ) {
|
||||||
|
ELFIO::symbol_section_accessor symbols( reader, sec );
|
||||||
|
auto sym_no = symbols.get_symbols_num();
|
||||||
|
std::string name;
|
||||||
|
ELFIO::Elf64_Addr value = 0;
|
||||||
|
ELFIO::Elf_Xword size = 0;
|
||||||
|
unsigned char bind = 0;
|
||||||
|
unsigned char type = 0;
|
||||||
|
ELFIO::Elf_Half section = 0;
|
||||||
|
unsigned char other = 0;
|
||||||
|
for ( auto i = 0U; i < sym_no; ++i ) {
|
||||||
|
symbols.get_symbol( i, name, value, size, bind, type, section, other );
|
||||||
|
if(name=="tohost") {
|
||||||
|
tohost = value;
|
||||||
|
} else if(name=="fromhost") {
|
||||||
|
fromhost = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sec->get_name() == ".tohost") {
|
||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(reader.get_entry(), true);
|
}
|
||||||
|
return std::make_pair(entry, true);
|
||||||
}
|
}
|
||||||
throw std::runtime_error("memory load file is not a valid elf file");
|
throw std::runtime_error("memory load file is not a valid elf file");
|
||||||
}
|
}
|
||||||
|
@ -1296,9 +1318,6 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
||||||
// bits in mtvec
|
// bits in mtvec
|
||||||
this->reg.NEXT_PC = ivec & ~0x3UL;
|
this->reg.NEXT_PC = ivec & ~0x3UL;
|
||||||
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
||||||
// reset trap state
|
|
||||||
this->reg.PRIV = new_priv;
|
|
||||||
this->reg.trap_state = 0;
|
|
||||||
std::array<char, 32> buffer;
|
std::array<char, 32> buffer;
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
if((flags&0xffffffff) != 0xffffffff)
|
if((flags&0xffffffff) != 0xffffffff)
|
||||||
|
@ -1306,6 +1325,9 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
||||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
||||||
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
||||||
<< lvl[cur_priv] << " to " << lvl[new_priv];
|
<< lvl[cur_priv] << " to " << lvl[new_priv];
|
||||||
|
// reset trap state
|
||||||
|
this->reg.PRIV = new_priv;
|
||||||
|
this->reg.trap_state = 0;
|
||||||
update_vm_info();
|
update_vm_info();
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -484,6 +484,7 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
||||||
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
|
||||||
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
|
||||||
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
|
||||||
|
auto entry = reader.get_entry();
|
||||||
for (const auto pseg : reader.segments) {
|
for (const auto pseg : reader.segments) {
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
const auto seg_data = pseg->get_data();
|
const auto seg_data = pseg->get_data();
|
||||||
|
@ -496,14 +497,35 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
||||||
<< pseg->get_physical_address();
|
<< pseg->get_physical_address();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if (sec->get_name() == ".tohost") {
|
if(sec->get_name() == ".symtab") {
|
||||||
|
if ( SHT_SYMTAB == sec->get_type() ||
|
||||||
|
SHT_DYNSYM == sec->get_type() ) {
|
||||||
|
ELFIO::symbol_section_accessor symbols( reader, sec );
|
||||||
|
auto sym_no = symbols.get_symbols_num();
|
||||||
|
std::string name;
|
||||||
|
ELFIO::Elf64_Addr value = 0;
|
||||||
|
ELFIO::Elf_Xword size = 0;
|
||||||
|
unsigned char bind = 0;
|
||||||
|
unsigned char type = 0;
|
||||||
|
ELFIO::Elf_Half section = 0;
|
||||||
|
unsigned char other = 0;
|
||||||
|
for ( auto i = 0U; i < sym_no; ++i ) {
|
||||||
|
symbols.get_symbol( i, name, value, size, bind, type, section, other );
|
||||||
|
if(name=="tohost") {
|
||||||
|
tohost = value;
|
||||||
|
} else if(name=="fromhost") {
|
||||||
|
fromhost = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sec->get_name() == ".tohost") {
|
||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(reader.get_entry(), true);
|
}
|
||||||
|
return std::make_pair(entry, true);
|
||||||
}
|
}
|
||||||
throw std::runtime_error("memory load file is not a valid elf file");
|
throw std::runtime_error("memory load file is not a valid elf file");
|
||||||
}
|
}
|
||||||
|
@ -525,8 +547,9 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
|
||||||
reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT;
|
reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT;
|
||||||
uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4);
|
uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4);
|
||||||
if (cfg & PMP_A) {
|
if (cfg & PMP_A) {
|
||||||
bool is_tor = (cfg & PMP_A) == PMP_TOR;
|
auto pmp_a = (cfg & PMP_A) >> 3;
|
||||||
bool is_na4 = (cfg & PMP_A) == PMP_NA4;
|
bool is_tor = pmp_a == PMP_TOR;
|
||||||
|
bool is_na4 = pmp_a == PMP_NA4;
|
||||||
|
|
||||||
reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4);
|
reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4);
|
||||||
mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
|
mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
|
||||||
|
@ -574,7 +597,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||||
switch (space) {
|
switch (space) {
|
||||||
case traits<BASE>::MEM: {
|
case traits<BASE>::MEM: {
|
||||||
if(FEAT & FEAT_PMP){
|
if(FEAT & FEAT_PMP){
|
||||||
if(!pmp_check(access, addr, length)) {
|
if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1
|
this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1
|
||||||
|
@ -669,7 +692,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||||
switch (space) {
|
switch (space) {
|
||||||
case traits<BASE>::MEM: {
|
case traits<BASE>::MEM: {
|
||||||
if(FEAT & FEAT_PMP){
|
if(FEAT & FEAT_PMP){
|
||||||
if(!pmp_check(access, addr, length)) {
|
if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1
|
this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1
|
||||||
|
@ -683,7 +706,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(length>1 && (addr&(length-1))){
|
if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
|
||||||
this->reg.trap_state = 1<<31 | 6<<16;
|
this->reg.trap_state = 1<<31 | 6<<16;
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
|
@ -1217,9 +1240,6 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
// bits in mtvec
|
// bits in mtvec
|
||||||
this->reg.NEXT_PC = ivec & ~0x3UL;
|
this->reg.NEXT_PC = ivec & ~0x3UL;
|
||||||
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
||||||
// reset trap state
|
|
||||||
this->reg.PRIV = new_priv;
|
|
||||||
this->reg.trap_state = 0;
|
|
||||||
std::array<char, 32> buffer;
|
std::array<char, 32> buffer;
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
if((flags&0xffffffff) != 0xffffffff)
|
if((flags&0xffffffff) != 0xffffffff)
|
||||||
|
@ -1227,6 +1247,9 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
||||||
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
<< " at address " << buffer.data() << " occurred, changing privilege level from "
|
||||||
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv];
|
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv];
|
||||||
|
// reset trap state
|
||||||
|
this->reg.PRIV = new_priv;
|
||||||
|
this->reg.trap_state = 0;
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -47,7 +47,7 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
|
||||||
#ifdef CORE_TGC_D
|
#ifdef CORE_TGC_D
|
||||||
#include "iss/arch/riscv_hart_mu_p.h"
|
#include "iss/arch/riscv_hart_mu_p.h"
|
||||||
#include "iss/arch/tgc_d.h"
|
#include "iss/arch/tgc_d.h"
|
||||||
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, iss::arch::FEAT_PMP>;
|
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_LLVM
|
#ifdef WITH_LLVM
|
||||||
#include <iss/llvm/jit_helper.h>
|
#include <iss/llvm/jit_helper.h>
|
||||||
|
@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
|
||||||
("mem,m", po::value<std::string>(), "the memory input file")
|
("mem,m", po::value<std::string>(), "the memory input file")
|
||||||
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
||||||
("backend", po::value<std::string>()->default_value("interp"), "the memory input file")
|
("backend", po::value<std::string>()->default_value("interp"), "the memory input file")
|
||||||
("isa", po::value<std::string>()->default_value("tgf_c"), "isa to use for simulation");
|
("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||||
try {
|
try {
|
||||||
|
@ -123,18 +123,18 @@ int main(int argc, char *argv[]) {
|
||||||
iss::vm_ptr vm{nullptr};
|
iss::vm_ptr vm{nullptr};
|
||||||
iss::cpu_ptr cpu{nullptr};
|
iss::cpu_ptr cpu{nullptr};
|
||||||
std::string isa_opt(clim["isa"].as<std::string>());
|
std::string isa_opt(clim["isa"].as<std::string>());
|
||||||
if (isa_opt == "tgf_c") {
|
if (isa_opt == "tgc_c") {
|
||||||
std::tie(cpu, vm) =
|
std::tie(cpu, vm) =
|
||||||
iss::create_cpu<tgc_c_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
iss::create_cpu<tgc_c_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||||
} else
|
} else
|
||||||
#ifdef CORE_TGC_B
|
#ifdef CORE_TGC_B
|
||||||
if (isa_opt == "tgf_b") {
|
if (isa_opt == "tgc_b") {
|
||||||
std::tie(cpu, vm) =
|
std::tie(cpu, vm) =
|
||||||
iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
#ifdef CORE_TGC_D
|
#ifdef CORE_TGC_D
|
||||||
if (isa_opt == "tgf_d") {
|
if (isa_opt == "tgc_d") {
|
||||||
std::tie(cpu, vm) =
|
std::tie(cpu, vm) =
|
||||||
iss::create_cpu<tgc_d_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
iss::create_cpu<tgc_d_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||||
} else
|
} else
|
||||||
|
|
Loading…
Reference in New Issue