KVM: SVM: Add AP_JUMP_TABLE support in prep for AP booting
authorTom Lendacky <thomas.lendacky@amd.com>
Tue, 15 Dec 2020 17:44:07 +0000 (12:44 -0500)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 15 Dec 2020 17:47:53 +0000 (12:47 -0500)
The GHCB specification requires the hypervisor to save the address of an
AP Jump Table so that, for example, vCPUs that have been parked by UEFI
can be started by the OS. Provide support for the AP Jump Table set/get
exit code.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.h

index 6eb0977..8b5ef0f 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/trace_events.h>
 #include <asm/fpu/internal.h>
 
+#include <asm/trapnr.h>
+
 #include "x86.h"
 #include "svm.h"
 #include "cpuid.h"
@@ -1559,6 +1561,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
                        goto vmgexit_err;
                break;
        case SVM_VMGEXIT_NMI_COMPLETE:
+       case SVM_VMGEXIT_AP_JUMP_TABLE:
        case SVM_VMGEXIT_UNSUPPORTED_EVENT:
                break;
        default:
@@ -1883,6 +1886,31 @@ int sev_handle_vmgexit(struct vcpu_svm *svm)
        case SVM_VMGEXIT_NMI_COMPLETE:
                ret = svm_invoke_exit_handler(svm, SVM_EXIT_IRET);
                break;
+       case SVM_VMGEXIT_AP_JUMP_TABLE: {
+               struct kvm_sev_info *sev = &to_kvm_svm(svm->vcpu.kvm)->sev_info;
+
+               switch (control->exit_info_1) {
+               case 0:
+                       /* Set AP jump table address */
+                       sev->ap_jump_table = control->exit_info_2;
+                       break;
+               case 1:
+                       /* Get AP jump table address */
+                       ghcb_set_sw_exit_info_2(ghcb, sev->ap_jump_table);
+                       break;
+               default:
+                       pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n",
+                              control->exit_info_1);
+                       ghcb_set_sw_exit_info_1(ghcb, 1);
+                       ghcb_set_sw_exit_info_2(ghcb,
+                                               X86_TRAP_UD |
+                                               SVM_EVTINJ_TYPE_EXEPT |
+                                               SVM_EVTINJ_VALID);
+               }
+
+               ret = 1;
+               break;
+       }
        case SVM_VMGEXIT_UNSUPPORTED_EVENT:
                vcpu_unimpl(&svm->vcpu,
                            "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n",
index a5067f7..5431e63 100644 (file)
@@ -78,6 +78,7 @@ struct kvm_sev_info {
        int fd;                 /* SEV device fd */
        unsigned long pages_locked; /* Number of pages locked */
        struct list_head regions_list;  /* List of registered regions */
+       u64 ap_jump_table;      /* SEV-ES AP Jump Table address */
 };
 
 struct kvm_svm {