debuggers.hg

changeset 22255:50c1cc209f8f

xenpaging: page-in granttable entries

When converting a gfn to mfn, check if the page is paged-out.
If it is, request a page-in and return GNTST_eagain to the caller
to indicate a retry of the hypercall is required.
This fixes granttable errors when xenpaging is enabled in the guest.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Sep 22 18:29:24 2010 +0100 (2010-09-22)
parents e20ee3a57645
children 4d95192b2fc8
files xen/common/grant_table.c
line diff
     1.1 --- a/xen/common/grant_table.c	Wed Sep 22 18:28:16 2010 +0100
     1.2 +++ b/xen/common/grant_table.c	Wed Sep 22 18:29:24 2010 +0100
     1.3 @@ -139,6 +139,34 @@ shared_entry_header(struct grant_table *
     1.4  #define active_entry(t, e) \
     1.5      ((t)->active[(e)/ACGNT_PER_PAGE][(e)%ACGNT_PER_PAGE])
     1.6  
     1.7 +/* Check if the page has been paged out */
     1.8 +static int __get_paged_frame(unsigned long gfn, unsigned long *frame, int readonly, struct domain *rd)
     1.9 +{
    1.10 +    struct p2m_domain *p2m;
    1.11 +    p2m_type_t p2mt;
    1.12 +    mfn_t mfn;
    1.13 +    int rc = GNTST_okay;
    1.14 +    
    1.15 +    p2m = p2m_get_hostp2m(rd);
    1.16 +    if ( readonly )
    1.17 +        mfn = gfn_to_mfn(p2m, gfn, &p2mt);
    1.18 +    else
    1.19 +        mfn = gfn_to_mfn_unshare(p2m, gfn, &p2mt, 1);
    1.20 +    
    1.21 +    if ( p2m_is_valid(p2mt) ) {
    1.22 +        *frame = mfn_x(mfn);
    1.23 +        if ( p2m_is_paged(p2mt) )
    1.24 +            p2m_mem_paging_populate(p2m, gfn);
    1.25 +        if ( p2m_is_paging(p2mt) )
    1.26 +            rc = GNTST_eagain;
    1.27 +    } else {
    1.28 +       *frame = INVALID_MFN;
    1.29 +       rc = GNTST_bad_page;
    1.30 +    }
    1.31 +    
    1.32 +    return rc;
    1.33 +}
    1.34 +
    1.35  static inline int
    1.36  __get_maptrack_handle(
    1.37      struct grant_table *t)
    1.38 @@ -527,14 +555,16 @@ static void
    1.39  
    1.40          if ( !act->pin )
    1.41          {
    1.42 +            unsigned long gfn;
    1.43 +            unsigned long frame;
    1.44 +
    1.45 +            gfn = sha1 ? sha1->frame : sha2->full_page.frame;
    1.46 +            rc = __get_paged_frame(gfn, &frame, !!(op->flags & GNTMAP_readonly), rd);
    1.47 +            if ( rc != GNTST_okay )
    1.48 +	         goto unlock_out;
    1.49 +            act->gfn = gfn;
    1.50              act->domid = ld->domain_id;
    1.51 -            if ( sha1 )
    1.52 -                act->gfn = sha1->frame;
    1.53 -            else
    1.54 -                act->gfn = sha2->full_page.frame;
    1.55 -            act->frame = (op->flags & GNTMAP_readonly) ?  
    1.56 -                            gmfn_to_mfn(rd, act->gfn) :
    1.57 -                            gfn_to_mfn_private(rd, act->gfn); 
    1.58 +            act->frame = frame;
    1.59              act->start = 0;
    1.60              act->length = PAGE_SIZE;
    1.61              act->is_sub_page = 0;
    1.62 @@ -1697,6 +1727,7 @@ static int
    1.63      domid_t trans_domid;
    1.64      grant_ref_t trans_gref;
    1.65      struct domain *rrd;
    1.66 +    unsigned long gfn;
    1.67      unsigned long grant_frame;
    1.68      unsigned trans_page_off;
    1.69      unsigned trans_length;
    1.70 @@ -1814,9 +1845,11 @@ static int
    1.71          }
    1.72          else if ( sha1 )
    1.73          {
    1.74 -            act->gfn = sha1->frame;
    1.75 -            grant_frame = readonly ? gmfn_to_mfn(rd, act->gfn) :
    1.76 -                                     gfn_to_mfn_private(rd, act->gfn);
    1.77 +            gfn = sha1->frame;
    1.78 +            rc = __get_paged_frame(gfn, &grant_frame, readonly, rd);
    1.79 +            if ( rc != GNTST_okay )
    1.80 +		goto unlock_out;
    1.81 +            act->gfn = gfn;
    1.82              is_sub_page = 0;
    1.83              trans_page_off = 0;
    1.84              trans_length = PAGE_SIZE;
    1.85 @@ -1824,9 +1857,11 @@ static int
    1.86          }
    1.87          else if ( !(sha2->hdr.flags & GTF_sub_page) )
    1.88          {
    1.89 -            act->gfn = sha2->full_page.frame;
    1.90 -            grant_frame = readonly ? gmfn_to_mfn(rd, act->gfn) :
    1.91 -                                     gfn_to_mfn_private(rd, act->gfn);
    1.92 +            gfn = sha2->full_page.frame;
    1.93 +            rc = __get_paged_frame(gfn, &grant_frame, readonly, rd);
    1.94 +            if ( rc != GNTST_okay )
    1.95 +		    goto unlock_out;
    1.96 +            act->gfn = gfn;
    1.97              is_sub_page = 0;
    1.98              trans_page_off = 0;
    1.99              trans_length = PAGE_SIZE;
   1.100 @@ -1834,9 +1869,11 @@ static int
   1.101          }
   1.102          else
   1.103          {
   1.104 -            act->gfn = sha2->sub_page.frame;
   1.105 -            grant_frame = readonly ? gmfn_to_mfn(rd, act->gfn) :
   1.106 -                                     gfn_to_mfn_private(rd, act->gfn);
   1.107 +            gfn = sha2->sub_page.frame;
   1.108 +            rc = __get_paged_frame(gfn, &grant_frame, readonly, rd);
   1.109 +            if ( rc != GNTST_okay )
   1.110 +		    goto unlock_out;
   1.111 +            act->gfn = gfn;
   1.112              is_sub_page = 1;
   1.113              trans_page_off = sha2->sub_page.page_off;
   1.114              trans_length = sha2->sub_page.length;
   1.115 @@ -1932,17 +1969,9 @@ static void
   1.116      else
   1.117      {
   1.118  #ifdef CONFIG_X86
   1.119 -        p2m_type_t p2mt;
   1.120 -        struct p2m_domain *p2m = p2m_get_hostp2m(sd);
   1.121 -        s_frame = mfn_x(gfn_to_mfn(p2m, op->source.u.gmfn, &p2mt));
   1.122 -        if ( !p2m_is_valid(p2mt) )
   1.123 -          s_frame = INVALID_MFN;
   1.124 -        if ( p2m_is_paging(p2mt) )
   1.125 -        {
   1.126 -            p2m_mem_paging_populate(p2m, op->source.u.gmfn);
   1.127 -            rc = -ENOENT;
   1.128 -            goto error_out;
   1.129 -        }
   1.130 +	rc = __get_paged_frame(op->source.u.gmfn, &s_frame, 1, sd);
   1.131 +	if ( rc != GNTST_okay )
   1.132 +		goto error_out;
   1.133  #else
   1.134          s_frame = gmfn_to_mfn(sd, op->source.u.gmfn);        
   1.135  #endif
   1.136 @@ -1979,17 +2008,9 @@ static void
   1.137      else
   1.138      {
   1.139  #ifdef CONFIG_X86
   1.140 -        p2m_type_t p2mt;
   1.141 -        struct p2m_domain *p2m = p2m_get_hostp2m(dd);
   1.142 -        d_frame = mfn_x(gfn_to_mfn_unshare(p2m, op->dest.u.gmfn, &p2mt, 1));
   1.143 -        if ( !p2m_is_valid(p2mt) )
   1.144 -          d_frame = INVALID_MFN;
   1.145 -        if ( p2m_is_paging(p2mt) )
   1.146 -        {
   1.147 -            p2m_mem_paging_populate(p2m, op->dest.u.gmfn);
   1.148 -            rc = -ENOENT;
   1.149 -            goto error_out;
   1.150 -        }
   1.151 +	rc = __get_paged_frame(op->dest.u.gmfn, &d_frame, 0, dd);
   1.152 +	if ( rc != GNTST_okay )
   1.153 +		goto error_out;
   1.154  #else
   1.155          d_frame = gmfn_to_mfn(dd, op->dest.u.gmfn);
   1.156  #endif