Skip to content

Commit

Permalink
feat: Add memory range introspection
Browse files Browse the repository at this point in the history
  • Loading branch information
diegonehab committed Oct 11, 2023
1 parent cc52626 commit 0f67a2f
Show file tree
Hide file tree
Showing 20 changed files with 245 additions and 179 deletions.
12 changes: 12 additions & 0 deletions src/clua-i-virtual-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,17 @@ static int machine_obj_index_reset_uarch_state(lua_State *L) {
return 0;
}

/// \brief This is the machine:get_memory_ranges() method implementation.
/// \param L Lua state.
static int machine_obj_index_get_memory_ranges(lua_State *L) {
auto &m = clua_check<clua_managed_cm_ptr<cm_machine>>(L, 1);
auto &managed_mrds = clua_push_to(L, clua_managed_cm_ptr<cm_memory_range_description_array>(nullptr));
TRY_EXECUTE(cm_get_memory_ranges(m.get(), &managed_mrds.get(), err_msg));
clua_push_cm_memory_range_description_array(L, managed_mrds.get());
managed_mrds.reset();
return 1;
}

/// \brief This is the machine:run_uarch() method implementation.
/// \param L Lua state.
static int machine_obj_index_run_uarch(lua_State *L) {
Expand Down Expand Up @@ -646,6 +657,7 @@ static const auto machine_obj_index = cartesi::clua_make_luaL_Reg_array({
{"read_uarch_halt_flag", machine_obj_index_read_uarch_halt_flag},
{"set_uarch_halt_flag", machine_obj_index_set_uarch_halt_flag},
{"reset_uarch_state", machine_obj_index_reset_uarch_state},
{"get_memory_ranges", machine_obj_index_get_memory_ranges},
});

/// \brief This is the machine __close metamethod implementation.
Expand Down
18 changes: 18 additions & 0 deletions src/clua-machine-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ void cm_delete(cm_memory_range_config *ptr) {
cm_delete_memory_range_config(ptr);
}

/// \brief Deleter for C api memory range description array
template <>
void cm_delete(cm_memory_range_description_array *ptr) {
cm_delete_memory_range_description_array(ptr);
}

static char *copy_lua_str(lua_State *L, int idx) {
const char *lua_str = lua_tostring(L, idx);
auto size = strlen(lua_str) + 1;
Expand Down Expand Up @@ -693,6 +699,18 @@ void clua_push_cm_proof(lua_State *L, const cm_merkle_tree_proof *proof) {
lua_setfield(L, -2, "target_hash"); // proof
}

void clua_push_cm_memory_range_description_array(lua_State *L, const cm_memory_range_description_array *mrds) {
lua_newtable(L); // array
for (size_t i = 0; i < mrds->count; ++i) {
const auto &mrd = mrds->entry[i];
lua_newtable(L); // array config
clua_setintegerfield(L, mrd.start, "start", -1); // array config
clua_setintegerfield(L, mrd.length, "length", -1); // array config
clua_setstringfield(L, mrd.description, "description", -1); // array config
lua_rawseti(L, -2, i + 1); // array
}
}

cm_access_log_type clua_check_cm_log_type(lua_State *L, int tabidx) {
luaL_checktype(L, tabidx, LUA_TTABLE);
return cm_access_log_type{opt_boolean_field(L, tabidx, "proofs"), opt_boolean_field(L, tabidx, "annotations")};
Expand Down
9 changes: 9 additions & 0 deletions src/clua-machine-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ void cm_delete(cm_memory_range_config *p);
template <>
void cm_delete(const cm_semantic_version *p);

/// \brief Deleter for C api memory range description array
template <>
void cm_delete(cm_memory_range_description_array *p);

// clua_managed_cm_ptr is a smart pointer,
// however we don't use all its functionally, therefore we exclude it from code coverage.
// LCOV_EXCL_START
Expand Down Expand Up @@ -175,6 +179,11 @@ void clua_push_cm_hash(lua_State *L, const cm_hash *hash);
/// \param c Machine configuration to be pushed
void clua_push_cm_machine_config(lua_State *L, const cm_machine_config *c);

/// \brief Pushes a C api cm_memory_range_description_array to the Lua stack
/// \param L Lua state
/// \param mrds Memory range description array to be pushed
void clua_push_cm_memory_range_description_array(lua_State *L, const cm_memory_range_description_array *mrds);

#if 0
/// \brief Pushes a cm_machine_runtime_config to the Lua stack
/// \param L Lua state
Expand Down
1 change: 1 addition & 0 deletions src/clua-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ int clua_machine_init(lua_State *L, int ctxidx) {
clua_createnewtype<clua_managed_cm_ptr<char>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<unsigned char>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_memory_range_config>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_memory_range_description_array>>(L, ctxidx);
if (!clua_typeexists<machine_class>(L, ctxidx)) {
clua_createtype<machine_class>(L, "cartesi machine class", ctxidx);
clua_setmethods<machine_class>(L, machine_class_index.data(), 0, ctxidx);
Expand Down
5 changes: 5 additions & 0 deletions src/grpc-virtual-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -952,4 +952,9 @@ uarch_interpreter_break_reason grpc_virtual_machine::do_run_uarch(uint64_t uarch
return uarch_interpreter_break_reason::reached_target_cycle;
}

const machine::memory_range_descriptions &grpc_virtual_machine::do_get_memory_ranges(void) const {
static machine::memory_range_descriptions mrds{};
return mrds;
}

} // namespace cartesi
1 change: 1 addition & 0 deletions src/grpc-virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ class grpc_virtual_machine : public i_virtual_machine {
void do_reset_uarch_state() override;
bool do_read_uarch_halt_flag(void) const override;
uarch_interpreter_break_reason do_run_uarch(uint64_t uarch_cycle_end) override;
const machine::memory_range_descriptions &do_get_memory_ranges(void) const override;

grpc_machine_stub_ptr m_stub;
};
Expand Down
6 changes: 6 additions & 0 deletions src/i-virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,11 @@ class i_virtual_machine {
return do_run_uarch(uarch_cycle_end);
}

/// \brief Returns a list of descriptions for all PMA entries registered in the machine, sorted by start
virtual const machine::memory_range_descriptions &get_memory_ranges(void) const {
return do_get_memory_ranges();
}

private:
virtual interpreter_break_reason do_run(uint64_t mcycle_end) = 0;
virtual void do_store(const std::string &dir) = 0;
Expand Down Expand Up @@ -760,6 +765,7 @@ class i_virtual_machine {
virtual void do_reset_uarch_state() = 0;
virtual uint64_t do_read_uarch_ram_length(void) const = 0;
virtual uarch_interpreter_break_reason do_run_uarch(uint64_t uarch_cycle_end) = 0;
virtual const machine::memory_range_descriptions &do_get_memory_ranges(void) const = 0;
};

} // namespace cartesi
Expand Down
5 changes: 5 additions & 0 deletions src/jsonrpc-virtual-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,11 @@ uarch_interpreter_break_reason jsonrpc_virtual_machine::do_run_uarch(uint64_t ua
return result;
}

const machine::memory_range_descriptions &jsonrpc_virtual_machine::do_get_memory_ranges(void) const {
static machine::memory_range_descriptions mrds{};
return mrds;
}

#pragma GCC diagnostic pop

} // namespace cartesi
1 change: 1 addition & 0 deletions src/jsonrpc-virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class jsonrpc_virtual_machine final : public i_virtual_machine {
void do_write_uarch_cycle(uint64_t val) override;
uint64_t do_read_uarch_ram_length(void) const override;
uarch_interpreter_break_reason do_run_uarch(uint64_t uarch_cycle_end) override;
const machine::memory_range_descriptions &do_get_memory_ranges(void) const override;

jsonrpc_mg_mgr_ptr m_mgr;
};
Expand Down
43 changes: 43 additions & 0 deletions src/machine-c-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,27 @@ cartesi::access_log convert_from_c(const cm_access_log *c_acc_log) {
return new_cpp_acc_log;
}

// --------------------------------------------
// Memory range description conversion functions
// --------------------------------------------
cm_memory_range_description convert_to_c(const cartesi::machine::memory_range_description &cpp_mrd) {
cm_memory_range_description new_mrd{};
new_mrd.start = cpp_mrd.start;
new_mrd.length = cpp_mrd.length;
new_mrd.description = convert_to_c(cpp_mrd.description);
return new_mrd;
}

cm_memory_range_description_array *convert_to_c(const cartesi::machine::memory_range_descriptions &cpp_mrds) {
auto *new_mrda = new cm_memory_range_description_array{};
new_mrda->count = cpp_mrds.size();
new_mrda->entry = new cm_memory_range_description[new_mrda->count];
for (size_t i = 0; i < new_mrda->count; ++i) {
new_mrda->entry[i] = convert_to_c(cpp_mrds[i]);
}
return new_mrda;
}

// -----------------------------------------------------
// Public API functions for generation of default configs
// -----------------------------------------------------
Expand Down Expand Up @@ -1349,3 +1370,25 @@ int cm_rollback(cm_machine *m, char **err_msg) try {
} catch (...) {
return cm_result_failure(err_msg);
}

CM_API int cm_get_memory_ranges(cm_machine *m, cm_memory_range_description_array **mrds, char **err_msg) try {
if (mrds == nullptr) {
throw std::invalid_argument("invalid memory range output");
}
auto *cpp_machine = convert_from_c(m);
*mrds = convert_to_c(cpp_machine->get_memory_ranges());
return cm_result_success(err_msg);
} catch (...) {
return cm_result_failure(err_msg);
}

CM_API void cm_delete_memory_range_description_array(cm_memory_range_description_array *mrds) {
if (mrds == nullptr) {
return;
}
for (size_t i = 0; i < mrds->count; ++i) {
delete[] mrds->entry[i].description;
}
delete[] mrds->entry;
delete mrds;
}
33 changes: 32 additions & 1 deletion src/machine-c-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,19 @@ typedef struct { // NOLINT(modernize-use-using)
const char *build;
} cm_semantic_version;

/// \brief Memory range description
typedef struct { // NOLINT(modernize-use-using)
uint64_t start;
uint64_t length;
const char *description;
} cm_memory_range_description;

/// \brief Memory range description array
typedef struct { // NOLINT(modernize-use-using)
cm_memory_range_description *entry;
size_t count;
} cm_memory_range_description_array;

// ---------------------------------
// API function definitions
// ---------------------------------
Expand Down Expand Up @@ -1698,7 +1711,9 @@ CM_API int cm_set_uarch_halt_flag(cm_machine *m, char **err_msg);
CM_API int cm_reset_uarch_state(cm_machine *m, char **err_msg);

/// \brief Runs the machine in the microarchitecture until the mcycle advances by one unit or the micro cycles counter
/// (uarch_cycle) reaches uarch_cycle_end \param m Pointer to valid machine instance \param mcycle_end End cycle value
/// (uarch_cycle) reaches uarch_cycle_end
/// \param m Pointer to valid machine instance
/// \param mcycle_end End cycle value
/// \param status_result Receives status of machine run_uarch when not NULL
/// \param err_msg Receives the error message if function execution fails
/// or NULL in case of successful function execution. In case of failure error_msg
Expand All @@ -1708,6 +1723,22 @@ CM_API int cm_reset_uarch_state(cm_machine *m, char **err_msg);
CM_API int cm_machine_run_uarch(cm_machine *m, uint64_t uarch_cycle_end, CM_UARCH_BREAK_REASON *status_result,
char **err_msg);

/// \brief Returns an array with the description of each memory range in the machine.
/// \param m Pointer to valid machine instance
/// \param mrda Receives pointer to array of memory range descriptions. Must be deleted by the function caller using
/// cm_delete_memory_range_description_array.
/// \param err_msg Receives the error message if function execution fails
/// or NULL in case of successful function execution. In case of failure error_msg
/// must be deleted by the function caller using cm_delete_cstring.
/// err_msg can be NULL, meaning the error message won't be received.
/// \returns 0 for success, non zero code for error
CM_API int cm_get_memory_ranges(cm_machine *m, cm_memory_range_description_array **mrda, char **err_msg);

/// \brief Delete memory range description array acquired from cm_get_memory_ranges.
/// \param mrda Pointer to array of memory range descriptions to delete.
/// \returns void
CM_API void cm_delete_memory_range_description_array(cm_memory_range_description_array *mrda);

#ifdef __cplusplus
}
#endif
Expand Down
10 changes: 10 additions & 0 deletions src/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,16 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
if (m_c.htif.console_getchar) {
tty_initialize();
}

// Initialize memory range descriptions returned by get_memory_ranges method
for (auto *pma : m_pmas) {
if (pma->get_length() != 0) {
m_mrds.push_back(memory_range_description{pma->get_start(), pma->get_length(), pma->get_description()});
}
}
// Sort it by increasing start address
std::sort(m_mrds.begin(), m_mrds.end(),
[](const memory_range_description &a, const memory_range_description &b) { return a.start < b.start; });
}

