aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-02-26 18:48:33 -0500
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-04-08 14:51:44 -0400
commite791ca0fd79461ad72559a6e01362da4d7d16253 (patch)
treeeffc71a0e9b54f45e5800b54a611e3d9bda336c7 /arch
parentd6382bf77e30799b78f19c0a129d4a9e0e9f2e2a (diff)
xen: separate p2m allocation from setting
When doing very early p2m setting, we need to separate setting from allocation, so split things up accordingly. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/xen/mmu.c61
-rw-r--r--arch/x86/xen/mmu.h3
2 files changed, 47 insertions, 17 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index b6e56594fe13..0b2d554d1d58 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -233,47 +233,74 @@ unsigned long get_phys_to_machine(unsigned long pfn)
233} 233}
234EXPORT_SYMBOL_GPL(get_phys_to_machine); 234EXPORT_SYMBOL_GPL(get_phys_to_machine);
235 235
236static void alloc_p2m(unsigned long **pp, unsigned long *mfnp) 236/* install a new p2m_top page */
237bool install_p2mtop_page(unsigned long pfn, unsigned long *p)
237{ 238{
238 unsigned long *p; 239 unsigned topidx = p2m_top_index(pfn);
240 unsigned long **pfnp, *mfnp;
239 unsigned i; 241 unsigned i;
240 242
241 p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL); 243 pfnp = &p2m_top[topidx];
242 BUG_ON(p == NULL); 244 mfnp = &p2m_top_mfn[topidx];
243 245
244 for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++) 246 for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++)
245 p[i] = INVALID_P2M_ENTRY; 247 p[i] = INVALID_P2M_ENTRY;
246 248
247 if (cmpxchg(pp, p2m_missing, p) != p2m_missing) 249 if (cmpxchg(pfnp, p2m_missing, p) == p2m_missing) {
248 free_page((unsigned long)p);
249 else
250 *mfnp = virt_to_mfn(p); 250 *mfnp = virt_to_mfn(p);
251 return true;
252 }
253
254 return false;
251} 255}
252 256
253void set_phys_to_machine(unsigned long pfn, unsigned long mfn) 257static void alloc_p2m(unsigned long pfn)
254{ 258{
255 unsigned topidx, idx; 259 unsigned long *p;
256 260
257 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { 261 p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
258 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 262 BUG_ON(p == NULL);
259 return; 263
260 } 264 if (!install_p2mtop_page(pfn, p))
265 free_page((unsigned long)p);
266}
267
268/* Try to install p2m mapping; fail if intermediate bits missing */
269bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
270{
271 unsigned topidx, idx;
261 272
262 if (unlikely(pfn >= MAX_DOMAIN_PAGES)) { 273 if (unlikely(pfn >= MAX_DOMAIN_PAGES)) {
263 BUG_ON(mfn != INVALID_P2M_ENTRY); 274 BUG_ON(mfn != INVALID_P2M_ENTRY);
264 return; 275 return true;
265 } 276 }
266 277
267 topidx = p2m_top_index(pfn); 278 topidx = p2m_top_index(pfn);
268 if (p2m_top[topidx] == p2m_missing) { 279 if (p2m_top[topidx] == p2m_missing) {
269 /* no need to allocate a page to store an invalid entry */
270 if (mfn == INVALID_P2M_ENTRY) 280 if (mfn == INVALID_P2M_ENTRY)
271 return; 281 return true;
272 alloc_p2m(&p2m_top[topidx], &p2m_top_mfn[topidx]); 282 return false;
273 } 283 }
274 284
275 idx = p2m_index(pfn); 285 idx = p2m_index(pfn);
276 p2m_top[topidx][idx] = mfn; 286 p2m_top[topidx][idx] = mfn;
287
288 return true;
289}
290
291void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
292{
293 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
294 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
295 return;
296 }
297
298 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
299 alloc_p2m(pfn);
300
301 if (!__set_phys_to_machine(pfn, mfn))
302 BUG();
303 }
277} 304}
278 305
279unsigned long arbitrary_virt_to_mfn(void *vaddr) 306unsigned long arbitrary_virt_to_mfn(void *vaddr)
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 24d1b44a337d..da7302624897 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -11,6 +11,9 @@ enum pt_level {
11}; 11};
12 12
13 13
14bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
15bool install_p2mtop_page(unsigned long pfn, unsigned long *p);
16
14void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); 17void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
15 18
16 19