Skip to content

Commit d03411e

Browse files
committed
feat: allow running machines directly from mmaped backing files
1 parent 4a3040d commit d03411e

16 files changed

+635
-424
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ LIBCARTESI_OBJS:= \
337337
virtio-net-carrier-slirp.o \
338338
dtb.o \
339339
os.o \
340+
os-mmap.o \
340341
htif.o \
341342
htif-factory.o \
342343
shadow-state.o \

src/json-util.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, machine_runtime_con
789789
ju_get_opt_field(j[key], "skip_root_hash_store"s, value.skip_root_hash_store, path + to_string(key) + "/");
790790
ju_get_opt_field(j[key], "skip_version_check"s, value.skip_version_check, path + to_string(key) + "/");
791791
ju_get_opt_field(j[key], "soft_yield"s, value.soft_yield, path + to_string(key) + "/");
792+
ju_get_opt_field(j[key], "backing_storage"s, value.backing_storage, path + to_string(key) + "/");
792793
}
793794

794795
template void ju_get_opt_field<uint64_t>(const nlohmann::json &j, const uint64_t &key, machine_runtime_config &value,
@@ -1971,6 +1972,7 @@ void to_json(nlohmann::json &j, const machine_runtime_config &runtime) {
19711972
{"skip_root_hash_store", runtime.skip_root_hash_store},
19721973
{"skip_version_check", runtime.skip_version_check},
19731974
{"soft_yield", runtime.soft_yield},
1975+
{"backing_storage", runtime.backing_storage},
19741976
};
19751977
}
19761978

src/machine-runtime-config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define MACHINE_RUNTIME_CONFIG_H
1919

2020
#include <cstdint>
21+
#include <string>
2122

2223
/// \file
2324
/// \brief Runtime configuration for machines.
@@ -42,6 +43,7 @@ struct machine_runtime_config {
4243
bool skip_root_hash_store{};
4344
bool skip_version_check{};
4445
bool soft_yield{};
46+
std::string backing_storage{};
4547
};
4648

4749
/// \brief CONCURRENCY constants

src/machine.cpp

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -108,39 +108,6 @@ const pma_entry::flags machine::m_cmio_tx_buffer_flags{
108108
PMA_ISTART_DID::cmio_tx_buffer // DID
109109
};
110110

111-
pma_entry machine::make_memory_range_pma_entry(const std::string &description, const memory_range_config &c) {
112-
if (c.image_filename.empty()) {
113-
return make_callocd_memory_pma_entry(description, c.start, c.length);
114-
}
115-
return make_mmapd_memory_pma_entry(description, c.start, c.length, c.image_filename, c.shared);
116-
}
117-
118-
pma_entry machine::make_flash_drive_pma_entry(const std::string &description, const memory_range_config &c) {
119-
return make_memory_range_pma_entry(description, c).set_flags(m_flash_drive_flags);
120-
}
121-
122-
pma_entry machine::make_cmio_rx_buffer_pma_entry(const cmio_config &c) {
123-
const auto description = "cmio rx buffer memory range"s;
124-
if (!c.rx_buffer.image_filename.empty()) {
125-
return make_mmapd_memory_pma_entry(description, PMA_CMIO_RX_BUFFER_START, PMA_CMIO_RX_BUFFER_LENGTH,
126-
c.rx_buffer.image_filename, c.rx_buffer.shared)
127-
.set_flags(m_cmio_rx_buffer_flags);
128-
}
129-
return make_callocd_memory_pma_entry(description, PMA_CMIO_RX_BUFFER_START, PMA_CMIO_RX_BUFFER_LENGTH)
130-
.set_flags(m_cmio_rx_buffer_flags);
131-
}
132-
133-
pma_entry machine::make_cmio_tx_buffer_pma_entry(const cmio_config &c) {
134-
const auto description = "cmio tx buffer memory range"s;
135-
if (!c.tx_buffer.image_filename.empty()) {
136-
return make_mmapd_memory_pma_entry(description, PMA_CMIO_TX_BUFFER_START, PMA_CMIO_TX_BUFFER_LENGTH,
137-
c.tx_buffer.image_filename, c.tx_buffer.shared)
138-
.set_flags(m_cmio_tx_buffer_flags);
139-
}
140-
return make_callocd_memory_pma_entry(description, PMA_CMIO_TX_BUFFER_START, PMA_CMIO_TX_BUFFER_LENGTH)
141-
.set_flags(m_cmio_tx_buffer_flags);
142-
}
143-
144111
pma_entry &machine::register_pma_entry(pma_entry &&pma) {
145112
if (m_s.pmas.capacity() <= m_s.pmas.size()) { // NOLINT(readability-static-accessed-through-instance)
146113
throw std::runtime_error{"too many PMAs when adding "s + pma.get_description()};
@@ -199,7 +166,9 @@ void machine::replace_memory_range(const memory_range_config &range) {
199166
throw std::invalid_argument{"attempt to replace a protected range "s + pma.get_description()};
200167
}
201168
// replace range preserving original flags
202-
pma = make_memory_range_pma_entry(pma.get_description(), range).set_flags(pma.get_flags());
169+
pma = make_mmapd_memory_pma_entry(pma.get_description(), range.start, range.length, range.image_filename,
170+
range.shared)
171+
.set_flags(pma.get_flags());
203172
return;
204173
}
205174
}
@@ -322,19 +291,22 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
322291
write_reg(reg::iflags, m_c.processor.iflags);
323292
write_reg(reg::iunrep, m_c.processor.iunrep);
324293

