Skip to content

Commit 5383fc0

Browse files
committed
Merge tag 'kvm-x86-fixes-6.16-rcN' of https://github.com/kvm-x86/linux into HEAD
KVM x86 fixes for 6.16-rcN - Reject SEV{-ES} intra-host migration if one or more vCPUs are actively being created so as not to create a non-SEV{-ES} vCPU in an SEV{-ES} VM. - Use a pre-allocated, per-vCPU buffer for handling de-sparsified vCPU masks when emulating Hyper-V hypercalls to fix a "stack frame too large" issue. - Allow out-of-range/invalid Xen event channel ports when configuring IRQ routing to avoid dictating a specific ioctl() ordering to userspace. - Conditionally reschedule when setting memory attributes to avoid soft lockups when userspace converts huge swaths of memory to/from private. - Add back MWAIT as a required feature for the MONITOR/MWAIT selftest. - Add a missing field in struct sev_data_snp_launch_start that resulted in the guest-visible workarounds field being filled at the wrong offset. - Skip non-canonical address when processing Hyper-V PV TLB flushes to avoid VM-Fail on INVVPID. - Advertise supported TDX TDVMCALLs to userspace.
2 parents 7e7a7bf + fa787ac commit 5383fc0

File tree

13 files changed

+117
-23
lines changed

13 files changed

+117
-23
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7196,6 +7196,10 @@ The valid value for 'flags' is:
71967196
u64 leaf;
71977197
u64 r11, r12, r13, r14;
71987198
} get_tdvmcall_info;
7199+
struct {
7200+
u64 ret;
7201+
u64 vector;
7202+
} setup_event_notify;
71997203
};
72007204
} tdx;
72017205

@@ -7210,21 +7214,24 @@ number from register R11. The remaining field of the union provide the
72107214
inputs and outputs of the TDVMCALL. Currently the following values of
72117215
``nr`` are defined:
72127216

7213-
* ``TDVMCALL_GET_QUOTE``: the guest has requested to generate a TD-Quote
7214-
signed by a service hosting TD-Quoting Enclave operating on the host.
7215-
Parameters and return value are in the ``get_quote`` field of the union.
7216-
The ``gpa`` field and ``size`` specify the guest physical address
7217-
(without the shared bit set) and the size of a shared-memory buffer, in
7218-
which the TDX guest passes a TD Report. The ``ret`` field represents
7219-
the return value of the GetQuote request. When the request has been
7220-
queued successfully, the TDX guest can poll the status field in the
7221-
shared-memory area to check whether the Quote generation is completed or
7222-
not. When completed, the generated Quote is returned via the same buffer.
7223-
7224-
* ``TDVMCALL_GET_TD_VM_CALL_INFO``: the guest has requested the support
7225-
status of TDVMCALLs. The output values for the given leaf should be
7226-
placed in fields from ``r11`` to ``r14`` of the ``get_tdvmcall_info``
7227-
field of the union.
7217+
* ``TDVMCALL_GET_QUOTE``: the guest has requested to generate a TD-Quote
7218+
signed by a service hosting TD-Quoting Enclave operating on the host.
7219+
Parameters and return value are in the ``get_quote`` field of the union.
7220+
The ``gpa`` field and ``size`` specify the guest physical address
7221+
(without the shared bit set) and the size of a shared-memory buffer, in
7222+
which the TDX guest passes a TD Report. The ``ret`` field represents
7223+
the return value of the GetQuote request. When the request has been
7224+
queued successfully, the TDX guest can poll the status field in the
7225+
shared-memory area to check whether the Quote generation is completed or
7226+
not. When completed, the generated Quote is returned via the same buffer.
7227+
7228+
* ``TDVMCALL_GET_TD_VM_CALL_INFO``: the guest has requested the support
7229+
status of TDVMCALLs. The output values for the given leaf should be
7230+
placed in fields from ``r11`` to ``r14`` of the ``get_tdvmcall_info``
7231+
field of the union.
7232+
7233+
* ``TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT``: the guest has requested to
7234+
set up a notification interrupt for vector ``vector``.
72287235

72297236
KVM may add support for more values in the future that may cause a userspace
72307237
exit, even without calls to ``KVM_ENABLE_CAP`` or similar. In this case,

