]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: x86/xen: Maintain valid mapping of Xen shared_info page
authorDavid Woodhouse <dwmw@amazon.co.uk>
Sat, 30 Oct 2021 18:53:23 +0000 (19:53 +0100)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Wed, 17 Nov 2021 17:15:44 +0000 (17:15 +0000)
Use the newly reinstated gfn_to_pfn_cache to maintain a kernel mapping
of the Xen shared_info page so that it can be accessed in atomic context.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/xen.c

index 6ac61f85e07b9971c40158d0f7d88cde0e3ba55c..4b2b4ecf3b46eed41350c1c8a21f64c2532f68c7 100644 (file)
@@ -1014,7 +1014,7 @@ struct msr_bitmap_range {
 struct kvm_xen {
        bool long_mode;
        u8 upcall_vector;
-       gfn_t shinfo_gfn;
+       struct gfn_to_pfn_cache shinfo_cache;
 };
 
 enum kvm_irqchip_mode {
index dff2bdf9507a8cf679f449b277666df1ccf34773..32a915a4fe2046a785465f6c2d85a4dd78b137a5 100644 (file)
@@ -23,16 +23,21 @@ DEFINE_STATIC_KEY_DEFERRED_FALSE(kvm_xen_enabled, HZ);
 
 static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
 {
+       struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
        gpa_t gpa = gfn_to_gpa(gfn);
        int wc_ofs, sec_hi_ofs;
        int ret = 0;
        int idx = srcu_read_lock(&kvm->srcu);
 
-       if (kvm_is_error_hva(gfn_to_hva(kvm, gfn))) {
-               ret = -EFAULT;
+       if (gfn == GPA_INVALID) {
+               kvm_gfn_to_pfn_cache_destroy(kvm, gpc);
                goto out;
        }
-       kvm->arch.xen.shinfo_gfn = gfn;
+
+       ret = kvm_gfn_to_pfn_cache_init(kvm, gpc, NULL, false, true, gpa,
+                                       PAGE_SIZE, true);
+       if (ret)
+               goto out;
 
        /* Paranoia checks on the 32-bit struct layout */
        BUILD_BUG_ON(offsetof(struct compat_shared_info, wc) != 0x900);
@@ -260,15 +265,9 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
                break;
 
        case KVM_XEN_ATTR_TYPE_SHARED_INFO:
-               if (data->u.shared_info.gfn == GPA_INVALID) {
-                       kvm->arch.xen.shinfo_gfn = GPA_INVALID;
-                       r = 0;
-                       break;
-               }
                r = kvm_xen_shared_info_init(kvm, data->u.shared_info.gfn);
                break;
 
-
        case KVM_XEN_ATTR_TYPE_UPCALL_VECTOR:
                if (data->u.vector && data->u.vector < 0x10)
                        r = -EINVAL;
@@ -299,7 +298,10 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
                break;
 
        case KVM_XEN_ATTR_TYPE_SHARED_INFO:
-               data->u.shared_info.gfn = kvm->arch.xen.shinfo_gfn;
+               if (kvm->arch.xen.shinfo_cache.active)
+                       data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_cache.gpa);
+               else
+                       data->u.shared_info.gfn = GPA_INVALID;
                r = 0;
                break;
 
@@ -661,11 +663,12 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc)
 
 void kvm_xen_init_vm(struct kvm *kvm)
 {
-       kvm->arch.xen.shinfo_gfn = GPA_INVALID;
 }
 
 void kvm_xen_destroy_vm(struct kvm *kvm)
 {
+       kvm_gfn_to_pfn_cache_destroy(kvm, &kvm->arch.xen.shinfo_cache);
+
        if (kvm->arch.xen_hvm_config.msr)
                static_branch_slow_dec_deferred(&kvm_xen_enabled);
 }