aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/p2m.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen/p2m.c')
-rw-r--r--arch/x86/xen/p2m.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 259ec3bb8b6f..8db19d50c467 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -27,6 +27,8 @@
27 27
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/list.h>
31#include <linux/hash.h>
30 32
31#include <asm/cache.h> 33#include <asm/cache.h>
32#include <asm/setup.h> 34#include <asm/setup.h>
@@ -37,6 +39,8 @@
37 39
38#include "xen-ops.h" 40#include "xen-ops.h"
39 41
42static void __init m2p_override_init(void);
43
40unsigned long xen_max_p2m_pfn __read_mostly; 44unsigned long xen_max_p2m_pfn __read_mostly;
41 45
42#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) 46#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
@@ -234,6 +238,8 @@ void __init xen_build_dynamic_phys_to_machine(void)
234 238
235 p2m_top[topidx][mididx] = &mfn_list[pfn]; 239 p2m_top[topidx][mididx] = &mfn_list[pfn];
236 } 240 }
241
242 m2p_override_init();
237} 243}
238 244
239unsigned long get_phys_to_machine(unsigned long pfn) 245unsigned long get_phys_to_machine(unsigned long pfn)
@@ -374,3 +380,77 @@ bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
374 380
375 return true; 381 return true;
376} 382}
383
384#define M2P_OVERRIDE_HASH_SHIFT 10
385#define M2P_OVERRIDE_HASH (1 << M2P_OVERRIDE_HASH_SHIFT)
386
387static RESERVE_BRK_ARRAY(struct list_head, m2p_overrides, M2P_OVERRIDE_HASH);
388static DEFINE_SPINLOCK(m2p_override_lock);
389
390static void __init m2p_override_init(void)
391{
392 unsigned i;
393
394 m2p_overrides = extend_brk(sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH,
395 sizeof(unsigned long));
396
397 for (i = 0; i < M2P_OVERRIDE_HASH; i++)
398 INIT_LIST_HEAD(&m2p_overrides[i]);
399}
400
401static unsigned long mfn_hash(unsigned long mfn)
402{
403 return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
404}
405
406/* Add an MFN override for a particular page */
407void m2p_add_override(unsigned long mfn, struct page *page)
408{
409 unsigned long flags;
410 page->private = mfn;
411
412 spin_lock_irqsave(&m2p_override_lock, flags);
413 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
414 spin_unlock_irqrestore(&m2p_override_lock, flags);
415}
416
417void m2p_remove_override(struct page *page)
418{
419 unsigned long flags;
420 spin_lock_irqsave(&m2p_override_lock, flags);
421 list_del(&page->lru);
422 spin_unlock_irqrestore(&m2p_override_lock, flags);
423}
424
425struct page *m2p_find_override(unsigned long mfn)
426{
427 unsigned long flags;
428 struct list_head *bucket = &m2p_overrides[mfn_hash(mfn)];
429 struct page *p, *ret;
430
431 ret = NULL;
432
433 spin_lock_irqsave(&m2p_override_lock, flags);
434
435 list_for_each_entry(p, bucket, lru) {
436 if (p->private == mfn) {
437 ret = p;
438 break;
439 }
440 }
441
442 spin_unlock_irqrestore(&m2p_override_lock, flags);
443
444 return ret;
445}
446
447unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
448{
449 struct page *p = m2p_find_override(mfn);
450 unsigned long ret = pfn;
451
452 if (p)
453 ret = page_to_pfn(p);
454
455 return ret;
456}