static void load_hash(const std::string &dir, machine::hash_type &h) {
Expand Down
29 changes: 23 additions & 6 deletions src/machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,31 @@ constexpr skip_merkle_tree_update_t skip_merkle_tree_update;
/// \class machine
/// \brief Cartesi Machine implementation
class machine final {
public:
/// \brief Description of memory range used for instrospection (i.e., get_memory_ranges())
struct memory_range_description {
uint64_t start; ///< Start of memory range
uint64_t length; ///< Length of memory range
std::string description; ///< User-friendly description for memory range
};

/// \brief List of memory range descriptions used for instrospection (i.e., get_memory_ranges())
using memory_range_descriptions = std::vector<memory_range_description>;

private:
//??D Ideally, we would hold a unique_ptr to the state. This
// would allow us to remove the machine-state.h include and
// therefore hide its contents from anyone who includes only
// machine.h. Maybe the compiler can do a good job we we are
// not constantly going through the extra indirection. We
// should test this.
mutable machine_state m_s; ///< Opaque machine state
mutable machine_merkle_tree m_t; ///< Merkle tree of state
std::vector<pma_entry *> m_pmas; ///< Combines uarch PMAs and machine state PMAs.
machine_config m_c; ///< Copy of initialization config
uarch_machine m_uarch; ///< Microarchitecture machine
machine_runtime_config m_r; ///< Copy of initialization runtime config
mutable machine_state m_s; ///< Opaque machine state
mutable machine_merkle_tree m_t; ///< Merkle tree of state
std::vector<pma_entry *> m_pmas; ///< Combines uarch PMAs and machine state PMAs for use with Merkle tree.
machine_config m_c; ///< Copy of initialization config
uarch_machine m_uarch; ///< Microarchitecture machine
machine_runtime_config m_r; ///< Copy of initialization runtime config
memory_range_descriptions m_mrds; ///< List of memory ranges returned by get_memory_ranges().

static const pma_entry::flags m_dtb_flags; ///< PMA flags used for DTB
static const pma_entry::flags m_ram_flags; ///< PMA flags used for RAM
Expand Down Expand Up @@ -253,6 +265,11 @@ class machine final {
return m_s;
}

/// \brief Returns a list of descriptions for all PMA entries registered in the machine, sorted by start
const memory_range_descriptions &get_memory_ranges(void) const {
return m_mrds;
}

/// \brief Destructor.
~machine();

Expand Down
2 changes: 1 addition & 1 deletion src/test-machine-c-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static hash_type get_verification_root_hash(cm_machine *machine) {
}
cm_delete_machine_config(cfg);

auto hash = calculate_emulator_hash(dump_list);
auto hash = calculate_emulator_hash(machine);
for (const auto &file : dump_list) {
std::filesystem::remove(file);
}
Expand Down
Loading

0 comments on commit 0f67a2f

Please sign in to comment.