direct-io.hg

changeset 11510:2ba5452795d2

[POWERPC][XEN] Handle foreign page mappings correctly

The following patch performs the following:
- add free_rma() to go with allocate_rma()
- allocate_rma() returns -EINVAL if an RMA is already allocated
- PFN_TYPE_REMOTE is now PFN_TYPE_FOREIGN
- better checking of page_info in pfn2mfn()
- Stop using RPN and LPN and use PFN and MFN respectively
- Increase/decrease foreign domain refcount when another domain
maps/unmaps it

Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Tue Sep 12 11:01:04 2006 -0400 (2006-09-12)
parents 2e6c10dc7c0b
children 990bd509a5f5
files xen/arch/powerpc/domain.c xen/arch/powerpc/mm.c xen/arch/powerpc/papr/xlate.c xen/arch/powerpc/usercopy.c xen/include/asm-powerpc/mm.h
line diff
     1.1 --- a/xen/arch/powerpc/domain.c	Tue Sep 12 10:53:46 2006 -0400
     1.2 +++ b/xen/arch/powerpc/domain.c	Tue Sep 12 11:01:04 2006 -0400
     1.3 @@ -244,8 +244,7 @@ void sync_vcpu_execstate(struct vcpu *v)
     1.4  
     1.5  void domain_relinquish_resources(struct domain *d)
     1.6  {
     1.7 -    if (d->arch.rma_page)
     1.8 -        free_domheap_pages(d->arch.rma_page, d->arch.rma_order);
     1.9 +    free_rma(d);
    1.10      free_extents(d);
    1.11  }
    1.12  
     2.1 --- a/xen/arch/powerpc/mm.c	Tue Sep 12 10:53:46 2006 -0400
     2.2 +++ b/xen/arch/powerpc/mm.c	Tue Sep 12 11:01:04 2006 -0400
     2.3 @@ -299,7 +299,7 @@ int allocate_rma(struct domain *d, unsig
     2.4      ulong rma_sz;
     2.5  
     2.6      if (d->arch.rma_page)
     2.7 -        free_domheap_pages(d->arch.rma_page, d->arch.rma_order);
     2.8 +        return -EINVAL;
     2.9  
    2.10      d->arch.rma_page = alloc_domheap_pages(d, order, 0);
    2.11      if (d->arch.rma_page == NULL) {
    2.12 @@ -329,50 +329,74 @@ int allocate_rma(struct domain *d, unsig
    2.13      return 0;
    2.14  }
    2.15  
    2.16 +void free_rma(struct domain *d)
    2.17 +{
    2.18 +    if (d->arch.rma_page) {
    2.19 +        free_domheap_pages(d->arch.rma_page, d->arch.rma_order);
    2.20 +    }
    2.21 +}
    2.22 +
    2.23  ulong pfn2mfn(struct domain *d, ulong pfn, int *type)
    2.24  {
    2.25      ulong rma_base_mfn = page_to_mfn(d->arch.rma_page);
    2.26      ulong rma_size_mfn = 1UL << d->arch.rma_order;
    2.27      struct page_extents *pe;
    2.28 -
    2.29 -    if (type)
    2.30 -        *type = PFN_TYPE_NONE;
    2.31 +    ulong mfn = INVALID_MFN;
    2.32 +    int t = PFN_TYPE_NONE;
    2.33  
    2.34      /* quick tests first */
    2.35 -    if (pfn < rma_size_mfn) {
    2.36 -        if (type)
    2.37 -            *type = PFN_TYPE_RMA;
    2.38 -        return pfn + rma_base_mfn;
    2.39 -    }
    2.40 -
    2.41      if (test_bit(_DOMF_privileged, &d->domain_flags) &&
    2.42          cpu_io_mfn(pfn)) {
    2.43 -        if (type)
    2.44 -            *type = PFN_TYPE_IO;
    2.45 -        return pfn;
    2.46 +        t = PFN_TYPE_IO;
    2.47 +        mfn = pfn;
    2.48 +    } else {
    2.49 +        if (pfn < rma_size_mfn) {
    2.50 +            t = PFN_TYPE_RMA;
    2.51 +            mfn = pfn + rma_base_mfn;
    2.52 +        } else {
    2.53 +            list_for_each_entry (pe, &d->arch.extent_list, pe_list) {
    2.54 +                uint end_pfn = pe->pfn + (1 << pe->order);
    2.55 +
    2.56 +                if (pfn >= pe->pfn && pfn < end_pfn) {
    2.57 +                    t = PFN_TYPE_LOGICAL;
    2.58 +                    mfn = page_to_mfn(pe->pg) + (pfn - pe->pfn);
    2.59 +                    break;
    2.60 +                }
    2.61 +            }
    2.62 +        }
    2.63 +        BUG_ON(t != PFN_TYPE_NONE && page_get_owner(mfn_to_page(mfn)) != d);
    2.64      }
    2.65  
    2.66 -    list_for_each_entry (pe, &d->arch.extent_list, pe_list) {
    2.67 -        uint end_pfn = pe->pfn + (1 << pe->order);
    2.68 +    if (t == PFN_TYPE_NONE) {
    2.69 +        /* This hack allows dom0 to map all memory, necessary to
    2.70 +         * initialize domU state. */
    2.71 +        if (test_bit(_DOMF_privileged, &d->domain_flags) &&
    2.72 +            mfn_valid(pfn)) {
    2.73 +            struct page_info *pg;
    2.74  
    2.75 -        if (pfn >= pe->pfn && pfn < end_pfn) {
    2.76 -            if (type)
    2.77 -                *type = PFN_TYPE_LOGICAL;
    2.78 -            return page_to_mfn(pe->pg) + (pfn - pe->pfn);
    2.79 +            /* page better be allocated to some domain but not the caller */
    2.80 +            pg = mfn_to_page(pfn);
    2.81 +            if (!(pg->count_info & PGC_allocated))
    2.82 +                panic("Foreign page: 0x%lx is not owned by any domain\n",
    2.83 +                      mfn);
    2.84 +            if (page_get_owner(pg) == d)
    2.85 +                panic("Foreign page: 0x%lx is owned by this domain\n",
    2.86 +                      mfn);
    2.87 +                
    2.88 +            t = PFN_TYPE_FOREIGN;
    2.89 +            mfn = pfn;
    2.90          }
    2.91      }
    2.92  
    2.93 -    /* This hack allows dom0 to map all memory, necessary to
    2.94 -     * initialize domU state. */
    2.95 -    if (test_bit(_DOMF_privileged, &d->domain_flags) &&
    2.96 -        pfn < max_page) {
    2.97 -        if (type)
    2.98 -            *type = PFN_TYPE_REMOTE;
    2.99 -        return pfn;
   2.100 +    if (mfn == INVALID_MFN) {
   2.101 +        printk("%s: Dom[%d] pfn 0x%lx is not a valid page\n",
   2.102 +               __func__, d->domain_id, pfn);
   2.103      }
   2.104  
   2.105 -    BUG();
   2.106 -    return INVALID_MFN;
   2.107 +    if (type)
   2.108 +        *type = t;
   2.109 +
   2.110 +    return mfn;
   2.111  }
   2.112  
   2.113  void guest_physmap_add_page(
     3.1 --- a/xen/arch/powerpc/papr/xlate.c	Tue Sep 12 10:53:46 2006 -0400
     3.2 +++ b/xen/arch/powerpc/papr/xlate.c	Tue Sep 12 11:01:04 2006 -0400
     3.3 @@ -118,8 +118,8 @@ static void h_enter(struct cpu_user_regs
     3.4      int pgshift = PAGE_SHIFT;
     3.5      ulong idx;
     3.6      int limit = 0;                /* how many PTEs to examine in the PTEG */
     3.7 -    ulong lpn;
     3.8 -    ulong rpn;
     3.9 +    ulong pfn;
    3.10 +    ulong mfn;
    3.11      struct vcpu *v = get_current();
    3.12      struct domain *d = v->domain;
    3.13      int mtype;
    3.14 @@ -160,11 +160,11 @@ static void h_enter(struct cpu_user_regs
    3.15      /* get the correct logical RPN in terms of 4K pages need to mask
    3.16       * off lp bits and unused arpn bits if this is a large page */
    3.17  
    3.18 -    lpn = ~0ULL << (pgshift - PAGE_SHIFT);
    3.19 -    lpn = pte.bits.rpn & lpn;
    3.20 +    pfn = ~0ULL << (pgshift - PAGE_SHIFT);
    3.21 +    pfn = pte.bits.rpn & pfn;
    3.22  
    3.23 -    rpn = pfn2mfn(d, lpn, &mtype);
    3.24 -    if (rpn == INVALID_MFN) {
    3.25 +    mfn = pfn2mfn(d, pfn, &mtype);
    3.26 +    if (mfn == INVALID_MFN) {
    3.27          regs->gprs[3] =  H_Parameter;
    3.28          return;
    3.29      }
    3.30 @@ -173,8 +173,8 @@ static void h_enter(struct cpu_user_regs
    3.31          /* only a privilaged dom can access outside IO space */
    3.32          if ( !test_bit(_DOMF_privileged, &d->domain_flags) ) {
    3.33              regs->gprs[3] =  H_Privilege;
    3.34 -            printk("%s: unprivileged access to logical page: 0x%lx\n",
    3.35 -                   __func__, lpn);
    3.36 +            printk("%s: unprivileged access to physical page: 0x%lx\n",
    3.37 +                   __func__, pfn);
    3.38              return;
    3.39          }
    3.40  
    3.41 @@ -192,7 +192,7 @@ static void h_enter(struct cpu_user_regs
    3.42          }
    3.43      }
    3.44      /* fixup the RPN field of our local PTE copy */
    3.45 -    pte.bits.rpn = rpn | lp_bits;
    3.46 +    pte.bits.rpn = mfn | lp_bits;
    3.47  
    3.48      /* clear reserved bits in high word */
    3.49      pte.bits.lock = 0x0;
    3.50 @@ -211,12 +211,12 @@ static void h_enter(struct cpu_user_regs
    3.51  
    3.52          /* data manipulations should be done prior to the pte insertion. */
    3.53      if ( flags & H_ZERO_PAGE ) {
    3.54 -        memset((void *)(rpn << PAGE_SHIFT), 0, 1UL << pgshift);
    3.55 +        memset((void *)(mfn << PAGE_SHIFT), 0, 1UL << pgshift);
    3.56      }
    3.57  
    3.58      if ( flags & H_ICACHE_INVALIDATE ) {
    3.59          ulong k;
    3.60 -        ulong addr = rpn << PAGE_SHIFT;
    3.61 +        ulong addr = mfn << PAGE_SHIFT;
    3.62  
    3.63          for (k = 0; k < (1UL << pgshift); k += L1_CACHE_BYTES) {
    3.64              dcbst(addr + k);
    3.65 @@ -229,7 +229,7 @@ static void h_enter(struct cpu_user_regs
    3.66  
    3.67      if ( flags & H_ICACHE_SYNCHRONIZE ) {
    3.68          ulong k;
    3.69 -        ulong addr = rpn << PAGE_SHIFT;
    3.70 +        ulong addr = mfn << PAGE_SHIFT;
    3.71          for (k = 0; k < (1UL << pgshift); k += L1_CACHE_BYTES) {
    3.72              icbi(addr + k);
    3.73              sync();
    3.74 @@ -252,6 +252,26 @@ static void h_enter(struct cpu_user_regs
    3.75              regs->gprs[3] = H_Success;
    3.76              regs->gprs[4] = idx;
    3.77  
    3.78 +            
    3.79 +            switch (mtype) {
    3.80 +            case PFN_TYPE_IO:
    3.81 +                break;
    3.82 +            case PFN_TYPE_FOREIGN:
    3.83 +            {
    3.84 +                struct page_info *pg = mfn_to_page(mfn);
    3.85 +                struct domain *f = page_get_owner(pg);
    3.86 +
    3.87 +                BUG_ON(f == d);
    3.88 +                get_domain(f);
    3.89 +            }
    3.90 +                break;
    3.91 +            case PFN_TYPE_RMA:
    3.92 +            case PFN_TYPE_LOGICAL:
    3.93 +                break;
    3.94 +            default:
    3.95 +                BUG();
    3.96 +            }
    3.97 +
    3.98              return;
    3.99          }
   3.100      }
   3.101 @@ -480,9 +500,21 @@ static void h_remove(struct cpu_user_reg
   3.102  
   3.103      /* XXX - I'm very skeptical of doing ANYTHING if not bits.v */
   3.104      /* XXX - I think the spec should be questioned in this case (MFM) */
   3.105 -    if (pte->bits.v == 0) {
   3.106 +    if (lpte.bits.v == 0) {
   3.107          printk("%s: removing invalid entry\n", __func__);
   3.108      }
   3.109 +
   3.110 +    if (lpte.bits.v) {
   3.111 +        ulong mfn = lpte.bits.rpn;
   3.112 +        if (!cpu_io_mfn(mfn)) {
   3.113 +            struct page_info *pg = mfn_to_page(mfn);
   3.114 +            struct domain *f = page_get_owner(pg);
   3.115 +
   3.116 +            if (f != d)
   3.117 +                put_domain(f);
   3.118 +        }
   3.119 +    }
   3.120 +
   3.121      asm volatile("eieio; std %1, 0(%0); ptesync"
   3.122              :
   3.123              : "b" (pte), "r" (0)
     4.1 --- a/xen/arch/powerpc/usercopy.c	Tue Sep 12 10:53:46 2006 -0400
     4.2 +++ b/xen/arch/powerpc/usercopy.c	Tue Sep 12 11:01:04 2006 -0400
     4.3 @@ -57,10 +57,10 @@ static unsigned long paddr_to_maddr(unsi
     4.4      case PFN_TYPE_LOGICAL:
     4.5          break;
     4.6  
     4.7 -    case PFN_TYPE_REMOTE:
     4.8 +    case PFN_TYPE_FOREIGN:
     4.9          /* I don't think this should ever happen, but I suppose it
    4.10           * could be possible */
    4.11 -        printk("%s: Dom:%d paddr: 0x%lx type: REMOTE\n",
    4.12 +        printk("%s: Dom:%d paddr: 0x%lx type: FOREIGN\n",
    4.13                 __func__, d->domain_id, paddr);
    4.14          WARN();
    4.15          break;
     5.1 --- a/xen/include/asm-powerpc/mm.h	Tue Sep 12 10:53:46 2006 -0400
     5.2 +++ b/xen/include/asm-powerpc/mm.h	Tue Sep 12 11:01:04 2006 -0400
     5.3 @@ -154,7 +154,7 @@ static inline void put_page(struct page_
     5.4      while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) );
     5.5  
     5.6      if ( unlikely((nx & PGC_count_mask) == 0) ) {
     5.7 -        panic("about to free page\n");
     5.8 +        panic("about to free page: 0x%lx\n", page_to_mfn(page));
     5.9          free_domheap_page(page);
    5.10      }
    5.11  }
    5.12 @@ -239,7 +239,7 @@ extern int update_grant_va_mapping(unsig
    5.13  #define PFN_TYPE_RMA 1
    5.14  #define PFN_TYPE_LOGICAL 2
    5.15  #define PFN_TYPE_IO 3
    5.16 -#define PFN_TYPE_REMOTE 4
    5.17 +#define PFN_TYPE_FOREIGN 4
    5.18  
    5.19  extern ulong pfn2mfn(struct domain *d, ulong pfn, int *type);
    5.20  
    5.21 @@ -259,6 +259,7 @@ static inline unsigned long gmfn_to_mfn(
    5.22  #define mfn_to_gmfn(_d, mfn) (mfn)
    5.23  
    5.24  extern int allocate_rma(struct domain *d, unsigned int order_pages);
    5.25 +extern void free_rma(struct domain *d);
    5.26  extern uint allocate_extents(struct domain *d, uint nrpages, uint rma_nrpages);
    5.27  extern void free_extents(struct domain *d);
    5.28