When the kvm file descriptor changes as a part of confidential guest reset, some architecture specific setups including SEV/SEV-SNP/TDX specific setups needs to be redone. These changes are implemented as a part of the kvm_arch_vmfd_change_ops() call which was introduced previously.
Signed-off-by: Ani Sinha <[email protected]> --- target/i386/kvm/kvm.c | 132 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 13 deletions(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index cdfcb70f40..e971f5f8c4 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -3252,9 +3252,126 @@ static int kvm_vm_enable_energy_msrs(KVMState *s) return 0; } +static int xen_init_wrapper(MachineState *ms, KVMState *s); + int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s) { - abort(); + Error *local_err = NULL; + int ret; + + /* + * Initialize confidential context, if required + * + * If no memory encryption is requested (ms->cgs == NULL) this is + * a no-op. + * + */ + if (ms->cgs) { + ret = confidential_guest_kvm_init(ms->cgs, &local_err); + if (ret < 0) { + error_report_err(local_err); + return ret; + } + } + + ret = kvm_vm_enable_exception_payload(s); + if (ret < 0) { + return ret; + } + + ret = kvm_vm_enable_triple_fault_event(s); + if (ret < 0) { + return ret; + } + + if (s->xen_version) { + ret = xen_init_wrapper(ms, s); + if (ret < 0) { + return ret; + } + } + + ret = kvm_vm_set_identity_map_addr(s, KVM_IDENTITY_BASE); + if (ret < 0) { + return ret; + } + + ret = kvm_vm_set_tss_addr(s, KVM_IDENTITY_BASE + 0x1000); + if (ret < 0) { + return ret; + } + ret = kvm_vm_set_nr_mmu_pages(s); + if (ret < 0) { + return ret; + } + + if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE) && + x86_machine_is_smm_enabled(X86_MACHINE(ms))) { + memory_listener_register(&smram_listener.listener, + &smram_address_space); + } + + if (enable_cpu_pm) { + ret = kvm_vm_enable_disable_exits(s); + if (ret < 0) { + error_report("kvm: guest stopping CPU not supported: %s", + strerror(-ret)); + return ret; + } + } + + if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) { + X86MachineState *x86ms = X86_MACHINE(ms); + + if (x86ms->bus_lock_ratelimit > 0) { + ret = kvm_vm_enable_bus_lock_exit(s); + if (ret < 0) { + return ret; + } + } + kvm_set_max_apic_id(x86ms->apic_id_limit); + } + + if (kvm_check_extension(s, KVM_CAP_X86_NOTIFY_VMEXIT)) { + ret = kvm_vm_enable_notify_vmexit(s); + if (ret < 0) { + return ret; + } + } + + if (kvm_vm_check_extension(s, KVM_CAP_X86_USER_SPACE_MSR)) { + ret = kvm_vm_enable_userspace_msr(s); + if (ret < 0) { + return ret; + } + + if (s->msr_energy.enable == true) { + ret = kvm_vm_enable_energy_msrs(s); + if (ret < 0) { + return ret; + } + } + } + + return 0; +} + +static int xen_init_wrapper(MachineState *ms, KVMState *s) +{ + int ret = 0; +#ifdef CONFIG_XEN_EMU + if (!object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE)) { + error_report("kvm: Xen support only available in PC machine"); + return -ENOTSUP; + } + /* hyperv_enabled() doesn't work yet. */ + uint32_t msr = XEN_HYPERCALL_MSR; + ret = kvm_xen_init(s, msr); +#else + error_report("kvm: Xen support not enabled in qemu"); + return -ENOTSUP; +#endif + return ret; } int kvm_arch_init(MachineState *ms, KVMState *s) @@ -3290,21 +3407,10 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } if (s->xen_version) { -#ifdef CONFIG_XEN_EMU - if (!object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE)) { - error_report("kvm: Xen support only available in PC machine"); - return -ENOTSUP; - } - /* hyperv_enabled() doesn't work yet. */ - uint32_t msr = XEN_HYPERCALL_MSR; - ret = kvm_xen_init(s, msr); + ret = xen_init_wrapper(ms, s); if (ret < 0) { return ret; } -#else - error_report("kvm: Xen support not enabled in qemu"); - return -ENOTSUP; -#endif } ret = kvm_get_supported_msrs(s); -- 2.42.0
