Skip to content

Commit 4d2dc9a

Browse files
committed
Merge branch 'kvm-tdx-userspace-exit' into HEAD
Introduces support for VM exits that are forwarded the host VMM in userspace. These are initiated from the TDCALL exit code; although these userspace exits have the same TDX exit code, they result in several different types of exits to userspace. When a guest TD issues a TDVMCALL, it exits to VMM with a new exit reason. The arguments from the guest TD and return values from the VMM are passed through the guest registers. The ABI details for the guest TD hypercalls are specified in the TDX GHCI specification. There are two types of hypercalls defined in the GHCI specification: - Standard TDVMCALLs: When input of R10 from guest TD is set to 0, it indicates that the TDVMCALL sub-function used in R11 is defined in GHCI specification. - Vendor-Specific TDVMCALLs: When input of R10 from guest TD is non-zero, it indicates a vendor-specific TDVMCALL. KVM hypercalls from the guest follow this interface, using R10 as KVM hypercall number and R11-R14 as 4 arguments. The error code returned in R10. This series includes basic standard TDVMCALLs that map to existing eixt reasons: - TDG.VP.VMCALL<MapGPA> reuses exit reason KVM_EXIT_HYPERCALL with the hypercall number KVM_HC_MAP_GPA_RANGE. - TDG.VP.VMCALL<ReportFatalError> reuses exit reason KVM_EXIT_SYSTEM_EVENT with a new event type KVM_SYSTEM_EVENT_TDX_FATAL. - TDG.VP.VMCALL<Instruction.IO> reuses exit reason KVM_EXIT_IO. - TDG.VP.VMCALL<#VE.RequestMMIO> reuses exit reason KVM_EXIT_MMIO. Notably, handling for TDG.VP.VMCALL<SetupEventNotifyInterrupt> and TDG.VP.VMCALL<GetQuote> is not included yet.
2 parents 77ab80c + bb723be commit 4d2dc9a

File tree

14 files changed

+611
-35
lines changed

14 files changed

+611
-35
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6823,6 +6823,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
68236823
#define KVM_SYSTEM_EVENT_WAKEUP 4
68246824
#define KVM_SYSTEM_EVENT_SUSPEND 5
68256825
#define KVM_SYSTEM_EVENT_SEV_TERM 6
6826+
#define KVM_SYSTEM_EVENT_TDX_FATAL 7
68266827
__u32 type;
68276828
__u32 ndata;
68286829
__u64 data[16];
@@ -6849,6 +6850,11 @@ Valid values for 'type' are:
68496850
reset/shutdown of the VM.
68506851
- KVM_SYSTEM_EVENT_SEV_TERM -- an AMD SEV guest requested termination.
68516852
The guest physical address of the guest's GHCB is stored in `data[0]`.
6853+
- KVM_SYSTEM_EVENT_TDX_FATAL -- a TDX guest reported a fatal error state.
6854+
KVM doesn't do any parsing or conversion, it just dumps 16 general-purpose
6855+
registers to userspace, in ascending order of the 4-bit indices for x86-64
6856+
general-purpose registers in instruction encoding, as defined in the Intel
6857+
SDM.
68526858
- KVM_SYSTEM_EVENT_WAKEUP -- the exiting vCPU is in a suspended state and
68536859
KVM has recognized a wakeup event. Userspace may honor this event by
68546860
marking the exiting vCPU as runnable, or deny it and call KVM_RUN again.

arch/x86/include/asm/shared/tdx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#define TDVMCALL_STATUS_SUCCESS 0x0000000000000000ULL
7878
#define TDVMCALL_STATUS_RETRY 0x0000000000000001ULL
7979
#define TDVMCALL_STATUS_INVALID_OPERAND 0x8000000000000000ULL
80+
#define TDVMCALL_STATUS_ALIGN_ERROR 0x8000000000000002ULL
8081

8182
/*
8283
* Bitmasks of exposed registers (with VMM).

arch/x86/include/asm/tdx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* TDX module.
2020
*/
2121
#define TDX_ERROR _BITUL(63)
22+
#define TDX_NON_RECOVERABLE _BITUL(62)
2223
#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40))
2324
#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _UL(0xFFFF0000))
2425

