[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 5/5] viridian: introduce struct viridian_page



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@xxxxxxxxxx>
Reviewed-by: Roger Pau Monne <roger.pau@xxxxxxxxxx>
Reviewed-by: Wei Liu <wei.liu2@xxxxxxxxxx>
---
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>

v3:
 - Move the typedef of HV_VP_ASSIST_PAGE back into synic.c after re-
   location in eariler patch
 - Move init and teardown functions into viridian.c now that they are more
   generic, and use map/unmap naming to better reflect what they do
 - Drop unnecessary !!
---
 tools/misc/xen-hvmctx.c                |  4 +-
 xen/arch/x86/hvm/viridian/private.h    |  5 ++
 xen/arch/x86/hvm/viridian/synic.c      | 90 ++++++----------------------------
 xen/arch/x86/hvm/viridian/viridian.c   | 57 +++++++++++++++++++++
 xen/include/asm-x86/hvm/viridian.h     | 13 ++---
 xen/include/public/arch-x86/hvm/save.h |  2 +-
 6 files changed, 87 insertions(+), 84 deletions(-)

diff --git a/tools/misc/xen-hvmctx.c b/tools/misc/xen-hvmctx.c
index 823aa7d736..4f336a6cea 100644
--- a/tools/misc/xen-hvmctx.c
+++ b/tools/misc/xen-hvmctx.c
@@ -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)
diff --git a/xen/arch/x86/hvm/viridian/private.h 
b/xen/arch/x86/hvm/viridian/private.h
index a5e06f9866..398b22f12d 100644
--- a/xen/arch/x86/hvm/viridian/private.h
+++ b/xen/arch/x86/hvm/viridian/private.h
@@ -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 */
 
 /*
diff --git a/xen/arch/x86/hvm/viridian/synic.c 
b/xen/arch/x86/hvm/viridian/synic.c
index d8d6f6e1c9..845029b568 100644
--- a/xen/arch/x86/hvm/viridian/synic.c
+++ b/xen/arch/x86/hvm/viridian/synic.c
@@ -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;
 }
 
 /*
diff --git a/xen/arch/x86/hvm/viridian/viridian.c 
b/xen/arch/x86/hvm/viridian/viridian.c
index 8630bc7bb6..7d73f41de6 100644
--- a/xen/arch/x86/hvm/viridian/viridian.c
+++ b/xen/arch/x86/hvm/viridian/viridian.c
@@ -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)
 {
diff --git a/xen/include/asm-x86/hvm/viridian.h 
b/xen/include/asm-x86/hvm/viridian.h
index 22f14a526e..ec5ef8d3f9 100644
--- a/xen/include/asm-x86/hvm/viridian.h
+++ b/xen/include/asm-x86/hvm/viridian.h
@@ -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];
 };
 
diff --git a/xen/include/public/arch-x86/hvm/save.h 
b/xen/include/public/arch-x86/hvm/save.h
index 4691d4d4aa..80e762c335 100644
--- a/xen/include/public/arch-x86/hvm/save.h
+++ b/xen/include/public/arch-x86/hvm/save.h
@@ -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];
 };
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.