diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2010-12-15 08:19:33 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-01-11 14:31:18 -0500 |
commit | 448f2831934381e9d3c4d93e700ba7bbe14612dc (patch) | |
tree | 8a57a520698e86640a22522c130fe866ba466e55 /arch/x86/xen/p2m.c | |
parent | b5eafe924bb054d7c56e6ebd18106352e8a3f916 (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.c | 80 |
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 | ||
42 | static void __init m2p_override_init(void); | ||
43 | |||
40 | unsigned long xen_max_p2m_pfn __read_mostly; | 44 | unsigned 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 | ||
239 | unsigned long get_phys_to_machine(unsigned long pfn) | 245 | unsigned 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 | |||
387 | static RESERVE_BRK_ARRAY(struct list_head, m2p_overrides, M2P_OVERRIDE_HASH); | ||
388 | static DEFINE_SPINLOCK(m2p_override_lock); | ||
389 | |||
390 | static 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 | |||
401 | static 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 */ | ||
407 | void 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 | |||
417 | void 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 | |||
425 | struct 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 | |||
447 | unsigned 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 | } | ||