325-
// Register RAM
326-
if (m_c.ram.image_filename.empty()) {
327-
register_pma_entry(make_callocd_memory_pma_entry("RAM"s, PMA_RAM_START, m_c.ram.length).set_flags(m_ram_flags));
328-
} else {
329-
register_pma_entry(make_callocd_memory_pma_entry("RAM"s, PMA_RAM_START, m_c.ram.length, m_c.ram.image_filename)
330-
.set_flags(m_ram_flags));
294+
// TODO(edubart): handle case when backing storage is the same dir
295+
// TODO(edubart): remove directory + files on failure
296+
if (!m_r.backing_storage.empty()) {
297+
os_mkdir(m_r.backing_storage.c_str(), 0700);
331298
}
332299

300+
// Register uarch PMAs
301+
m_uarch.register_pmas(m_r);
302+
303+
// Register RAM
304+
register_pma_entry(make_memory_range_pma_entry("RAM"s, m_ram_flags, PMA_RAM_START, m_c.ram.length,
305+
m_c.ram.image_filename, false, m_r));
306+
333307
// Register DTB
334-
pma_entry &dtb = register_pma_entry((m_c.dtb.image_filename.empty() ?
335-
make_callocd_memory_pma_entry("DTB"s, PMA_DTB_START, PMA_DTB_LENGTH) :
336-
make_callocd_memory_pma_entry("DTB"s, PMA_DTB_START, PMA_DTB_LENGTH, m_c.dtb.image_filename))
337-
.set_flags(m_dtb_flags));
308+
pma_entry &dtb = register_pma_entry(make_memory_range_pma_entry("DTB"s, m_dtb_flags, PMA_DTB_START, PMA_DTB_LENGTH,
309+
m_c.dtb.image_filename, false, m_r));
338310

339311
// Register all flash drives
340312
int i = 0;
@@ -360,13 +332,18 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
360332
}
361333
f.length = length;
362334
}
363-
register_pma_entry(make_flash_drive_pma_entry(flash_description, f));
335+
register_pma_entry(make_memory_range_pma_entry(flash_description, m_flash_drive_flags, f.start, f.length,
336+
f.image_filename, f.shared, m_r));
364337
i++;
365338
}
366339

367340
// Register cmio memory ranges
368-
register_pma_entry(make_cmio_tx_buffer_pma_entry(m_c.cmio));
369-
register_pma_entry(make_cmio_rx_buffer_pma_entry(m_c.cmio));
341+
register_pma_entry(
342+
make_memory_range_pma_entry("cmio tx buffer memory range"s, m_cmio_tx_buffer_flags, PMA_CMIO_TX_BUFFER_START,
343+
PMA_CMIO_TX_BUFFER_LENGTH, m_c.cmio.tx_buffer.image_filename, m_c.cmio.tx_buffer.shared, m_r));
344+
register_pma_entry(
345+
make_memory_range_pma_entry("cmio rx buffer memory range"s, m_cmio_rx_buffer_flags, PMA_CMIO_RX_BUFFER_START,
346+
PMA_CMIO_RX_BUFFER_LENGTH, m_c.cmio.rx_buffer.image_filename, m_c.cmio.rx_buffer.shared, m_r));
370347

