Skip to content

Commit 4bd4bc6

Browse files
committed
refactor!: convert shadow ranges to memory ranges
1 parent f25f7d6 commit 4bd4bc6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2019
-1923
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*.a
77
*.lib
88
*.wasm
9+
*.TODO
910

1011
build
1112
pkg

src/Makefile

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ HASH_LIBS=
151151

152152
#DEFS+= -DMT_ALL_DIRTY
153153

154-
WARNS=-Wall -Wextra -Wpedantic
154+
C_WARNS=-Wall -Wextra -Wpedantic
155+
CXX_WARNS=$(C_WARNS) -Wno-missing-field-initializers
155156

156157
# Place our include directories before the system's
157158
INCS+= \
@@ -305,8 +306,8 @@ else
305306
DEFS+=-DNO_THREADS
306307
endif
307308

308-
CXXFLAGS+=$(OPTFLAGS) -std=gnu++20 -fvisibility=hidden -MMD $(PICCFLAGS) $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(WARNS)
309-
CFLAGS+=$(OPTFLAGS) -std=gnu99 -fvisibility=hidden -MMD $(PICCFLAGS) $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(WARNS)
309+
CXXFLAGS+=$(OPTFLAGS) -std=gnu++20 -fvisibility=hidden -MMD $(PICCFLAGS) $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(CXX_WARNS)
310+
CFLAGS+=$(OPTFLAGS) -std=gnu99 -fvisibility=hidden -MMD $(PICCFLAGS) $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(C_WARNS)
310311
LDFLAGS+=$(UBFLAGS)
311312

312313
ifeq ($(coverage),yes)
@@ -357,14 +358,12 @@ LIBCARTESI_OBJS:= \
357358
machine.o \
358359
memory-address-range.o \
359360
os.o \
361+
os-mmap.o \
360362
plic-address-range.o \
361363
pristine-merkle-tree.o \
362364
replay-step-state-access-interop.o \
363365
send-cmio-response.o \
364366
sha3.o \
365-
shadow-state-address-range.o \
366-
shadow-tlb-address-range.o \
367-
shadow-uarch-state-address-range.o \
368367
uarch-pristine-hash.o \
369368
uarch-pristine-ram.o \
370369
uarch-pristine-state-hash.o \

