debuggers.hg

changeset 19970:c0cb307d927f

Mapping grant references into HVM guests, take 2

After some discussion, here's a second version of the patch I posted a
couple of weeks back to map grant references into HVM guests. As
before, this is done by modifying the P2M map, but this time there's
no new hypercall to do it. Instead, the existing GNTTABOP_map is
overloaded to perform a P2M mapping if called from a shadow mode
translate guest. This matches the IA64 API.

Signed-off-by: Steven Smith <steven.smith@citrix.com>
Acked-by: Tim Deegan <tim.deegan@citrix.com>
CC: Bhaskar Jayaraman <Bhaskar.Jayaraman@lsi.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jul 13 12:35:34 2009 +0100 (2009-07-13)
parents 09dbdf12c33d
children 75e63b73075a
files xen/arch/x86/hvm/emulate.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/stdvga.c xen/arch/x86/hvm/svm/emulate.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/viridian.c xen/arch/x86/mm.c xen/arch/x86/mm/hap/p2m-ept.c xen/arch/x86/mm/p2m.c xen/arch/x86/mm/paging.c xen/arch/x86/mm/shadow/common.c xen/arch/x86/mm/shadow/multi.c xen/common/grant_table.c xen/include/asm-ia64/grant_table.h xen/include/asm-x86/grant_table.h xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/support.h xen/include/asm-x86/p2m.h
line diff
     1.1 --- a/xen/arch/x86/hvm/emulate.c	Mon Jul 13 12:18:04 2009 +0100
     1.2 +++ b/xen/arch/x86/hvm/emulate.c	Mon Jul 13 12:35:34 2009 +0100
     1.3 @@ -408,20 +408,23 @@ static int __hvmemul_read(
     1.4      rc = ((access_type == hvm_access_insn_fetch) ?
     1.5            hvm_fetch_from_guest_virt(p_data, addr, bytes, pfec) :
     1.6            hvm_copy_from_guest_virt(p_data, addr, bytes, pfec));
     1.7 -    if ( rc == HVMCOPY_bad_gva_to_gfn )
     1.8 +
     1.9 +    switch ( rc )
    1.10 +    {
    1.11 +    case HVMCOPY_bad_gva_to_gfn:
    1.12          return X86EMUL_EXCEPTION;
    1.13 -
    1.14 -    if ( rc == HVMCOPY_bad_gfn_to_mfn )
    1.15 -    {
    1.16 +    case HVMCOPY_unhandleable:
    1.17 +        return X86EMUL_UNHANDLEABLE;
    1.18 +    case  HVMCOPY_bad_gfn_to_mfn:
    1.19          if ( access_type == hvm_access_insn_fetch )
    1.20              return X86EMUL_UNHANDLEABLE;
    1.21 -
    1.22          rc = hvmemul_linear_to_phys(
    1.23              addr, &gpa, bytes, &reps, pfec, hvmemul_ctxt);
    1.24          if ( rc != X86EMUL_OKAY )
    1.25              return rc;
    1.26 -
    1.27          return hvmemul_do_mmio(gpa, &reps, bytes, 0, IOREQ_READ, 0, p_data);
    1.28 +    default:
    1.29 +        break;
    1.30      }
    1.31  
    1.32      return X86EMUL_OKAY;
    1.33 @@ -496,18 +499,22 @@ static int hvmemul_write(
    1.34          pfec |= PFEC_user_mode;
    1.35  
    1.36      rc = hvm_copy_to_guest_virt(addr, p_data, bytes, pfec);
    1.37 -    if ( rc == HVMCOPY_bad_gva_to_gfn )
    1.38 +
    1.39 +    switch ( rc )
    1.40 +    {
    1.41 +    case HVMCOPY_bad_gva_to_gfn:
    1.42          return X86EMUL_EXCEPTION;
    1.43 -
    1.44 -    if ( rc == HVMCOPY_bad_gfn_to_mfn )
    1.45 -    {
    1.46 +    case HVMCOPY_unhandleable:
    1.47 +        return X86EMUL_UNHANDLEABLE;
    1.48 +    case  HVMCOPY_bad_gfn_to_mfn:
    1.49          rc = hvmemul_linear_to_phys(
    1.50              addr, &gpa, bytes, &reps, pfec, hvmemul_ctxt);
    1.51          if ( rc != X86EMUL_OKAY )
    1.52              return rc;
    1.53 -
    1.54          return hvmemul_do_mmio(gpa, &reps, bytes, 0,
    1.55                                 IOREQ_WRITE, 0, p_data);
    1.56 +    default:
    1.57 +        break;
    1.58      }
    1.59  
    1.60      return X86EMUL_OKAY;
    1.61 @@ -636,12 +643,12 @@ static int hvmemul_rep_movs(
    1.62          return rc;
    1.63  
    1.64      (void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
    1.65 -    if ( !p2m_is_ram(p2mt) )
    1.66 +    if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
    1.67          return hvmemul_do_mmio(
    1.68              sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL);
    1.69  
    1.70      (void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
    1.71 -    if ( !p2m_is_ram(p2mt) )
    1.72 +    if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
    1.73          return hvmemul_do_mmio(
    1.74              dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL);
    1.75  
     2.1 --- a/xen/arch/x86/hvm/hvm.c	Mon Jul 13 12:18:04 2009 +0100
     2.2 +++ b/xen/arch/x86/hvm/hvm.c	Mon Jul 13 12:35:34 2009 +0100
     2.3 @@ -1589,6 +1589,8 @@ static enum hvm_copy_result __hvm_copy(
     2.4  
     2.5          mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
     2.6  
     2.7 +        if ( p2m_is_grant(p2mt) )
     2.8 +            return HVMCOPY_unhandleable;
     2.9          if ( !p2m_is_ram(p2mt) )
    2.10              return HVMCOPY_bad_gfn_to_mfn;
    2.11          ASSERT(mfn_valid(mfn));
    2.12 @@ -1997,7 +1999,8 @@ enum hvm_intblk hvm_interrupt_blocked(st
    2.13  static long hvm_grant_table_op(
    2.14      unsigned int cmd, XEN_GUEST_HANDLE(void) uop, unsigned int count)
    2.15  {
    2.16 -    if ( (cmd != GNTTABOP_query_size) && (cmd != GNTTABOP_setup_table) )
    2.17 +    if ( (cmd != GNTTABOP_query_size) && (cmd != GNTTABOP_setup_table) &&
    2.18 +         (cmd != GNTTABOP_map_grant_ref) && (cmd != GNTTABOP_unmap_grant_ref) )
    2.19          return -ENOSYS; /* all other commands need auditing */
    2.20      return do_grant_table_op(cmd, uop, count);
    2.21  }
    2.22 @@ -2804,17 +2807,36 @@ long do_hvm_op(unsigned long op, XEN_GUE
    2.23              
    2.24          if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
    2.25              goto param_fail4;
    2.26 -            
    2.27 -        rc = 0;
    2.28 -        
    2.29 +
    2.30          for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
    2.31          {
    2.32              p2m_type_t t;
    2.33 +            p2m_type_t nt;
    2.34              mfn_t mfn;
    2.35              mfn = gfn_to_mfn(d, pfn, &t);
    2.36 -            p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
    2.37 +            if ( p2m_is_grant(t) )
    2.38 +            {
    2.39 +                gdprintk(XENLOG_WARNING,
    2.40 +                         "type for pfn 0x%lx changed to grant while "
    2.41 +                         "we were working?\n", pfn);
    2.42 +                goto param_fail4;
    2.43 +            }
    2.44 +            else
    2.45 +            {
    2.46 +                nt = p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
    2.47 +                if ( nt != t )
    2.48 +                {
    2.49 +                    gdprintk(XENLOG_WARNING,
    2.50 +                             "type of pfn 0x%lx changed from %d to %d while "
    2.51 +                             "we were trying to change it to %d\n",
    2.52 +                             pfn, t, nt, memtype[a.hvmmem_type]);
    2.53 +                    goto param_fail4;
    2.54 +                }
    2.55 +            }
    2.56          }
    2.57 -         
    2.58 +
    2.59 +        rc = 0;
    2.60 +
    2.61      param_fail4:
    2.62          rcu_unlock_domain(d);
    2.63          break;
     3.1 --- a/xen/arch/x86/hvm/stdvga.c	Mon Jul 13 12:18:04 2009 +0100
     3.2 +++ b/xen/arch/x86/hvm/stdvga.c	Mon Jul 13 12:35:34 2009 +0100
     3.3 @@ -478,8 +478,8 @@ static int mmio_move(struct hvm_hw_stdvg
     3.4              for ( i = 0; i < p->count; i++ ) 
     3.5              {
     3.6                  tmp = stdvga_mem_read(addr, p->size);
     3.7 -                if ( hvm_copy_to_guest_phys(data, &tmp, p->size) ==
     3.8 -                     HVMCOPY_bad_gfn_to_mfn )
     3.9 +                if ( hvm_copy_to_guest_phys(data, &tmp, p->size) !=
    3.10 +                     HVMCOPY_okay )
    3.11                  {
    3.12                      (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
    3.13                      /*
    3.14 @@ -500,8 +500,8 @@ static int mmio_move(struct hvm_hw_stdvg
    3.15              uint32_t addr = p->addr, data = p->data, tmp;
    3.16              for ( i = 0; i < p->count; i++ )
    3.17              {
    3.18 -                if ( hvm_copy_from_guest_phys(&tmp, data, p->size) ==
    3.19 -                     HVMCOPY_bad_gfn_to_mfn )
    3.20 +                if ( hvm_copy_from_guest_phys(&tmp, data, p->size) !=
    3.21 +                     HVMCOPY_okay )
    3.22                  {
    3.23                      (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
    3.24                      if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) ||
     4.1 --- a/xen/arch/x86/hvm/svm/emulate.c	Mon Jul 13 12:18:04 2009 +0100
     4.2 +++ b/xen/arch/x86/hvm/svm/emulate.c	Mon Jul 13 12:35:34 2009 +0100
     4.3 @@ -121,11 +121,10 @@ static int fetch(struct vcpu *v, u8 *buf
     4.4      switch ( hvm_fetch_from_guest_virt(buf, addr, len, pfec) )
     4.5      {
     4.6      case HVMCOPY_okay:
     4.7 -        return 1;
     4.8 +        break;
     4.9      case HVMCOPY_bad_gva_to_gfn:
    4.10          /* OK just to give up; we'll have injected #PF already */
    4.11          return 0;
    4.12 -    case HVMCOPY_bad_gfn_to_mfn:
    4.13      default:
    4.14          /* Not OK: fetches from non-RAM pages are not supportable. */
    4.15          gdprintk(XENLOG_WARNING, "Bad instruction fetch at %#lx (%#lx)\n",
    4.16 @@ -133,6 +132,7 @@ static int fetch(struct vcpu *v, u8 *buf
    4.17          hvm_inject_exception(TRAP_gp_fault, 0, 0);
    4.18          return 0;
    4.19      }
    4.20 +    return 1;
    4.21  }
    4.22  
    4.23  int __get_instruction_length_from_list(struct vcpu *v,
     5.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Jul 13 12:18:04 2009 +0100
     5.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Jul 13 12:35:34 2009 +0100
     5.3 @@ -938,8 +938,27 @@ static void svm_do_nested_pgfault(paddr_
     5.4      }
     5.5  
     5.6      /* Log-dirty: mark the page dirty and let the guest write it again */
     5.7 -    paging_mark_dirty(current->domain, mfn_x(mfn));
     5.8 -    p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
     5.9 +    if ( p2mt == p2m_ram_logdirty )
    5.10 +    {
    5.11 +        paging_mark_dirty(current->domain, mfn_x(mfn));
    5.12 +        p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
    5.13 +        return;
    5.14 +    }
    5.15 +
    5.16 +    /* Okay, this shouldn't happen.  Maybe the guest was writing to a
    5.17 +       read-only grant mapping? */
    5.18 +    if ( p2mt == p2m_grant_map_ro )
    5.19 +    {
    5.20 +        /* Naughty... */
    5.21 +        gdprintk(XENLOG_WARNING,
    5.22 +                 "trying to write to read-only grant mapping\n");
    5.23 +        hvm_inject_exception(TRAP_gp_fault, 0, 0);
    5.24 +        return;
    5.25 +    }
    5.26 +
    5.27 +    /* Something bad has happened; either Xen or the hardware have
    5.28 +       screwed up. */
    5.29 +    gdprintk(XENLOG_WARNING, "unexpected SVM nested page fault\n");
    5.30  }
    5.31  
    5.32  static void svm_fpu_dirty_intercept(void)
     6.1 --- a/xen/arch/x86/hvm/viridian.c	Mon Jul 13 12:18:04 2009 +0100
     6.2 +++ b/xen/arch/x86/hvm/viridian.c	Mon Jul 13 12:35:34 2009 +0100
     6.3 @@ -213,7 +213,7 @@ int wrmsr_viridian_regs(uint32_t idx, ui
     6.4          {
     6.5              uint32_t word = 0;
     6.6              paddr_t page_start = val & ~1ul;
     6.7 -            hvm_copy_to_guest_phys(page_start, &word, sizeof(word));
     6.8 +            (void)hvm_copy_to_guest_phys(page_start, &word, sizeof(word));
     6.9          }
    6.10          break;
    6.11  
     7.1 --- a/xen/arch/x86/mm.c	Mon Jul 13 12:18:04 2009 +0100
     7.2 +++ b/xen/arch/x86/mm.c	Mon Jul 13 12:35:34 2009 +0100
     7.3 @@ -2672,10 +2672,16 @@ int do_mmuext_op(
     7.4              break;
     7.5          }
     7.6  
     7.7 -        okay = 1;
     7.8          gmfn  = op.arg1.mfn;
     7.9          mfn = gmfn_to_mfn(FOREIGNDOM, gmfn);
    7.10 +        if ( mfn == INVALID_MFN )
    7.11 +        {
    7.12 +            MEM_LOG("Bad gmfn_to_mfn");
    7.13 +            rc = -EFAULT;
    7.14 +            break;
    7.15 +        }
    7.16          page = mfn_to_page(mfn);
    7.17 +        okay = 1;
    7.18  
    7.19          switch ( op.cmd )
    7.20          {
    7.21 @@ -3475,11 +3481,37 @@ static int destroy_grant_va_mapping(
    7.22      return replace_grant_va_mapping(addr, frame, l1e_empty(), v);
    7.23  }
    7.24  
    7.25 +static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame,
    7.26 +                                    unsigned int flags,
    7.27 +                                    unsigned int cache_flags)
    7.28 +{
    7.29 +    p2m_type_t p2mt;
    7.30 +    int rc;
    7.31 +
    7.32 +    if ( cache_flags  || (flags & ~GNTMAP_readonly) != GNTMAP_host_map )
    7.33 +        return GNTST_general_error;
    7.34 +
    7.35 +    if ( flags & GNTMAP_readonly )
    7.36 +        p2mt = p2m_grant_map_ro;
    7.37 +    else
    7.38 +        p2mt = p2m_grant_map_rw;
    7.39 +    rc = guest_physmap_add_entry(current->domain, addr >> PAGE_SHIFT,
    7.40 +                                 frame, 0, p2mt);
    7.41 +    if ( rc )
    7.42 +        return GNTST_general_error;
    7.43 +    else
    7.44 +        return GNTST_okay;
    7.45 +}
    7.46 +
    7.47  int create_grant_host_mapping(uint64_t addr, unsigned long frame, 
    7.48                                unsigned int flags, unsigned int cache_flags)
    7.49  {
    7.50 -    l1_pgentry_t pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
    7.51 -
    7.52 +    l1_pgentry_t pte;
    7.53 +
    7.54 +    if ( paging_mode_external(current->domain) )
    7.55 +        return create_grant_p2m_mapping(addr, frame, flags, cache_flags);
    7.56 +
    7.57 +    pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
    7.58      if ( (flags & GNTMAP_application_map) )
    7.59          l1e_add_flags(pte,_PAGE_USER);
    7.60      if ( !(flags & GNTMAP_readonly) )
    7.61 @@ -3496,6 +3528,29 @@ int create_grant_host_mapping(uint64_t a
    7.62      return create_grant_va_mapping(addr, pte, current);
    7.63  }
    7.64  
    7.65 +static int replace_grant_p2m_mapping(
    7.66 +    uint64_t addr, unsigned long frame, uint64_t new_addr, unsigned int flags)
    7.67 +{
    7.68 +    unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
    7.69 +    p2m_type_t type;
    7.70 +    mfn_t old_mfn;
    7.71 +
    7.72 +    if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
    7.73 +        return GNTST_general_error;
    7.74 +
    7.75 +    old_mfn = gfn_to_mfn_current(gfn, &type);
    7.76 +    if ( !p2m_is_grant(type) || mfn_x(old_mfn) != frame )
    7.77 +    {
    7.78 +        gdprintk(XENLOG_WARNING,
    7.79 +                 "replace_grant_p2m_mapping: old mapping invalid (type %d, mfn %lx, frame %lx)\n",
    7.80 +                 type, mfn_x(old_mfn), frame);
    7.81 +        return GNTST_general_error;
    7.82 +    }
    7.83 +    guest_physmap_remove_page(current->domain, gfn, frame, 0);
    7.84 +
    7.85 +    return GNTST_okay;
    7.86 +}
    7.87 +
    7.88  int replace_grant_host_mapping(
    7.89      uint64_t addr, unsigned long frame, uint64_t new_addr, unsigned int flags)
    7.90  {
    7.91 @@ -3505,6 +3560,9 @@ int replace_grant_host_mapping(
    7.92      struct page_info *l1pg;
    7.93      int rc;
    7.94      
    7.95 +    if ( paging_mode_external(current->domain) )
    7.96 +        return replace_grant_p2m_mapping(addr, frame, new_addr, flags);
    7.97 +
    7.98      if ( flags & GNTMAP_contains_pte )
    7.99      {
   7.100          if ( !new_addr )
     8.1 --- a/xen/arch/x86/mm/hap/p2m-ept.c	Mon Jul 13 12:18:04 2009 +0100
     8.2 +++ b/xen/arch/x86/mm/hap/p2m-ept.c	Mon Jul 13 12:35:34 2009 +0100
     8.3 @@ -39,10 +39,12 @@ static void ept_p2m_type_to_flags(ept_en
     8.4              return;
     8.5          case p2m_ram_rw:
     8.6          case p2m_mmio_direct:
     8.7 +        case p2m_grant_map_rw:
     8.8               entry->r = entry->w = entry->x = 1;
     8.9              return;
    8.10          case p2m_ram_logdirty:
    8.11          case p2m_ram_ro:
    8.12 +        case p2m_grant_map_ro:
    8.13               entry->r = entry->x = 1;
    8.14               entry->w = 0;
    8.15              return;
     9.1 --- a/xen/arch/x86/mm/p2m.c	Mon Jul 13 12:18:04 2009 +0100
     9.2 +++ b/xen/arch/x86/mm/p2m.c	Mon Jul 13 12:35:34 2009 +0100
     9.3 @@ -102,17 +102,27 @@
     9.4  
     9.5  static unsigned long p2m_type_to_flags(p2m_type_t t) 
     9.6  {
     9.7 -    unsigned long flags = (t & 0x7UL) << 9;
     9.8 +    unsigned long flags;
     9.9 +#ifdef __x86_64__
    9.10 +    flags = (unsigned long)(t & 0x3fff) << 9;
    9.11 +#else
    9.12 +    flags = (t & 0x7UL) << 9;
    9.13 +#endif
    9.14 +#ifndef HAVE_GRANT_MAP_P2M
    9.15 +    BUG_ON(p2m_is_grant(t));
    9.16 +#endif
    9.17      switch(t)
    9.18      {
    9.19      case p2m_invalid:
    9.20      default:
    9.21          return flags;
    9.22      case p2m_ram_rw:
    9.23 +    case p2m_grant_map_rw:
    9.24          return flags | P2M_BASE_FLAGS | _PAGE_RW;
    9.25      case p2m_ram_logdirty:
    9.26          return flags | P2M_BASE_FLAGS;
    9.27      case p2m_ram_ro:
    9.28 +    case p2m_grant_map_ro:
    9.29          return flags | P2M_BASE_FLAGS;
    9.30      case p2m_mmio_dm:
    9.31          return flags;
    9.32 @@ -1321,7 +1331,7 @@ pod_retry_l1:
    9.33      unmap_domain_page(l1e);
    9.34  
    9.35      ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t));
    9.36 -    return (p2m_is_valid(*t)) ? mfn : _mfn(INVALID_MFN);
    9.37 +    return (p2m_is_valid(*t) || p2m_is_grant(*t)) ? mfn : _mfn(INVALID_MFN);
    9.38  }
    9.39  
    9.40  /* Read the current domain's p2m table (through the linear mapping). */
    9.41 @@ -1438,7 +1448,7 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
    9.42                  }
    9.43              }
    9.44  
    9.45 -            if ( p2m_is_valid(p2mt) )
    9.46 +            if ( p2m_is_valid(p2mt) || p2m_is_grant(p2mt) )
    9.47                  mfn = _mfn(l1e_get_pfn(l1e));
    9.48              else 
    9.49                  /* XXX see above */
    9.50 @@ -1790,18 +1800,21 @@ static void audit_p2m(struct domain *d)
    9.51  
    9.52                      for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ )
    9.53                      {
    9.54 +                        p2m_type_t type;
    9.55 +
    9.56 +                        type = p2m_flags_to_type(l1e_get_flags(l1e[i1]));
    9.57                          if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) )
    9.58                          {
    9.59 -                            if ( p2m_flags_to_type(l1e_get_flags(l1e[i1]))
    9.60 -                                 == p2m_populate_on_demand )
    9.61 -                            entry_count++;
    9.62 +                            if ( type == p2m_populate_on_demand )
    9.63 +                                entry_count++;
    9.64                              continue;
    9.65                          }
    9.66                          mfn = l1e_get_pfn(l1e[i1]);
    9.67                          ASSERT(mfn_valid(_mfn(mfn)));
    9.68                          m2pfn = get_gpfn_from_mfn(mfn);
    9.69                          if ( m2pfn != gfn &&
    9.70 -                             p2m_flags_to_type(l1e_get_flags(l1e[i1])) != p2m_mmio_direct )
    9.71 +                             type != p2m_mmio_direct &&
    9.72 +                             !p2m_is_grant(type) )
    9.73                          {
    9.74                              pmbad++;
    9.75                              printk("mismatch: gfn %#lx -> mfn %#lx"
    9.76 @@ -1854,6 +1867,8 @@ p2m_remove_page(struct domain *d, unsign
    9.77                  unsigned int page_order)
    9.78  {
    9.79      unsigned long i;
    9.80 +    mfn_t mfn_return;
    9.81 +    p2m_type_t t;
    9.82  
    9.83      if ( !paging_mode_translate(d) )
    9.84      {
    9.85 @@ -1865,9 +1880,14 @@ p2m_remove_page(struct domain *d, unsign
    9.86  
    9.87      P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn);
    9.88  
    9.89 +    for ( i = 0; i < (1UL << page_order); i++ )
    9.90 +    {
    9.91 +        mfn_return = p2m_gfn_to_mfn(d, gfn + i, &t, p2m_query);
    9.92 +        if ( !p2m_is_grant(t) )
    9.93 +            set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
    9.94 +        ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
    9.95 +    }
    9.96      set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid);
    9.97 -    for ( i = 0; i < (1UL << page_order); i++ )
    9.98 -        set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
    9.99  }
   9.100  
   9.101  void
   9.102 @@ -2003,7 +2023,14 @@ guest_physmap_add_entry(struct domain *d
   9.103      for ( i = 0; i < (1UL << page_order); i++ )
   9.104      {
   9.105          omfn = gfn_to_mfn_query(d, gfn + i, &ot);
   9.106 -        if ( p2m_is_ram(ot) )
   9.107 +        if ( p2m_is_grant(ot) )
   9.108 +        {
   9.109 +            /* Really shouldn't be unmapping grant maps this way */
   9.110 +            domain_crash(d);
   9.111 +            p2m_unlock(d->arch.p2m);
   9.112 +            return -EINVAL;
   9.113 +        }
   9.114 +        else if ( p2m_is_ram(ot) )
   9.115          {
   9.116              ASSERT(mfn_valid(omfn));
   9.117              set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
   9.118 @@ -2018,6 +2045,8 @@ guest_physmap_add_entry(struct domain *d
   9.119      /* Then, look for m->p mappings for this range and deal with them */
   9.120      for ( i = 0; i < (1UL << page_order); i++ )
   9.121      {
   9.122 +        if ( page_get_owner(mfn_to_page(_mfn(mfn + i))) != d )
   9.123 +            continue;
   9.124          ogfn = mfn_to_gfn(d, _mfn(mfn+i));
   9.125          if (
   9.126  #ifdef __x86_64__
   9.127 @@ -2033,6 +2062,9 @@ guest_physmap_add_entry(struct domain *d
   9.128              P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
   9.129                        mfn + i, ogfn, gfn + i);
   9.130              omfn = gfn_to_mfn_query(d, ogfn, &ot);
   9.131 +            /* If we get here, we know the local domain owns the page,
   9.132 +               so it can't have been grant mapped in. */
   9.133 +            BUG_ON( p2m_is_grant(ot) );
   9.134              if ( p2m_is_ram(ot) )
   9.135              {
   9.136                  ASSERT(mfn_valid(omfn));
   9.137 @@ -2049,8 +2081,11 @@ guest_physmap_add_entry(struct domain *d
   9.138      {
   9.139          if ( !set_p2m_entry(d, gfn, _mfn(mfn), page_order, t) )
   9.140              rc = -EINVAL;
   9.141 -        for ( i = 0; i < (1UL << page_order); i++ )
   9.142 -            set_gpfn_from_mfn(mfn+i, gfn+i);
   9.143 +        if ( !p2m_is_grant(t) )
   9.144 +        {
   9.145 +            for ( i = 0; i < (1UL << page_order); i++ )
   9.146 +                set_gpfn_from_mfn(mfn+i, gfn+i);
   9.147 +        }
   9.148      }
   9.149      else
   9.150      {
   9.151 @@ -2090,6 +2125,8 @@ void p2m_change_type_global(struct domai
   9.152      int i4;
   9.153  #endif /* CONFIG_PAGING_LEVELS == 4 */
   9.154  
   9.155 +    BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
   9.156 +
   9.157      if ( !paging_mode_translate(d) )
   9.158          return;
   9.159  
   9.160 @@ -2185,6 +2222,8 @@ p2m_type_t p2m_change_type(struct domain
   9.161      p2m_type_t pt;
   9.162      mfn_t mfn;
   9.163  
   9.164 +    BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
   9.165 +
   9.166      p2m_lock(d->arch.p2m);
   9.167  
   9.168      mfn = gfn_to_mfn(d, gfn, &pt);
   9.169 @@ -2207,7 +2246,12 @@ set_mmio_p2m_entry(struct domain *d, uns
   9.170          return 0;
   9.171  
   9.172      omfn = gfn_to_mfn_query(d, gfn, &ot);
   9.173 -    if ( p2m_is_ram(ot) )
   9.174 +    if ( p2m_is_grant(ot) )
   9.175 +    {
   9.176 +        domain_crash(d);
   9.177 +        return 0;
   9.178 +    }
   9.179 +    else if ( p2m_is_ram(ot) )
   9.180      {
   9.181          ASSERT(mfn_valid(omfn));
   9.182          set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
    10.1 --- a/xen/arch/x86/mm/paging.c	Mon Jul 13 12:18:04 2009 +0100
    10.2 +++ b/xen/arch/x86/mm/paging.c	Mon Jul 13 12:35:34 2009 +0100
    10.3 @@ -272,7 +272,8 @@ void paging_mark_dirty(struct domain *d,
    10.4  
    10.5      gmfn = _mfn(guest_mfn);
    10.6  
    10.7 -    if ( !paging_mode_log_dirty(d) || !mfn_valid(gmfn) )
    10.8 +    if ( !paging_mode_log_dirty(d) || !mfn_valid(gmfn) ||
    10.9 +         page_get_owner(mfn_to_page(gmfn)) != d )
   10.10          return;
   10.11  
   10.12      log_dirty_lock(d);
    11.1 --- a/xen/arch/x86/mm/shadow/common.c	Mon Jul 13 12:18:04 2009 +0100
    11.2 +++ b/xen/arch/x86/mm/shadow/common.c	Mon Jul 13 12:35:34 2009 +0100
    11.3 @@ -172,10 +172,12 @@ hvm_read(enum x86_segment seg,
    11.4          return X86EMUL_OKAY;
    11.5      case HVMCOPY_bad_gva_to_gfn:
    11.6          return X86EMUL_EXCEPTION;
    11.7 -    default:
    11.8 -        break;
    11.9 +    case HVMCOPY_bad_gfn_to_mfn:
   11.10 +    case HVMCOPY_unhandleable:
   11.11 +        return X86EMUL_UNHANDLEABLE;
   11.12      }
   11.13  
   11.14 +    BUG();
   11.15      return X86EMUL_UNHANDLEABLE;
   11.16  }
   11.17  
   11.18 @@ -3431,7 +3433,7 @@ shadow_write_p2m_entry(struct vcpu *v, u
   11.19      {
   11.20          mfn_t mfn = _mfn(l1e_get_pfn(*p));
   11.21          p2m_type_t p2mt = p2m_flags_to_type(l1e_get_flags(*p));
   11.22 -        if ( p2m_is_valid(p2mt) && mfn_valid(mfn) ) 
   11.23 +        if ( (p2m_is_valid(p2mt) || p2m_is_grant(p2mt)) && mfn_valid(mfn) ) 
   11.24          {
   11.25              sh_remove_all_shadows_and_parents(v, mfn);
   11.26              if ( sh_remove_all_mappings(v, mfn) )
    12.1 --- a/xen/arch/x86/mm/shadow/multi.c	Mon Jul 13 12:18:04 2009 +0100
    12.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Mon Jul 13 12:35:34 2009 +0100
    12.3 @@ -484,7 +484,7 @@ static always_inline void
    12.4      ASSERT(GUEST_PAGING_LEVELS > 3 || level != 3);
    12.5  
    12.6      /* Check there's something for the shadows to map to */
    12.7 -    if ( !p2m_is_valid(p2mt) )
    12.8 +    if ( !p2m_is_valid(p2mt) && !p2m_is_grant(p2mt) )
    12.9      {
   12.10          *sp = shadow_l1e_empty();
   12.11          goto done;
   12.12 @@ -630,7 +630,7 @@ static always_inline void
   12.13      }
   12.14  
   12.15      /* Read-only memory */
   12.16 -    if ( p2mt == p2m_ram_ro ) 
   12.17 +    if ( p2m_is_readonly(p2mt) )
   12.18          sflags &= ~_PAGE_RW;
   12.19      
   12.20      // protect guest page tables
   12.21 @@ -807,8 +807,10 @@ perms_strictly_increased(u32 old_flags, 
   12.22      return ((of | (of ^ nf)) == nf);
   12.23  }
   12.24  
   12.25 +/* type is only used to distinguish grant map pages from ordinary RAM
   12.26 + * i.e. non-p2m_is_grant() pages are treated as p2m_ram_rw.  */
   12.27  static int inline
   12.28 -shadow_get_page_from_l1e(shadow_l1e_t sl1e, struct domain *d)
   12.29 +shadow_get_page_from_l1e(shadow_l1e_t sl1e, struct domain *d, p2m_type_t type)
   12.30  {
   12.31      int res;
   12.32      mfn_t mfn;
   12.33 @@ -838,6 +840,20 @@ shadow_get_page_from_l1e(shadow_l1e_t sl
   12.34                         res ? "success" : "failed");
   12.35      }
   12.36  
   12.37 +    /* Okay, it might still be a grant mapping PTE.  Try it. */
   12.38 +    if ( unlikely(!res) &&
   12.39 +         (type == p2m_grant_map_rw ||
   12.40 +          (type == p2m_grant_map_ro &&
   12.41 +           !(shadow_l1e_get_flags(sl1e) & _PAGE_RW))) )
   12.42 +    {
   12.43 +        /* It's a grant mapping.  The grant table implementation will
   12.44 +           already have checked that we're supposed to have access, so
   12.45 +           we can just grab a reference directly. */
   12.46 +        mfn = shadow_l1e_get_mfn(sl1e);
   12.47 +        if ( mfn_valid(mfn) )
   12.48 +            res = get_page_from_l1e(sl1e, d, page_get_owner(mfn_to_page(mfn)));
   12.49 +    }
   12.50 +
   12.51      if ( unlikely(!res) )
   12.52      {
   12.53          perfc_incr(shadow_get_page_fail);
   12.54 @@ -1133,6 +1149,7 @@ static inline void shadow_vram_put_l1e(s
   12.55  static int shadow_set_l1e(struct vcpu *v, 
   12.56                            shadow_l1e_t *sl1e, 
   12.57                            shadow_l1e_t new_sl1e,
   12.58 +                          p2m_type_t new_type,
   12.59                            mfn_t sl1mfn)
   12.60  {
   12.61      int flags = 0;
   12.62 @@ -1160,7 +1177,7 @@ static int shadow_set_l1e(struct vcpu *v
   12.63          /* About to install a new reference */        
   12.64          if ( shadow_mode_refcounts(d) ) {
   12.65              TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SHADOW_L1_GET_REF);
   12.66 -            if ( shadow_get_page_from_l1e(new_sl1e, d) == 0 ) 
   12.67 +            if ( shadow_get_page_from_l1e(new_sl1e, d, new_type) == 0 ) 
   12.68              {
   12.69                  /* Doesn't look like a pagetable. */
   12.70                  flags |= SHADOW_SET_ERROR;
   12.71 @@ -2377,7 +2394,7 @@ static int validate_gl1e(struct vcpu *v,
   12.72      gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
   12.73  
   12.74      l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
   12.75 -    result |= shadow_set_l1e(v, sl1p, new_sl1e, sl1mfn);
   12.76 +    result |= shadow_set_l1e(v, sl1p, new_sl1e, p2mt, sl1mfn);
   12.77  
   12.78  #if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
   12.79      gl1mfn = _mfn(mfn_to_page(sl1mfn)->v.sh.back);
   12.80 @@ -2436,8 +2453,8 @@ void sh_resync_l1(struct vcpu *v, mfn_t 
   12.81              gfn = guest_l1e_get_gfn(gl1e);
   12.82              gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
   12.83              l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
   12.84 -            rc |= shadow_set_l1e(v, sl1p, nsl1e, sl1mfn);
   12.85 -            
   12.86 +            rc |= shadow_set_l1e(v, sl1p, nsl1e, p2mt, sl1mfn);
   12.87 +
   12.88              *snpl1p = gl1e;
   12.89          }
   12.90      });
   12.91 @@ -2754,7 +2771,7 @@ static void sh_prefetch(struct vcpu *v, 
   12.92  
   12.93          /* Propagate the entry.  */
   12.94          l1e_propagate_from_guest(v, gl1e, gmfn, &sl1e, ft_prefetch, p2mt);
   12.95 -        (void) shadow_set_l1e(v, ptr_sl1e + i, sl1e, sl1mfn);
   12.96 +        (void) shadow_set_l1e(v, ptr_sl1e + i, sl1e, p2mt, sl1mfn);
   12.97  
   12.98  #if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
   12.99          if ( snpl1p != NULL )
  12.100 @@ -3109,7 +3126,8 @@ static int sh_page_fault(struct vcpu *v,
  12.101      gmfn = gfn_to_mfn_guest(d, gfn, &p2mt);
  12.102  
  12.103      if ( shadow_mode_refcounts(d) && 
  12.104 -         (!p2m_is_valid(p2mt) || (!p2m_is_mmio(p2mt) && !mfn_valid(gmfn))) )
  12.105 +         ((!p2m_is_valid(p2mt) && !p2m_is_grant(p2mt)) ||
  12.106 +          (!p2m_is_mmio(p2mt) && !mfn_valid(gmfn))) )
  12.107      {
  12.108          perfc_incr(shadow_fault_bail_bad_gfn);
  12.109          SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n", 
  12.110 @@ -3207,7 +3225,7 @@ static int sh_page_fault(struct vcpu *v,
  12.111  
  12.112      /* Calculate the shadow entry and write it */
  12.113      l1e_propagate_from_guest(v, gw.l1e, gmfn, &sl1e, ft, p2mt);
  12.114 -    r = shadow_set_l1e(v, ptr_sl1e, sl1e, sl1mfn);
  12.115 +    r = shadow_set_l1e(v, ptr_sl1e, sl1e, p2mt, sl1mfn);
  12.116  
  12.117  #if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
  12.118      if ( mfn_valid(gw.l1mfn) 
  12.119 @@ -3260,7 +3278,7 @@ static int sh_page_fault(struct vcpu *v,
  12.120      }
  12.121  
  12.122      /* Ignore attempts to write to read-only memory. */
  12.123 -    if ( (p2mt == p2m_ram_ro) && (ft == ft_demand_write) )
  12.124 +    if ( p2m_is_readonly(p2mt) && (ft == ft_demand_write) )
  12.125      {
  12.126          static unsigned long lastpage;
  12.127          if ( xchg(&lastpage, va & PAGE_MASK) != (va & PAGE_MASK) )
  12.128 @@ -3603,7 +3621,8 @@ sh_invlpg(struct vcpu *v, unsigned long 
  12.129                  shadow_l1e_t *sl1;
  12.130                  sl1 = sh_linear_l1_table(v) + shadow_l1_linear_offset(va);
  12.131                  /* Remove the shadow entry that maps this VA */
  12.132 -                (void) shadow_set_l1e(v, sl1, shadow_l1e_empty(), sl1mfn);
  12.133 +                (void) shadow_set_l1e(v, sl1, shadow_l1e_empty(),
  12.134 +                                      p2m_invalid, sl1mfn);
  12.135              }
  12.136              shadow_unlock(v->domain);
  12.137              /* Need the invlpg, to pick up the disappeareance of the sl1e */
  12.138 @@ -4318,7 +4337,7 @@ int sh_rm_write_access_from_sl1p(struct 
  12.139  
  12.140      /* Found it!  Need to remove its write permissions. */
  12.141      sl1e = shadow_l1e_remove_flags(sl1e, _PAGE_RW);
  12.142 -    r = shadow_set_l1e(v, sl1p, sl1e, smfn);
  12.143 +    r = shadow_set_l1e(v, sl1p, sl1e, p2m_ram_rw, smfn);
  12.144      ASSERT( !(r & SHADOW_SET_ERROR) );
  12.145  
  12.146      sh_unmap_domain_page(sl1p);
  12.147 @@ -4372,8 +4391,12 @@ static int sh_guess_wrmap(struct vcpu *v
  12.148      /* Found it!  Need to remove its write permissions. */
  12.149      sl1mfn = shadow_l2e_get_mfn(*sl2p);
  12.150      sl1e = shadow_l1e_remove_flags(sl1e, _PAGE_RW);
  12.151 -    r = shadow_set_l1e(v, sl1p, sl1e, sl1mfn);
  12.152 -    ASSERT( !(r & SHADOW_SET_ERROR) );
  12.153 +    r = shadow_set_l1e(v, sl1p, sl1e, p2m_ram_rw, sl1mfn);
  12.154 +    if ( r & SHADOW_SET_ERROR ) {
  12.155 +        /* Can only currently happen if we found a grant-mapped
  12.156 +         * page.  Just make the guess fail. */
  12.157 +        return 0;
  12.158 +    }
  12.159      TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP_GUESS_FOUND);
  12.160      return 1;
  12.161  }
  12.162 @@ -4398,7 +4421,7 @@ int sh_rm_write_access_from_l1(struct vc
  12.163               && (mfn_x(shadow_l1e_get_mfn(*sl1e)) == mfn_x(readonly_mfn)) )
  12.164          {
  12.165              shadow_l1e_t ro_sl1e = shadow_l1e_remove_flags(*sl1e, _PAGE_RW);
  12.166 -            (void) shadow_set_l1e(v, sl1e, ro_sl1e, sl1mfn);
  12.167 +            (void) shadow_set_l1e(v, sl1e, ro_sl1e, p2m_ram_rw, sl1mfn);
  12.168  #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC 
  12.169              /* Remember the last shadow that we shot a writeable mapping in */
  12.170              v->arch.paging.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn);
  12.171 @@ -4426,7 +4449,8 @@ int sh_rm_mappings_from_l1(struct vcpu *
  12.172          if ( (flags & _PAGE_PRESENT) 
  12.173               && (mfn_x(shadow_l1e_get_mfn(*sl1e)) == mfn_x(target_mfn)) )
  12.174          {
  12.175 -            (void) shadow_set_l1e(v, sl1e, shadow_l1e_empty(), sl1mfn);
  12.176 +            (void) shadow_set_l1e(v, sl1e, shadow_l1e_empty(),
  12.177 +                                  p2m_invalid, sl1mfn);
  12.178              if ( (mfn_to_page(target_mfn)->count_info & PGC_count_mask) == 0 )
  12.179                  /* This breaks us cleanly out of the FOREACH macro */
  12.180                  done = 1;
  12.181 @@ -4444,17 +4468,21 @@ void sh_clear_shadow_entry(struct vcpu *
  12.182      switch ( mfn_to_page(smfn)->u.sh.type )
  12.183      {
  12.184      case SH_type_l1_shadow:
  12.185 -        (void) shadow_set_l1e(v, ep, shadow_l1e_empty(), smfn); break;
  12.186 +        (void) shadow_set_l1e(v, ep, shadow_l1e_empty(), p2m_invalid, smfn);
  12.187 +        break;
  12.188      case SH_type_l2_shadow:
  12.189  #if GUEST_PAGING_LEVELS >= 3
  12.190      case SH_type_l2h_shadow:
  12.191  #endif
  12.192 -        (void) shadow_set_l2e(v, ep, shadow_l2e_empty(), smfn); break;
  12.193 +        (void) shadow_set_l2e(v, ep, shadow_l2e_empty(), smfn);
  12.194 +        break;
  12.195  #if GUEST_PAGING_LEVELS >= 4
  12.196      case SH_type_l3_shadow:
  12.197 -        (void) shadow_set_l3e(v, ep, shadow_l3e_empty(), smfn); break;
  12.198 +        (void) shadow_set_l3e(v, ep, shadow_l3e_empty(), smfn);
  12.199 +        break;
  12.200      case SH_type_l4_shadow:
  12.201 -        (void) shadow_set_l4e(v, ep, shadow_l4e_empty(), smfn); break;
  12.202 +        (void) shadow_set_l4e(v, ep, shadow_l4e_empty(), smfn);
  12.203 +        break;
  12.204  #endif
  12.205      default: BUG(); /* Called with the wrong kind of shadow. */
  12.206      }
  12.207 @@ -4562,7 +4590,7 @@ static mfn_t emulate_gva_to_mfn(struct v
  12.208      else
  12.209          mfn = gfn_to_mfn(v->domain, _gfn(gfn), &p2mt);
  12.210          
  12.211 -    if ( p2mt == p2m_ram_ro )
  12.212 +    if ( p2m_is_readonly(p2mt) )
  12.213          return _mfn(READONLY_GFN);
  12.214      if ( !p2m_is_ram(p2mt) )
  12.215          return _mfn(BAD_GFN_TO_MFN);
  12.216 @@ -4966,7 +4994,7 @@ int sh_audit_l1_table(struct vcpu *v, mf
  12.217                  gfn = guest_l1e_get_gfn(*gl1e);
  12.218                  mfn = shadow_l1e_get_mfn(*sl1e);
  12.219                  gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
  12.220 -                if ( mfn_x(gmfn) != mfn_x(mfn) )
  12.221 +                if ( !p2m_is_grant(p2mt) && mfn_x(gmfn) != mfn_x(mfn) )
  12.222                      AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
  12.223                                 " --> %" PRI_mfn " != mfn %" PRI_mfn,
  12.224                                 gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn));
    13.1 --- a/xen/common/grant_table.c	Mon Jul 13 12:18:04 2009 +0100
    13.2 +++ b/xen/common/grant_table.c	Mon Jul 13 12:35:34 2009 +0100
    13.3 @@ -227,6 +227,15 @@ static void
    13.4          return;
    13.5      }
    13.6  
    13.7 +    if ( unlikely(paging_mode_external(ld) &&
    13.8 +                  (op->flags & (GNTMAP_device_map|GNTMAP_application_map|
    13.9 +                            GNTMAP_contains_pte))) )
   13.10 +    {
   13.11 +        gdprintk(XENLOG_INFO, "No device mapping in HVM domain.\n");
   13.12 +        op->status = GNTST_general_error;
   13.13 +        return;
   13.14 +    }
   13.15 +
   13.16      if ( unlikely((rd = rcu_lock_domain_by_id(op->dom)) == NULL) )
   13.17      {
   13.18          gdprintk(XENLOG_INFO, "Could not find domain %d\n", op->dom);
   13.19 @@ -344,6 +353,13 @@ static void
   13.20          if ( mfn_valid(frame) )
   13.21              put_page(mfn_to_page(frame));
   13.22  
   13.23 +        if ( paging_mode_external(ld) )
   13.24 +        {
   13.25 +            gdprintk(XENLOG_WARNING, "HVM guests can't grant map iomem\n");
   13.26 +            rc = GNTST_general_error;
   13.27 +            goto undo_out;
   13.28 +        }
   13.29 +
   13.30          if ( !iomem_access_permitted(rd, frame, frame) )
   13.31          {
   13.32              gdprintk(XENLOG_WARNING,
   13.33 @@ -396,7 +412,12 @@ static void
   13.34           !(old_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) &&
   13.35           (act_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
   13.36      {
   13.37 -        if ( iommu_map_page(ld, mfn_to_gmfn(ld, frame), frame) )
   13.38 +        /* Shouldn't happen, because you can't use iommu in a HVM
   13.39 +         * domain. */
   13.40 +        BUG_ON(paging_mode_translate(ld));
   13.41 +        /* We're not translated, so we know that gmfns and mfns are
   13.42 +           the same things, so the IOMMU entry is always 1-to-1. */
   13.43 +        if ( iommu_map_page(ld, frame, frame) )
   13.44          {
   13.45              rc = GNTST_general_error;
   13.46              goto undo_out;
   13.47 @@ -576,7 +597,8 @@ static void
   13.48           (old_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) &&
   13.49           !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
   13.50      {
   13.51 -        if ( iommu_unmap_page(ld, mfn_to_gmfn(ld, op->frame)) )
   13.52 +        BUG_ON(paging_mode_translate(ld));
   13.53 +        if ( iommu_unmap_page(ld, op->frame) )
   13.54          {
   13.55              rc = GNTST_general_error;
   13.56              goto unmap_out;
   13.57 @@ -1765,7 +1787,7 @@ gnttab_release_mappings(
   13.58              {
   13.59                  BUG_ON(!(act->pin & GNTPIN_hstr_mask));
   13.60                  act->pin -= GNTPIN_hstr_inc;
   13.61 -                if ( gnttab_release_host_mappings &&
   13.62 +                if ( gnttab_release_host_mappings(d) &&
   13.63                       !is_iomem_page(act->frame) )
   13.64                      put_page(mfn_to_page(act->frame));
   13.65              }
   13.66 @@ -1784,7 +1806,7 @@ gnttab_release_mappings(
   13.67              {
   13.68                  BUG_ON(!(act->pin & GNTPIN_hstw_mask));
   13.69                  act->pin -= GNTPIN_hstw_inc;
   13.70 -                if ( gnttab_release_host_mappings &&
   13.71 +                if ( gnttab_release_host_mappings(d) &&
   13.72                       !is_iomem_page(act->frame) )
   13.73                  {
   13.74                      if ( gnttab_host_mapping_get_page_type(map, d, rd) )
    14.1 --- a/xen/include/asm-ia64/grant_table.h	Mon Jul 13 12:18:04 2009 +0100
    14.2 +++ b/xen/include/asm-ia64/grant_table.h	Mon Jul 13 12:35:34 2009 +0100
    14.3 @@ -68,7 +68,7 @@ static inline void gnttab_clear_flag(uns
    14.4  #define gnttab_host_mapping_get_page_type(op, ld, rd)   \
    14.5      (!((op)->flags & GNTMAP_readonly))
    14.6  
    14.7 -#define gnttab_release_host_mappings 1
    14.8 +#define gnttab_release_host_mappings(domain) 1
    14.9  
   14.10  static inline int replace_grant_supported(void)
   14.11  {
    15.1 --- a/xen/include/asm-x86/grant_table.h	Mon Jul 13 12:18:04 2009 +0100
    15.2 +++ b/xen/include/asm-x86/grant_table.h	Mon Jul 13 12:35:34 2009 +0100
    15.3 @@ -44,7 +44,7 @@ static inline void gnttab_clear_flag(uns
    15.4       (((ld) == (rd)) || !paging_mode_external(rd)))
    15.5  
    15.6  /* Done implicitly when page tables are destroyed. */
    15.7 -#define gnttab_release_host_mappings 0
    15.8 +#define gnttab_release_host_mappings(domain) ( paging_mode_external(domain) )
    15.9  
   15.10  static inline int replace_grant_supported(void)
   15.11  {
    16.1 --- a/xen/include/asm-x86/hvm/domain.h	Mon Jul 13 12:18:04 2009 +0100
    16.2 +++ b/xen/include/asm-x86/hvm/domain.h	Mon Jul 13 12:35:34 2009 +0100
    16.3 @@ -31,6 +31,7 @@
    16.4  #include <asm/hvm/viridian.h>
    16.5  #include <asm/hvm/vmx/vmcs.h>
    16.6  #include <asm/hvm/svm/vmcb.h>
    16.7 +#include <public/grant_table.h>
    16.8  #include <public/hvm/params.h>
    16.9  #include <public/hvm/save.h>
   16.10  
    17.1 --- a/xen/include/asm-x86/hvm/support.h	Mon Jul 13 12:18:04 2009 +0100
    17.2 +++ b/xen/include/asm-x86/hvm/support.h	Mon Jul 13 12:35:34 2009 +0100
    17.3 @@ -71,7 +71,8 @@ void hvm_enable(struct hvm_function_tabl
    17.4  enum hvm_copy_result {
    17.5      HVMCOPY_okay = 0,
    17.6      HVMCOPY_bad_gva_to_gfn,
    17.7 -    HVMCOPY_bad_gfn_to_mfn
    17.8 +    HVMCOPY_bad_gfn_to_mfn,
    17.9 +    HVMCOPY_unhandleable
   17.10  };
   17.11  
   17.12  /*
    18.1 --- a/xen/include/asm-x86/p2m.h	Mon Jul 13 12:18:04 2009 +0100
    18.2 +++ b/xen/include/asm-x86/p2m.h	Mon Jul 13 12:35:34 2009 +0100
    18.3 @@ -45,6 +45,10 @@
    18.4   */
    18.5  #define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START)
    18.6  
    18.7 +#ifdef __x86_64__
    18.8 +#define HAVE_GRANT_MAP_P2M
    18.9 +#endif
   18.10 +
   18.11  /*
   18.12   * The upper levels of the p2m pagetable always contain full rights; all 
   18.13   * variation in the access control bits is made in the level-1 PTEs.
   18.14 @@ -65,6 +69,12 @@ typedef enum {
   18.15      p2m_mmio_dm = 4,            /* Reads and write go to the device model */
   18.16      p2m_mmio_direct = 5,        /* Read/write mapping of genuine MMIO area */
   18.17      p2m_populate_on_demand = 6, /* Place-holder for empty memory */
   18.18 +
   18.19 +    /* Note that these can only be used if HAVE_GRANT_MAP_P2M is
   18.20 +       defined.  They get defined anyway so as to avoid lots of
   18.21 +       #ifdef's everywhere else. */
   18.22 +    p2m_grant_map_rw = 7,       /* Read/write grant mapping */
   18.23 +    p2m_grant_map_ro = 8,       /* Read-only grant mapping */
   18.24  } p2m_type_t;
   18.25  
   18.26  typedef enum {
   18.27 @@ -81,13 +91,19 @@ typedef enum {
   18.28                         | p2m_to_mask(p2m_ram_logdirty)  \
   18.29                         | p2m_to_mask(p2m_ram_ro))
   18.30  
   18.31 +/* Grant mapping types, which map to a real machine frame in another
   18.32 + * VM */
   18.33 +#define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw)  \
   18.34 +                         | p2m_to_mask(p2m_grant_map_ro) )
   18.35 +
   18.36  /* MMIO types, which don't have to map to anything in the frametable */
   18.37  #define P2M_MMIO_TYPES (p2m_to_mask(p2m_mmio_dm)        \
   18.38                          | p2m_to_mask(p2m_mmio_direct))
   18.39  
   18.40  /* Read-only types, which must have the _PAGE_RW bit clear in their PTEs */
   18.41  #define P2M_RO_TYPES (p2m_to_mask(p2m_ram_logdirty)     \
   18.42 -                      | p2m_to_mask(p2m_ram_ro))
   18.43 +                      | p2m_to_mask(p2m_ram_ro)         \
   18.44 +                      | p2m_to_mask(p2m_grant_map_ro) )
   18.45  
   18.46  #define P2M_MAGIC_TYPES (p2m_to_mask(p2m_populate_on_demand))
   18.47  
   18.48 @@ -96,6 +112,10 @@ typedef enum {
   18.49  #define p2m_is_mmio(_t) (p2m_to_mask(_t) & P2M_MMIO_TYPES)
   18.50  #define p2m_is_readonly(_t) (p2m_to_mask(_t) & P2M_RO_TYPES)
   18.51  #define p2m_is_magic(_t) (p2m_to_mask(_t) & P2M_MAGIC_TYPES)
   18.52 +#define p2m_is_grant(_t) (p2m_to_mask(_t) & P2M_GRANT_TYPES)
   18.53 +/* Grant types are *not* considered valid, because they can be
   18.54 +   unmapped at any time and, unless you happen to be the shadow or p2m
   18.55 +   implementations, there's no way of synchronising against that. */
   18.56  #define p2m_is_valid(_t) (p2m_to_mask(_t) & (P2M_RAM_TYPES | P2M_MMIO_TYPES))
   18.57  
   18.58  /* Populate-on-demand */
   18.59 @@ -161,8 +181,12 @@ struct p2m_domain {
   18.60  /* Extract the type from the PTE flags that store it */
   18.61  static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
   18.62  {
   18.63 -    /* Type is stored in the "available" bits, 9, 10 and 11 */
   18.64 +    /* Type is stored in the "available" bits */
   18.65 +#ifdef __x86_64__
   18.66 +    return (flags >> 9) & 0x3fff;
   18.67 +#else
   18.68      return (flags >> 9) & 0x7;
   18.69 +#endif
   18.70  }
   18.71  
   18.72  /* Read the current domain's p2m table.  Do not populate PoD pages. */
   18.73 @@ -226,17 +250,6 @@ static inline unsigned long mfn_to_gfn(s
   18.74          return mfn_x(mfn);
   18.75  }
   18.76  
   18.77 -/* Translate the frame number held in an l1e from guest to machine */
   18.78 -static inline l1_pgentry_t
   18.79 -gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e)
   18.80 -{
   18.81 -    if ( unlikely(paging_mode_translate(d)) )
   18.82 -        l1e = l1e_from_pfn(gmfn_to_mfn(d, l1e_get_pfn(l1e)),
   18.83 -                           l1e_get_flags(l1e));
   18.84 -    return l1e;
   18.85 -}
   18.86 -
   18.87 -
   18.88  /* Init the datastructures for later use by the p2m code */
   18.89  int p2m_init(struct domain *d);
   18.90