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

[Xen-changelog] [xen-unstable] hvm, vt-d: Add memory cache-attribute pinning domctl for HVM



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1193146727 -3600
# Node ID b3fa9b58a102c17313da66e4c6150b117f3b3661
# Parent  9d1d27fddc50f65ba69966e33ef5026d0183d0dc
hvm, vt-d: Add memory cache-attribute pinning domctl for HVM
guests. Use this to pin virtual framebuffer VRAM as attribute WB, even
if guest tries to map with other attributes.
Signed-off-by: Disheng Su <disheng.su@xxxxxxxxx>
---
 tools/ioemu/hw/cirrus_vga.c         |    6 ++
 tools/libxc/xc_domain.c             |   15 ++++++
 tools/libxc/xenctrl.h               |    6 ++
 xen/arch/x86/domctl.c               |   19 ++++++++
 xen/arch/x86/hvm/hvm.c              |   20 +++++++-
 xen/arch/x86/hvm/mtrr.c             |   81 ++++++++++++++++++++++++++++++++++++
 xen/arch/x86/mm/shadow/multi.c      |   11 ++++
 xen/include/asm-x86/hvm/cacheattr.h |   33 ++++++++++++++
 xen/include/asm-x86/hvm/domain.h    |    7 ++-
 xen/include/public/domctl.h         |   18 ++++++++
 10 files changed, 209 insertions(+), 7 deletions(-)

diff -r 9d1d27fddc50 -r b3fa9b58a102 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c       Tue Oct 23 13:47:01 2007 +0100
+++ b/tools/ioemu/hw/cirrus_vga.c       Tue Oct 23 14:38:47 2007 +0100
@@ -2565,6 +2565,12 @@ static void *set_vram_mapping(unsigned l
         return NULL;
     }
 
+    (void)xc_domain_pin_memory_cacheattr(
+        xc_handle, domid,
+        begin >> TARGET_PAGE_BITS,
+        end >> TARGET_PAGE_BITS,
+        XEN_DOMCTL_MEM_CACHEATTR_WB);
+
     vram_pointer = xc_map_foreign_pages(xc_handle, domid,
                                         PROT_READ|PROT_WRITE,
                                         extent_start, nr_extents);
diff -r 9d1d27fddc50 -r b3fa9b58a102 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Tue Oct 23 13:47:01 2007 +0100
+++ b/tools/libxc/xc_domain.c   Tue Oct 23 14:38:47 2007 +0100
@@ -373,6 +373,21 @@ int xc_domain_setmaxmem(int xc_handle,
     domctl.cmd = XEN_DOMCTL_max_mem;
     domctl.domain = (domid_t)domid;
     domctl.u.max_mem.max_memkb = max_memkb;
+    return do_domctl(xc_handle, &domctl);
+}
+
+int xc_domain_pin_memory_cacheattr(int xc_handle,
+                                   uint32_t domid,
+                                   unsigned long start,
+                                   unsigned long end,
+                                   unsigned int type)
+{
+    DECLARE_DOMCTL;
+    domctl.cmd = XEN_DOMCTL_pin_mem_cacheattr;
+    domctl.domain = (domid_t)domid;
+    domctl.u.pin_mem_cacheattr.start = start;
+    domctl.u.pin_mem_cacheattr.end = end;
+    domctl.u.pin_mem_cacheattr.type = type;
     return do_domctl(xc_handle, &domctl);
 }
 
diff -r 9d1d27fddc50 -r b3fa9b58a102 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Tue Oct 23 13:47:01 2007 +0100
+++ b/tools/libxc/xenctrl.h     Tue Oct 23 14:38:47 2007 +0100
@@ -614,6 +614,12 @@ int xc_domain_iomem_permission(int xc_ha
                                unsigned long nr_mfns,
                                uint8_t allow_access);
 
+int xc_domain_pin_memory_cacheattr(int xc_handle,
+                                   uint32_t domid,
+                                   unsigned long start,
+                                   unsigned long end,
+                                   unsigned int type);
+
 unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
                                     unsigned long mfn);
 
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Tue Oct 23 13:47:01 2007 +0100
+++ b/xen/arch/x86/domctl.c     Tue Oct 23 14:38:47 2007 +0100
@@ -23,6 +23,7 @@
 #include <asm/irq.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
+#include <asm/hvm/cacheattr.h>
 #include <asm/processor.h>
 #include <xsm/xsm.h>
 #include <xen/list.h>
@@ -678,6 +679,24 @@ long arch_do_domctl(
     }
     break;    
 