Documentation/virt/kvm/x86/intel-tdx.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,20 @@ to be configured to the TDX guest.
7979
struct kvm_tdx_capabilities {
8080
__u64 supported_attrs;
8181
__u64 supported_xfam;
82-
__u64 reserved[254];
82+
83+
/* TDG.VP.VMCALL hypercalls executed in kernel and forwarded to
84+
* userspace, respectively
85+
*/
86+
__u64 kernel_tdvmcallinfo_1_r11;
87+
__u64 user_tdvmcallinfo_1_r11;
88+
89+
/* TDG.VP.VMCALL instruction executions subfunctions executed in kernel
90+
* and forwarded to userspace, respectively
91+
*/
92+
__u64 kernel_tdvmcallinfo_1_r12;
93+
__u64 user_tdvmcallinfo_1_r12;
94+
95+
__u64 reserved[250];
8396

8497
/* Configurable CPUID bits for userspace */
8598
struct kvm_cpuid2 cpuid;

arch/x86/include/asm/kvm_host.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,13 @@ struct kvm_vcpu_hv {
700700

701701
struct kvm_vcpu_hv_tlb_flush_fifo tlb_flush_fifo[HV_NR_TLB_FLUSH_FIFOS];
702702

703-
/* Preallocated buffer for handling hypercalls passing sparse vCPU set */
703+
/*
704+
* Preallocated buffers for handling hypercalls that pass sparse vCPU
705+
* sets (for high vCPU counts, they're too large to comfortably fit on
706+
* the stack).
707+
*/
704708
u64 sparse_banks[HV_MAX_SPARSE_VCPU_BANKS];
709+
DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS);
705710

706711
struct hv_vp_assist_page vp_assist_page;
707712

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#define TDVMCALL_MAP_GPA 0x10001
7373
#define TDVMCALL_GET_QUOTE 0x10002
7474
#define TDVMCALL_REPORT_FATAL_ERROR 0x10003
75+
#define TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT 0x10004ULL
7576

7677
/*
7778
* TDG.VP.VMCALL Status Codes (returned in R10)

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,13 @@ struct kvm_tdx_cmd {
965965
struct kvm_tdx_capabilities {
966966
__u64 supported_attrs;
967967
__u64 supported_xfam;
968-
__u64 reserved[254];
968+
969+
__u64 kernel_tdvmcallinfo_1_r11;
970+
__u64 user_tdvmcallinfo_1_r11;
971+
__u64 kernel_tdvmcallinfo_1_r12;
972+
__u64 user_tdvmcallinfo_1_r12;
973+
974+
__u64 reserved[250];
969975

970976
/* Configurable CPUID bits for userspace */
971977
struct kvm_cpuid2 cpuid;

arch/x86/kvm/hyperv.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1979,6 +1979,9 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
19791979
if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY)
19801980
goto out_flush_all;
19811981

1982+
if (is_noncanonical_invlpg_address(entries[i], vcpu))
1983+
continue;
1984+
19821985
/*
19831986
* Lower 12 bits of 'address' encode the number of additional
19841987
* pages to flush.
@@ -2001,11 +2004,11 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
20012004
static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
20022005
{
20032006
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
2007+
unsigned long *vcpu_mask = hv_vcpu->vcpu_mask;
20042008
u64 *sparse_banks = hv_vcpu->sparse_banks;
20052009
struct kvm *kvm = vcpu->kvm;
20062010
struct hv_tlb_flush_ex flush_ex;
20072011
struct hv_tlb_flush flush;
2008-
DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS);
20092012
struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo;
20102013
/*
20112014
* Normally, there can be no more than 'KVM_HV_TLB_FLUSH_FIFO_SIZE'

arch/x86/kvm/svm/sev.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,6 +1971,10 @@ static int sev_check_source_vcpus(struct kvm *dst, struct kvm *src)
19711971
struct kvm_vcpu *src_vcpu;
19721972
unsigned long i;
19731973

1974+
if (src->created_vcpus != atomic_read(&src->online_vcpus) ||
1975+
dst->created_vcpus != atomic_read(&dst->online_vcpus))
1976+
return -EBUSY;
1977+
19741978
if (!sev_es_guest(src))
19751979
return 0;
19761980

@@ -4445,8 +4449,12 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
44454449
* the VMSA will be NULL if this vCPU is the destination for intrahost
44464450
* migration, and will be copied later.
44474451
*/
4448-
if (svm->sev_es.vmsa && !svm->sev_es.snp_has_guest_vmsa)
4449-
svm->vmcb->control.vmsa_pa = __pa(svm->sev_es.vmsa);
4452+
if (!svm->sev_es.snp_has_guest_vmsa) {
4453+
if (svm->sev_es.vmsa)
4454+
svm->vmcb->control.vmsa_pa = __pa(svm->sev_es.vmsa);
4455+
else
4456+
svm->vmcb->control.vmsa_pa = INVALID_PAGE;
4457+
}
44504458

44514459
if (cpu_feature_enabled(X86_FEATURE_ALLOWED_SEV_FEATURES))
44524460
svm->vmcb->control.allowed_sev_features = sev->vmsa_features |

arch/x86/kvm/vmx/tdx.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ static void td_init_cpuid_entry2(struct kvm_cpuid_entry2 *entry, unsigned char i
173173
tdx_clear_unsupported_cpuid(entry);
174174
}
175175

