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 | 135 +++++++++++++++++++++++++++++++---- target/i386/kvm/trace-events | 1 + 2 files changed, 122 insertions(+), 14 deletions(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 89f9e11d3a..4fedc621b8 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -3265,14 +3265,132 @@ 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; + } + } + } + + trace_kvm_arch_vmfd_change_ops(); + 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; } bool kvm_arch_supports_vmfd_change(void) { - return false; + return true; } int kvm_arch_init(MachineState *ms, KVMState *s) @@ -3308,21 +3426,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); diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events index 74a6234ff7..1f4786f687 100644 --- a/target/i386/kvm/trace-events +++ b/target/i386/kvm/trace-events @@ -6,6 +6,7 @@ kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d" kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d" kvm_x86_update_msi_routes(int num) "Updated %d MSI routes" kvm_hc_map_gpa_range(uint64_t gpa, uint64_t size, uint64_t attributes, uint64_t flags) "gpa 0x%" PRIx64 " size 0x%" PRIx64 " attributes 0x%" PRIx64 " flags 0x%" PRIx64 +kvm_arch_vmfd_change_ops(void) "" # xen-emu.c kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64 -- 2.42.0
