ia64/xen-unstable

changeset 16197:b3fa9b58a102

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@intel.com>
author Keir Fraser <keir@xensource.com>
date Tue Oct 23 14:38:47 2007 +0100 (2007-10-23)
parents 9d1d27fddc50
children 8f33d2c6c67c
files tools/ioemu/hw/cirrus_vga.c tools/libxc/xc_domain.c tools/libxc/xenctrl.h xen/arch/x86/domctl.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/mtrr.c xen/arch/x86/mm/shadow/multi.c xen/include/asm-x86/hvm/cacheattr.h xen/include/asm-x86/hvm/domain.h xen/include/public/domctl.h
line diff
     1.1 --- a/tools/ioemu/hw/cirrus_vga.c	Tue Oct 23 13:47:01 2007 +0100
     1.2 +++ b/tools/ioemu/hw/cirrus_vga.c	Tue Oct 23 14:38:47 2007 +0100
     1.3 @@ -2565,6 +2565,12 @@ static void *set_vram_mapping(unsigned l
     1.4          return NULL;
     1.5      }
     1.6  
     1.7 +    (void)xc_domain_pin_memory_cacheattr(
     1.8 +        xc_handle, domid,
     1.9 +        begin >> TARGET_PAGE_BITS,
    1.10 +        end >> TARGET_PAGE_BITS,
    1.11 +        XEN_DOMCTL_MEM_CACHEATTR_WB);
    1.12 +
    1.13      vram_pointer = xc_map_foreign_pages(xc_handle, domid,
    1.14                                          PROT_READ|PROT_WRITE,
    1.15                                          extent_start, nr_extents);
     2.1 --- a/tools/libxc/xc_domain.c	Tue Oct 23 13:47:01 2007 +0100
     2.2 +++ b/tools/libxc/xc_domain.c	Tue Oct 23 14:38:47 2007 +0100
     2.3 @@ -376,6 +376,21 @@ int xc_domain_setmaxmem(int xc_handle,
     2.4      return do_domctl(xc_handle, &domctl);
     2.5  }
     2.6  
     2.7 +int xc_domain_pin_memory_cacheattr(int xc_handle,
     2.8 +                                   uint32_t domid,
     2.9 +                                   unsigned long start,
    2.10 +                                   unsigned long end,
    2.11 +                                   unsigned int type)
    2.12 +{
    2.13 +    DECLARE_DOMCTL;
    2.14 +    domctl.cmd = XEN_DOMCTL_pin_mem_cacheattr;
    2.15 +    domctl.domain = (domid_t)domid;
    2.16 +    domctl.u.pin_mem_cacheattr.start = start;
    2.17 +    domctl.u.pin_mem_cacheattr.end = end;
    2.18 +    domctl.u.pin_mem_cacheattr.type = type;
    2.19 +    return do_domctl(xc_handle, &domctl);
    2.20 +}
    2.21 +
    2.22  #if defined(__i386__) || defined(__x86_64__)
    2.23  #include "xc_e820.h"
    2.24  int xc_domain_set_memmap_limit(int xc_handle,
     3.1 --- a/tools/libxc/xenctrl.h	Tue Oct 23 13:47:01 2007 +0100
     3.2 +++ b/tools/libxc/xenctrl.h	Tue Oct 23 14:38:47 2007 +0100
     3.3 @@ -614,6 +614,12 @@ int xc_domain_iomem_permission(int xc_ha
     3.4                                 unsigned long nr_mfns,
     3.5                                 uint8_t allow_access);
     3.6  
     3.7 +int xc_domain_pin_memory_cacheattr(int xc_handle,
     3.8 +                                   uint32_t domid,
     3.9 +                                   unsigned long start,
    3.10 +                                   unsigned long end,
    3.11 +                                   unsigned int type);
    3.12 +
    3.13  unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
    3.14                                      unsigned long mfn);
    3.15  
     4.1 --- a/xen/arch/x86/domctl.c	Tue Oct 23 13:47:01 2007 +0100
     4.2 +++ b/xen/arch/x86/domctl.c	Tue Oct 23 14:38:47 2007 +0100
     4.3 @@ -23,6 +23,7 @@
     4.4  #include <asm/irq.h>
     4.5  #include <asm/hvm/hvm.h>
     4.6  #include <asm/hvm/support.h>
     4.7 +#include <asm/hvm/cacheattr.h>
     4.8  #include <asm/processor.h>
     4.9  #include <xsm/xsm.h>
    4.10  #include <xen/list.h>
    4.11 @@ -678,6 +679,24 @@ long arch_do_domctl(
    4.12      }
    4.13      break;    
    4.14  
    4.15 +    case XEN_DOMCTL_pin_mem_cacheattr:
    4.16 +    {
    4.17 +        struct domain *d;
    4.18 +
    4.19 +        ret = -ESRCH;
    4.20 +        d = rcu_lock_domain_by_id(domctl->domain);
    4.21 +        if ( d == NULL )
    4.22 +            break;
    4.23 +
    4.24 +        ret = hvm_set_mem_pinned_cacheattr(
    4.25 +            d, domctl->u.pin_mem_cacheattr.start,
    4.26 +            domctl->u.pin_mem_cacheattr.end,
    4.27 +            domctl->u.pin_mem_cacheattr.type);
    4.28 +
    4.29 +        rcu_unlock_domain(d);
    4.30 +    }
    4.31 +    break;
    4.32 +
    4.33      default:
    4.34          ret = -ENOSYS;
    4.35          break;
     5.1 --- a/xen/arch/x86/hvm/hvm.c	Tue Oct 23 13:47:01 2007 +0100
     5.2 +++ b/xen/arch/x86/hvm/hvm.c	Tue Oct 23 14:38:47 2007 +0100
     5.3 @@ -44,6 +44,7 @@
     5.4  #include <asm/hvm/hvm.h>
     5.5  #include <asm/hvm/vpt.h>
     5.6  #include <asm/hvm/support.h>
     5.7 +#include <asm/hvm/cacheattr.h>
     5.8  #include <public/sched.h>
     5.9  #include <public/hvm/ioreq.h>
    5.10  #include <public/version.h>
    5.11 @@ -228,20 +229,32 @@ int hvm_domain_initialise(struct domain 
    5.12      spin_lock_init(&d->arch.hvm_domain.irq_lock);
    5.13      spin_lock_init(&d->arch.hvm_domain.uc_lock);
    5.14  
    5.15 +    hvm_init_cacheattr_region_list(d);
    5.16 +
    5.17      rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
    5.18      if ( rc != 0 )
    5.19 -        return rc;
    5.20 +        goto fail1;
    5.21  
    5.22      vpic_init(d);
    5.23  
    5.24      rc = vioapic_init(d);
    5.25      if ( rc != 0 )
    5.26 -        return rc;
    5.27 +        goto fail1;
    5.28  
    5.29      hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
    5.30      hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
    5.31  
    5.32 -    return hvm_funcs.domain_initialise(d);
    5.33 +    rc = hvm_funcs.domain_initialise(d);
    5.34 +    if ( rc != 0 )
    5.35 +        goto fail2;
    5.36 +
    5.37 +    return 0;
    5.38 +
    5.39 + fail2:
    5.40 +    vioapic_deinit(d);
    5.41 + fail1:
    5.42 +    hvm_destroy_cacheattr_region_list(d);
    5.43 +    return rc;
    5.44  }
    5.45  
    5.46  void hvm_domain_relinquish_resources(struct domain *d)
    5.47 @@ -259,6 +272,7 @@ void hvm_domain_destroy(struct domain *d
    5.48  {
    5.49      hvm_funcs.domain_destroy(d);
    5.50      vioapic_deinit(d);
    5.51 +    hvm_destroy_cacheattr_region_list(d);
    5.52  }
    5.53  
    5.54  static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
     6.1 --- a/xen/arch/x86/hvm/mtrr.c	Tue Oct 23 13:47:01 2007 +0100
     6.2 +++ b/xen/arch/x86/hvm/mtrr.c	Tue Oct 23 14:38:47 2007 +0100
     6.3 @@ -26,6 +26,7 @@
     6.4  #include <stdbool.h>
     6.5  #include <asm/mtrr.h>
     6.6  #include <asm/hvm/support.h>
     6.7 +#include <asm/hvm/cacheattr.h>
     6.8  
     6.9  /* Xen holds the native MTRR MSRs */
    6.10  extern struct mtrr_state mtrr_state;
    6.11 @@ -685,3 +686,83 @@ bool_t mtrr_pat_not_equal(struct vcpu *v
    6.12  
    6.13      return 0;
    6.14  }
    6.15 +
    6.16 +void hvm_init_cacheattr_region_list(
    6.17 +    struct domain *d)
    6.18 +{
    6.19 +    INIT_LIST_HEAD(&d->arch.hvm_domain.pinned_cacheattr_ranges);
    6.20 +}
    6.21 +
    6.22 +void hvm_destroy_cacheattr_region_list(
    6.23 +    struct domain *d)
    6.24 +{
    6.25 +    struct list_head *head = &d->arch.hvm_domain.pinned_cacheattr_ranges;
    6.26 +    struct hvm_mem_pinned_cacheattr_range *range;
    6.27 +
    6.28 +    while ( !list_empty(head) )
    6.29 +    {
    6.30 +        range = list_entry(head->next,
    6.31 +                           struct hvm_mem_pinned_cacheattr_range,
    6.32 +                           list);
    6.33 +        list_del(&range->list);
    6.34 +        xfree(range);
    6.35 +    }
    6.36 +}
    6.37 +
    6.38 +int hvm_get_mem_pinned_cacheattr(
    6.39 +    struct domain *d,
    6.40 +    unsigned long guest_fn,
    6.41 +    unsigned int *type)
    6.42 +{
    6.43 +    struct hvm_mem_pinned_cacheattr_range *range;
    6.44 +
    6.45 +    *type = 0;
    6.46 +
    6.47 +    if ( !is_hvm_domain(d) )
    6.48 +        return 0;
    6.49 +
    6.50 +    list_for_each_entry_rcu ( range,
    6.51 +                              &d->arch.hvm_domain.pinned_cacheattr_ranges,
    6.52 +                              list )
    6.53 +    {
    6.54 +        if ( (guest_fn >= range->start) && (guest_fn <= range->end) )
    6.55 +        {
    6.56 +            *type = range->type;
    6.57 +            return 1;
    6.58 +        }
    6.59 +    }
    6.60 +
    6.61 +    return 0;
    6.62 +}
    6.63 +
    6.64 +int hvm_set_mem_pinned_cacheattr(
    6.65 +    struct domain *d,
    6.66 +    unsigned long gfn_start,
    6.67 +    unsigned long gfn_end,
    6.68 +    unsigned int  type)
    6.69 +{
    6.70 +    struct hvm_mem_pinned_cacheattr_range *range;
    6.71 +
    6.72 +    if ( !((type == PAT_TYPE_UNCACHABLE) ||
    6.73 +           (type == PAT_TYPE_WRCOMB) ||
    6.74 +           (type == PAT_TYPE_WRTHROUGH) ||
    6.75 +           (type == PAT_TYPE_WRPROT) ||
    6.76 +           (type == PAT_TYPE_WRBACK) ||
    6.77 +           (type == PAT_TYPE_UC_MINUS)) ||
    6.78 +         !is_hvm_domain(d) )
    6.79 +        return -EINVAL;
    6.80 +
    6.81 +    range = xmalloc(struct hvm_mem_pinned_cacheattr_range);
    6.82 +    if ( range == NULL )
    6.83 +        return -ENOMEM;
    6.84 +
    6.85 +    memset(range, 0, sizeof(*range));
    6.86 +
    6.87 +    range->start = gfn_start;
    6.88 +    range->end = gfn_end;
    6.89 +    range->type = type;
    6.90 +
    6.91 +    list_add_rcu(&range->list, &d->arch.hvm_domain.pinned_cacheattr_ranges);
    6.92 +
    6.93 +    return 0;
    6.94 +}
     7.1 --- a/xen/arch/x86/mm/shadow/multi.c	Tue Oct 23 13:47:01 2007 +0100
     7.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Tue Oct 23 14:38:47 2007 +0100
     7.3 @@ -33,6 +33,7 @@
     7.4  #include <asm/shadow.h>
     7.5  #include <asm/flushtlb.h>
     7.6  #include <asm/hvm/hvm.h>
     7.7 +#include <asm/hvm/cacheattr.h>
     7.8  #include <asm/mtrr.h>
     7.9  #include "private.h"
    7.10  #include "types.h"
    7.11 @@ -715,8 +716,14 @@ static always_inline void
    7.12      sflags = gflags & pass_thru_flags;
    7.13  
    7.14      /* Only change memory caching type for pass-through domain */
    7.15 -    if ( (level == 1) && !list_empty(&(domain_hvm_iommu(d)->pdev_list)) ) {
    7.16 -        if ( v->domain->arch.hvm_domain.is_in_uc_mode )
    7.17 +    if ( (level == 1) && is_hvm_domain(d) &&
    7.18 +         !list_empty(&(domain_hvm_iommu(d)->pdev_list)) )
    7.19 +    {
    7.20 +        unsigned int type;
    7.21 +        if ( hvm_get_mem_pinned_cacheattr(d, gfn_x(guest_l1e_get_gfn(*gp)),
    7.22 +                                          &type) )
    7.23 +            sflags |= pat_type_2_pte_flags(type);
    7.24 +        else if ( v->domain->arch.hvm_domain.is_in_uc_mode )
    7.25              sflags |= pat_type_2_pte_flags(PAT_TYPE_UNCACHABLE);
    7.26          else
    7.27              sflags |= get_pat_flags(v,
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/include/asm-x86/hvm/cacheattr.h	Tue Oct 23 14:38:47 2007 +0100
     8.3 @@ -0,0 +1,33 @@
     8.4 +#ifndef __HVM_CACHEATTR_H__
     8.5 +#define __HVM_CACHEATTR_H__
     8.6 +
     8.7 +struct hvm_mem_pinned_cacheattr_range {
     8.8 +    struct list_head list;
     8.9 +    uint64_t start, end;
    8.10 +    unsigned int type;
    8.11 +};
    8.12 +
    8.13 +void hvm_init_cacheattr_region_list(
    8.14 +    struct domain *d);
    8.15 +void hvm_destroy_cacheattr_region_list(
    8.16 +    struct domain *d);
    8.17 +
    8.18 +/*
    8.19 + * To see guest_fn is in the pinned range or not,
    8.20 + * if yes, return 1, and set type to value in this range
    8.21 + * if no,  return 0, and set type to 0
    8.22 + */
    8.23 +int hvm_get_mem_pinned_cacheattr(
    8.24 +    struct domain *d,
    8.25 +    unsigned long guest_fn,
    8.26 +    unsigned int *type);
    8.27 +
    8.28 +
    8.29 +/* Set pinned caching type for a domain. */
    8.30 +int hvm_set_mem_pinned_cacheattr(
    8.31 +    struct domain *d,
    8.32 +    unsigned long gfn_start,
    8.33 +    unsigned long gfn_end,
    8.34 +    unsigned int  type);
    8.35 +
    8.36 +#endif /* __HVM_CACHEATTR_H__ */
     9.1 --- a/xen/include/asm-x86/hvm/domain.h	Tue Oct 23 13:47:01 2007 +0100
     9.2 +++ b/xen/include/asm-x86/hvm/domain.h	Tue Oct 23 14:38:47 2007 +0100
     9.3 @@ -61,11 +61,14 @@ struct hvm_domain {
     9.4  
     9.5      unsigned long          vmx_apic_access_mfn;
     9.6  
     9.7 +    /* Memory ranges with pinned cache attributes. */
     9.8 +    struct list_head       pinned_cacheattr_ranges;
     9.9 +
    9.10      /* If one of vcpus of this domain is in no_fill_mode or
    9.11       * mtrr/pat between vcpus is not the same, set is_in_uc_mode
    9.12       */
    9.13 -    spinlock_t       uc_lock;
    9.14 -    bool_t           is_in_uc_mode;
    9.15 +    spinlock_t             uc_lock;
    9.16 +    bool_t                 is_in_uc_mode;
    9.17  
    9.18      /* Pass-through */
    9.19      struct hvm_iommu       hvm_iommu;
    10.1 --- a/xen/include/public/domctl.h	Tue Oct 23 13:47:01 2007 +0100
    10.2 +++ b/xen/include/public/domctl.h	Tue Oct 23 14:38:47 2007 +0100
    10.3 @@ -495,6 +495,23 @@ struct xen_domctl_ioport_mapping {
    10.4  typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
    10.5  DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
    10.6  
    10.7 +/*
    10.8 + * Pin caching type of RAM space for x86 HVM domU.
    10.9 + */
   10.10 +#define XEN_DOMCTL_pin_mem_cacheattr 41
   10.11 +/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */
   10.12 +#define XEN_DOMCTL_MEM_CACHEATTR_UC  0
   10.13 +#define XEN_DOMCTL_MEM_CACHEATTR_WC  1
   10.14 +#define XEN_DOMCTL_MEM_CACHEATTR_WT  4
   10.15 +#define XEN_DOMCTL_MEM_CACHEATTR_WP  5
   10.16 +#define XEN_DOMCTL_MEM_CACHEATTR_WB  6
   10.17 +#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
   10.18 +struct xen_domctl_pin_mem_cacheattr {
   10.19 +    uint64_t start, end;
   10.20 +    unsigned int type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
   10.21 +};
   10.22 +typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t;
   10.23 +DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t);
   10.24  
   10.25  struct xen_domctl {
   10.26      uint32_t cmd;
   10.27 @@ -529,6 +546,7 @@ struct xen_domctl {
   10.28          struct xen_domctl_bind_pt_irq       bind_pt_irq;
   10.29          struct xen_domctl_memory_mapping    memory_mapping;
   10.30          struct xen_domctl_ioport_mapping    ioport_mapping;
   10.31 +        struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr;
   10.32          uint8_t                             pad[128];
   10.33      } u;
   10.34  };