its current form) in a future version of systemd.</para>
<para>Configures whether to run the guest as a confidential VM. Takes one of
- <literal>no</literal> or <literal>sev-snp</literal>. Defaults to <literal>no</literal>.</para>
+ <literal>no</literal>, <literal>sev-snp</literal> or <literal>tdx</literal>. Defaults to
+ <literal>no</literal>.</para>
<para><literal>sev-snp</literal> enables AMD SEV-SNP. This requires KVM on an x86_64 host with
SNP-capable hardware and firmware. <option>--firmware=</option> must point to a raw SNP-built
recent version of systemd (supporting <filename>/.extra/system_credentials/</filename>). A vTPM,
if attached via <option>--tpm=</option>, must be treated as untrusted by the guest.</para>
+ <para><literal>tdx</literal> enables Intel TDX. This requires KVM on an x86_64 host with
+ TDX-capable hardware and a TDX-enabled host kernel. As with <literal>sev-snp</literal>,
+ <option>--firmware=</option> must point to a raw TDX-built OVMF (TDVF) <filename>.fd</filename>
+ image, which is loaded via QEMU's <option>-bios</option> (pflash + NVRAM split is not
+ supported), and the CPU model is fixed to <literal>host</literal>. Firmware is measured into
+ MRTD when the TD is built. Secure Boot cannot be enrolled at runtime (there is no writable
+ NVRAM); its state is fixed by the supplied TDVF image and is part of the measured firmware.
+ When booting a UKI, the whole UKI PE is measured into RTMR 1, and the loaded sections are
+ measured individually by <command>systemd-stub</command> into RTMR 2. For direct linux boot,
+ firmware measures the kernel PE into RTMR 1, and the Linux EFI stub measures initrd and
+ command line into RTMR 2. A vTPM, if attached via <option>--tpm=</option>, must be treated
+ as untrusted by the guest.
+ <xi:include href="version-info.xml" xpointer="v262"/></para>
+
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
</variablelist>
break;
}
- OPTION_LONG("coco", "no|sev-snp", "Run the guest as a confidential VM"): {
+ OPTION_LONG("coco", "no|sev-snp|tdx", "Run the guest as a confidential VM"): {
ConfidentialComputing cc = confidential_computing_from_string(opts.arg);
if (cc < 0)
return log_error_errno(cc, "Unknown --coco= value: %s", opts.arg);
use_kvm = r;
}
- if (arg_confidential_computing == COCO_AMD_SEV_SNP && !use_kvm)
+ if (arg_confidential_computing != COCO_NO && !use_kvm)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "--coco=sev-snp requires KVM, but KVM is not available.");
+ "--coco= requires KVM, but KVM is not available.");
- if (arg_firmware_type == FIRMWARE_UEFI && arg_confidential_computing != COCO_AMD_SEV_SNP) {
+ if (arg_firmware_type == FIRMWARE_UEFI && arg_confidential_computing == COCO_NO) {
if (arg_firmware)
r = load_ovmf_config(arg_firmware, &ovmf_config);
else
if (r < 0)
return r;
- if (arg_confidential_computing == COCO_AMD_SEV_SNP) {
+ if (arg_confidential_computing != COCO_NO) {
r = qemu_config_key(config_file, "kernel-irqchip", "split");
if (r < 0)
return r;
r = qemu_config_key(config_file, "confidential-guest-support", "snp0");
if (r < 0)
return r;
+ } else if (arg_confidential_computing == COCO_INTEL_TDX) {
+ r = qemu_config_key(config_file, "confidential-guest-support", "tdx0");
+ if (r < 0)
+ return r;
}
r = qemu_config_section(config_file, "smp-opts", /* id= */ NULL,
"kernel-hashes", "on");
if (r < 0)
return r;
+ } else if (arg_confidential_computing == COCO_INTEL_TDX) {
+ r = qemu_config_section(config_file, "object", "tdx0",
+ "qom-type", "tdx-guest");
+ if (r < 0)
+ return r;
}
unsigned child_cid = arg_vsock_cid;
/* -cpu stays on cmdline since not all flags are supported in config. SNP needs a stable,
* named CPU model so the launch measurement is reproducible across hosts; EPYC-v4 is the
- * baseline that covers all SNP-capable processors (Milan and later). */
+ * baseline that covers all SNP-capable processors (Milan and later). TDX requires host
+ * CPU model. */
const char *cpu_model =
#ifdef __x86_64__
- arg_confidential_computing == COCO_AMD_SEV_SNP ? "EPYC-v4"
- : "max,hv_relaxed,hv-vapic,hv-time";
+ arg_confidential_computing == COCO_AMD_SEV_SNP ? "EPYC-v4" :
+ arg_confidential_computing == COCO_INTEL_TDX ? "host" :
+ "max,hv_relaxed,hv-vapic,hv-time";
#else
"max";
#endif
"--coco=sev-snp requires KVM, remove --kvm=no.");
if (arg_firmware_type != FIRMWARE_UEFI)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--coco can't be used with %s firmware",
+ "--coco=sev-snp can't be used with %s firmware",
firmware_to_string(arg_firmware_type));
/* SNP can't use pflash + NVRAM split, so the firmware-descriptor
* machinery doesn't apply. Require an explicit raw .fd path and
log_debug("Using raw SNP firmware at %s (no NVRAM, no Secure Boot).", arg_firmware);
if (set_contains(arg_firmware_features_include, "secure-boot"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--secure-boot=yes cannot be combined with --coco.");
+ "--coco=sev-snp cannot be combined with --secure-boot=yes.");
if (arg_tpm > 0)
log_warning("TPM can't be trusted by the confidential computing guest");
/* kernel-hashes=on only covers what QEMU itself loads via -kernel/-initrd/-append.
"so kernel, initrd and cmdline are covered by the launch measurement.");
}
+ if (arg_confidential_computing == COCO_INTEL_TDX) {
+ if (native_architecture() != ARCHITECTURE_X86_64)
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "--coco=tdx is only supported on x86_64.");
+ if (arg_kvm == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--coco=tdx requires KVM, remove --kvm=no.");
+ if (arg_firmware_type != FIRMWARE_UEFI)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--coco=tdx can't be used with %s firmware",
+ firmware_to_string(arg_firmware_type));
+ /* TDX can't use pflash + NVRAM split, so the firmware-descriptor
+ * machinery doesn't apply. Require an explicit raw .fd path and
+ * use it verbatim with -bios later. */
+ if (!arg_firmware)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--coco=tdx requires --firmware=PATH "
+ "pointing at a raw TDX-built OVMF (TDVF) .fd binary.");
+ log_debug("Using raw TDX firmware at %s (no NVRAM, no Secure Boot).", arg_firmware);
+ /* Secure Boot state is baked into the supplied TDVF image and can't be enrolled at
+ * runtime (no writable NVRAM), so --secure-boot=yes would silently have no effect. */
+ if (set_contains(arg_firmware_features_include, "secure-boot"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--coco=tdx cannot be combined with --secure-boot=yes.");
+ if (arg_tpm > 0)
+ log_warning("TPM can't be trusted by the confidential computing guest");
+ }
+
return 0;
}