371348
// Register HTIF device
372349
register_pma_entry(make_htif_pma_entry(PMA_HTIF_START, PMA_HTIF_LENGTH, &m_r.htif));
@@ -485,7 +462,7 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
485462
if (!m_c.tlb.image_filename.empty()) {
486463
// Create a temporary PMA entry just to load TLB contents from an image file
487464
pma_entry tlb_image_pma = make_mmapd_memory_pma_entry("shadow TLB device"s, PMA_SHADOW_TLB_START,
488-
PMA_SHADOW_TLB_LENGTH, m_c.tlb.image_filename, false);
465+
PMA_SHADOW_TLB_LENGTH, m_c.tlb.image_filename);
489466
unsigned char *hmem = tlb_image_pma.get_memory().get_host_memory();
490467
for (uint64_t i = 0; i < PMA_TLB_SIZE; ++i) {
491468
load_tlb_entry<TLB_CODE>(*this, i, hmem);
@@ -771,9 +748,8 @@ static void store_hash(const machine::hash_type &h, const std::string &dir) {
771748
}
772749

773750
void machine::store(const std::string &dir) const {
774-
if (os_mkdir(dir.c_str(), 0700)) {
775-
throw std::system_error{errno, std::generic_category(), "error creating directory '"s + dir + "'"s};
776-
}
751+
// TODO(edubart): handle the case of saving to backing storage
752+
os_mkdir(dir.c_str(), 0700);
777753
if (!m_r.skip_root_hash_store) {
778754
if (!update_merkle_tree()) {
779755
throw std::runtime_error{"error updating Merkle tree"};
@@ -789,6 +765,19 @@ void machine::store(const std::string &dir) const {
789765

790766
// NOLINTNEXTLINE(modernize-use-equals-default)
791767
machine::~machine() {
768+
if (!m_r.backing_storage.empty()) {
769+
try {
770+
// TODO(edubart): save root hash?
771+
// TODO(edubart): make tlb a memory PMA?
772+
store_device_pma(*this, find_pma_entry<uint64_t>(PMA_SHADOW_TLB_START), m_r.backing_storage);
773+
auto c = get_serialization_config();
774+
c.store(m_r.backing_storage);
775+
} catch (std::exception &e) {
776+
// Silently fail
777+
(void) fprintf(stderr, "unable to save backing storage machine config: %s\n", e.what());
778+
}
779+
}
780+
792781
// Cleanup TTY if console input was enabled
793782
if (m_c.htif.console_getchar || has_virtio_console()) {
794783
os_close_tty();

src/machine.h

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,28 +77,6 @@ class machine final {
7777
/// \returns Reference to corresponding entry in machine state.
7878
pma_entry &register_pma_entry(pma_entry &&pma);
7979

80-
/// \brief Creates a new PMA entry reflecting a memory range configuration.
81-
/// \param description Informative description of PMA entry for use in error messages
82-
/// \param c Memory range configuration.
83-
/// \returns New PMA entry (with default flags).
84-
static pma_entry make_memory_range_pma_entry(const std::string &description, const memory_range_config &c);
85-
86-
/// \brief Creates a new flash drive PMA entry.
87-
/// \param description Informative description of PMA entry for use in error messages
88-
/// \param c Memory range configuration.
89-
/// \returns New PMA entry with flash drive flags already set.
90-
static pma_entry make_flash_drive_pma_entry(const std::string &description, const memory_range_config &c);
91-
92-
/// \brief Creates a new cmio rx buffer PMA entry.
93-
// \param c Optional cmio configuration
94-
/// \returns New PMA entry with rx buffer flags already set.
95-
static pma_entry make_cmio_rx_buffer_pma_entry(const cmio_config &cmio_config);
96-
97-
/// \brief Creates a new cmio tx buffer PMA entry.
98-
// \param c Optional cmio configuration
99-
/// \returns New PMA entry with tx buffer flags already set.
100-
static pma_entry make_cmio_tx_buffer_pma_entry(const cmio_config &cmio_config);
101-
10280
/// \brief Saves PMAs into files for serialization
10381
/// \param config Machine config to be stored
10482
/// \param directory Directory where PMAs will be stored

src/os-features.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
#define HAVE_MMAP
4141
#endif
4242

43+
#if !defined(NO_FLOCK) && !defined(_WIN32) && !defined(__wasi__)
44+
#define HAVE_FLOCK
45+
#endif
46+
4347
#if !defined(NO_MKDIR)
4448
#define HAVE_MKDIR
4549
#endif

0 commit comments

Comments
 (0)