debuggers.hg
changeset 16756:fba4e7357744
x86: Allow batched mmu updates which preserve accessed/dirty pte bits.
Signed-off-by: Bruce Rogers <brogers@novell.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Bruce Rogers <brogers@novell.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Tue Jan 15 14:32:15 2008 +0000 (2008-01-15) |
parents | 58dfcad8d56d |
children | d13c4d2836a8 |
files | xen/arch/x86/mm.c xen/include/public/xen.h |
line diff
1.1 --- a/xen/arch/x86/mm.c Tue Jan 15 14:27:15 2008 +0000 1.2 +++ b/xen/arch/x86/mm.c Tue Jan 15 14:32:15 2008 +0000 1.3 @@ -1342,21 +1342,30 @@ static inline int update_intpte(intpte_t 1.4 intpte_t old, 1.5 intpte_t new, 1.6 unsigned long mfn, 1.7 - struct vcpu *v) 1.8 + struct vcpu *v, 1.9 + int preserve_ad) 1.10 { 1.11 int rv = 1; 1.12 #ifndef PTE_UPDATE_WITH_CMPXCHG 1.13 - rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); 1.14 -#else 1.15 + if ( !preserve_ad ) 1.16 + { 1.17 + rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); 1.18 + } 1.19 + else 1.20 +#endif 1.21 { 1.22 intpte_t t = old; 1.23 for ( ; ; ) 1.24 { 1.25 - rv = paging_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); 1.26 + intpte_t _new = new; 1.27 + if ( preserve_ad ) 1.28 + _new |= old & (_PAGE_ACCESSED | _PAGE_DIRTY); 1.29 + 1.30 + rv = paging_cmpxchg_guest_entry(v, p, &t, _new, _mfn(mfn)); 1.31 if ( unlikely(rv == 0) ) 1.32 { 1.33 MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte 1.34 - ": saw %" PRIpte, old, new, t); 1.35 + ": saw %" PRIpte, old, _new, t); 1.36 break; 1.37 } 1.38 1.39 @@ -1369,20 +1378,19 @@ static inline int update_intpte(intpte_t 1.40 old = t; 1.41 } 1.42 } 1.43 -#endif 1.44 return rv; 1.45 } 1.46 1.47 /* Macro that wraps the appropriate type-changes around update_intpte(). 1.48 * Arguments are: type, ptr, old, new, mfn, vcpu */ 1.49 -#define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v) \ 1.50 +#define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v,_ad) \ 1.51 update_intpte(&_t ## e_get_intpte(*(_p)), \ 1.52 _t ## e_get_intpte(_o), _t ## e_get_intpte(_n), \ 1.53 - (_m), (_v)) 1.54 + (_m), (_v), (_ad)) 1.55 1.56 /* Update the L1 entry at pl1e to new value nl1e. */ 1.57 static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, 1.58 - unsigned long gl1mfn) 1.59 + unsigned long gl1mfn, int preserve_ad) 1.60 { 1.61 l1_pgentry_t ol1e; 1.62 struct vcpu *curr = current; 1.63 @@ -1393,7 +1401,7 @@ static int mod_l1_entry(l1_pgentry_t *pl 1.64 return 0; 1.65 1.66 if ( unlikely(paging_mode_refcounts(d)) ) 1.67 - return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr); 1.68 + return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, preserve_ad); 1.69 1.70 if ( l1e_get_flags(nl1e) & _PAGE_PRESENT ) 1.71 { 1.72 @@ -1415,12 +1423,14 @@ static int mod_l1_entry(l1_pgentry_t *pl 1.73 1.74 /* Fast path for identical mapping, r/w and presence. */ 1.75 if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) ) 1.76 - return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr); 1.77 + return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, 1.78 + preserve_ad); 1.79 1.80 if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) ) 1.81 return 0; 1.82 1.83 - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr)) ) 1.84 + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, 1.85 + preserve_ad)) ) 1.86 { 1.87 put_page_from_l1e(nl1e, d); 1.88 return 0; 1.89 @@ -1428,7 +1438,8 @@ static int mod_l1_entry(l1_pgentry_t *pl 1.90 } 1.91 else 1.92 { 1.93 - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr)) ) 1.94 + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, 1.95 + preserve_ad)) ) 1.96 return 0; 1.97 } 1.98 1.99 @@ -1441,7 +1452,8 @@ static int mod_l1_entry(l1_pgentry_t *pl 1.100 static int mod_l2_entry(l2_pgentry_t *pl2e, 1.101 l2_pgentry_t nl2e, 1.102 unsigned long pfn, 1.103 - unsigned long type) 1.104 + unsigned long type, 1.105 + int preserve_ad) 1.106 { 1.107 l2_pgentry_t ol2e; 1.108 struct vcpu *curr = current; 1.109 @@ -1469,18 +1481,20 @@ static int mod_l2_entry(l2_pgentry_t *pl 1.110 1.111 /* Fast path for identical mapping and presence. */ 1.112 if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT)) 1.113 - return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr); 1.114 + return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, preserve_ad); 1.115 1.116 if ( unlikely(!get_page_from_l2e(nl2e, pfn, d)) ) 1.117 return 0; 1.118 1.119 - if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr)) ) 1.120 + if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, 1.121 + preserve_ad)) ) 1.122 { 1.123 put_page_from_l2e(nl2e, pfn); 1.124 return 0; 1.125 } 1.126 } 1.127 - else if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr)) ) 1.128 + else if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, 1.129 + preserve_ad)) ) 1.130 { 1.131 return 0; 1.132 } 1.133 @@ -1494,7 +1508,8 @@ static int mod_l2_entry(l2_pgentry_t *pl 1.134 /* Update the L3 entry at pl3e to new value nl3e. pl3e is within frame pfn. */ 1.135 static int mod_l3_entry(l3_pgentry_t *pl3e, 1.136 l3_pgentry_t nl3e, 1.137 - unsigned long pfn) 1.138 + unsigned long pfn, 1.139 + int preserve_ad) 1.140 { 1.141 l3_pgentry_t ol3e; 1.142 struct vcpu *curr = current; 1.143 @@ -1532,18 +1547,20 @@ static int mod_l3_entry(l3_pgentry_t *pl 1.144 1.145 /* Fast path for identical mapping and presence. */ 1.146 if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT)) 1.147 - return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr); 1.148 + return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, preserve_ad); 1.149 1.150 if ( unlikely(!get_page_from_l3e(nl3e, pfn, d)) ) 1.151 return 0; 1.152 1.153 - if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr)) ) 1.154 + if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, 1.155 + preserve_ad)) ) 1.156 { 1.157 put_page_from_l3e(nl3e, pfn); 1.158 return 0; 1.159 } 1.160 } 1.161 - else if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr)) ) 1.162 + else if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, 1.163 + preserve_ad)) ) 1.164 { 1.165 return 0; 1.166 } 1.167 @@ -1564,7 +1581,8 @@ static int mod_l3_entry(l3_pgentry_t *pl 1.168 /* Update the L4 entry at pl4e to new value nl4e. pl4e is within frame pfn. */ 1.169 static int mod_l4_entry(l4_pgentry_t *pl4e, 1.170 l4_pgentry_t nl4e, 1.171 - unsigned long pfn) 1.172 + unsigned long pfn, 1.173 + int preserve_ad) 1.174 { 1.175 struct vcpu *curr = current; 1.176 struct domain *d = curr->domain; 1.177 @@ -1592,18 +1610,20 @@ static int mod_l4_entry(l4_pgentry_t *pl 1.178 1.179 /* Fast path for identical mapping and presence. */ 1.180 if (!l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT)) 1.181 - return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr); 1.182 + return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, preserve_ad); 1.183 1.184 if ( unlikely(!get_page_from_l4e(nl4e, pfn, d)) ) 1.185 return 0; 1.186 1.187 - if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr)) ) 1.188 + if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, 1.189 + preserve_ad)) ) 1.190 { 1.191 put_page_from_l4e(nl4e, pfn); 1.192 return 0; 1.193 } 1.194 } 1.195 - else if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr)) ) 1.196 + else if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, 1.197 + preserve_ad)) ) 1.198 { 1.199 return 0; 1.200 } 1.201 @@ -1946,7 +1966,7 @@ int new_guest_cr3(unsigned long mfn) 1.202 l4e_from_pfn( 1.203 mfn, 1.204 (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)), 1.205 - pagetable_get_pfn(v->arch.guest_table)); 1.206 + pagetable_get_pfn(v->arch.guest_table), 0); 1.207 if ( unlikely(!okay) ) 1.208 { 1.209 MEM_LOG("Error while installing new compat baseptr %lx", mfn); 1.210 @@ -2458,13 +2478,16 @@ int do_mmu_update( 1.211 { 1.212 /* 1.213 * MMU_NORMAL_PT_UPDATE: Normal update to any level of page table. 1.214 + * MMU_UPDATE_PT_PRESERVE_AD: As above but also preserve (OR) 1.215 + * current A/D bits. 1.216 */ 1.217 case MMU_NORMAL_PT_UPDATE: 1.218 - 1.219 + case MMU_PT_UPDATE_PRESERVE_AD: 1.220 rc = xsm_mmu_normal_update(d, req.val); 1.221 if ( rc ) 1.222 break; 1.223 1.224 + req.ptr -= cmd; 1.225 gmfn = req.ptr >> PAGE_SHIFT; 1.226 mfn = gmfn_to_mfn(d, gmfn); 1.227 1.228 @@ -2501,20 +2524,23 @@ int do_mmu_update( 1.229 case PGT_l1_page_table: 1.230 { 1.231 l1_pgentry_t l1e = l1e_from_intpte(req.val); 1.232 - okay = mod_l1_entry(va, l1e, mfn); 1.233 + okay = mod_l1_entry(va, l1e, mfn, 1.234 + cmd == MMU_PT_UPDATE_PRESERVE_AD); 1.235 } 1.236 break; 1.237 case PGT_l2_page_table: 1.238 { 1.239 l2_pgentry_t l2e = l2e_from_intpte(req.val); 1.240 - okay = mod_l2_entry(va, l2e, mfn, type_info); 1.241 + okay = mod_l2_entry(va, l2e, mfn, type_info, 1.242 + cmd == MMU_PT_UPDATE_PRESERVE_AD); 1.243 } 1.244 break; 1.245 #if CONFIG_PAGING_LEVELS >= 3 1.246 case PGT_l3_page_table: 1.247 { 1.248 l3_pgentry_t l3e = l3e_from_intpte(req.val); 1.249 - okay = mod_l3_entry(va, l3e, mfn); 1.250 + okay = mod_l3_entry(va, l3e, mfn, 1.251 + cmd == MMU_PT_UPDATE_PRESERVE_AD); 1.252 } 1.253 break; 1.254 #endif 1.255 @@ -2522,7 +2548,8 @@ int do_mmu_update( 1.256 case PGT_l4_page_table: 1.257 { 1.258 l4_pgentry_t l4e = l4e_from_intpte(req.val); 1.259 - okay = mod_l4_entry(va, l4e, mfn); 1.260 + okay = mod_l4_entry(va, l4e, mfn, 1.261 + cmd == MMU_PT_UPDATE_PRESERVE_AD); 1.262 } 1.263 break; 1.264 #endif 1.265 @@ -2652,7 +2679,7 @@ static int create_grant_pte_mapping( 1.266 } 1.267 1.268 ol1e = *(l1_pgentry_t *)va; 1.269 - if ( !UPDATE_ENTRY(l1, (l1_pgentry_t *)va, ol1e, nl1e, mfn, v) ) 1.270 + if ( !UPDATE_ENTRY(l1, (l1_pgentry_t *)va, ol1e, nl1e, mfn, v, 0) ) 1.271 { 1.272 put_page_type(page); 1.273 rc = GNTST_general_error; 1.274 @@ -2720,9 +2747,11 @@ static int destroy_grant_pte_mapping( 1.275 } 1.276 1.277 /* Delete pagetable entry. */ 1.278 - if ( unlikely(!UPDATE_ENTRY(l1, 1.279 - (l1_pgentry_t *)va, ol1e, l1e_empty(), mfn, 1.280 - d->vcpu[0] /* Change if we go to per-vcpu shadows. */)) ) 1.281 + if ( unlikely(!UPDATE_ENTRY 1.282 + (l1, 1.283 + (l1_pgentry_t *)va, ol1e, l1e_empty(), mfn, 1.284 + d->vcpu[0] /* Change if we go to per-vcpu shadows. */, 1.285 + 0)) ) 1.286 { 1.287 MEM_LOG("Cannot delete PTE entry at %p", va); 1.288 put_page_type(page); 1.289 @@ -2758,7 +2787,7 @@ static int create_grant_va_mapping( 1.290 return GNTST_general_error; 1.291 } 1.292 ol1e = *pl1e; 1.293 - okay = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v); 1.294 + okay = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0); 1.295 guest_unmap_l1e(v, pl1e); 1.296 pl1e = NULL; 1.297 1.298 @@ -2796,7 +2825,7 @@ static int replace_grant_va_mapping( 1.299 } 1.300 1.301 /* Delete pagetable entry. */ 1.302 - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v)) ) 1.303 + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) ) 1.304 { 1.305 MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); 1.306 rc = GNTST_general_error; 1.307 @@ -2860,7 +2889,8 @@ int replace_grant_host_mapping( 1.308 } 1.309 ol1e = *pl1e; 1.310 1.311 - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), gl1mfn, curr)) ) 1.312 + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), 1.313 + gl1mfn, curr, 0)) ) 1.314 { 1.315 MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); 1.316 guest_unmap_l1e(curr, pl1e); 1.317 @@ -2948,7 +2978,7 @@ int do_update_va_mapping(unsigned long v 1.318 1.319 pl1e = guest_map_l1e(v, va, &gl1mfn); 1.320 1.321 - if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn)) ) 1.322 + if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn, 0)) ) 1.323 rc = -EINVAL; 1.324 1.325 if ( pl1e ) 1.326 @@ -3517,7 +3547,7 @@ static int ptwr_emulated_update( 1.327 else 1.328 { 1.329 ol1e = *pl1e; 1.330 - if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) ) 1.331 + if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v, 0) ) 1.332 BUG(); 1.333 } 1.334
2.1 --- a/xen/include/public/xen.h Tue Jan 15 14:27:15 2008 +0000 2.2 +++ b/xen/include/public/xen.h Tue Jan 15 14:32:15 2008 +0000 2.3 @@ -168,9 +168,14 @@ 2.4 * ptr[:2] -- Machine address within the frame whose mapping to modify. 2.5 * The frame must belong to the FD, if one is specified. 2.6 * val -- Value to write into the mapping entry. 2.7 + * 2.8 + * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD: 2.9 + * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed 2.10 + * with those in @val. 2.11 */ 2.12 -#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ 2.13 -#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ 2.14 +#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ 2.15 +#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ 2.16 +#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ 2.17 2.18 /* 2.19 * MMU EXTENDED OPERATIONS