Skip to content

Commit 3991f35

Browse files
Paul Durrantsean-jc
authored andcommitted
KVM: x86/xen: allow vcpu_info to be mapped by fixed HVA
If the guest does not explicitly set the GPA of vcpu_info structure in memory then, for guests with 32 vCPUs or fewer, the vcpu_info embedded in the shared_info page may be used. As described in a previous commit, the shared_info page is an overlay at a fixed HVA within the VMM, so in this case it also more optimal to activate the vcpu_info cache with a fixed HVA to avoid unnecessary invalidation if the guest memory layout is modified. Signed-off-by: Paul Durrant <pdurrant@amazon.com> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> Link: https://lore.kernel.org/r/20240215152916.1158-14-paul@xen.org [sean: use kvm_gpc_is_{gpa,hva}_active()] Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent b9220d3 commit 3991f35

File tree

3 files changed

+52
-12
lines changed

3 files changed

+52
-12
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5523,11 +5523,12 @@ KVM_XEN_ATTR_TYPE_SHARED_INFO
55235523
Sets the guest physical frame number at which the Xen shared_info
55245524
page resides. Note that although Xen places vcpu_info for the first
55255525
32 vCPUs in the shared_info page, KVM does not automatically do so
5526-
and instead requires that KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO be used
5527-
explicitly even when the vcpu_info for a given vCPU resides at the
5528-
"default" location in the shared_info page. This is because KVM may
5529-
not be aware of the Xen CPU id which is used as the index into the
5530-
vcpu_info[] array, so may know the correct default location.
5526+
and instead requires that KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO or
5527+
KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA be used explicitly even when
5528+
the vcpu_info for a given vCPU resides at the "default" location
5529+
in the shared_info page. This is because KVM may not be aware of
5530+
the Xen CPU id which is used as the index into the vcpu_info[]
5531+
array, so may know the correct default location.
55315532

55325533
Note that the shared_info page may be constantly written to by KVM;
55335534
it contains the event channel bitmap used to deliver interrupts to
@@ -5649,6 +5650,21 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO
56495650
on dirty logging. Setting the gpa to KVM_XEN_INVALID_GPA will disable
56505651
the vcpu_info.
56515652

5653+
KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA
5654+
If the KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA flag is also set in the
5655+
Xen capabilities, then this attribute may be used to set the
5656+
userspace address of the vcpu_info for a given vCPU. It should
5657+
only be used when the vcpu_info resides at the "default" location
5658+
in the shared_info page. In this case it is safe to assume the
5659+
userspace address will not change, because the shared_info page is
5660+
an overlay on guest memory and remains at a fixed host address
5661+
regardless of where it is mapped in guest physical address space
5662+
and hence unnecessary invalidation of an internal cache may be
5663+
avoided if the guest memory layout is modified.
5664+
If the vcpu_info does not reside at the "default" location then
5665+
it is not guaranteed to remain at the same host address and
5666+
hence the aforementioned cache invalidation is required.
5667+
56525668
KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO
56535669
Sets the guest physical address of an additional pvclock structure
56545670
for a given vCPU. This is typically used for guest vsyscall support.

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ struct kvm_xen_vcpu_attr {
622622
union {
623623
__u64 gpa;
624624
#define KVM_XEN_INVALID_GPA ((__u64)-1)
625+
__u64 hva;
625626
__u64 pad[8];
626627
struct {
627628
__u64 state;
@@ -652,6 +653,8 @@ struct kvm_xen_vcpu_attr {
652653
#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID 0x6
653654
#define KVM_XEN_VCPU_ATTR_TYPE_TIMER 0x7
654655
#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR 0x8
656+
/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */
657+
#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA 0x9
655658

656659
/* Secure Encrypted Virtualization command */
657660
enum sev_cmd_id {

arch/x86/kvm/xen.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -782,20 +782,33 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
782782

783783
switch (data->type) {
784784
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO:
785+
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA:
785786
/* No compat necessary here. */
786787
BUILD_BUG_ON(sizeof(struct vcpu_info) !=
787788
sizeof(struct compat_vcpu_info));
788789
BUILD_BUG_ON(offsetof(struct vcpu_info, time) !=
789790
offsetof(struct compat_vcpu_info, time));
790791

791-
if (data->u.gpa == KVM_XEN_INVALID_GPA) {
792-
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache);
793-
r = 0;
794-
break;
792+
if (data->type == KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO) {
793+
if (data->u.gpa == KVM_XEN_INVALID_GPA) {
794+
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache);
795+
r = 0;
796+
break;
797+
}
798+
799+
r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_info_cache,
800+
data->u.gpa, sizeof(struct vcpu_info));
801+
} else {
802+
if (data->u.hva == 0) {
803+
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache);
804+
r = 0;
805+
break;
806+
}
807+
808+
r = kvm_gpc_activate_hva(&vcpu->arch.xen.vcpu_info_cache,
809+
data->u.hva, sizeof(struct vcpu_info));
795810
}
796811

797-
r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_info_cache,
798-
data->u.gpa, sizeof(struct vcpu_info));
799812
if (!r)
800813
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
801814

@@ -1017,13 +1030,21 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
10171030

10181031
switch (data->type) {
10191032
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO:
1020-
if (vcpu->arch.xen.vcpu_info_cache.active)
1033+
if (kvm_gpc_is_gpa_active(&vcpu->arch.xen.vcpu_info_cache))
10211034
data->u.gpa = vcpu->arch.xen.vcpu_info_cache.gpa;
10221035
else
10231036
data->u.gpa = KVM_XEN_INVALID_GPA;
10241037
r = 0;
10251038
break;
10261039

1040+
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA:
1041+
if (kvm_gpc_is_hva_active(&vcpu->arch.xen.vcpu_info_cache))
1042+
data->u.hva = vcpu->arch.xen.vcpu_info_cache.uhva;
1043+
else
1044+
data->u.hva = 0;
1045+
r = 0;
1046+
break;
1047+
10271048
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
10281049
if (vcpu->arch.xen.vcpu_time_info_cache.active)
10291050
data->u.gpa = vcpu->arch.xen.vcpu_time_info_cache.gpa;

0 commit comments

Comments
 (0)