Hyper-V provides two modes for running a TDX/SNP VM: 1) In TD Partitioning mode (TDX) or vTOM mode (SNP) with a paravisor; 2) In "fully enlightened" mode with the normal TDX shared bit or SNP C-bit control over page encryption, and no paravisor. In the first mode (i.e. paravisor mode), the native TDX/SNP CPUID capability is hidden from the VM, but cc_platform_has(CC_ATTR_MEM_ENCRYPT) and cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) are true; as a result, mem_encrypt_init() incorrectly prints the below message when an Intel TDX VM with a paravisor runs on Hyper-V: "Memory Encryption Features active: AMD SEV". Introduce x86_platform.print_mem_enc_feature_info and allow hv_vtom_init() to override the function pointer so that the correct message is printed. BTW, when a VBS (Virtualization-based Security) VM running on Hyper-V (the physical CPU can be an AMD CPU or an Intel CPU), the VM's memory is not encrypted, but mem_encrypt_init() also prints the same incorrect message. The introduction of x86_platform.print_mem_enc_feature_info can also fix the issue. Signed-off-by: Dexuan Cui <decui@xxxxxxxxxxxxx> --- Some open questions: 1. Should we refactor the existing print_memory_encrypt_feature_info() into a TDX-specific function and an SEV-specific function? The function pointer in x86_platform_ops would be initialized to a no-op function, and then early_tdx_init(), sme_enable() and hv_vtom_init() would fill it in accordingly. 2. Should we rename "print_mem_enc_feature_info()" to "print_coco_feature_info()"? CC_ATTR_GUEST_STATE_ENCRYPT (and CC_ATTR_GUEST_SEV_SNP?) may not look like *memory* encryption to me? arch/x86/hyperv/ivm.c | 11 +++++++++++ arch/x86/include/asm/mem_encrypt.h | 1 + arch/x86/include/asm/x86_init.h | 2 ++ arch/x86/kernel/x86_init.c | 1 + arch/x86/mm/mem_encrypt.c | 4 ++-- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index e68051eba25a..fdc2fab0415e 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -450,6 +450,16 @@ static bool hv_is_private_mmio(u64 addr) return false; } +static void hv_print_mem_enc_feature_info(void) +{ + enum hv_isolation_type type = hv_get_isolation_type(); + + if (type == HV_ISOLATION_TYPE_SNP) + pr_info("Memory Encryption Features active: AMD SEV\n"); + else if (type == HV_ISOLATION_TYPE_TDX) + pr_info("Memory Encryption Features active: Intel TDX\n"); +} + void __init hv_vtom_init(void) { enum hv_isolation_type type = hv_get_isolation_type(); @@ -479,6 +489,7 @@ void __init hv_vtom_init(void) cc_set_mask(ms_hyperv.shared_gpa_boundary); physical_mask &= ms_hyperv.shared_gpa_boundary - 1; + x86_platform.print_mem_enc_feature_info = hv_print_mem_enc_feature_info; x86_platform.hyper.is_private_mmio = hv_is_private_mmio; x86_platform.guest.enc_cache_flush_required = hv_vtom_cache_flush_required; x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required; diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h index 7f97a8a97e24..6e8050a9138e 100644 --- a/arch/x86/include/asm/mem_encrypt.h +++ b/arch/x86/include/asm/mem_encrypt.h @@ -19,6 +19,7 @@ #ifdef CONFIG_X86_MEM_ENCRYPT void __init mem_encrypt_init(void); +void print_mem_encrypt_feature_info(void); #else static inline void mem_encrypt_init(void) { } #endif diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 14b0562c1d8b..7798174d4b8d 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -291,6 +291,7 @@ struct x86_hyper_runtime { * semantics. * @realmode_reserve: reserve memory for realmode trampoline * @realmode_init: initialize realmode trampoline + * @print_mem_enc_feature_info: print the supported memory encryption features * @hyper: x86 hypervisor specific runtime callbacks */ struct x86_platform_ops { @@ -309,6 +310,7 @@ struct x86_platform_ops { void (*set_legacy_features)(void); void (*realmode_reserve)(void); void (*realmode_init)(void); + void (*print_mem_enc_feature_info)(void); struct x86_hyper_runtime hyper; struct x86_guest guest; }; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 6117662ae4e6..ccb53db1b51e 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -149,6 +149,7 @@ struct x86_platform_ops x86_platform __ro_after_init = { .restore_sched_clock_state = tsc_restore_sched_clock_state, .realmode_reserve = reserve_real_mode, .realmode_init = init_real_mode, + .print_mem_enc_feature_info = print_mem_encrypt_feature_info, .hyper.pin_vcpu = x86_op_int_noop, .hyper.is_private_mmio = is_private_mmio_noop, diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 9f27e14e185f..8d37048bc1df 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -39,7 +39,7 @@ bool force_dma_unencrypted(struct device *dev) return false; } -static void print_mem_encrypt_feature_info(void) +void print_mem_encrypt_feature_info(void) { pr_info("Memory Encryption Features active:"); @@ -84,5 +84,5 @@ void __init mem_encrypt_init(void) /* Call into SWIOTLB to update the SWIOTLB DMA buffers */ swiotlb_update_mem_attributes(); - print_mem_encrypt_feature_info(); + x86_platform.print_mem_enc_feature_info(); } -- 2.25.1