Skip to content

Commit c01c55a

Browse files
Paul Durrantsean-jc
authored andcommitted
KVM: x86/xen: separate initialization of shared_info cache and content
A subsequent patch will allow shared_info to be initialized using either a GPA or a user-space (i.e. VMM) HVA. To make that patch cleaner, separate the initialization of the shared_info content from the activation of the pfncache. Signed-off-by: Paul Durrant <pdurrant@amazon.com> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> Link: https://lore.kernel.org/r/20240215152916.1158-11-paul@xen.org Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 721f5b0 commit c01c55a

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

arch/x86/kvm/xen.c

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,41 +34,32 @@ static bool kvm_xen_hcall_evtchn_send(struct kvm_vcpu *vcpu, u64 param, u64 *r);
3434

3535
DEFINE_STATIC_KEY_DEFERRED_FALSE(kvm_xen_enabled, HZ);
3636

37-
static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
37+
static int kvm_xen_shared_info_init(struct kvm *kvm)
3838
{
3939
struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
4040
struct pvclock_wall_clock *wc;
41-
gpa_t gpa = gfn_to_gpa(gfn);
4241
u32 *wc_sec_hi;
4342
u32 wc_version;
4443
u64 wall_nsec;
4544
int ret = 0;
4645
int idx = srcu_read_lock(&kvm->srcu);
4746

48-
if (gfn == KVM_XEN_INVALID_GFN) {
49-
kvm_gpc_deactivate(gpc);
50-
goto out;
51-
}
47+
read_lock_irq(&gpc->lock);
48+
while (!kvm_gpc_check(gpc, PAGE_SIZE)) {
49+
read_unlock_irq(&gpc->lock);
5250

53-
do {
54-
ret = kvm_gpc_activate(gpc, gpa, PAGE_SIZE);
51+
ret = kvm_gpc_refresh(gpc, PAGE_SIZE);
5552
if (ret)
5653
goto out;
5754

58-
/*
59-
* This code mirrors kvm_write_wall_clock() except that it writes
60-
* directly through the pfn cache and doesn't mark the page dirty.
61-
*/
62-
wall_nsec = kvm_get_wall_clock_epoch(kvm);
63-
64-
/* It could be invalid again already, so we need to check */
6555
read_lock_irq(&gpc->lock);
56+
}
6657

67-
if (gpc->valid)
68-
break;
69-
70-
read_unlock_irq(&gpc->lock);
71-
} while (1);
58+
/*
59+
* This code mirrors kvm_write_wall_clock() except that it writes
60+
* directly through the pfn cache and doesn't mark the page dirty.
61+
*/
62+
wall_nsec = kvm_get_wall_clock_epoch(kvm);
7263

7364
/* Paranoia checks on the 32-bit struct layout */
7465
BUILD_BUG_ON(offsetof(struct compat_shared_info, wc) != 0x900);
@@ -639,12 +630,30 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
639630
}
640631
break;
641632

642-
case KVM_XEN_ATTR_TYPE_SHARED_INFO:
633+
case KVM_XEN_ATTR_TYPE_SHARED_INFO: {
634+
int idx;
635+
643636
mutex_lock(&kvm->arch.xen.xen_lock);
644-
r = kvm_xen_shared_info_init(kvm, data->u.shared_info.gfn);
637+
638+
idx = srcu_read_lock(&kvm->srcu);
639+
640+
if (data->u.shared_info.gfn == KVM_XEN_INVALID_GFN) {
641+
kvm_gpc_deactivate(&kvm->arch.xen.shinfo_cache);
642+
r = 0;
643+
} else {
644+
r = kvm_gpc_activate(&kvm->arch.xen.shinfo_cache,
645+
gfn_to_gpa(data->u.shared_info.gfn),
646+
PAGE_SIZE);
647+
}
648+
649+
srcu_read_unlock(&kvm->srcu, idx);
650+
651+
if (!r && kvm->arch.xen.shinfo_cache.active)
652+
r = kvm_xen_shared_info_init(kvm);
653+
645654
mutex_unlock(&kvm->arch.xen.xen_lock);
646655
break;
647-
656+
}
648657
case KVM_XEN_ATTR_TYPE_UPCALL_VECTOR:
649658
if (data->u.vector && data->u.vector < 0x10)
650659
r = -EINVAL;

0 commit comments

Comments
 (0)