Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 99550
b: refs/heads/master
c: d451bb7
h: refs/heads/master
v: v3
  • Loading branch information
Jeremy Fitzhardinge authored and Thomas Gleixner committed May 27, 2008
1 parent a8172de commit 9cf6602
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 955d6f1778da5a9795f2dfb07f760006f194609a
refs/heads/master: d451bb7aa852627bdf7be7937dc3d9d9f261b235
2 changes: 1 addition & 1 deletion trunk/arch/x86/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,7 @@ asmlinkage void __init xen_start_kernel(void)

/* Get mfn list */
if (!xen_feature(XENFEAT_auto_translated_physmap))
phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
xen_build_dynamic_phys_to_machine();

pgd = (pgd_t *)xen_start_info->pt_base;

Expand Down
85 changes: 85 additions & 0 deletions trunk/arch/x86/xen/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,91 @@
#include "multicalls.h"
#include "mmu.h"

/*
* This should probably be a config option. On 32-bit, it costs 1
* page/gig of memory; on 64-bit its 2 pages/gig. If we want it to be
* completely unbounded we can add another level to the p2m structure.
*/
#define MAX_GUEST_PAGES (16ull * 1024*1024*1024 / PAGE_SIZE)
#define P2M_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))

static unsigned long *p2m_top[MAX_GUEST_PAGES / P2M_ENTRIES_PER_PAGE];

static inline unsigned p2m_top_index(unsigned long pfn)
{
BUG_ON(pfn >= MAX_GUEST_PAGES);
return pfn / P2M_ENTRIES_PER_PAGE;
}

static inline unsigned p2m_index(unsigned long pfn)
{
return pfn % P2M_ENTRIES_PER_PAGE;
}

void __init xen_build_dynamic_phys_to_machine(void)
{
unsigned pfn;
unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;

BUG_ON(xen_start_info->nr_pages >= MAX_GUEST_PAGES);

for(pfn = 0;
pfn < xen_start_info->nr_pages;
pfn += P2M_ENTRIES_PER_PAGE) {
unsigned topidx = p2m_top_index(pfn);

p2m_top[topidx] = &mfn_list[pfn];
}
}

unsigned long get_phys_to_machine(unsigned long pfn)
{
unsigned topidx, idx;

topidx = p2m_top_index(pfn);
if (p2m_top[topidx] == NULL)
return INVALID_P2M_ENTRY;

idx = p2m_index(pfn);
return p2m_top[topidx][idx];
}

static void alloc_p2m(unsigned long **pp)
{
unsigned long *p;
unsigned i;

p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
BUG_ON(p == NULL);

for(i = 0; i < P2M_ENTRIES_PER_PAGE; i++)
p[i] = INVALID_P2M_ENTRY;

if (cmpxchg(pp, NULL, p) != NULL)
free_page((unsigned long)p);
}

void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
{
unsigned topidx, idx;

if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
return;
}

topidx = p2m_top_index(pfn);
if (p2m_top[topidx] == NULL) {
/* no need to allocate a page to store an invalid entry */
if (mfn == INVALID_P2M_ENTRY)
return;
alloc_p2m(&p2m_top[topidx]);
}

idx = p2m_index(pfn);
p2m_top[topidx][idx] = mfn;
}

xmaddr_t arbitrary_virt_to_machine(unsigned long address)
{
unsigned int level;
Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/x86/xen/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
extern const char xen_hypervisor_callback[];
extern const char xen_failsafe_callback[];

unsigned long *phys_to_machine_mapping;
EXPORT_SYMBOL(phys_to_machine_mapping);

/**
* machine_specific_memory_setup - Hook for machine specific memory setup.
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/x86/xen/xen-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ void __init xen_arch_setup(void);
void __init xen_init_IRQ(void);
void xen_enable_sysenter(void);

void __init xen_build_dynamic_phys_to_machine(void);

void xen_setup_timer(int cpu);
void xen_setup_cpu_clockevents(void);
unsigned long xen_cpu_khz(void);
Expand Down
20 changes: 6 additions & 14 deletions trunk/include/asm-x86/xen/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ typedef struct xpaddr {
#define FOREIGN_FRAME_BIT (1UL<<31)
#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)

extern unsigned long *phys_to_machine_mapping;
extern unsigned long get_phys_to_machine(unsigned long pfn);
extern void set_phys_to_machine(unsigned long pfn, unsigned long mfn);

static inline unsigned long pfn_to_mfn(unsigned long pfn)
{
if (xen_feature(XENFEAT_auto_translated_physmap))
return pfn;

return phys_to_machine_mapping[(unsigned int)(pfn)] &
~FOREIGN_FRAME_BIT;
return get_phys_to_machine(pfn) & ~FOREIGN_FRAME_BIT;
}

static inline int phys_to_machine_mapping_valid(unsigned long pfn)
{
if (xen_feature(XENFEAT_auto_translated_physmap))
return 1;

return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
return get_phys_to_machine(pfn) != INVALID_P2M_ENTRY;
}

static inline unsigned long mfn_to_pfn(unsigned long mfn)
Expand Down Expand Up @@ -106,20 +106,12 @@ static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
unsigned long pfn = mfn_to_pfn(mfn);
if ((pfn < max_mapnr)
&& !xen_feature(XENFEAT_auto_translated_physmap)
&& (phys_to_machine_mapping[pfn] != mfn))
&& (get_phys_to_machine(pfn) != mfn))
return max_mapnr; /* force !pfn_valid() */
/* XXX fixme; not true with sparsemem */
return pfn;
}

static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
{
if (xen_feature(XENFEAT_auto_translated_physmap)) {
BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
return;
}
phys_to_machine_mapping[pfn] = mfn;
}

/* VIRT <-> MACHINE conversion */
#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v))))
Expand Down

0 comments on commit 9cf6602

Please sign in to comment.