arch/x86/include/uapi/asm/vmx.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#define EXIT_REASON_TPAUSE 68
9393
#define EXIT_REASON_BUS_LOCK 74
9494
#define EXIT_REASON_NOTIFY 75
95+
#define EXIT_REASON_TDCALL 77
9596

9697
#define VMX_EXIT_REASONS \
9798
{ EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
@@ -155,7 +156,8 @@
155156
{ EXIT_REASON_UMWAIT, "UMWAIT" }, \
156157
{ EXIT_REASON_TPAUSE, "TPAUSE" }, \
157158
{ EXIT_REASON_BUS_LOCK, "BUS_LOCK" }, \
158-
{ EXIT_REASON_NOTIFY, "NOTIFY" }
159+
{ EXIT_REASON_NOTIFY, "NOTIFY" }, \
160+
{ EXIT_REASON_TDCALL, "TDCALL" }
159161

160162
#define VMX_EXIT_REASON_FLAGS \
161163
{ VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" }

arch/x86/kvm/vmx/main.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,15 @@ static fastpath_t vt_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
181181
return vmx_vcpu_run(vcpu, force_immediate_exit);
182182
}
183183

184+
static int vt_handle_exit(struct kvm_vcpu *vcpu,
185+
enum exit_fastpath_completion fastpath)
186+
{
187+
if (is_td_vcpu(vcpu))
188+
return tdx_handle_exit(vcpu, fastpath);
189+
190+
return vmx_handle_exit(vcpu, fastpath);
191+
}
192+
184193
static void vt_flush_tlb_all(struct kvm_vcpu *vcpu)
185194
{
186195
if (is_td_vcpu(vcpu)) {
@@ -228,6 +237,29 @@ static void vt_load_mmu_pgd(struct kvm_vcpu *vcpu, hpa_t root_hpa,
228237
vmx_load_mmu_pgd(vcpu, root_hpa, pgd_level);
229238
}
230239

240+
static void vt_get_entry_info(struct kvm_vcpu *vcpu, u32 *intr_info, u32 *error_code)
241+
{
242+
*intr_info = 0;
243+
*error_code = 0;
244+
245+
if (is_td_vcpu(vcpu))
246+
return;
247+
248+
vmx_get_entry_info(vcpu, intr_info, error_code);
249+
}
250+
251+
static void vt_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
252+
u64 *info1, u64 *info2, u32 *intr_info, u32 *error_code)
253+
{
254+
if (is_td_vcpu(vcpu)) {
255+
tdx_get_exit_info(vcpu, reason, info1, info2, intr_info,
256+
error_code);
257+
return;
258+
}
259+
260+
vmx_get_exit_info(vcpu, reason, info1, info2, intr_info, error_code);
261+
}
262+
231263
static int vt_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
232264
{
233265
if (!is_td(kvm))
@@ -323,7 +355,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
323355

324356
.vcpu_pre_run = vt_vcpu_pre_run,
325357
.vcpu_run = vt_vcpu_run,
326-
.handle_exit = vmx_handle_exit,
358+
.handle_exit = vt_handle_exit,
327359
.skip_emulated_instruction = vmx_skip_emulated_instruction,
328360
.update_emulated_instruction = vmx_update_emulated_instruction,
329361
.set_interrupt_shadow = vmx_set_interrupt_shadow,
@@ -357,8 +389,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
357389
.set_identity_map_addr = vmx_set_identity_map_addr,
358390
.get_mt_mask = vmx_get_mt_mask,
359391

360-
.get_exit_info = vmx_get_exit_info,
361-
.get_entry_info = vmx_get_entry_info,
392+
.get_exit_info = vt_get_exit_info,
393+
.get_entry_info = vt_get_entry_info,
362394

363395
.vcpu_after_set_cpuid = vmx_vcpu_after_set_cpuid,
364396

0 commit comments

Comments
 (0)