Merge branches 'stable/bug.fixes-3.2' and 'stable/mmu.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
* 'stable/bug.fixes-3.2' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen/p2m/debugfs: Make type_name more obvious. xen/p2m/debugfs: Fix potential pointer exception. xen/enlighten: Fix compile warnings and set cx to known value. xen/xenbus: Remove the unnecessary check. xen/irq: If we fail during msi_capability_init return proper error code. xen/events: Don't check the info for NULL as it is already done. xen/events: BUG() when we can't allocate our event->irq array. * 'stable/mmu.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen: Fix selfballooning and ensure it doesn't go too far xen/gntdev: Fix sleep-inside-spinlock xen: modify kernel mappings corresponding to granted pages xen: add an "highmem" parameter to alloc_xenballooned_pages xen/p2m: Use SetPagePrivate and its friends for M2P overrides. xen/p2m: Make debug/xen/mmu/p2m visible again. Revert "xen/debug: WARN_ON when identity PFN has no _PAGE_IOMAP flag set."
此提交包含在:
@@ -49,11 +49,3 @@ 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.
|
||||
|
@@ -251,6 +251,7 @@ static void __init xen_init_cpuid_mask(void)
|
||||
~((1 << X86_FEATURE_APIC) | /* disable local APIC */
|
||||
(1 << X86_FEATURE_ACPI)); /* disable ACPI */
|
||||
ax = 1;
|
||||
cx = 0;
|
||||
xen_cpuid(&ax, &bx, &cx, &dx);
|
||||
|
||||
xsave_mask =
|
||||
|
@@ -495,41 +495,6 @@ static 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_ONCE(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_ONCE((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
|
||||
|
||||
static pgd_t xen_make_pgd(pgdval_t pgd)
|
||||
{
|
||||
pgd = pte_pfn_to_mfn(pgd);
|
||||
@@ -1992,9 +1957,6 @@ void __init xen_ident_map_ISA(void)
|
||||
|
||||
static void __init 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;
|
||||
@@ -2404,17 +2366,3 @@ out:
|
||||
return err;
|
||||
}
|
||||
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,
|
||||
};
|
||||
#endif /* CONFIG_XEN_DEBUG_FS */
|
||||
|
@@ -161,7 +161,9 @@
|
||||
#include <asm/xen/page.h>
|
||||
#include <asm/xen/hypercall.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
#include <xen/grant_table.h>
|
||||
|
||||
#include "multicalls.h"
|
||||
#include "xen-ops.h"
|
||||
|
||||
static void __init m2p_override_init(void);
|
||||
@@ -676,7 +678,8 @@ static unsigned long mfn_hash(unsigned long mfn)
|
||||
}
|
||||
|
||||
/* Add an MFN override for a particular page */
|
||||
int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
|
||||
int m2p_add_override(unsigned long mfn, struct page *page,
|
||||
struct gnttab_map_grant_ref *kmap_op)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long pfn;
|
||||
@@ -692,16 +695,28 @@ int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
|
||||
"m2p_add_override: pfn %lx not mapped", pfn))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
page->private = mfn;
|
||||
WARN_ON(PagePrivate(page));
|
||||
SetPagePrivate(page);
|
||||
set_page_private(page, mfn);
|
||||
page->index = pfn_to_mfn(pfn);
|
||||
|
||||
if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
|
||||
return -ENOMEM;
|
||||
|
||||
if (clear_pte && !PageHighMem(page))
|
||||
/* Just zap old mapping for now */
|
||||
pte_clear(&init_mm, address, ptep);
|
||||
if (kmap_op != NULL) {
|
||||
if (!PageHighMem(page)) {
|
||||
struct multicall_space mcs =
|
||||
xen_mc_entry(sizeof(*kmap_op));
|
||||
|
||||
MULTI_grant_table_op(mcs.mc,
|
||||
GNTTABOP_map_grant_ref, kmap_op, 1);
|
||||
|
||||
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
||||
}
|
||||
/* let's use dev_bus_addr to record the old mfn instead */
|
||||
kmap_op->dev_bus_addr = page->index;
|
||||
page->index = (unsigned long) kmap_op;
|
||||
}
|
||||
spin_lock_irqsave(&m2p_override_lock, flags);
|
||||
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
|
||||
spin_unlock_irqrestore(&m2p_override_lock, flags);
|
||||
@@ -735,13 +750,56 @@ int m2p_remove_override(struct page *page, bool clear_pte)
|
||||
spin_lock_irqsave(&m2p_override_lock, flags);
|
||||
list_del(&page->lru);
|
||||
spin_unlock_irqrestore(&m2p_override_lock, flags);
|
||||
set_phys_to_machine(pfn, page->index);
|
||||
WARN_ON(!PagePrivate(page));
|
||||
ClearPagePrivate(page);
|
||||
|
||||
if (clear_pte && !PageHighMem(page))
|
||||
set_pte_at(&init_mm, address, ptep,
|
||||
pfn_pte(pfn, PAGE_KERNEL));
|
||||
/* No tlb flush necessary because the caller already
|
||||
* left the pte unmapped. */
|
||||
if (clear_pte) {
|
||||
struct gnttab_map_grant_ref *map_op =
|
||||
(struct gnttab_map_grant_ref *) page->index;
|
||||
set_phys_to_machine(pfn, map_op->dev_bus_addr);
|
||||
if (!PageHighMem(page)) {
|
||||
struct multicall_space mcs;
|
||||
struct gnttab_unmap_grant_ref *unmap_op;
|
||||
|
||||
/*
|
||||
* It might be that we queued all the m2p grant table
|
||||
* hypercalls in a multicall, then m2p_remove_override
|
||||
* get called before the multicall has actually been
|
||||
* issued. In this case handle is going to -1 because
|
||||
* it hasn't been modified yet.
|
||||
*/
|
||||
if (map_op->handle == -1)
|
||||
xen_mc_flush();
|
||||
/*
|
||||
* Now if map_op->handle is negative it means that the
|
||||
* hypercall actually returned an error.
|
||||
*/
|
||||
if (map_op->handle == GNTST_general_error) {
|
||||
printk(KERN_WARNING "m2p_remove_override: "
|
||||
"pfn %lx mfn %lx, failed to modify kernel mappings",
|
||||
pfn, mfn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mcs = xen_mc_entry(
|
||||
sizeof(struct gnttab_unmap_grant_ref));
|
||||
unmap_op = mcs.args;
|
||||
unmap_op->host_addr = map_op->host_addr;
|
||||
unmap_op->handle = map_op->handle;
|
||||
unmap_op->dev_bus_addr = 0;
|
||||
|
||||
MULTI_grant_table_op(mcs.mc,
|
||||
GNTTABOP_unmap_grant_ref, unmap_op, 1);
|
||||
|
||||
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
||||
|
||||
set_pte_at(&init_mm, address, ptep,
|
||||
pfn_pte(pfn, PAGE_KERNEL));
|
||||
__flush_tlb_single(address);
|
||||
map_op->host_addr = 0;
|
||||
}
|
||||
} else
|
||||
set_phys_to_machine(pfn, page->index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -758,7 +816,7 @@ struct page *m2p_find_override(unsigned long mfn)
|
||||
spin_lock_irqsave(&m2p_override_lock, flags);
|
||||
|
||||
list_for_each_entry(p, bucket, lru) {
|
||||
if (p->private == mfn) {
|
||||
if (page_private(p) == mfn) {
|
||||
ret = p;
|
||||
break;
|
||||
}
|
||||
@@ -782,17 +840,21 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
|
||||
EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
|
||||
|
||||
#ifdef CONFIG_XEN_DEBUG_FS
|
||||
|
||||
int p2m_dump_show(struct seq_file *m, void *v)
|
||||
#include <linux/debugfs.h>
|
||||
#include "debugfs.h"
|
||||
static int p2m_dump_show(struct seq_file *m, void *v)
|
||||
{
|
||||
static const char * const level_name[] = { "top", "middle",
|
||||
"entry", "abnormal" };
|
||||
static const char * const type_name[] = { "identity", "missing",
|
||||
"pfn", "abnormal"};
|
||||
"entry", "abnormal", "error"};
|
||||
#define TYPE_IDENTITY 0
|
||||
#define TYPE_MISSING 1
|
||||
#define TYPE_PFN 2
|
||||
#define TYPE_UNKNOWN 3
|
||||
static const char * const type_name[] = {
|
||||
[TYPE_IDENTITY] = "identity",
|
||||
[TYPE_MISSING] = "missing",
|
||||
[TYPE_PFN] = "pfn",
|
||||
[TYPE_UNKNOWN] = "abnormal"};
|
||||
unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
|
||||
unsigned int uninitialized_var(prev_level);
|
||||
unsigned int uninitialized_var(prev_type);
|
||||
@@ -856,4 +918,32 @@ int p2m_dump_show(struct seq_file *m, void *v)
|
||||
#undef TYPE_PFN
|
||||
#undef TYPE_UNKNOWN
|
||||
}
|
||||
#endif
|
||||
|
||||
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_p2m_debugfs(void)
|
||||
{
|
||||
struct dentry *d_xen = xen_init_debugfs();
|
||||
|
||||
if (d_xen == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
d_mmu_debug = debugfs_create_dir("mmu", d_xen);
|
||||
|
||||
debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
|
||||
return 0;
|
||||
}
|
||||
fs_initcall(xen_p2m_debugfs);
|
||||
#endif /* CONFIG_XEN_DEBUG_FS */
|
||||
|
新增問題並參考
封鎖使用者