@@ -7179,7 +7179,27 @@ TDX guest passes a TD report. When completed, the generated quote is returned
via the same buffer. The 'ret' field represents the return value. The userspace
should update the return value before resuming the vCPU according to TDX GHCI
spec. It's an asynchronous request. After the TDVMCALL is returned and back to
-TDX guest, TDX guest can poll the status field of the shared-memory area.
+TDX guest, TDX guest can poll the status field of the shared-memory area. Or TDX
+guest can register an event-notify vector by TDVMCALL_SETUP_EVENT_NOTIFY, so
+that on completion, an interrupt can be injected to TDX guest.
+
+::
+
+ /* KVM_EXIT_TDX_SETUP_EVENT_NOTIFY */
+ struct tdx_get_quote {
+ __u64 ret;
+ __u8 vector;
+ };
+
+If the exit reason is KVM_EXIT_TDX_SETUP_EVENT_NOTIFY, then it indicates that a
+TDX guest has requested to specify an interrupt vector used as the event-notify
+vector. E.g., for GetQuote operation, which may take several seconds, if the
+TDX guest has set up the event-notify vector, the host injects an interrupt
+with the specified vector to the guest on the completion of the operation. The
+'vector' field specifies the interrupt vector, with a valid range [32, 255], to
+be used for the event-notify. The 'ret' field represents the return value. The
+userspace should update the return value before resuming the vCPU according
+to TDX GHCI spec.
::
@@ -71,6 +71,7 @@
#define TDVMCALL_MAP_GPA 0x10001
#define TDVMCALL_GET_QUOTE 0x10002
#define TDVMCALL_REPORT_FATAL_ERROR 0x10003
+#define TDVMCALL_SETUP_EVENT_NOTIFY 0x10004
/*
* TDG.VP.VMCALL Status Codes (returned in R10)
@@ -1463,7 +1463,10 @@ static int tdx_get_td_vm_call_info(struct kvm_vcpu *vcpu)
return 1;
}
-static int tdx_complete_get_quote(struct kvm_vcpu *vcpu)
+static_assert(offsetof(struct kvm_run, tdx_setup_event_notify.ret) ==
+ offsetof(struct kvm_run, tdx_get_quote.ret));
+
+static int tdx_complete_tdcall_common(struct kvm_vcpu *vcpu)
{
tdvmcall_set_return_code(vcpu, vcpu->run->tdx_get_quote.ret);
return 1;
@@ -1491,7 +1494,23 @@ static int tdx_get_quote(struct kvm_vcpu *vcpu)
vcpu->run->tdx_get_quote.gpa = gpa;
vcpu->run->tdx_get_quote.size = size;
- vcpu->arch.complete_userspace_io = tdx_complete_get_quote;
+ vcpu->arch.complete_userspace_io = tdx_complete_tdcall_common;
+
+ return 0;
+}
+
+static int tdx_setup_event_notify(struct kvm_vcpu *vcpu)
+{
+ u64 vector = to_tdx(vcpu)->vp_enter_args.r12;
+
+ if (vector < 32 || vector > 255) {
+ tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND);
+ return 1;
+ }
+
+ vcpu->run->exit_reason = KVM_EXIT_TDX_SETUP_EVENT_NOTIFY;
+ vcpu->run->tdx_setup_event_notify.vector = (u8)vector;
+ vcpu->arch.complete_userspace_io = tdx_complete_tdcall_common;
return 0;
}
@@ -1507,6 +1526,8 @@ static int handle_tdvmcall(struct kvm_vcpu *vcpu)
return tdx_get_td_vm_call_info(vcpu);
case TDVMCALL_GET_QUOTE:
return tdx_get_quote(vcpu);
+ case TDVMCALL_SETUP_EVENT_NOTIFY:
+ return tdx_setup_event_notify(vcpu);
default:
break;
}
@@ -179,6 +179,7 @@ struct kvm_xen_exit {
#define KVM_EXIT_LOONGARCH_IOCSR 38
#define KVM_EXIT_MEMORY_FAULT 39
#define KVM_EXIT_TDX_GET_QUOTE 41
+#define KVM_EXIT_TDX_SETUP_EVENT_NOTIFY 42
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -454,6 +455,11 @@ struct kvm_run {
__u64 gpa;
__u64 size;
} tdx_get_quote;
+ /* KVM_EXIT_TDX_SETUP_EVENT_NOTIFY */
+ struct {
+ __u64 ret;
+ __u8 vector;
+ } tdx_setup_event_notify;
/* Fix the size of the union. */
char padding[256];
};
Handle TDVMCALL for SetupEventNotifyInterrupt to set up an event-notify vector. TDX guests can make a request to host VMMs to specify which interrupt vector to use as an event-notify vector. E.g., for GetQuote operation, which may take several seconds, if a TDX guest has set up the event-notify vector, the host VMM can inject an interrupt with the specified vector to the TDX guest on the completion of the operation. KVM itself doesn't use this mechanism. Add KVM_EXIT_TDX_SETUP_EVENT_NOTIFY as a new exit reason to userspace to forward the request to userspace VMM (e.g., QEMU) after sanity checks, so that userspace can inject an interrupt with the event-notify vector to the TDX guest when the operation completes. Since there is nothing special for SetupEventNotifyInterrupt beyond setting the return code in the complete_userspace_io() callback, the code reuses the version developed for GetQuote. Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com> --- Documentation/virt/kvm/api.rst | 22 +++++++++++++++++++++- arch/x86/include/asm/shared/tdx.h | 1 + arch/x86/kvm/vmx/tdx.c | 25 +++++++++++++++++++++++-- include/uapi/linux/kvm.h | 6 ++++++ 4 files changed, 51 insertions(+), 3 deletions(-)