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>
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