Skip to content

Commit 37005ad

Browse files
committed
cpiovfs snapshot support: initrd re-map on restore
Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent f4ab6d5 commit 37005ad

5 files changed

Lines changed: 86 additions & 10 deletions

File tree

examples/python-agent-driver/kraft.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ unikraft:
1111
CONFIG_LIBUKINTCTLR_HYPERLIGHT: 'y'
1212
CONFIG_HYPERLIGHT_MAX_GUEST_LOG_LEVEL: 4
1313

14-
CONFIG_LIBUKPRINT_KLVL_CRIT: 'y'
14+
CONFIG_LIBUKPRINT_KLVL_INFO: 'y'
1515
CONFIG_LIBUKPRINT_PRINT_TIME: 'n'
16-
CONFIG_LIBUKPRINT_PRINT_SRCNAME: 'n'
16+
CONFIG_LIBUKPRINT_PRINT_SRCNAME: 'y'
1717
CONFIG_LIBUKBOOT_BANNER_NONE: 'y'
1818
CONFIG_OPTIMIZE_SIZE: 'y'
1919
CONFIG_OPTIMIZE_PIE: 'y'
2020

2121
CONFIG_LIBVFSCORE: 'y'
2222
CONFIG_LIBVFSCORE_AUTOMOUNT_CI: 'y'
23-
CONFIG_LIBVFSCORE_AUTOMOUNT_CI_INITRD: 'y'
24-
CONFIG_LIBRAMFS: 'y'
23+
CONFIG_LIBVFSCORE_AUTOMOUNT_CI_CUSTOM: 'y'
24+
CONFIG_LIBVFSCORE_AUTOMOUNT_CI0_MP: '/'
25+
CONFIG_LIBVFSCORE_AUTOMOUNT_CI0_DRIVER: 'cpiovfs'
26+
CONFIG_LIBVFSCORE_AUTOMOUNT_CI0_UKOPTS_IFINITRD0: 'y'
27+
CONFIG_LIBCPIOVFS: 'y'
2528
CONFIG_LIBUKCPIO: 'y'
2629

2730
CONFIG_LIBDEVFS: 'y'

host/examples/test_cpiovfs.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use hyperlight_unikraft::Sandbox;
2+
3+
fn main() -> anyhow::Result<()> {
4+
let kernel = std::env::args()
5+
.nth(1)
6+
.expect("usage: test_cpiovfs <kernel> <initrd>");
7+
let initrd = std::env::args()
8+
.nth(2)
9+
.expect("usage: test_cpiovfs <kernel> <initrd>");
10+
11+
eprintln!("=== Test: build + init + snapshot + restore + call ===");
12+
{
13+
let mut sbox = Sandbox::builder(&kernel)
14+
.initrd_file(&initrd)
15+
.heap_size(3 * 512 * 1024 * 1024)
16+
.build()?;
17+
eprintln!(" build OK");
18+
sbox.restore()?;
19+
let _: () = sbox.call_named("init", ())?;
20+
eprintln!(" init OK");
21+
sbox.snapshot_now()?;
22+
eprintln!(" snapshot OK");
23+
24+
let snap_path = "/tmp/cpiovfs_snapshot.hls";
25+
sbox.save_snapshot(snap_path)?;
26+
let snap_size = std::fs::metadata(snap_path)?.len();
27+
eprintln!(
28+
" snapshot size: {} MiB ({} bytes)",
29+
snap_size / 1024 / 1024,
30+
snap_size
31+
);
32+
33+
sbox.restore()?;
34+
eprintln!(" restore OK");
35+
let _: () = sbox.call_named("run", "print('test ok')".to_string())?;
36+
eprintln!(" call OK");
37+
}
38+
39+
eprintln!("=== All tests passed ===");
40+
Ok(())
41+
}

