aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/p2m.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-12-15 08:19:33 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-01-11 14:31:18 -0500
commit448f2831934381e9d3c4d93e700ba7bbe14612dc (patch)
tree8a57a520698e86640a22522c130fe866ba466e55 /arch/x86/xen/p2m.c
parentb5eafe924bb054d7c56e6ebd18106352e8a3f916 (diff)
xen: add m2p override mechanism
Add a simple hashtable based mechanism to override some portions of the m2p, so that we can find out the pfn corresponding to an mfn of a granted page. In fact entries corresponding to granted pages in the m2p hold the original pfn value of the page in the source domain that granted it. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
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}