Skip to content

Commit 7582aa8

Browse files
committed
fix(dstack-mr): correct ACPI table generation for UEFI disk boot
UKI mode uses a minimal device config (single disk + net, no vsock/9p) matching the actual QEMU command for UEFI disk boot. The previous code reused the -kernel mode device list which includes vsock and 9p, causing different ACPI tables and wrong RTMR[0]. All four measurements now match TDX hardware: MRTD: ✓ (OVMF firmware) RTMR0: ✓ (14 events including ACPI tables) RTMR1: ✓ (8 events: EFI apps + boot transitions) RTMR2: ✓ (2 events: cmdline + initrd)
1 parent 69313bf commit 7582aa8

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

dstack-mr/src/acpi.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,96 @@ pub struct Tables {
2323

2424
impl Machine<'_> {
2525
fn create_tables(&self) -> Result<Vec<u8>> {
26+
if self.is_uki_mode() {
27+
return self.create_tables_uefi_disk();
28+
}
29+
self.create_tables_direct_kernel()
30+
}
31+
32+
/// Generate ACPI tables for UEFI disk boot (UKI mode).
33+
/// Device config: single disk (hd0) + net. No vsock, no 9p, no -kernel.
34+
fn create_tables_uefi_disk(&self) -> Result<Vec<u8>> {
35+
if self.cpu_count == 0 {
36+
bail!("cpuCount must be greater than 0");
37+
}
38+
let mem_size_mb = self.memory_size / (1024 * 1024);
39+
let dummy_disk = "/bin/sh";
40+
41+
let mut cmd = std::process::Command::new("dstack-acpi-tables");
42+
cmd.args([
43+
"-cpu",
44+
"qemu64",
45+
"-smp",
46+
&self.cpu_count.to_string(),
47+
"-m",
48+
&format!("{mem_size_mb}M"),
49+
"-nographic",
50+
"-nodefaults",
51+
"-serial",
52+
"stdio",
53+
"-bios",
54+
self.firmware,
55+
// No -kernel/-initrd: UEFI disk boot loads from ESP
56+
"-drive",
57+
&format!("file={dummy_disk},if=none,id=hd0,format=raw,readonly=on"),
58+
"-device",
59+
"virtio-blk-pci,drive=hd0",
60+
"-netdev",
61+
"user,id=net0",
62+
"-device",
63+
"virtio-net-pci,netdev=net0",
64+
"-object",
65+
"tdx-guest,id=tdx",
66+
// No vsock, no 9p — UKI mode uses simple device config
67+
]);
68+
69+
let mut machine =
70+
"q35,kernel-irqchip=split,confidential-guest-support=tdx,hpet=off".to_string();
71+
if self.smm {
72+
machine.push_str(",smm=on");
73+
} else {
74+
machine.push_str(",smm=off");
75+
}
76+
let vopt = self
77+
.versioned_options()
78+
.context("Failed to get versioned options")?;
79+
if vopt.pic {
80+
machine.push_str(",pic=on");
81+
} else {
82+
machine.push_str(",pic=off");
83+
}
84+
cmd.args(["-machine", &machine]);
85+
86+
if self.hotplug_off {
87+
cmd.args([
88+
"-global",
89+
"ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off",
90+
]);
91+
}
92+
if let Some(pci_hole64_size) = self.pci_hole64_size {
93+
cmd.args([
94+
"-global",
95+
&format!("q35-pcihost.pci-hole64-size=0x{:x}", pci_hole64_size),
96+
]);
97+
}
98+
99+
let ver = vopt.version;
100+
let output = cmd
101+
.env(
102+
"QEMU_ACPI_COMPAT_VER",
103+
format!("{}.{}.{}", ver.0, ver.1, ver.2),
104+
)
105+
.output()
106+
.context("failed to execute dstack-acpi-tables")?;
107+
108+
if !output.status.success() {
109+
let stderr = String::from_utf8_lossy(&output.stderr);
110+
bail!("dstack-acpi-tables failed: {stderr}");
111+
}
112+
Ok(output.stdout)
113+
}
114+
115+
fn create_tables_direct_kernel(&self) -> Result<Vec<u8>> {
26116
if self.cpu_count == 0 {
27117
bail!("cpuCount must be greater than 0");
28118
}

0 commit comments

Comments
 (0)