Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions c_emulator/riscv_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,37 @@ unit trap_callback(bool is_interrupt, fbits cause)
}
return UNIT;
}
// Page table walk callback
unit ptw_start_callback(uint64_t vpn, struct zMemoryAccessTypezIuzK access_type,
enum zPrivilege privilege)
{
for (auto c : callbacks) {
c->ptw_start_callback(vpn, access_type, privilege);
}
return UNIT;
}

unit ptw_step_callback(sail_int level, sbits pte_addr, uint64_t pte)
{
for (auto c : callbacks) {
c->ptw_step_callback(level, pte_addr, pte);
}
return UNIT;
}

unit ptw_success_callback(uint64_t final_ppn, sail_int level)
{
for (auto c : callbacks) {
c->ptw_success_callback(final_ppn, level);
}
return UNIT;
}

unit ptw_fail_callback(struct zPTW_Error error_type, sail_int level,
sbits pte_addr)
{
for (auto c : callbacks) {
c->ptw_fail_callback(error_type, level, pte_addr);
}
return UNIT;
}
8 changes: 8 additions & 0 deletions c_emulator/riscv_callbacks.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "sail.h"
#include "sail_riscv_model.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -25,6 +26,13 @@ unit vreg_write_callback(unsigned reg, lbits value);
unit pc_write_callback(sbits new_pc);
unit redirect_callback(sbits new_pc);
unit trap_callback(bool is_interrupt, fbits cause);
// Page table walk callbacks
unit ptw_start_callback(uint64_t vpn, struct zMemoryAccessTypezIuzK access_type,
enum zPrivilege privilege);
unit ptw_step_callback(sail_int level, sbits pte_addr, uint64_t pte);
unit ptw_success_callback(uint64_t final_ppn, sail_int level);
unit ptw_fail_callback(struct zPTW_Error error_type, sail_int level,
sbits pte_addr);

#ifdef __cplusplus
}
Expand Down
22 changes: 22 additions & 0 deletions c_emulator/riscv_callbacks_if.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "sail.h"
#include "sail_riscv_model.h"

// This class is not declared in "riscv_callbacks.h" as that file is
// included in the C model generated by Sail.
Expand Down Expand Up @@ -66,6 +67,27 @@ class callbacks_if {
[[maybe_unused]] fbits cause)
{
}
// Page table walk callbacks
virtual void
ptw_start_callback([[maybe_unused]] uint64_t vpn,
[[maybe_unused]] struct zMemoryAccessTypezIuzK access_type,
[[maybe_unused]] enum zPrivilege privilege)
{
}
virtual void ptw_step_callback([[maybe_unused]] sail_int level,
[[maybe_unused]] sbits pte_addr,
[[maybe_unused]] uint64_t pte)
{
}
virtual void ptw_success_callback([[maybe_unused]] uint64_t final_ppn,
[[maybe_unused]] sail_int level)
{
}
virtual void ptw_fail_callback([[maybe_unused]] struct zPTW_Error error_type,
[[maybe_unused]] sail_int level,
[[maybe_unused]] sbits pte_addr)
{
}
};

void register_callback(callbacks_if *cb);
Expand Down
57 changes: 56 additions & 1 deletion c_emulator/riscv_callbacks_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ void print_lbits_hex(FILE *trace_log, lbits val, int length = 0)

log_callbacks::log_callbacks(bool config_print_reg,
bool config_print_mem_access,
bool config_use_abi_names, FILE *trace_log)
bool config_print_ptw, bool config_use_abi_names,
FILE *trace_log)
: config_print_reg(config_print_reg)
, config_print_mem_access(config_print_mem_access)
, config_use_abi_names(config_use_abi_names)
, config_print_ptw(config_print_ptw)
, trace_log(trace_log)
{
}
Expand Down Expand Up @@ -101,3 +103,56 @@ void log_callbacks::vreg_write_callback(unsigned reg, lbits value)
print_lbits_hex(trace_log, value);
}
}

