]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
viridian: introduce struct viridian_page
authorPaul Durrant <paul.durrant@citrix.com>
Fri, 9 Nov 2018 10:40:12 +0000 (11:40 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 9 Nov 2018 10:40:12 +0000 (11:40 +0100)
The 'vp_assist' page is currently an example of a guest page which needs to
be kept mapped throughout the life-time of a guest, but there are other
such examples in the specifiction [1]. This patch therefore introduces a
generic 'viridian_page' type and converts the current vp_assist/apic_assist
related code to use it. Subsequent patches implementing other enlightments
can then also make use of it.

This patch also renames the 'vp_assist_pending' field in struct
hvm_viridian_vcpu_context to 'apic_assist_pending' to more accurately
reflect its meaning. The term 'vp_assist' applies to the whole page rather
than just the EOI-avoidance enlightenment. New versons of the specification
have defined data structures for other enlightenments within the same page.

No functional change.

[1] https://github.com/MicrosoftDocs/Virtualization-Documentation/raw/live/tlfs/Hypervisor%20Top%20Level%20Functional%20Specification%20v5.0C.pdf

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monne <roger.pau@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
tools/misc/xen-hvmctx.c
xen/arch/x86/hvm/viridian/private.h
xen/arch/x86/hvm/viridian/synic.c
xen/arch/x86/hvm/viridian/viridian.c
xen/include/asm-x86/hvm/viridian.h
xen/include/public/arch-x86/hvm/save.h

index 823aa7d7368de5273f9f7d0dd3bbf4341443e399..4f336a6cea736e8ceba06b8eeb3ac5a6e443bad5 100644 (file)
@@ -370,9 +370,9 @@ static void dump_viridian_vcpu(void)
 {
     HVM_SAVE_TYPE(VIRIDIAN_VCPU) p;
     READ(p);
-    printf("    VIRIDIAN_VCPU: vp_assist_msr 0x%llx, vp_assist_pending %s\n",
+    printf("    VIRIDIAN_VCPU: vp_assist_msr 0x%llx, apic_assist_pending %s\n",
            (unsigned long long) p.vp_assist_msr,
-           p.vp_assist_pending ? "true" : "false");
+           p.apic_assist_pending ? "true" : "false");
 }
 
 static void dump_vmce_vcpu(void)
index a5e06f98660819a0a2bfde22b376f75d8173ff91..398b22f12d965dfe3f6607dada414ce4787752bb 100644 (file)
@@ -87,6 +87,11 @@ void viridian_time_save_domain_ctxt(
 void viridian_time_load_domain_ctxt(
     struct domain *d, const struct hvm_viridian_domain_context *ctxt);
 
+void viridian_dump_guest_page(const struct vcpu *v, const char *name,
+                              const struct viridian_page *vp);
+void viridian_map_guest_page(struct vcpu *v, struct viridian_page *vp);
+void viridian_unmap_guest_page(struct viridian_page *vp);
+
 #endif /* X86_HVM_VIRIDIAN_PRIVATE_H */
 
 /*
index d8d6f6e1c99ff69f2e515d495217632161e50fce..845029b5682f772b568f9e718ccc531106d1a8f4 100644 (file)
@@ -22,73 +22,11 @@ typedef struct _HV_VIRTUAL_APIC_ASSIST
     uint32_t reserved_zero:31;
 } HV_VIRTUAL_APIC_ASSIST;
 
-union _HV_VP_ASSIST_PAGE
+typedef union _HV_VP_ASSIST_PAGE
 {
     HV_VIRTUAL_APIC_ASSIST ApicAssist;
     uint8_t ReservedZBytePadding[PAGE_SIZE];
-};
-
-static void dump_vp_assist(const struct vcpu *v)
-{
-    const union viridian_page_msr *va = &v->arch.hvm.viridian.vp_assist.msr;
-
-    if ( !va->fields.enabled )
-        return;
-
-    printk(XENLOG_G_INFO "%pv: VIRIDIAN VP_ASSIST_PAGE: pfn: %lx\n",
-           v, (unsigned long)va->fields.pfn);
-}
-
-static void initialize_vp_assist(struct vcpu *v)
-{
-    struct domain *d = v->domain;
-    unsigned long gmfn = v->arch.hvm.viridian.vp_assist.msr.fields.pfn;
-    struct page_info *page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
-    HV_VP_ASSIST_PAGE *ptr;
-
-    ASSERT(!v->arch.hvm.viridian.vp_assist.ptr);
-
-    if ( !page )
-        goto fail;
-
-    if ( !get_page_type(page, PGT_writable_page) )
-    {
-        put_page(page);
-        goto fail;
-    }
-
-    ptr = __map_domain_page_global(page);
-    if ( !ptr )
-    {
-        put_page_and_type(page);
-        goto fail;
-    }
-
-    clear_page(ptr);
-
-    v->arch.hvm.viridian.vp_assist.ptr = ptr;
-    return;
-
- fail:
-    gdprintk(XENLOG_WARNING, "Bad GMFN %#"PRI_gfn" (MFN %#"PRI_mfn")\n",
-             gmfn, mfn_x(page ? page_to_mfn(page) : INVALID_MFN));
-}
-
-static void teardown_vp_assist(struct vcpu *v)
-{
-    HV_VP_ASSIST_PAGE *ptr = v->arch.hvm.viridian.vp_assist.ptr;
-    struct page_info *page;
-
-    if ( !ptr )
-        return;
-
-    v->arch.hvm.viridian.vp_assist.ptr = NULL;
-
-    page = mfn_to_page(domain_page_map_to_mfn(ptr));
-
-    unmap_domain_page_global(ptr);
-    put_page_and_type(page);
-}
+} HV_VP_ASSIST_PAGE;
 
 void viridian_apic_assist_set(struct vcpu *v)
 {
@@ -102,10 +40,10 @@ void viridian_apic_assist_set(struct vcpu *v)
      * wrong and the VM will most likely hang so force a crash now
      * to make the problem clear.
      */
-    if ( v->arch.hvm.viridian.vp_assist.pending )
+    if ( v->arch.hvm.viridian.apic_assist_pending )
         domain_crash(v->domain);
 
-    v->arch.hvm.viridian.vp_assist.pending = true;
+    v->arch.hvm.viridian.apic_assist_pending = true;
     ptr->ApicAssist.no_eoi = 1;
 }
 
@@ -116,11 +54,11 @@ bool viridian_apic_assist_completed(struct vcpu *v)
     if ( !ptr )
         return false;
 
-    if ( v->arch.hvm.viridian.vp_assist.pending &&
+    if ( v->arch.hvm.viridian.apic_assist_pending &&
          !ptr->ApicAssist.no_eoi )
     {
         /* An EOI has been avoided */
-        v->arch.hvm.viridian.vp_assist.pending = false;
+        v->arch.hvm.viridian.apic_assist_pending = false;
         return true;
     }
 
@@ -135,7 +73,7 @@ void viridian_apic_assist_clear(struct vcpu *v)
         return;
 
     ptr->ApicAssist.no_eoi = 0;
-    v->arch.hvm.viridian.vp_assist.pending = false;
+    v->arch.hvm.viridian.apic_assist_pending = false;
 }
 
 int viridian_synic_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val)