+    case XEN_DOMCTL_pin_mem_cacheattr:
+    {
+        struct domain *d;
+
+        ret = -ESRCH;
+        d = rcu_lock_domain_by_id(domctl->domain);
+        if ( d == NULL )
+            break;
+
+        ret = hvm_set_mem_pinned_cacheattr(
+            d, domctl->u.pin_mem_cacheattr.start,
+            domctl->u.pin_mem_cacheattr.end,
+            domctl->u.pin_mem_cacheattr.type);
+
+        rcu_unlock_domain(d);
+    }
+    break;
+
     default:
         ret = -ENOSYS;
         break;
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Tue Oct 23 13:47:01 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Tue Oct 23 14:38:47 2007 +0100
@@ -44,6 +44,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/vpt.h>
 #include <asm/hvm/support.h>
+#include <asm/hvm/cacheattr.h>
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
 #include <public/version.h>
@@ -228,20 +229,32 @@ int hvm_domain_initialise(struct domain 
     spin_lock_init(&d->arch.hvm_domain.irq_lock);
     spin_lock_init(&d->arch.hvm_domain.uc_lock);
 
+    hvm_init_cacheattr_region_list(d);
+
     rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
     if ( rc != 0 )
-        return rc;
+        goto fail1;
 
     vpic_init(d);
 
     rc = vioapic_init(d);
     if ( rc != 0 )
-        return rc;
+        goto fail1;
 
     hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
     hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
 
-    return hvm_funcs.domain_initialise(d);
+    rc = hvm_funcs.domain_initialise(d);
+    if ( rc != 0 )
+        goto fail2;
+
+    return 0;
+
+ fail2:
+    vioapic_deinit(d);
+ fail1:
+    hvm_destroy_cacheattr_region_list(d);
+    return rc;
 }
 
 void hvm_domain_relinquish_resources(struct domain *d)
