ia64/xen-unstable

changeset 16407:2e5d922b7ee3

xen: Allow granting of foreign access to iomem pages, and with
arbitrary cache attributes.
Signed-off-by: Kieran Mansley <kmansley@solarflare.com>
Signed-off-by: Keir Fraser <keir.fraser@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Nov 20 17:26:48 2007 +0000 (2007-11-20)
parents f62e6c697eeb
children 9a9ddc04eea2 00fec8212ae6
files xen/arch/ia64/xen/mm.c xen/arch/powerpc/mm.c xen/arch/x86/mm.c xen/common/grant_table.c xen/include/asm-ia64/grant_table.h xen/include/asm-powerpc/grant_table.h xen/include/asm-x86/grant_table.h xen/include/public/grant_table.h
line diff
     1.1 --- a/xen/arch/ia64/xen/mm.c	Tue Nov 20 15:34:25 2007 +0000
     1.2 +++ b/xen/arch/ia64/xen/mm.c	Tue Nov 20 17:26:48 2007 +0000
     1.3 @@ -2144,16 +2144,18 @@ dom0vp_unexpose_foreign_p2m(struct domai
     1.4  // mfn: frame: machine page frame
     1.5  // flags: GNTMAP_readonly | GNTMAP_application_map | GNTMAP_contains_pte
     1.6  int
     1.7 -create_grant_host_mapping(unsigned long gpaddr,
     1.8 -              unsigned long mfn, unsigned int flags)
     1.9 +create_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, 
    1.10 +                          unsigned int flags, unsigned int cache_flags)
    1.11  {
    1.12      struct domain* d = current->domain;
    1.13      struct page_info* page;
    1.14      int ret;
    1.15  
    1.16 -    if (flags & (GNTMAP_device_map |
    1.17 -                 GNTMAP_application_map | GNTMAP_contains_pte)) {
    1.18 -        gdprintk(XENLOG_INFO, "%s: flags 0x%x\n", __func__, flags);
    1.19 +    if ((flags & (GNTMAP_device_map | 
    1.20 +                  GNTMAP_application_map | GNTMAP_contains_pte)) ||
    1.21 +        (cache_flags)) {
    1.22 +        gdprintk(XENLOG_INFO, "%s: flags 0x%x cache_flags 0x%x\n",
    1.23 +                 __func__, flags, cache_flags);
    1.24          return GNTST_general_error;
    1.25      }
    1.26  
     2.1 --- a/xen/arch/powerpc/mm.c	Tue Nov 20 15:34:25 2007 +0000
     2.2 +++ b/xen/arch/powerpc/mm.c	Tue Nov 20 17:26:48 2007 +0000
     2.3 @@ -168,7 +168,7 @@ static int destroy_grant_va_mapping(
     2.4  }
     2.5  
     2.6  int create_grant_host_mapping(
     2.7 -    unsigned long addr, unsigned long frame, unsigned int flags)
     2.8 +    unsigned long addr, unsigned long frame, unsigned int flags, unsigned int cache_flags)
     2.9  {
    2.10      if (flags & GNTMAP_application_map) {
    2.11          printk("%s: GNTMAP_application_map not supported\n", __func__);
    2.12 @@ -180,6 +180,11 @@ int create_grant_host_mapping(
    2.13          BUG();
    2.14          return GNTST_general_error;
    2.15      }
    2.16 +    if (cache_flags) {
    2.17 +        printk("%s: cache_flags not supported\n", __func__);
    2.18 +        BUG();
    2.19 +        return GNTST_general_error;
    2.20 +    }
    2.21      return create_grant_va_mapping(addr, frame, current);
    2.22  }
    2.23  
     3.1 --- a/xen/arch/x86/mm.c	Tue Nov 20 15:34:25 2007 +0000
     3.2 +++ b/xen/arch/x86/mm.c	Tue Nov 20 17:26:48 2007 +0000
     3.3 @@ -645,11 +645,7 @@ get_page_from_l1e(
     3.4              return 0;
     3.5          }
     3.6  
     3.7 -        /* No reference counting for out-of-range I/O pages. */
     3.8 -        if ( !mfn_valid(mfn) )
     3.9 -            return 1;
    3.10 -
    3.11 -        d = dom_io;
    3.12 +        return 1;
    3.13      }
    3.14  
    3.15      /* Foreign mappings into guests in shadow external mode don't
    3.16 @@ -667,9 +663,8 @@ get_page_from_l1e(
    3.17                  mfn, get_gpfn_from_mfn(mfn),
    3.18                  l1e_get_intpte(l1e), d->domain_id);
    3.19      }
    3.20 -    else if ( (pte_flags_to_cacheattr(l1f) !=
    3.21 -               ((page->count_info >> PGC_cacheattr_base) & 7)) &&
    3.22 -              !is_iomem_page(mfn) )
    3.23 +    else if ( pte_flags_to_cacheattr(l1f) !=
    3.24 +              ((page->count_info >> PGC_cacheattr_base) & 7) )
    3.25      {
    3.26          uint32_t x, nx, y = page->count_info;
    3.27          uint32_t cacheattr = pte_flags_to_cacheattr(l1f);
    3.28 @@ -848,14 +843,16 @@ get_page_from_l4e(
    3.29  
    3.30  void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
    3.31  {
    3.32 -    unsigned long    pfn  = l1e_get_pfn(l1e);
    3.33 -    struct page_info *page = mfn_to_page(pfn);
    3.34 -    struct domain   *e;
    3.35 -    struct vcpu     *v;
    3.36 -
    3.37 -    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || !mfn_valid(pfn) )
    3.38 +    unsigned long     pfn = l1e_get_pfn(l1e);
    3.39 +    struct page_info *page;
    3.40 +    struct domain    *e;
    3.41 +    struct vcpu      *v;
    3.42 +
    3.43 +    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || is_iomem_page(pfn) )
    3.44          return;
    3.45  
    3.46 +    page = mfn_to_page(pfn);
    3.47 +
    3.48      e = page_get_owner(page);
    3.49  
    3.50      /*
    3.51 @@ -2763,8 +2760,8 @@ static int destroy_grant_va_mapping(
    3.52      return replace_grant_va_mapping(addr, frame, l1e_empty(), v);
    3.53  }
    3.54  
    3.55 -int create_grant_host_mapping(
    3.56 -    uint64_t addr, unsigned long frame, unsigned int flags)
    3.57 +int create_grant_host_mapping(uint64_t addr, unsigned long frame, 
    3.58 +                              unsigned int flags, unsigned int cache_flags)
    3.59  {
    3.60      l1_pgentry_t pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
    3.61  
    3.62 @@ -2773,6 +2770,8 @@ int create_grant_host_mapping(
    3.63      if ( !(flags & GNTMAP_readonly) )
    3.64          l1e_add_flags(pte,_PAGE_RW);
    3.65  
    3.66 +    l1e_add_flags(pte, cacheattr_to_pte_flags(cache_flags >> 5));
    3.67 +
    3.68      if ( flags & GNTMAP_contains_pte )
    3.69          return create_grant_pte_mapping(addr, pte, current);
    3.70      return create_grant_va_mapping(addr, pte, current);
     4.1 --- a/xen/common/grant_table.c	Tue Nov 20 15:34:25 2007 +0000
     4.2 +++ b/xen/common/grant_table.c	Tue Nov 20 17:26:48 2007 +0000
     4.3 @@ -198,6 +198,7 @@ static void
     4.4      int            handle;
     4.5      unsigned long  frame = 0;
     4.6      int            rc = GNTST_okay;
     4.7 +    unsigned int   cache_flags;
     4.8      struct active_grant_entry *act;
     4.9      struct grant_mapping *mt;
    4.10      grant_entry_t *sha;
    4.11 @@ -326,36 +327,58 @@ static void
    4.12  
    4.13      frame = act->frame;
    4.14  
    4.15 +    cache_flags = (sha->flags & (GTF_PAT | GTF_PWT | GTF_PCD) );
    4.16 +
    4.17      spin_unlock(&rd->grant_table->lock);
    4.18  
    4.19 -    if ( unlikely(!mfn_valid(frame)) ||
    4.20 -         unlikely(!((op->flags & GNTMAP_readonly) ?
    4.21 -                    get_page(mfn_to_page(frame), rd) :
    4.22 -                    get_page_and_type(mfn_to_page(frame), rd,
    4.23 -                                      PGT_writable_page))) )
    4.24 +    if ( is_iomem_page(frame) )
    4.25      {
    4.26 -        if ( !rd->is_dying )
    4.27 -            gdprintk(XENLOG_WARNING, "Could not pin grant frame %lx\n", frame);
    4.28 -        rc = GNTST_general_error;
    4.29 -        goto undo_out;
    4.30 -    }
    4.31 -        
    4.32 -    if ( op->flags & GNTMAP_host_map )
    4.33 -    {
    4.34 -        rc = create_grant_host_mapping(op->host_addr, frame, op->flags);
    4.35 -        if ( rc != GNTST_okay )
    4.36 +        if ( !iomem_access_permitted(rd, frame, frame) )
    4.37          {
    4.38 -            if ( !(op->flags & GNTMAP_readonly) )
    4.39 -                put_page_type(mfn_to_page(frame));
    4.40 -            put_page(mfn_to_page(frame));
    4.41 +            gdprintk(XENLOG_WARNING,
    4.42 +                     "Iomem mapping not permitted %lx (domain %d)\n", 
    4.43 +                     frame, rd->domain_id);
    4.44 +            rc = GNTST_general_error;
    4.45              goto undo_out;
    4.46          }
    4.47  
    4.48 -        if ( op->flags & GNTMAP_device_map )
    4.49 +        rc = create_grant_host_mapping(
    4.50 +            op->host_addr, frame, op->flags, cache_flags);
    4.51 +        if ( rc != GNTST_okay )
    4.52 +            goto undo_out;
    4.53 +    }
    4.54 +    else
    4.55 +    {
    4.56 +        if ( unlikely(!mfn_valid(frame)) ||
    4.57 +             unlikely(!((op->flags & GNTMAP_readonly) ?
    4.58 +                        get_page(mfn_to_page(frame), rd) :
    4.59 +                        get_page_and_type(mfn_to_page(frame), rd,
    4.60 +                                          PGT_writable_page))) )
    4.61          {
    4.62 -            (void)get_page(mfn_to_page(frame), rd);
    4.63 -            if ( !(op->flags & GNTMAP_readonly) )
    4.64 -                get_page_type(mfn_to_page(frame), PGT_writable_page);
    4.65 +            if ( !rd->is_dying )
    4.66 +                gdprintk(XENLOG_WARNING, "Could not pin grant frame %lx\n",
    4.67 +                         frame);
    4.68 +            rc = GNTST_general_error;
    4.69 +            goto undo_out;
    4.70 +        }
    4.71 +        
    4.72 +        if ( op->flags & GNTMAP_host_map )
    4.73 +        {
    4.74 +            rc = create_grant_host_mapping(op->host_addr, frame, op->flags, 0);
    4.75 +            if ( rc != GNTST_okay )
    4.76 +            {
    4.77 +                if ( !(op->flags & GNTMAP_readonly) )
    4.78 +                    put_page_type(mfn_to_page(frame));
    4.79 +                put_page(mfn_to_page(frame));
    4.80 +                goto undo_out;
    4.81 +            }
    4.82 +
    4.83 +            if ( op->flags & GNTMAP_device_map )
    4.84 +            {
    4.85 +                (void)get_page(mfn_to_page(frame), rd);
    4.86 +                if ( !(op->flags & GNTMAP_readonly) )
    4.87 +                    get_page_type(mfn_to_page(frame), PGT_writable_page);
    4.88 +            }
    4.89          }
    4.90      }
    4.91  
    4.92 @@ -559,10 +582,13 @@ static void
    4.93  
    4.94      if ( op->flags & GNTMAP_device_map ) 
    4.95      {
    4.96 -        if ( op->flags & GNTMAP_readonly )
    4.97 -            put_page(mfn_to_page(op->frame));
    4.98 -        else
    4.99 -            put_page_and_type(mfn_to_page(op->frame));
   4.100 +        if ( !is_iomem_page(act->frame) )
   4.101 +        {
   4.102 +            if ( op->flags & GNTMAP_readonly )
   4.103 +                put_page(mfn_to_page(op->frame));
   4.104 +            else
   4.105 +                put_page_and_type(mfn_to_page(op->frame));
   4.106 +        }
   4.107      }
   4.108  
   4.109      if ( (op->host_addr != 0) && (op->flags & GNTMAP_host_map) )
   4.110 @@ -576,10 +602,12 @@ static void
   4.111              goto unmap_out;
   4.112          }
   4.113  
   4.114 -        if ( op->flags & GNTMAP_readonly )
   4.115 +        if ( !is_iomem_page(op->frame) ) 
   4.116 +        {
   4.117 +            if ( !(op->flags & GNTMAP_readonly) )
   4.118 +                put_page_type(mfn_to_page(op->frame));
   4.119              put_page(mfn_to_page(op->frame));
   4.120 -        else
   4.121 -            put_page_and_type(mfn_to_page(op->frame));
   4.122 +        }
   4.123      }
   4.124  
   4.125      if ( (op->map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
   4.126 @@ -1595,14 +1623,16 @@ gnttab_release_mappings(
   4.127              {
   4.128                  BUG_ON(!(act->pin & GNTPIN_devr_mask));
   4.129                  act->pin -= GNTPIN_devr_inc;
   4.130 -                put_page(mfn_to_page(act->frame));
   4.131 +                if ( !is_iomem_page(act->frame) )
   4.132 +                    put_page(mfn_to_page(act->frame));
   4.133              }
   4.134  
   4.135              if ( map->flags & GNTMAP_host_map )
   4.136              {
   4.137                  BUG_ON(!(act->pin & GNTPIN_hstr_mask));
   4.138                  act->pin -= GNTPIN_hstr_inc;
   4.139 -                gnttab_release_put_page(mfn_to_page(act->frame));
   4.140 +                if ( !is_iomem_page(act->frame) )
   4.141 +                    gnttab_release_put_page(mfn_to_page(act->frame));
   4.142              }
   4.143          }
   4.144          else
   4.145 @@ -1611,14 +1641,16 @@ gnttab_release_mappings(
   4.146              {
   4.147                  BUG_ON(!(act->pin & GNTPIN_devw_mask));
   4.148                  act->pin -= GNTPIN_devw_inc;
   4.149 -                put_page_and_type(mfn_to_page(act->frame));
   4.150 +                if ( !is_iomem_page(act->frame) )
   4.151 +                    put_page_and_type(mfn_to_page(act->frame));
   4.152              }
   4.153  
   4.154              if ( map->flags & GNTMAP_host_map )
   4.155              {
   4.156                  BUG_ON(!(act->pin & GNTPIN_hstw_mask));
   4.157                  act->pin -= GNTPIN_hstw_inc;
   4.158 -                gnttab_release_put_page_and_type(mfn_to_page(act->frame));
   4.159 +                if ( !is_iomem_page(act->frame) )
   4.160 +                    gnttab_release_put_page_and_type(mfn_to_page(act->frame));
   4.161              }
   4.162  
   4.163              if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 )
     5.1 --- a/xen/include/asm-ia64/grant_table.h	Tue Nov 20 15:34:25 2007 +0000
     5.2 +++ b/xen/include/asm-ia64/grant_table.h	Tue Nov 20 17:26:48 2007 +0000
     5.3 @@ -8,7 +8,8 @@
     5.4  #define INITIAL_NR_GRANT_FRAMES 1
     5.5  
     5.6  // for grant map/unmap
     5.7 -int create_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned int flags);
     5.8 +int create_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, 
     5.9 +			      unsigned int flags, unsigned int cache_flags);
    5.10  int replace_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned long new_gpaddr, unsigned int flags);
    5.11  
    5.12  // for grant transfer
     6.1 --- a/xen/include/asm-powerpc/grant_table.h	Tue Nov 20 15:34:25 2007 +0000
     6.2 +++ b/xen/include/asm-powerpc/grant_table.h	Tue Nov 20 17:26:48 2007 +0000
     6.3 @@ -33,8 +33,8 @@ extern long pte_enter(ulong flags, ulong
     6.4  extern long pte_remove(ulong flags, ulong ptex, ulong avpn,
     6.5                         ulong *hi, ulong *lo);
     6.6  
     6.7 -int create_grant_host_mapping(
     6.8 -    unsigned long addr, unsigned long frame, unsigned int flags);
     6.9 +int create_grant_host_mapping(unsigned long addr, unsigned long frame, 
    6.10 +			      unsigned int flags, unsigned int cache_flags);
    6.11  int replace_grant_host_mapping(
    6.12      unsigned long addr, unsigned long frame, unsigned long new_addr,
    6.13      unsigned int flags);
     7.1 --- a/xen/include/asm-x86/grant_table.h	Tue Nov 20 15:34:25 2007 +0000
     7.2 +++ b/xen/include/asm-x86/grant_table.h	Tue Nov 20 17:26:48 2007 +0000
     7.3 @@ -13,8 +13,8 @@
     7.4   * Caller must own caller's BIGLOCK, is responsible for flushing the TLB, and
     7.5   * must hold a reference to the page.
     7.6   */
     7.7 -int create_grant_host_mapping(
     7.8 -    uint64_t addr, unsigned long frame, unsigned int flags);
     7.9 +int create_grant_host_mapping(uint64_t addr, unsigned long frame,
    7.10 +			      unsigned int flags, unsigned int cache_flags);
    7.11  int replace_grant_host_mapping(
    7.12      uint64_t addr, unsigned long frame, uint64_t new_addr, unsigned int flags);
    7.13  
     8.1 --- a/xen/include/public/grant_table.h	Tue Nov 20 15:34:25 2007 +0000
     8.2 +++ b/xen/include/public/grant_table.h	Tue Nov 20 17:26:48 2007 +0000
     8.3 @@ -119,6 +119,7 @@ typedef struct grant_entry grant_entry_t
     8.4   *  GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
     8.5   *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
     8.6   *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
     8.7 + *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
     8.8   */
     8.9  #define _GTF_readonly       (2)
    8.10  #define GTF_readonly        (1U<<_GTF_readonly)
    8.11 @@ -126,6 +127,12 @@ typedef struct grant_entry grant_entry_t
    8.12  #define GTF_reading         (1U<<_GTF_reading)
    8.13  #define _GTF_writing        (4)
    8.14  #define GTF_writing         (1U<<_GTF_writing)
    8.15 +#define _GTF_PWT            (5)
    8.16 +#define GTF_PWT             (1U<<_GTF_PWT)
    8.17 +#define _GTF_PCD            (6)
    8.18 +#define GTF_PCD             (1U<<_GTF_PCD)
    8.19 +#define _GTF_PAT            (7)
    8.20 +#define GTF_PAT             (1U<<_GTF_PAT)
    8.21  
    8.22  /*
    8.23   * Subflags for GTF_accept_transfer: