Skip to content

Commit

Permalink
Merge branches 'stable/p2m-identity.v4.9.1' and 'stable/e820' of git:…
Browse files Browse the repository at this point in the history
…//git.kernel.org/pub/scm/linux/kernel/git/konrad/xen

* 'stable/p2m-identity.v4.9.1' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/m2p: Check whether the MFN has IDENTITY_FRAME bit set..
  xen/m2p: No need to catch exceptions when we know that there is no RAM
  xen/debug: WARN_ON when identity PFN has no _PAGE_IOMAP flag set.
  xen/debugfs: Add 'p2m' file for printing out the P2M layout.
  xen/setup: Set identity mapping for non-RAM E820 and E820 gaps.
  xen/mmu: WARN_ON when racing to swap middle leaf.
  xen/mmu: Set _PAGE_IOMAP if PFN is an identity PFN.
  xen/mmu: Add the notion of identity (1-1) mapping.
  xen: Mark all initial reserved pages for the balloon as INVALID_P2M_ENTRY.

* 'stable/e820' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/e820: Don't mark balloon memory as E820_UNUSABLE when running as guest and fix overflow.
  xen/setup: Inhibit resource API from using System RAM E820 gaps as PCI mem gaps.
  • Loading branch information
Linus Torvalds committed Mar 15, 2011
3 parents 521cb40 + 706cc9d + 86b3212 commit c7146dd
Show file tree
Hide file tree
Showing 6 changed files with 499 additions and 22 deletions.
47 changes: 37 additions & 10 deletions arch/x86/include/asm/xen/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ typedef struct xpaddr {

/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
#define INVALID_P2M_ENTRY (~0UL)
#define FOREIGN_FRAME_BIT (1UL<<31)
#define FOREIGN_FRAME_BIT (1UL<<(BITS_PER_LONG-1))
#define IDENTITY_FRAME_BIT (1UL<<(BITS_PER_LONG-2))
#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
#define IDENTITY_FRAME(m) ((m) | IDENTITY_FRAME_BIT)

/* Maximum amount of memory we can handle in a domain in pages */
#define MAX_DOMAIN_PAGES \
Expand All @@ -41,12 +43,18 @@ extern unsigned int machine_to_phys_order;

extern unsigned long get_phys_to_machine(unsigned long pfn);
extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
extern unsigned long set_phys_range_identity(unsigned long pfn_s,
unsigned long pfn_e);

extern int m2p_add_override(unsigned long mfn, struct page *page);
extern int m2p_remove_override(struct page *page);
extern struct page *m2p_find_override(unsigned long mfn);
extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);

#ifdef CONFIG_XEN_DEBUG_FS
extern int p2m_dump_show(struct seq_file *m, void *v);
#endif
static inline unsigned long pfn_to_mfn(unsigned long pfn)
{
unsigned long mfn;
Expand All @@ -57,7 +65,7 @@ static inline unsigned long pfn_to_mfn(unsigned long pfn)
mfn = get_phys_to_machine(pfn);

if (mfn != INVALID_P2M_ENTRY)
mfn &= ~FOREIGN_FRAME_BIT;
mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT);

return mfn;
}
Expand All @@ -73,25 +81,44 @@ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
static inline unsigned long mfn_to_pfn(unsigned long mfn)
{
unsigned long pfn;
int ret = 0;

if (xen_feature(XENFEAT_auto_translated_physmap))
return mfn;

if (unlikely((mfn >> machine_to_phys_order) != 0)) {
pfn = ~0;
goto try_override;
}
pfn = 0;
/*
* The array access can fail (e.g., device space beyond end of RAM).
* In such cases it doesn't matter what we return (we return garbage),
* but we must handle the fault without crashing!
*/
__get_user(pfn, &machine_to_phys_mapping[mfn]);

/*
* If this appears to be a foreign mfn (because the pfn
* doesn't map back to the mfn), then check the local override
* table to see if there's a better pfn to use.
ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
try_override:
/* ret might be < 0 if there are no entries in the m2p for mfn */
if (ret < 0)
pfn = ~0;
else if (get_phys_to_machine(pfn) != mfn)
/*
* If this appears to be a foreign mfn (because the pfn
* doesn't map back to the mfn), then check the local override
* table to see if there's a better pfn to use.
*
* m2p_find_override_pfn returns ~0 if it doesn't find anything.
*/
pfn = m2p_find_override_pfn(mfn, ~0);

/*
* pfn is ~0 if there are no entries in the m2p for mfn or if the
* entry doesn't map back to the mfn and m2p_override doesn't have a
* valid entry for it.
*/
if (get_phys_to_machine(pfn) != mfn)
pfn = m2p_find_override_pfn(mfn, pfn);
if (pfn == ~0 &&
get_phys_to_machine(mfn) == IDENTITY_FRAME(mfn))
pfn = mfn;

return pfn;
}
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/xen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ config XEN_DEBUG_FS
help
Enable statistics output and various tuning options in debugfs.
Enabling this option may incur a significant performance overhead.

config XEN_DEBUG
bool "Enable Xen debug checks"
depends on XEN
default n
help
Enable various WARN_ON checks in the Xen MMU code.
Enabling this option WILL incur a significant performance overhead.
72 changes: 69 additions & 3 deletions arch/x86/xen/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <linux/module.h>
#include <linux/gfp.h>
#include <linux/memblock.h>
#include <linux/seq_file.h>

#include <asm/pgtable.h>
#include <asm/tlbflush.h>
Expand Down Expand Up @@ -416,8 +417,12 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
if (val & _PAGE_PRESENT) {
unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
pteval_t flags = val & PTE_FLAGS_MASK;
unsigned long mfn = pfn_to_mfn(pfn);
unsigned long mfn;

if (!xen_feature(XENFEAT_auto_translated_physmap))
mfn = get_phys_to_machine(pfn);
else
mfn = pfn;
/*
* If there's no mfn for the pfn, then just create an
* empty non-present pte. Unfortunately this loses
Expand All @@ -427,8 +432,18 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
if (unlikely(mfn == INVALID_P2M_ENTRY)) {
mfn = 0;
flags = 0;
} else {
/*
* Paramount to do this test _after_ the
* INVALID_P2M_ENTRY as INVALID_P2M_ENTRY &
* IDENTITY_FRAME_BIT resolves to true.
*/
mfn &= ~FOREIGN_FRAME_BIT;
if (mfn & IDENTITY_FRAME_BIT) {
mfn &= ~IDENTITY_FRAME_BIT;
flags |= _PAGE_IOMAP;
}
}

val = ((pteval_t)mfn << PAGE_SHIFT) | flags;
}

Expand Down Expand Up @@ -532,6 +547,41 @@ pte_t xen_make_pte(pteval_t pte)
}
PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte);

#ifdef CONFIG_XEN_DEBUG
pte_t xen_make_pte_debug(pteval_t pte)
{
phys_addr_t addr = (pte & PTE_PFN_MASK);
phys_addr_t other_addr;
bool io_page = false;
pte_t _pte;

if (pte & _PAGE_IOMAP)
io_page = true;

_pte = xen_make_pte(pte);

if (!addr)
return _pte;

if (io_page &&
(xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT;
WARN(addr != other_addr,
"0x%lx is using VM_IO, but it is 0x%lx!\n",
(unsigned long)addr, (unsigned long)other_addr);
} else {
pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP;
other_addr = (_pte.pte & PTE_PFN_MASK);
WARN((addr == other_addr) && (!io_page) && (!iomap_set),
"0x%lx is missing VM_IO (and wasn't fixed)!\n",
(unsigned long)addr);
}

return _pte;
}
PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug);
#endif

pgd_t xen_make_pgd(pgdval_t pgd)
{
pgd = pte_pfn_to_mfn(pgd);
Expand Down Expand Up @@ -1940,6 +1990,9 @@ __init void xen_ident_map_ISA(void)

static __init void xen_post_allocator_init(void)
{
#ifdef CONFIG_XEN_DEBUG
pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
#endif
pv_mmu_ops.set_pte = xen_set_pte;
pv_mmu_ops.set_pmd = xen_set_pmd;
pv_mmu_ops.set_pud = xen_set_pud;
Expand Down Expand Up @@ -2072,7 +2125,7 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order,
in_frames[i] = virt_to_mfn(vaddr);

MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0);
set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);
__set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);

if (out_frames)
out_frames[i] = virt_to_pfn(vaddr);
Expand Down Expand Up @@ -2351,6 +2404,18 @@ EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);

#ifdef CONFIG_XEN_DEBUG_FS

static int p2m_dump_open(struct inode *inode, struct file *filp)
{
return single_open(filp, p2m_dump_show, NULL);
}

static const struct file_operations p2m_dump_fops = {
.open = p2m_dump_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};

static struct dentry *d_mmu_debug;

static int __init xen_mmu_debugfs(void)
Expand Down Expand Up @@ -2406,6 +2471,7 @@ static int __init xen_mmu_debugfs(void)
debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug,
&mmu_stats.prot_commit_batched);

debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
return 0;
}
fs_initcall(xen_mmu_debugfs);
Expand Down
Loading

0 comments on commit c7146dd

Please sign in to comment.