@@ -259,6 +272,7 @@ void hvm_domain_destroy(struct domain *d
 {
     hvm_funcs.domain_destroy(d);
     vioapic_deinit(d);
+    hvm_destroy_cacheattr_region_list(d);
 }
 
 static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/arch/x86/hvm/mtrr.c
--- a/xen/arch/x86/hvm/mtrr.c   Tue Oct 23 13:47:01 2007 +0100
+++ b/xen/arch/x86/hvm/mtrr.c   Tue Oct 23 14:38:47 2007 +0100
@@ -26,6 +26,7 @@
 #include <stdbool.h>
 #include <asm/mtrr.h>
 #include <asm/hvm/support.h>
+#include <asm/hvm/cacheattr.h>
 
 /* Xen holds the native MTRR MSRs */
 extern struct mtrr_state mtrr_state;
@@ -685,3 +686,83 @@ bool_t mtrr_pat_not_equal(struct vcpu *v
 
     return 0;
 }
+
+void hvm_init_cacheattr_region_list(
+    struct domain *d)
+{
+    INIT_LIST_HEAD(&d->arch.hvm_domain.pinned_cacheattr_ranges);
+}
+
+void hvm_destroy_cacheattr_region_list(
+    struct domain *d)
+{
+    struct list_head *head = &d->arch.hvm_domain.pinned_cacheattr_ranges;
+    struct hvm_mem_pinned_cacheattr_range *range;
+
+    while ( !list_empty(head) )
+    {
+        range = list_entry(head->next,
+                           struct hvm_mem_pinned_cacheattr_range,
+                           list);
+        list_del(&range->list);
+        xfree(range);
+    }
+}
+
+int hvm_get_mem_pinned_cacheattr(
+    struct domain *d,
+    unsigned long guest_fn,
+    unsigned int *type)
+{
+    struct hvm_mem_pinned_cacheattr_range *range;
+
+    *type = 0;
+
+    if ( !is_hvm_domain(d) )
+        return 0;
+
+    list_for_each_entry_rcu ( range,
+                              &d->arch.hvm_domain.pinned_cacheattr_ranges,
+                              list )
+    {
+        if ( (guest_fn >= range->start) && (guest_fn <= range->end) )
+        {
+            *type = range->type;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+int hvm_set_mem_pinned_cacheattr(
+    struct domain *d,
+    unsigned long gfn_start,
+    unsigned long gfn_end,
+    unsigned int  type)
+{
+    struct hvm_mem_pinned_cacheattr_range *range;
+
+    if ( !((type == PAT_TYPE_UNCACHABLE) ||
+           (type == PAT_TYPE_WRCOMB) ||
+           (type == PAT_TYPE_WRTHROUGH) ||
+           (type == PAT_TYPE_WRPROT) ||
+           (type == PAT_TYPE_WRBACK) ||
+           (type == PAT_TYPE_UC_MINUS)) ||
+         !is_hvm_domain(d) )
+        return -EINVAL;
+
+    range = xmalloc(struct hvm_mem_pinned_cacheattr_range);
+    if ( range == NULL )
+        return -ENOMEM;
+
+    memset(range, 0, sizeof(*range));
+
+    range->start = gfn_start;
+    range->end = gfn_end;
+    range->type = type;
+
+    list_add_rcu(&range->list, &d->arch.hvm_domain.pinned_cacheattr_ranges);
+
+    return 0;
+}
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Tue Oct 23 13:47:01 2007 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Tue Oct 23 14:38:47 2007 +0100
@@ -33,6 +33,7 @@
 #include <asm/shadow.h>
 #include <asm/flushtlb.h>
 #include <asm/hvm/hvm.h>
+#include <asm/hvm/cacheattr.h>
 #include <asm/mtrr.h>
 #include "private.h"
 #include "types.h"
@@ -715,8 +716,14 @@ _sh_propagate(struct vcpu *v,
     sflags = gflags & pass_thru_flags;
 
     /* Only change memory caching type for pass-through domain */
-    if ( (level == 1) && !list_empty(&(domain_hvm_iommu(d)->pdev_list)) ) {
-        if ( v->domain->arch.hvm_domain.is_in_uc_mode )
+    if ( (level == 1) && is_hvm_domain(d) &&
+         !list_empty(&(domain_hvm_iommu(d)->pdev_list)) )
+    {
+        unsigned int type;
+        if ( hvm_get_mem_pinned_cacheattr(d, gfn_x(guest_l1e_get_gfn(*gp)),
+                                          &type) )
+            sflags |= pat_type_2_pte_flags(type);
+        else if ( v->domain->arch.hvm_domain.is_in_uc_mode )
             sflags |= pat_type_2_pte_flags(PAT_TYPE_UNCACHABLE);
         else
             sflags |= get_pat_flags(v,
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/include/asm-x86/hvm/cacheattr.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hvm/cacheattr.h       Tue Oct 23 14:38:47 2007 +0100
@@ -0,0 +1,33 @@
+#ifndef __HVM_CACHEATTR_H__
+#define __HVM_CACHEATTR_H__
+
+struct hvm_mem_pinned_cacheattr_range {
+    struct list_head list;
+    uint64_t start, end;
+    unsigned int type;
+};
+
+void hvm_init_cacheattr_region_list(
+    struct domain *d);
+void hvm_destroy_cacheattr_region_list(
+    struct domain *d);
+
+/*
+ * To see guest_fn is in the pinned range or not,
+ * if yes, return 1, and set type to value in this range
+ * if no,  return 0, and set type to 0
+ */
+int hvm_get_mem_pinned_cacheattr(
+    struct domain *d,
+    unsigned long guest_fn,
+    unsigned int *type);
+
+
+/* Set pinned caching type for a domain. */
+int hvm_set_mem_pinned_cacheattr(
+    struct domain *d,
+    unsigned long gfn_start,
+    unsigned long gfn_end,
+    unsigned int  type);
+
+#endif /* __HVM_CACHEATTR_H__ */
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Tue Oct 23 13:47:01 2007 +0100
+++ b/xen/include/asm-x86/hvm/domain.h  Tue Oct 23 14:38:47 2007 +0100
@@ -61,11 +61,14 @@ struct hvm_domain {
 
     unsigned long          vmx_apic_access_mfn;
 
+    /* Memory ranges with pinned cache attributes. */
+    struct list_head       pinned_cacheattr_ranges;
+
     /* If one of vcpus of this domain is in no_fill_mode or
      * mtrr/pat between vcpus is not the same, set is_in_uc_mode
      */
-    spinlock_t       uc_lock;
-    bool_t           is_in_uc_mode;
+    spinlock_t             uc_lock;
+    bool_t                 is_in_uc_mode;
 
     /* Pass-through */
     struct hvm_iommu       hvm_iommu;
diff -r 9d1d27fddc50 -r b3fa9b58a102 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Tue Oct 23 13:47:01 2007 +0100
+++ b/xen/include/public/domctl.h       Tue Oct 23 14:38:47 2007 +0100
@@ -495,6 +495,23 @@ typedef struct xen_domctl_ioport_mapping
 typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
 
+/*
+ * Pin caching type of RAM space for x86 HVM domU.
+ */
+#define XEN_DOMCTL_pin_mem_cacheattr 41
+/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */
+#define XEN_DOMCTL_MEM_CACHEATTR_UC  0
+#define XEN_DOMCTL_MEM_CACHEATTR_WC  1
+#define XEN_DOMCTL_MEM_CACHEATTR_WT  4
+#define XEN_DOMCTL_MEM_CACHEATTR_WP  5
+#define XEN_DOMCTL_MEM_CACHEATTR_WB  6
+#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
+struct xen_domctl_pin_mem_cacheattr {
+    uint64_t start, end;
+    unsigned int type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
+};
+typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t);
 
 struct xen_domctl {
     uint32_t cmd;
@@ -529,6 +546,7 @@ struct xen_domctl {
         struct xen_domctl_bind_pt_irq       bind_pt_irq;
         struct xen_domctl_memory_mapping    memory_mapping;
         struct xen_domctl_ioport_mapping    ioport_mapping;
+        struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr;
         uint8_t                             pad[128];
     } u;
 };

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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