// Page table walk callback
void log_callbacks::ptw_start_callback(
uint64_t vpn, struct zMemoryAccessTypezIuzK access_type,
enum zPrivilege privilege)
{
if (trace_log != nullptr && config_print_ptw) {
sail_string str_ac, str_pr;
CREATE(sail_string)(&str_ac);
CREATE(sail_string)(&str_pr);
zaccessType_to_str(&str_ac, access_type);
zprivLevel_to_str(&str_pr, privilege);
fprintf(trace_log,
"PTW: Start, vpn=0x%" PRIx64 ", access_type=%s, privilege=%s", vpn,
str_ac, str_pr);
KILL(sail_string)(&str_ac);
KILL(sail_string)(&str_pr);
}
}

void log_callbacks::ptw_step_callback(sail_int level, sbits pte_addr,
uint64_t pte)
{
if (trace_log != nullptr && config_print_ptw) {
gmp_fprintf(trace_log,
"PTW: Step, level=0x%ZX, pte=0x%" PRIX64 ", pte_addr=0x%" PRIX64
"\n",
level, pte, pte_addr.bits);
}
}

void log_callbacks::ptw_success_callback(uint64_t final_ppn, sail_int level)
{
if (trace_log != nullptr && config_print_ptw) {
gmp_fprintf(trace_log, "PTW: Success, final_ppn=0x%" PRIx64 ", level=%ZX",
final_ppn, level);
}
}

void log_callbacks::ptw_fail_callback(struct zPTW_Error error_type,
sail_int level, sbits pte_addr)
{
// failed trace is always available
if (trace_log != nullptr) {
sail_string str_et;
CREATE(sail_string)(&str_et);
zptw_error_to_str(&str_et, error_type);
gmp_fprintf(trace_log,
"PTW: failed, error=%s, level=%ZX, pte_addr=0x%" PRIX64 "\n",
str_et, level, pte_addr.bits);
KILL(sail_string)(&str_et);
}
}
12 changes: 11 additions & 1 deletion c_emulator/riscv_callbacks_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ class log_callbacks : public callbacks_if {
public:
log_callbacks(bool config_print_reg = true,
bool config_print_mem_access = true,
bool config_use_abi_names = false, FILE *trace_log = nullptr);
bool config_print_ptw = true, bool config_use_abi_names = false,
FILE *trace_log = nullptr);

// callbacks_if
void mem_write_callback(const char *type, sbits paddr, uint64_t width,
Expand All @@ -22,10 +23,19 @@ class log_callbacks : public callbacks_if {
void csr_full_read_callback(const_sail_string csr_name, unsigned reg,
sbits value) override;
void vreg_write_callback(unsigned reg, lbits value) override;
// Page table walk callback
void ptw_start_callback(uint64_t vpn,
struct zMemoryAccessTypezIuzK access_type,
enum zPrivilege privilege) override;
void ptw_step_callback(sail_int level, sbits pte_addr, uint64_t pte) override;
void ptw_success_callback(uint64_t final_ppn, sail_int level) override;
void ptw_fail_callback(struct zPTW_Error error_type, sail_int /*level*/,
sbits pte_addr) override;

private:
bool config_print_reg;
bool config_print_mem_access;
bool config_use_abi_names;
bool config_print_ptw;
FILE *trace_log;
};
6 changes: 5 additions & 1 deletion c_emulator/riscv_sim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ bool config_print_htif = false;
bool config_print_pma = false;
bool config_print_rvfi = false;
bool config_print_step = false;
bool config_print_ptw = false;

bool config_use_abi_names = false;
bool config_enable_rvfi = false;
Expand Down Expand Up @@ -170,6 +171,8 @@ static void setup_options(CLI::App &app)

app.add_flag("--trace-instr", config_print_instr,
"Enable trace output for instruction execution");
app.add_flag("--trace-ptw", config_print_ptw,
"Enable trace output for Page Table walk");
app.add_flag("--trace-reg", config_print_reg,
"Enable trace output for register access");
app.add_flag("--trace-mem", config_print_mem_access,
Expand Down Expand Up @@ -215,6 +218,7 @@ static void setup_options(CLI::App &app)
config_print_htif = true;
config_print_pma = true;
config_print_step = true;
config_print_ptw = true;
config_print_reservation = true;
},
"Enable all trace output");
Expand Down Expand Up @@ -644,7 +648,7 @@ int inner_main(int argc, char **argv)

