diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 8599331ae..20b3676f9 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -631,8 +631,6 @@ pub fn generate_common_cpuid( CpuidPatch::patch_cpuid(&mut cpuid, &cpuid_patches); - let la57_enabled = CpuidPatch::is_feature_enabled(&cpuid, 7, 0, CpuidReg::ECX, 16); - #[cfg(feature = "tdx")] let tdx_capabilities = if config.tdx { let tdx_vm = vm.ok_or_else(|| { @@ -715,14 +713,9 @@ pub fn generate_common_cpuid( } // Set CPU physical bits 0x8000_0008 => { - let virt_addr_width = if la57_enabled { 57 } else { 48 }; - let mut guest_phys_bits = (entry.eax >> 16) & 0xff; - if guest_phys_bits > config.phys_bits as u32 { - guest_phys_bits = config.phys_bits as u32; - } - entry.eax = (config.phys_bits as u32 & 0xff) - | (virt_addr_width << 8) - | (guest_phys_bits << 16); + entry.eax = (entry.eax & 0xff00_ff00) + | (config.phys_bits as u32 & 0xff) + | ((config.phys_bits as u32 & 0xff) << 16); } 0x4000_0001 => { // Enable KVM_FEATURE_MSI_EXT_DEST_ID. This allows the guest to target diff --git a/docs/intel_tdx.md b/docs/intel_tdx.md index 0f5c7645d..efa4007c2 100644 --- a/docs/intel_tdx.md +++ b/docs/intel_tdx.md @@ -70,7 +70,7 @@ guest image containing the TDX enlightened kernel. ./cloud-hypervisor \ --platform tdx=on \ --firmware edk2/Build/IntelTdx/RELEASE_GCC5/FV/OVMF.fd \ - --cpus boot=1,max_phys_bits=52 \ + --cpus boot=1 \ --memory size=1G \ --serial tty \ --console off \ @@ -84,7 +84,7 @@ firmware: ./cloud-hypervisor \ --platform tdx=on \ --firmware edk2/Build/IntelTdx/DEBUG_GCC5/FV/OVMF.fd \ - --cpus boot=1,max_phys_bits=52 \ + --cpus boot=1 \ --memory size=1G \ --disk path=tdx_guest_img \ --serial tty \ @@ -139,7 +139,7 @@ option as well. --firmware td-shim/target/release/final.bin \ --kernel bzImage \ --cmdline "root=/dev/vda1 rw console=ttyS0 ignore_loglevel earlyprintk=ttyS0" \ - --cpus boot=1,max_phys_bits=52 \ + --cpus boot=1 \ --memory size=1G \ --disk path=tdx_guest_img ``` @@ -153,7 +153,7 @@ TDShim: --firmware td-shim/target/debug/final.bin \ --kernel bzImage \ --cmdline "root=/dev/vda1 rw console=ttyS0 ignore_loglevel earlyprintk=ttyS0" \ - --cpus boot=1,max_phys_bits=52 \ + --cpus boot=1 \ --memory size=1G \ --disk path=tdx_guest_img ``` diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 93ec6c891..0742100da 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -2873,6 +2873,16 @@ impl VmConfig { if tdx_enabled && (self.cpus.max_vcpus != self.cpus.boot_vcpus) { return Err(ValidationError::TdxNoCpuHotplug); } + if tdx_enabled { + // For TDX the guest physical address width (GPAW) is fixed at: + // 48 - (GPAW-48, 4-level EPT) + // 52 - (GPAW-52, 5-level EPT) + if self.cpus.max_phys_bits < 52 { + self.cpus.max_phys_bits = 48; + } else { + self.cpus.max_phys_bits = 52; + } + } } #[cfg(feature = "sev_snp")] @@ -4898,6 +4908,26 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" valid_config.validate().unwrap(); + #[cfg(feature = "tdx")] + { + let mut tdx_config = valid_config.clone(); + tdx_config.cpus.max_phys_bits = 51; + tdx_config.platform = Some(PlatformConfig { + tdx: true, + ..platform_fixture() + }); + if let Some(payload) = tdx_config.payload.as_mut() { + payload.firmware = Some(PathBuf::from("/path/to/firmware")); + } + + tdx_config.validate().unwrap(); + assert_eq!(tdx_config.cpus.max_phys_bits, 48); + + tdx_config.cpus.max_phys_bits = 52; + tdx_config.validate().unwrap(); + assert_eq!(tdx_config.cpus.max_phys_bits, 52); + } + let mut invalid_config = valid_config.clone(); invalid_config.serial.mode = ConsoleOutputMode::Tty; invalid_config.console.mode = ConsoleOutputMode::Tty;