src/address-range-constants.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ namespace cartesi {
2525

2626
/// \brief Fixed address ranges.
2727
enum AR_ranges : uint64_t {
28-
AR_SHADOW_STATE_START = EXPAND_UINT64_C(AR_SHADOW_STATE_START_DEF), ///< Start of shadow state range
29-
AR_SHADOW_STATE_LENGTH = EXPAND_UINT64_C(AR_SHADOW_STATE_LENGTH_DEF), ///< Length of shadow state range
30-
AR_PMAS_START = EXPAND_UINT64_C(AR_PMAS_START_DEF), ///< Start of PMAS list range
31-
AR_PMAS_LENGTH = EXPAND_UINT64_C(AR_PMAS_LENGTH_DEF), ///< Length of PMAS list range
32-
AR_DTB_START = EXPAND_UINT64_C(AR_DTB_START_DEF), ///< Start of DTB range
33-
AR_DTB_LENGTH = EXPAND_UINT64_C(AR_DTB_LENGTH_DEF), ///< Length of DTB range
34-
AR_SHADOW_TLB_START = EXPAND_UINT64_C(AR_SHADOW_TLB_START_DEF), ///< Start of shadow TLB range
35-
AR_SHADOW_TLB_LENGTH = EXPAND_UINT64_C(AR_SHADOW_TLB_LENGTH_DEF), ///< Length of shadow TLB range
28+
AR_SHADOW_STATE_START = EXPAND_UINT64_C(AR_SHADOW_STATE_START_DEF), ///< Start of shadow state range
29+
AR_SHADOW_STATE_LENGTH = EXPAND_UINT64_C(AR_SHADOW_STATE_LENGTH_DEF), ///< Length of shadow state range
30+
AR_SHADOW_REGISTERS_START = EXPAND_UINT64_C(AR_SHADOW_REGISTERS_START_DEF), ///< Start of shadow registers range
31+
AR_SHADOW_REGISTERS_LENGTH = EXPAND_UINT64_C(AR_SHADOW_REGISTERS_LENGTH_DEF), ///< Length of shadow registers range
32+
AR_SHADOW_TLB_START = EXPAND_UINT64_C(AR_SHADOW_TLB_START_DEF), ///< Start of shadow TLB range
33+
AR_SHADOW_TLB_LENGTH = EXPAND_UINT64_C(AR_SHADOW_TLB_LENGTH_DEF), ///< Length of shadow TLB range
34+
AR_PMAS_START = EXPAND_UINT64_C(AR_PMAS_START_DEF), ///< Start of PMAS list range
35+
AR_PMAS_LENGTH = EXPAND_UINT64_C(AR_PMAS_LENGTH_DEF), ///< Length of PMAS list range
36+
AR_DTB_START = EXPAND_UINT64_C(AR_DTB_START_DEF), ///< Start of DTB range
37+
AR_DTB_LENGTH = EXPAND_UINT64_C(AR_DTB_LENGTH_DEF), ///< Length of DTB range
3638
AR_SHADOW_UARCH_STATE_START =
3739
EXPAND_UINT64_C(AR_SHADOW_UARCH_STATE_START_DEF), ///< Start of uarch shadow state range
3840
AR_SHADOW_UARCH_STATE_LENGTH =
@@ -61,6 +63,10 @@ enum AR_ranges : uint64_t {
6163
AR_RAM_START = EXPAND_UINT64_C(AR_RAM_START_DEF), ///< Start of RAM range
6264
};
6365

66+
static_assert(AR_SHADOW_STATE_LENGTH >= AR_SHADOW_REGISTERS_LENGTH + AR_SHADOW_TLB_LENGTH);
67+
static_assert(AR_SHADOW_TLB_START == AR_SHADOW_REGISTERS_START + AR_SHADOW_REGISTERS_LENGTH);
68+
static_assert(AR_SHADOW_STATE_START == AR_SHADOW_REGISTERS_START);
69+
6470
/// \brief PMA constants.
6571
enum AR_constants : uint64_t {
6672
AR_PAGE_SIZE_LOG2 = EXPAND_UINT64_C(AR_PAGE_SIZE_LOG2_DEF), ///< Log<sub>2</sub> of physical memory page size.

src/address-range-defines.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919

2020
// NOLINTBEGIN(cppcoreguidelines-macro-usage,cppcoreguidelines-macro-to-enum,modernize-macro-to-enum)
2121
#define AR_SHADOW_STATE_START_DEF 0x0 ///< Shadow start address
22-
#define AR_SHADOW_STATE_LENGTH_DEF 0x1000 ///< Shadow length in bytes
22+
#define AR_SHADOW_STATE_LENGTH_DEF 0x8000 ///< Shadow length in bytes
23+
#define AR_SHADOW_REGISTERS_START_DEF 0x0 ///< Shadow registers start address
24+
#define AR_SHADOW_REGISTERS_LENGTH_DEF 0x1000 ///< Shadow registers length in bytes
25+
#define AR_SHADOW_TLB_START_DEF 0x1000 ///< Shadow TLB start address
26+
#define AR_SHADOW_TLB_LENGTH_DEF 0x6000 ///< Shadow TLB length in bytes
2327
#define AR_PMAS_START_DEF 0x10000 ///< PMA Array start address
2428
#define AR_PMAS_LENGTH_DEF 0x1000 ///< PMA Array length in bytes
25-
#define AR_SHADOW_TLB_START_DEF 0x1000 ///< TLB start address
26-
#define AR_SHADOW_TLB_LENGTH_DEF 0x6000 ///< TLB length in bytes
2729
#define AR_SHADOW_UARCH_STATE_START_DEF 0x400000 ///< microarchitecture shadow state start address
2830
#define AR_SHADOW_UARCH_STATE_LENGTH_DEF 0x1000 ///< microarchitecture shadow state length
2931
#define AR_UARCH_RAM_START_DEF 0x600000 ///< microarchitecture RAM start address

src/address-range.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,20 @@ class address_range {
220220
return m_flags.IW;
221221
}
222222

223+
/// \brief Tests if range can be replaced
224+
/// \returns True if and only if range can be replaced
225+
bool is_replaceable() const noexcept {
226+
switch (m_flags.DID) {
227+
case PMA_ISTART_DID::memory:
228+
case PMA_ISTART_DID::flash_drive:
229+
case PMA_ISTART_DID::cmio_rx_buffer:
230+
case PMA_ISTART_DID::cmio_tx_buffer:
231+
return true;
232+
default:
233+
return false;
234+
}
235+
}
236+
223237
/// \brief Returns driver ID associated to range
224238
/// \returns Teh driver ID
225239
PMA_ISTART_DID get_driver_id() const noexcept {
@@ -327,6 +341,18 @@ class address_range {
327341
return do_is_page_marked_dirty(offset);
328342
}
329343

344+
/// \brief Returns true if the mapped memory is read-only on the host
345+
/// \returns True if the memory is read-only in the host
346+
bool is_host_read_only() const noexcept {
347+
return do_is_host_read_only();
348+
}
349+
350+
/// \brief Returns true if pages marked as dirty once are uncleanable
351+
/// \returns True if and only if dirty pages are uncleanable
352+
bool is_page_uncleanable() const noexcept {
353+
return do_is_page_uncleanable();
354+
}
355+
330356
private:
331357
// Default implementation of peek() always fails
332358
virtual bool do_peek(const machine & /*m*/, uint64_t /*offset*/, uint64_t /*length*/,
@@ -371,6 +397,14 @@ class address_range {
371397
virtual bool do_is_page_marked_dirty(uint64_t /*offset*/) const noexcept {
372398
return true;
373399
}
400+
401+
virtual bool do_is_host_read_only() const noexcept {
402+
return false;
403+
}
404+
405+
virtual bool do_is_page_uncleanable() const noexcept {
406+
return false;
407+
}
374408
};
375409

376410
template <size_t N>

src/cartesi-machine.lua

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ where options are:
107107
data_filename:<filename>
108108
dht_filename:<filename>
109109
shared
110+
create
111+
truncate
112+
read_only
110113
mount:<string>
111114
user:<string>
112115
@@ -137,6 +140,18 @@ where options are:
137140
target modifications to flash drive modify the memory and hash tree files.
138141
by default, image files are not modified and changes are lost.
139142
143+
create (optional)
144+
create the backing storage file, shared must also be true.
145+
146+
truncate (optional)
147+
truncate the memory length to match memory lengths different from the backing storage,
148+
in case of shared flash drive, then it also truncates the underlying backing file.
149+
by default, when a length is present it must also match the backing storage length.
150+
151+
read_only (optional)
152+
mark flash drive as read-only, disallowing write attempts from the host or the guest.
153+
by default, flash drives are not read-only, thus writable.
154+
140155
mount (optional)
141156
whether the flash drive should be mounted automatically in init.
142157
by default, the drive is mounted if there is an image file backing it,
@@ -171,11 +186,12 @@ where options are:
171186
172187
--ram=<key>:<value>[,<key>:<value>[,...]...]
173188
--dtb=<key>:<value>[,<key>:<value>[,...]...]
174-
--tlb=<key>:<value>[,<key>:<value>[,...]...]
189+
--processor=<key>:<value>[,<key>:<value>[,...]...]
175190
--cmio-rx-buffer=<key>:<value>[,<key>:<value>[,...]...]
176191
--cmio-tx-buffer=<key>:<value>[,<key>:<value>[,...]...]
177192
--pmas=<key>:<value>[,<key>:<value>[,...]...]
178193
--uarch-ram=<key>:<value>[,<key>:<value>[,...]...]
194+
--uarch-processor=<key>:<value>[,<key>:<value>[,...]...]
179195
configures file storage for other memory ranges in the machine
180196
181197
<key>:<value> is one of
@@ -471,6 +487,31 @@ where options are:
471487
--load=<directory>
472488
load machine previously stored in <directory>.
473489
490+
--init-shared=<directory>
491+
initialize a machine sharing snapshot created in <directory>.
492+
writable address ranges are shared, thus runtime modifications persist in the snapshot.
493+
writable address ranges use reflinks on copy-on-write filesystems for efficient copying.
494+
read-only address ranges use hard links to avoid unnecessary copying.
495+
address ranges sparsity is preserved to minimize host storage usage.
496+
497+
MUST BE USED WITH --no-rollback
498+
499+
--load-shared=<directory>
500+
load an existing machine sharing snapshot from <directory>,
501+
writable address ranges are shared, thus runtime modifications persists in the snapshot.
502+
address ranges sparsity is preserved to minimize host storage usage.
503+
504+
MUST BE USED WITH --no-rollback
505+
506+
--clone-shared=<source_directory>,<destination_directory>
507+
clones a snapshot from source directory to destination directory and load a machine sharing it.
508+
writable address ranges are shared, thus runtime modifications persist in the snapshot.
509+
writable address ranges use reflinks on copy-on-write filesystems for efficient copying.
510+
read-only address ranges use hard links to avoid unnecessary copying.
511+
address ranges sparsity is preserved to minimize host storage usage.
512+
513+
MUST BE USED WITH --no-rollback
514+
474515
--initial-hash
475516
print initial state hash before running machine.
476517
@@ -614,6 +655,9 @@ local flash_data_filename = { root = images_path .. "rootfs.ext2" }
614655
local flash_dht_filename = {}
615656
local flash_label_order = { "root" }
616657
local flash_shared = {}
658+
local flash_create = {}
659+
local flash_truncate = {}
660+
local flash_read_only = {}
617661
local flash_mount = {}
618662
local flash_user = {}
619663
local flash_start = {}
@@ -1012,13 +1056,6 @@ local options = {
10121056
return true
10131057
end,
10141058
},
1015-
{
1016-
"^(%-%-tlb%=(.+))$",
1017-
function(all, opts)
1018-
tlb.backing_store = parse_backing_store(opts, "tlb", all, tlb.backing_store)
1019-
return true
1020-
end,
1021-
},
10221059
{
10231060
"^(%-%-pmas%=(.+))$",
10241061
function(all, opts)
@@ -1146,6 +1183,9 @@ local options = {
11461183
data_filename = true,
11471184
dht_filename = true,
11481185
shared = true,
1186+
create = true,
1187+
truncate = true,
1188+
read_only = true,
11491189
mount = true,
11501190
user = true,
11511191
length = true,
@@ -1155,6 +1195,9 @@ local options = {
11551195
if f.data_filename == true then f.data_filename = "" end
11561196
if f.dht_filename == true then f.dht_filename = "" end
11571197
assert(not f.shared or f.shared == true, "invalid flash drive shared value in " .. all)
1198+
assert(not f.create or f.create == true, "invalid flash drive create value in " .. all)
1199+
assert(not f.truncate or f.truncate == true, "invalid flash drive read_only value in " .. all)
1200+
assert(not f.read_only or f.read_only == true, "invalid flash drive truncate value in " .. all)
11581201
if f.mount == nil then
11591202
-- mount only if there is a file backing
11601203
if f.data_filename and f.data_filename ~= "" then
@@ -1179,8 +1222,14 @@ local options = {
11791222
flash_start[d] = f.start or flash_start[d]
11801223
flash_length[d] = f.length or flash_length[d]
11811224
flash_shared[d] = f.shared or flash_shared[d]
1225+
flash_create[d] = f.create or flash_create[d]
1226+
flash_truncate[d] = f.truncate or flash_truncate[d]
1227+
flash_read_only[d] = f.read_only or flash_read_only[d]
11821228
flash_mount[d] = f.mount or flash_mount[d]
11831229
flash_user[d] = f.user or flash_user[d]
1230+
if d == "root" and f.read_only then -- Mount root filesystem as read-only
1231+
dtb.bootargs = dtb.bootargs:gsub("rw", "ro")
1232+
end
11841233
return true
11851234
end,
11861235
},
@@ -1335,6 +1384,9 @@ local options = {
13351384
flash_start.root = nil
13361385
flash_length.root = nil
13371386
flash_shared.root = nil
1387+
flash_create.root = nil
1388+
flash_truncate.root = nil
1389+
flash_read_only.root = nil
13381390
table.remove(flash_label_order, 1)
13391391
dtb.bootargs = dtb.bootargs:gsub(" root=$", "")
13401392
return true
@@ -1846,7 +1898,10 @@ echo "
18461898
data_filename = flash_data_filename[label],
18471899
dht_filename = flash_dht_filename[label],
18481900
shared = flash_shared[label],
1901+
create = flash_create[label],
1902+
truncate = flash_truncate[label],
18491903
},
1904+
read_only = flash_read_only[label],
18501905
start = flash_start[label],
18511906
length = flash_length[label] or -1,
18521907
}

src/hot-tlb.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright Cartesi and individual authors (see AUTHORS)
2+
// SPDX-License-Identifier: LGPL-3.0-or-later
3+
//
4+
// This program is free software: you can redistribute it and/or modify it under
5+
// the terms of the GNU Lesser General Public License as published by the Free
6+
// Software Foundation, either version 3 of the License, or (at your option) any
7+
// later version.
8+
//
9+
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
10+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11+
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License along
14+
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
15+
//
16+
17+
#ifndef HOT_TLB_H
18+
#define HOT_TLB_H
19+
20+
/// \file
21+
/// \brief TLB definitions
22+
/// \details The Translation Lookaside Buffer is a small cache used to speed up translation between address spaces.
23+
24+
#include <array>
25+
#include <cstddef>
26+
#include <cstdint>
27+
28+
#include "host-addr.h"
29+
#include "shadow-tlb.h"
30+
31+
namespace cartesi {
32+
33+
/// \brief Hot TLB slot.
34+
/// \details
35+
/// Given a target virtual address vaddr within a page matching vaddr_page in TLB slot, the corresponding host address
36+
/// haddr = vaddr + vh_offset.
37+
struct hot_tlb_slot final {
38+
uint64_t vaddr_page{TLB_INVALID_PAGE}; ///< Target virtual address of start of page
39+
host_addr vh_offset{0}; ///< Offset from target virtual address in the same page to host address
40+
};
41+
42+
using hot_tlb_set = std::array<hot_tlb_slot, TLB_SET_SIZE>;
43+
using hot_tlb_state = std::array<hot_tlb_set, TLB_NUM_SETS_>;
44+
45+
static_assert(sizeof(uint64_t) >= sizeof(uintptr_t), "TLB expects host pointer fit in 64 bits");
46+
47+
// We need to ensure TLB state sizes are fixed across different platforms
48+
static_assert(sizeof(hot_tlb_state) == 3 * TLB_SET_SIZE * 2 * sizeof(uint64_t), "unexpected hot TLB state size");
49+
static_assert(alignof(hot_tlb_state) == sizeof(uint64_t), "unexpected hot TLB state alignment");
50+
51+
} // namespace cartesi
52+
53+
#endif

src/i-prefer-shadow-state.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
#include <type_traits>
2626

2727
#include "meta.h"
28-
#include "shadow-state.h"
29-
#include "tlb.h"
28+
#include "shadow-registers.h"
29+
#include "shadow-tlb.h"
3030

3131
namespace cartesi {
3232

@@ -48,12 +48,12 @@ class i_prefer_shadow_state { // CRTP
4848
}
4949

5050
public:
51-
uint64_t read_shadow_state(shadow_state_what what) const {
52-
return derived().do_read_shadow_state(what);
51+
uint64_t read_shadow_register(shadow_registers_what what) const {
52+
return derived().do_read_shadow_register(what);
5353
}
5454

55-
void write_shadow_state(shadow_state_what what, uint64_t val) const {
56-
derived().do_write_shadow_state(what, val);
55+
void write_shadow_register(shadow_registers_what what, uint64_t val) const {
56+
derived().do_write_shadow_register(what, val);
5757
}
5858
};
5959

src/i-prefer-shadow-uarch-state.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
#include <type_traits>
2626

2727
#include "meta.h"
28+
#include "shadow-tlb.h"
2829
#include "shadow-uarch-state.h"
29-
#include "tlb.h"
3030

3131
namespace cartesi {
3232

0 commit comments

Comments
 (0)