@@ -161,11 +99,13 @@ int viridian_synic_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val)
         break;
 
     case HV_X64_MSR_VP_ASSIST_PAGE:
-        teardown_vp_assist(v); /* release any previous mapping */
+        /* release any previous mapping */
+        viridian_unmap_guest_page(&v->arch.hvm.viridian.vp_assist);
         v->arch.hvm.viridian.vp_assist.msr.raw = val;
-        dump_vp_assist(v);
+        viridian_dump_guest_page(v, "VP_ASSIST",
+                                 &v->arch.hvm.viridian.vp_assist);
         if ( v->arch.hvm.viridian.vp_assist.msr.fields.enabled )
-            initialize_vp_assist(v);
+            viridian_map_guest_page(v, &v->arch.hvm.viridian.vp_assist);
         break;
 
     default:
@@ -211,7 +151,7 @@ int viridian_synic_rdmsr(const struct vcpu *v, uint32_t idx, uint64_t *val)
 void viridian_synic_save_vcpu_ctxt(const struct vcpu *v,
                                    struct hvm_viridian_vcpu_context *ctxt)
 {
-    ctxt->vp_assist_pending = v->arch.hvm.viridian.vp_assist.pending;
+    ctxt->apic_assist_pending = v->arch.hvm.viridian.apic_assist_pending;
     ctxt->vp_assist_msr = v->arch.hvm.viridian.vp_assist.msr.raw;
 }
 
