From 2f05083cf06b6e4623231f32508320224a38e348 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 19 Aug 2021 10:49:33 +0200 Subject: [PATCH] fix elf loader and pmp check for debug accesses --- incl/iss/arch/riscv_hart_m_p.h | 30 +++++++++++++++++--- incl/iss/arch/riscv_hart_msu_vp.h | 36 ++++++++++++++++++----- incl/iss/arch/riscv_hart_mu_p.h | 47 +++++++++++++++++++++++-------- src/main.cpp | 10 +++---- 4 files changed, 95 insertions(+), 28 deletions(-) diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 0c4bdaa..4cdb491 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -388,6 +388,7 @@ template std::pair riscv_hart_m_p::load_fi 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_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + auto entry = reader.get_entry(); for (const auto pseg : reader.segments) { const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto seg_data = pseg->get_data(); @@ -400,14 +401,35 @@ template std::pair riscv_hart_m_p::load_fi << pseg->get_physical_address(); } } - for (const auto sec : reader.sections) { - if (sec->get_name() == ".tohost") { + for(const auto sec : reader.sections) { + 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(); 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"); } diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index 9de36f3..ff1ed78 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -531,6 +531,7 @@ template std::pair riscv_hart_msu_vp::load 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_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + auto entry = reader.get_entry(); for (const auto pseg : reader.segments) { const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto seg_data = pseg->get_data(); @@ -543,14 +544,35 @@ template std::pair riscv_hart_msu_vp::load << pseg->get_physical_address(); } } - for (const auto sec : reader.sections) { - if (sec->get_name() == ".tohost") { + for(const auto sec : reader.sections) { + 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(); 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"); } @@ -1296,9 +1318,6 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f // bits in mtvec this->reg.NEXT_PC = ivec & ~0x3UL; 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 buffer; sprintf(buffer.data(), "0x%016lx", addr); if((flags&0xffffffff) != 0xffffffff) @@ -1306,6 +1325,9 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv] << " to " << lvl[new_priv]; + // reset trap state + this->reg.PRIV = new_priv; + this->reg.trap_state = 0; update_vm_info(); return this->reg.NEXT_PC; } diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 78bcf00..2a05997 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -484,6 +484,7 @@ template std::pair riscv_hart_m 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_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + auto entry = reader.get_entry(); for (const auto pseg : reader.segments) { const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto seg_data = pseg->get_data(); @@ -496,14 +497,35 @@ template std::pair riscv_hart_m << pseg->get_physical_address(); } } - for (const auto sec : reader.sections) { - if (sec->get_name() == ".tohost") { + for(const auto sec : reader.sections) { + 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(); 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"); } @@ -525,8 +547,9 @@ template bool riscv_hart_mu_p::pmp_ reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); if (cfg & PMP_A) { - bool is_tor = (cfg & PMP_A) == PMP_TOR; - bool is_na4 = (cfg & PMP_A) == PMP_NA4; + auto pmp_a = (cfg & PMP_A) >> 3; + bool is_tor = pmp_a == PMP_TOR; + bool is_na4 = pmp_a == PMP_NA4; reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; @@ -574,7 +597,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc switch (space) { case traits::MEM: { 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; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1 @@ -669,7 +692,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac switch (space) { case traits::MEM: { 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; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1 @@ -683,7 +706,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac return iss::Err; } 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; fault_data=addr; return iss::Err; @@ -1217,9 +1240,6 @@ template uint64_t riscv_hart_mu_p:: // bits in mtvec this->reg.NEXT_PC = ivec & ~0x3UL; 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 buffer; sprintf(buffer.data(), "0x%016lx", addr); if((flags&0xffffffff) != 0xffffffff) @@ -1227,6 +1247,9 @@ template uint64_t riscv_hart_mu_p:: << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" << " at address " << buffer.data() << " occurred, changing privilege level from " << 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; } diff --git a/src/main.cpp b/src/main.cpp index 7f5af13..ac139d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p; #ifdef CORE_TGC_D #include "iss/arch/riscv_hart_mu_p.h" #include "iss/arch/tgc_d.h" -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; +using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef WITH_LLVM #include @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) { ("mem,m", po::value(), "the memory input file") ("plugin,p", po::value>(), "plugin to activate") ("backend", po::value()->default_value("interp"), "the memory input file") - ("isa", po::value()->default_value("tgf_c"), "isa to use for simulation"); + ("isa", po::value()->default_value("tgc_c"), "isa to use for simulation"); // clang-format on auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); try { @@ -123,18 +123,18 @@ int main(int argc, char *argv[]) { iss::vm_ptr vm{nullptr}; iss::cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - if (isa_opt == "tgf_c") { + if (isa_opt == "tgc_c") { std::tie(cpu, vm) = iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else #ifdef CORE_TGC_B - if (isa_opt == "tgf_b") { + if (isa_opt == "tgc_b") { std::tie(cpu, vm) = iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else #endif #ifdef CORE_TGC_D - if (isa_opt == "tgf_d") { + if (isa_opt == "tgc_d") { std::tie(cpu, vm) = iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else