host/src/bin/pyhl.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,12 @@ fn cmd_run(args: RunArgs) -> Result<()> {
464464
.map(|m| parse_mount(m))
465465
.collect::<Result<_>>()?;
466466

467+
let initrd = home.join(INITRD_FILE);
468+
467469
let t_load = Instant::now();
468-
let mut sandbox = if run_preopens.is_empty() {
470+
let mut sandbox = if initrd.is_file() {
471+
Sandbox::from_snapshot_file_with_initrd(&snapshot, &run_preopens, &initrd)?
472+
} else if run_preopens.is_empty() {
469473
Sandbox::from_snapshot_file(&snapshot)?
470474
} else {
471475
Sandbox::from_snapshot_file_with(&snapshot, &run_preopens)?

host/src/lib.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ impl Sandbox {
13871387
/// a 2.5 GB snapshot — enough to double the whole `pyhl run` wall
13881388
/// time on simple scripts.
13891389
pub fn from_snapshot_file<P: AsRef<Path>>(path: P) -> Result<Self> {
1390-
Self::from_snapshot_file_with(path, &[])
1390+
Self::from_snapshot_file_full(path, &[], None)
13911391
}
13921392

13931393
/// Load a previously-persisted snapshot and register a
@@ -1402,6 +1402,26 @@ impl Sandbox {
14021402
/// fixed at setup time because it lives in the snapshot's memory
14031403
/// image.
14041404
pub fn from_snapshot_file_with<P: AsRef<Path>>(path: P, preopens: &[Preopen]) -> Result<Self> {
1405+
Self::from_snapshot_file_full(path, preopens, None)
1406+
}
1407+
1408+
/// Load a snapshot with an initrd file re-mapped at the standard
1409+
/// guest VA (0xC000_0000). Required when the snapshot was taken
1410+
/// from a cpiovfs-backed guest whose VFS nodes point into the
1411+
/// initrd region.
1412+
pub fn from_snapshot_file_with_initrd<P: AsRef<Path>, I: AsRef<Path>>(
1413+
path: P,
1414+
preopens: &[Preopen],
1415+
initrd: I,
1416+
) -> Result<Self> {
1417+
Self::from_snapshot_file_full(path, preopens, Some(initrd.as_ref().to_path_buf()))
1418+
}
1419+
1420+
fn from_snapshot_file_full<P: AsRef<Path>>(
1421+
path: P,
1422+
preopens: &[Preopen],
1423+
initrd: Option<std::path::PathBuf>,
1424+
) -> Result<Self> {
14051425
let loaded = Snapshot::from_file_unchecked(path.as_ref())?;
14061426
let arc = Arc::new(loaded);
14071427

@@ -1421,13 +1441,18 @@ impl Sandbox {
14211441
})?;
14221442
}
14231443

1424-
let inner = MultiUseSandbox::from_snapshot(arc.clone(), host_funcs, None)?;
1444+
let mut inner = MultiUseSandbox::from_snapshot(arc.clone(), host_funcs, None)?;
1445+
1446+
const INITRD_MAP_BASE: u64 = 0xC000_0000;
1447+
if let Some(ref initrd_path) = initrd {
1448+
inner.map_file_cow(initrd_path, INITRD_MAP_BASE, Some("initrd"))?;
1449+
}
14251450

14261451
Ok(Self {
14271452
inner,
14281453
snapshot: Some(arc),
1429-
file_mapping_path: None,
1430-
file_mapping_base: 0,
1454+
file_mapping_path: initrd,
1455+
file_mapping_base: INITRD_MAP_BASE,
14311456
})
14321457
}
14331458
}

host/src/pyhl.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,10 @@ impl Runtime {
222222
snap.display()
223223
);
224224
}
225-
let sandbox = if mounts.is_empty() {
225+
let initrd = home.join(INITRD_FILE);
226+
let sandbox = if initrd.is_file() {
227+
Sandbox::from_snapshot_file_with_initrd(&snap, mounts, &initrd)?
228+
} else if mounts.is_empty() {
226229
Sandbox::from_snapshot_file(&snap)?
227230
} else {
228231
Sandbox::from_snapshot_file_with(&snap, mounts)?

0 commit comments

Comments
 (0)