init_logs();
log_callbacks log_cbs(config_print_reg, config_print_mem_access,
config_use_abi_names, trace_log);
config_print_ptw, config_use_abi_names, trace_log);
register_callback(&log_cbs);

if (gettimeofday(&init_start, nullptr) < 0) {
Expand Down
2 changes: 2 additions & 0 deletions model/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ add_custom_command(
--c-preserve rvfi_mem_exception
--c-preserve rvfi_wX
--c-preserve rvfi_trap
# Preserve to_str functions.
--c-preserve ptw_error_to_str
# Input files.
${SAIL_MODULES}
${project_file}
Expand Down
1 change: 1 addition & 0 deletions model/riscv.sail_project
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ sys {
sys/mem.sail,
sys/vmem_pte.sail,
sys/vmem_ptw.sail,
sys/callbacks.sail,
sys/vmem_tlb.sail,
sys/vmem.sail,
sys/insts_begin.sail,
Expand Down
12 changes: 12 additions & 0 deletions model/sys/callbacks.sail
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Page table walk callback
val ptw_start_callback = pure {c: "ptw_start_callback"} : (/* vpn */ bits(64), /* access type */ MemoryAccessType(ext_access_type), /* privilege */ Privilege) -> unit
function ptw_start_callback(_) = ()

val ptw_step_callback = pure {c: "ptw_step_callback"} : (/* level */ int, /* pte_addr */ physaddrbits, /* pte */ bits(64)) -> unit
function ptw_step_callback(_) = ()

val ptw_success_callback = pure {c: "ptw_success_callback"} : (/* final_ppn */ bits(64), /* level */ int) -> unit
function ptw_success_callback(_) = ()

val ptw_fail_callback = pure {c: "ptw_fail_callback"} : (/* error_type */ PTW_Error, /* level */ int, /* pte_addr */ physaddrbits) -> unit
function ptw_fail_callback(_) = ()
Comment on lines +2 to +12
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using int for level, couldnt this be a range(0, 4)? If so, would that be a different type than sail_int, allowing you to keep fprintf instead of switching to gmp_fprintf? Anyway, this is probably a minor detail and not really important.

Suggested change
val ptw_start_callback = pure {c: "ptw_start_callback"} : (/* vpn */ bits(64), /* access type */ MemoryAccessType(ext_access_type), /* privilege */ Privilege) -> unit
function ptw_start_callback(_) = ()
val ptw_step_callback = pure {c: "ptw_step_callback"} : (/* level */ int, /* pte_addr */ physaddrbits, /* pte */ bits(64)) -> unit
function ptw_step_callback(_) = ()
val ptw_success_callback = pure {c: "ptw_success_callback"} : (/* final_ppn */ bits(64), /* level */ int) -> unit
function ptw_success_callback(_) = ()
val ptw_fail_callback = pure {c: "ptw_fail_callback"} : (/* error_type */ PTW_Error, /* level */ int, /* pte_addr */ physaddrbits) -> unit
function ptw_fail_callback(_) = ()
val ptw_start_callback = pure {c: "ptw_start_callback"} : (/* vpn */ bits(64), /* access type */ MemoryAccessType(ext_access_type), /* privilege */ Privilege) -> unit
function ptw_start_callback(_) = ()
val ptw_step_callback = pure {c: "ptw_step_callback"} : (/* level */ int, /* pte_addr */ physaddrbits, /* pte */ bits(64)) -> unit
function ptw_step_callback(_) = ()
val ptw_success_callback = pure {c: "ptw_success_callback"} : (/* final_ppn */ bits(64), /* level */ int) -> unit
function ptw_success_callback(_) = ()
val ptw_fail_callback = pure {c: "ptw_fail_callback"} : (/* error_type */ PTW_Error, /* level */ range(0, 4), /* pte_addr */ physaddrbits) -> unit
function ptw_fail_callback(_) = ()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall I change all level to range(0,4) or only this one?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of them.

34 changes: 26 additions & 8 deletions model/sys/vmem.sail
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ function pt_walk(
global,
ext_ptw,
) = {
ptw_start_callback(zero_extend(vpn), ac, priv);

// Extract the PPN component for this level; 10 bits on Sv32, otherwise 9.
let 'vpn_i_size = if 'v == 32 then 10 else 9;
let vpn_i = vpn[(level + 1) * vpn_i_size - 1 .. level * vpn_i_size];
Expand All @@ -105,14 +107,21 @@ function pt_walk(

// Read this-level PTE from mem (Step 2 of VATP)
match read_pte(pte_addr, 2 ^ log_pte_size_bytes) {
Err(_) => Err(PTW_No_Access(), ext_ptw),
Err(_) => {
ptw_fail_callback(PTW_No_Access(), level, bits_of(pte_addr));
Err(PTW_No_Access(), ext_ptw)
},
Ok(pte) => {
ptw_step_callback(level, bits_of(pte_addr), zero_extend(pte));

let pte_flags = Mk_PTE_Flags(pte[7 .. 0]);
let pte_ext = ext_bits_of_PTE(pte);

if pte_is_invalid(pte_flags, pte_ext) then
if pte_is_invalid(pte_flags, pte_ext) then {
// Step 3 of VATP.
ptw_fail_callback(PTW_Invalid_PTE(), level, bits_of(pte_addr));
Err(PTW_Invalid_PTE(), ext_ptw)
}
else {
// Step 4 of VATP.
let ppn = PPN_of_PTE(pte); // 22 or 44.
Expand All @@ -122,22 +131,29 @@ function pt_walk(
if level > 0 then
// follow the pointer to walk next level (i.e., go to Step 2)
pt_walk(sv_width, vpn, ac, priv, mxr, do_sum, ppn, level - 1, global, ext_ptw)
else
// level 0 PTE, but contains a pointer instead of a leaf
Err(PTW_Invalid_PTE(), ext_ptw)
else {
// level 0 PTE, but contains a pointer instead of a leaf
ptw_fail_callback(PTW_Invalid_PTE(), level, bits_of(pte_addr));
Err(PTW_Invalid_PTE(), ext_ptw)
}
} else {
// Leaf PTE (Step 5 of VATP).
let ppn_size_bits = if 'v == 32 then 10 else 9;
if level > 0 then {
// Check for misaligned superpage.
let low_bits = ppn_size_bits * level;
if ppn[low_bits - 1 .. 0] != zeros()
then return Err(PTW_Misaligned(), ext_ptw);
then {
ptw_fail_callback(PTW_Misaligned(), level, bits_of(pte_addr));
return Err(PTW_Misaligned(), ext_ptw);
};
};
// Steps 6, 7 (TODO: shadow stack protection), 8 of VATP.
match check_PTE_permission(ac, priv, mxr, do_sum, pte_flags, pte_ext, ext_ptw) {
PTE_Check_Failure(ext_ptw, pte_failure) =>
Err(ext_get_ptw_error(pte_failure), ext_ptw),
PTE_Check_Failure(ext_ptw, pte_failure) => {
ptw_fail_callback(ext_get_ptw_error(pte_failure), level, bits_of(pte_addr));
Err(ext_get_ptw_error(pte_failure), ext_ptw)
},
PTE_Check_Success(ext_ptw) => {
let ppn = if level > 0 then {
// Compose final PA in superpage:
Expand All @@ -147,6 +163,8 @@ function pt_walk(
} else {
ppn
};
ptw_success_callback(zero_extend(ppn), level);

Ok(struct {ppn=ppn, pte=pte, pteAddr=pte_addr, level=level, global=global}, ext_ptw)
}
}
Expand Down
Loading