@@ -220,9 +160,9 @@ void viridian_synic_load_vcpu_ctxt(
 {
     v->arch.hvm.viridian.vp_assist.msr.raw = ctxt->vp_assist_msr;
     if ( v->arch.hvm.viridian.vp_assist.msr.fields.enabled )
-        initialize_vp_assist(v);
+        viridian_map_guest_page(v, &v->arch.hvm.viridian.vp_assist);
 
-    v->arch.hvm.viridian.vp_assist.pending = !!ctxt->vp_assist_pending;
+    v->arch.hvm.viridian.apic_assist_pending = ctxt->apic_assist_pending;
 }
 
 /*
index 8630bc7bb695833e65a39c702e49034be7bfede0..7d73f41de623c82ace8874032741d37cb98a3342 100644 (file)
@@ -588,6 +588,63 @@ out:
     return HVM_HCALL_completed;
 }
 
+void viridian_dump_guest_page(const struct vcpu *v, const char *name,
+                              const struct viridian_page *vp)
+{
+    if ( !vp->msr.fields.enabled )
+        return;
+
+    printk(XENLOG_G_INFO "%pv: VIRIDIAN %s: pfn: %lx\n",
+           v, name, (unsigned long)vp->msr.fields.pfn);
+}
+
+void viridian_map_guest_page(struct vcpu *v, struct viridian_page *vp)
+{
+    struct domain *d = v->domain;
+    unsigned long gmfn = vp->msr.fields.pfn;
+    struct page_info *page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
+
+    ASSERT(!vp->ptr);
+
+    if ( !page )
+        goto fail;
+
+    if ( !get_page_type(page, PGT_writable_page) )
+    {
+        put_page(page);
+        goto fail;
+    }
+
+    vp->ptr = __map_domain_page_global(page);
+    if ( !vp->ptr )
+    {
+        put_page_and_type(page);
+        goto fail;
+    }
+
+    clear_page(vp->ptr);
+    return;
+
+ fail:
+    gdprintk(XENLOG_WARNING, "Bad GMFN %#"PRI_gfn" (MFN %#"PRI_mfn")\n",
+             gmfn, mfn_x(page ? page_to_mfn(page) : INVALID_MFN));
+}
+
+void viridian_unmap_guest_page(struct viridian_page *vp)
+{
+    struct page_info *page;
+
+    if ( !vp->ptr )
+        return;
+
+    page = mfn_to_page(domain_page_map_to_mfn(vp->ptr));
+
+    unmap_domain_page_global(vp->ptr);
+    vp->ptr = NULL;
+
+    put_page_and_type(page);
+}
+
 static int viridian_save_domain_ctxt(struct vcpu *v,
                                      hvm_domain_context_t *h)
 {
index 22f14a526ebea9f9e6a49a975f55c0b3dc9dbc8c..ec5ef8d3f94c4542b55ef6399cb3eeb8786dfbfa 100644 (file)
@@ -20,15 +20,16 @@ union viridian_page_msr
     } fields;
 };
 
-typedef union _HV_VP_ASSIST_PAGE HV_VP_ASSIST_PAGE;
+struct viridian_page
+{
+    union viridian_page_msr msr;
+    void *ptr;
+};
 
 struct viridian_vcpu
 {
-    struct {
-        union viridian_page_msr msr;
-        HV_VP_ASSIST_PAGE *ptr;
-        bool pending;
-    } vp_assist;
+    struct viridian_page vp_assist;
+    bool apic_assist_pending;
     uint64_t crash_param[5];
 };
 
index 4691d4d4aa66afa97ea3e781f85aa5323a3f3a4f..80e762c3353ec4217c3dc45cf96467ff307e3258 100644 (file)
@@ -600,7 +600,7 @@ DECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context);
 
 struct hvm_viridian_vcpu_context {
     uint64_t vp_assist_msr;
-    uint8_t  vp_assist_pending;
+    uint8_t  apic_assist_pending;
     uint8_t  _pad[7];
 };