Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: TDX: Exit to userspace for GetTdVmCallInfo

Exit to userspace for TDG.VP.VMCALL<GetTdVmCallInfo> via KVM_EXIT_TDX,
to allow userspace to provide information about the support of
TDVMCALLs when r12 is 1 for the TDVMCALLs beyond the GHCI base API.

GHCI spec defines the GHCI base TDVMCALLs: <GetTdVmCallInfo>, <MapGPA>,
<ReportFatalError>, <Instruction.CPUID>, <#VE.RequestMMIO>,
<Instruction.HLT>, <Instruction.IO>, <Instruction.RDMSR> and
<Instruction.WRMSR>. They must be supported by VMM to support TDX guests.

For GetTdVmCallInfo
- When leaf (r12) to enumerate TDVMCALL functionality is set to 0,
successful execution indicates all GHCI base TDVMCALLs listed above are
supported.

Update the KVM TDX document with the set of the GHCI base APIs.

- When leaf (r12) to enumerate TDVMCALL functionality is set to 1, it
indicates the TDX guest is querying the supported TDVMCALLs beyond
the GHCI base TDVMCALLs.
Exit to userspace to let userspace set the TDVMCALL sub-function bit(s)
accordingly to the leaf outputs. KVM could set the TDVMCALL bit(s)
supported by itself when the TDVMCALLs don't need support from userspace
after returning from userspace and before entering guest. Currently, no
such TDVMCALLs implemented, KVM just sets the values returned from
userspace.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
[Adjust userspace API. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Binbin Wu and committed by
Paolo Bonzini
25e8b1dd cf207eac

+54 -4
+10
Documentation/virt/kvm/api.rst
··· 7191 7191 u64 gpa; 7192 7192 u64 size; 7193 7193 } get_quote; 7194 + struct { 7195 + u64 ret; 7196 + u64 leaf; 7197 + u64 r11, r12, r13, r14; 7198 + } get_tdvmcall_info; 7194 7199 }; 7195 7200 } tdx; 7196 7201 ··· 7220 7215 queued successfully, the TDX guest can poll the status field in the 7221 7216 shared-memory area to check whether the Quote generation is completed or 7222 7217 not. When completed, the generated Quote is returned via the same buffer. 7218 + 7219 + * ``TDVMCALL_GET_TD_VM_CALL_INFO``: the guest has requested the support 7220 + status of TDVMCALLs. The output values for the given leaf should be 7221 + placed in fields from ``r11`` to ``r14`` of the ``get_tdvmcall_info`` 7222 + field of the union. 7223 7223 7224 7224 KVM may add support for more values in the future that may cause a userspace 7225 7225 exit, even without calls to ``KVM_ENABLE_CAP`` or similar. In this case,
+39 -4
arch/x86/kvm/vmx/tdx.c
··· 1451 1451 return 1; 1452 1452 } 1453 1453 1454 + static int tdx_complete_get_td_vm_call_info(struct kvm_vcpu *vcpu) 1455 + { 1456 + struct vcpu_tdx *tdx = to_tdx(vcpu); 1457 + 1458 + tdvmcall_set_return_code(vcpu, vcpu->run->tdx.get_tdvmcall_info.ret); 1459 + 1460 + /* 1461 + * For now, there is no TDVMCALL beyond GHCI base API supported by KVM 1462 + * directly without the support from userspace, just set the value 1463 + * returned from userspace. 1464 + */ 1465 + tdx->vp_enter_args.r11 = vcpu->run->tdx.get_tdvmcall_info.r11; 1466 + tdx->vp_enter_args.r12 = vcpu->run->tdx.get_tdvmcall_info.r12; 1467 + tdx->vp_enter_args.r13 = vcpu->run->tdx.get_tdvmcall_info.r13; 1468 + tdx->vp_enter_args.r14 = vcpu->run->tdx.get_tdvmcall_info.r14; 1469 + 1470 + return 1; 1471 + } 1472 + 1454 1473 static int tdx_get_td_vm_call_info(struct kvm_vcpu *vcpu) 1455 1474 { 1456 1475 struct vcpu_tdx *tdx = to_tdx(vcpu); 1457 1476 1458 - if (tdx->vp_enter_args.r12) 1459 - tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); 1460 - else { 1477 + switch (tdx->vp_enter_args.r12) { 1478 + case 0: 1461 1479 tdx->vp_enter_args.r11 = 0; 1480 + tdx->vp_enter_args.r12 = 0; 1462 1481 tdx->vp_enter_args.r13 = 0; 1463 1482 tdx->vp_enter_args.r14 = 0; 1483 + tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_SUCCESS); 1484 + return 1; 1485 + case 1: 1486 + vcpu->run->tdx.get_tdvmcall_info.leaf = tdx->vp_enter_args.r12; 1487 + vcpu->run->exit_reason = KVM_EXIT_TDX; 1488 + vcpu->run->tdx.flags = 0; 1489 + vcpu->run->tdx.nr = TDVMCALL_GET_TD_VM_CALL_INFO; 1490 + vcpu->run->tdx.get_tdvmcall_info.ret = TDVMCALL_STATUS_SUCCESS; 1491 + vcpu->run->tdx.get_tdvmcall_info.r11 = 0; 1492 + vcpu->run->tdx.get_tdvmcall_info.r12 = 0; 1493 + vcpu->run->tdx.get_tdvmcall_info.r13 = 0; 1494 + vcpu->run->tdx.get_tdvmcall_info.r14 = 0; 1495 + vcpu->arch.complete_userspace_io = tdx_complete_get_td_vm_call_info; 1496 + return 0; 1497 + default: 1498 + tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); 1499 + return 1; 1464 1500 } 1465 - return 1; 1466 1501 } 1467 1502 1468 1503 static int tdx_complete_simple(struct kvm_vcpu *vcpu)
+5
include/uapi/linux/kvm.h
··· 462 462 __u64 gpa; 463 463 __u64 size; 464 464 } get_quote; 465 + struct { 466 + __u64 ret; 467 + __u64 leaf; 468 + __u64 r11, r12, r13, r14; 469 + } get_tdvmcall_info; 465 470 }; 466 471 } tdx; 467 472 /* Fix the size of the union. */