176+
#define TDVMCALLINFO_GET_QUOTE BIT(0)
177+
#define TDVMCALLINFO_SETUP_EVENT_NOTIFY_INTERRUPT BIT(1)
178+
176179
static int init_kvm_tdx_caps(const struct tdx_sys_info_td_conf *td_conf,
177180
struct kvm_tdx_capabilities *caps)
178181
{
@@ -188,6 +191,10 @@ static int init_kvm_tdx_caps(const struct tdx_sys_info_td_conf *td_conf,
188191

189192
caps->cpuid.nent = td_conf->num_cpuid_config;
190193

194+
caps->user_tdvmcallinfo_1_r11 =
195+
TDVMCALLINFO_GET_QUOTE |
196+
TDVMCALLINFO_SETUP_EVENT_NOTIFY_INTERRUPT;
197+
191198
for (i = 0; i < td_conf->num_cpuid_config; i++)
192199
td_init_cpuid_entry2(&caps->cpuid.entries[i], i);
193200

@@ -1530,6 +1537,27 @@ static int tdx_get_quote(struct kvm_vcpu *vcpu)
15301537
return 0;
15311538
}
15321539

1540+
static int tdx_setup_event_notify_interrupt(struct kvm_vcpu *vcpu)
1541+
{
1542+
struct vcpu_tdx *tdx = to_tdx(vcpu);
1543+
u64 vector = tdx->vp_enter_args.r12;
1544+
1545+
if (vector < 32 || vector > 255) {
1546+
tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND);
1547+
return 1;
1548+
}
1549+
1550+
vcpu->run->exit_reason = KVM_EXIT_TDX;
1551+
vcpu->run->tdx.flags = 0;
1552+
vcpu->run->tdx.nr = TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT;
1553+
vcpu->run->tdx.setup_event_notify.ret = TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED;
1554+
vcpu->run->tdx.setup_event_notify.vector = vector;
1555+
1556+
vcpu->arch.complete_userspace_io = tdx_complete_simple;
1557+
1558+
return 0;
1559+
}
1560+
15331561
static int handle_tdvmcall(struct kvm_vcpu *vcpu)
15341562
{
15351563
switch (tdvmcall_leaf(vcpu)) {
@@ -1541,6 +1569,8 @@ static int handle_tdvmcall(struct kvm_vcpu *vcpu)
15411569
return tdx_get_td_vm_call_info(vcpu);
15421570
case TDVMCALL_GET_QUOTE:
15431571
return tdx_get_quote(vcpu);
1572+
case TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT:
1573+
return tdx_setup_event_notify_interrupt(vcpu);
15441574
default:
15451575
break;
15461576
}

arch/x86/kvm/xen.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,8 +1971,19 @@ int kvm_xen_setup_evtchn(struct kvm *kvm,
19711971
{
19721972
struct kvm_vcpu *vcpu;
19731973

1974-
if (ue->u.xen_evtchn.port >= max_evtchn_port(kvm))
1975-
return -EINVAL;
1974+
/*
1975+
* Don't check for the port being within range of max_evtchn_port().
1976+
* Userspace can configure what ever targets it likes; events just won't
1977+
* be delivered if/while the target is invalid, just like userspace can
1978+
* configure MSIs which target non-existent APICs.
1979+
*
1980+
* This allow on Live Migration and Live Update, the IRQ routing table
1981+
* can be restored *independently* of other things like creating vCPUs,
1982+
* without imposing an ordering dependency on userspace. In this
1983+
* particular case, the problematic ordering would be with setting the
1984+
* Xen 'long mode' flag, which changes max_evtchn_port() to allow 4096
1985+
* instead of 1024 event channels.
1986+
*/
19761987

19771988
/* We only support 2 level event channels for now */
19781989
if (ue->u.xen_evtchn.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL)

include/linux/psp-sev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ struct sev_data_snp_addr {
594594
* @imi_en: launch flow is launching an IMI (Incoming Migration Image) for the
595595
* purpose of guest-assisted migration.
596596
* @rsvd: reserved
597+
* @desired_tsc_khz: hypervisor desired mean TSC freq in kHz of the guest
597598
* @gosvw: guest OS-visible workarounds, as defined by hypervisor
598599
*/
599600
struct sev_data_snp_launch_start {
@@ -603,6 +604,7 @@ struct sev_data_snp_launch_start {
603604
u32 ma_en:1; /* In */
604605
u32 imi_en:1; /* In */
605606
u32 rsvd:30;
607+
u32 desired_tsc_khz; /* In */
606608
u8 gosvw[16]; /* In */
607609
} __packed;
608610

0 commit comments

Comments
 (0)