# 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
|