# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1228356137 -32400
# Node ID 17adc5c344fe10169ad00b4e9a78ea4dcf8b041e
# Parent 6743af9fffc6f531a73af66a86738aa3ab4a2366
# Parent ca213a56dba1f15a86d6edddf1aae39bf9b4a2a5
merge with linux-2.6.18-xen.hg
---
arch/i386/kernel/io_apic-xen.c | 14 +++++++-
arch/i386/mm/hypervisor.c | 43 ++++++++++++++++++++++---
arch/i386/mm/pgtable-xen.c | 8 ++++
arch/x86_64/kernel/io_apic-xen.c | 6 ++-
arch/x86_64/mm/pageattr-xen.c | 8 ++++
drivers/pci/msi-xen.c | 52 ++++++++++++++----------------
drivers/pci/pci.h | 1
drivers/pci/quirks.c | 3 +
drivers/pci/setup-bus.c | 2 -
drivers/pci/setup-res.c | 10 +++++
drivers/xen/blkback/blkback.c | 10 ++---
drivers/xen/blktap/blktap.c | 10 ++---
drivers/xen/core/evtchn.c | 66 +++++++++++++++++++++++++++++++--------
drivers/xen/core/gnttab.c | 5 +-
drivers/xen/netback/netback.c | 6 +--
include/asm-ia64/maddr.h | 1
include/linux/page-flags.h | 6 +--
include/xen/interface/physdev.h | 15 ++++++++
mm/page_alloc.c | 4 +-
19 files changed, 197 insertions(+), 73 deletions(-)
diff -r 6743af9fffc6 -r 17adc5c344fe arch/i386/kernel/io_apic-xen.c
--- a/arch/i386/kernel/io_apic-xen.c Wed Dec 03 11:38:32 2008 +0900
+++ b/arch/i386/kernel/io_apic-xen.c Thu Dec 04 11:02:17 2008 +0900
@@ -87,8 +87,10 @@ int (*ioapic_renumber_irq)(int ioapic, i
int (*ioapic_renumber_irq)(int ioapic, int irq);
atomic_t irq_mis_count;
+#ifndef CONFIG_XEN
/* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+#endif
static DEFINE_SPINLOCK(ioapic_lock);
static DEFINE_SPINLOCK(vector_lock);
@@ -793,6 +795,7 @@ static int find_irq_entry(int apic, int
return -1;
}
+#ifndef CONFIG_XEN
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
@@ -842,6 +845,7 @@ static int __init find_isa_irq_apic(int
return -1;
}
+#endif
/*
* Find a specific PCI IRQ entry.
@@ -1687,7 +1691,9 @@ static void __init enable_IO_APIC(void)
static void __init enable_IO_APIC(void)
{
union IO_APIC_reg_01 reg_01;
+#ifndef CONFIG_XEN
int i8259_apic, i8259_pin;
+#endif
int i, apic;
unsigned long flags;
@@ -1708,6 +1714,7 @@ static void __init enable_IO_APIC(void)
spin_unlock_irqrestore(&ioapic_lock, flags);
nr_ioapic_registers[apic] = reg_01.bits.entries+1;
}
+#ifndef CONFIG_XEN
for(apic = 0; apic < nr_ioapics; apic++) {
int pin;
/* See if any of the pins is in ExtINT mode */
@@ -1749,6 +1756,7 @@ static void __init enable_IO_APIC(void)
{
printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
}
+#endif
/*
* Do not trust the IO-APIC being empty at bootup
@@ -2517,6 +2525,8 @@ static int __init io_apic_bug_finalize(v
late_initcall(io_apic_bug_finalize);
+#ifndef CONFIG_XEN
+
struct sysfs_ioapic_data {
struct sys_device dev;
struct IO_APIC_route_entry entry[0];
@@ -2570,10 +2580,8 @@ static int ioapic_resume(struct sys_devi
static struct sysdev_class ioapic_sysdev_class = {
set_kset_name("ioapic"),
-#ifndef CONFIG_XEN
.suspend = ioapic_suspend,
.resume = ioapic_resume,
-#endif
};
static int __init ioapic_init_sysfs(void)
@@ -2611,6 +2619,8 @@ static int __init ioapic_init_sysfs(void
device_initcall(ioapic_init_sysfs);
+#endif /* CONFIG_XEN */
+
/* --------------------------------------------------------------------------
ACPI-based IOAPIC Configuration
--------------------------------------------------------------------------
*/
diff -r 6743af9fffc6 -r 17adc5c344fe arch/i386/mm/hypervisor.c
--- a/arch/i386/mm/hypervisor.c Wed Dec 03 11:38:32 2008 +0900
+++ b/arch/i386/mm/hypervisor.c Thu Dec 04 11:02:17 2008 +0900
@@ -374,6 +374,15 @@ void xen_destroy_contiguous_region(unsig
}
EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
+static void undo_limit_pages(struct page *pages, unsigned int order)
+{
+ BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+ BUG_ON(order > MAX_CONTIG_ORDER);
+ xen_limit_pages_to_max_mfn(pages, order, 0);
+ ClearPageForeign(pages);
+ __free_pages(pages, order);
+}
+
int xen_limit_pages_to_max_mfn(
struct page *pages, unsigned int order, unsigned int address_bits)
{
@@ -402,16 +411,28 @@ int xen_limit_pages_to_max_mfn(
if (unlikely(order > MAX_CONTIG_ORDER))
return -ENOMEM;
- bitmap_zero(limit_map, 1U << order);
+ if (address_bits) {
+ if (address_bits < PAGE_SHIFT)
+ return -EINVAL;
+ bitmap_zero(limit_map, 1U << order);
+ } else if (order) {
+ BUILD_BUG_ON(sizeof(pages->index) != sizeof(*limit_map));
+ for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
+ limit_map[i] = pages[i + 1].index;
+ } else
+ __set_bit(0, limit_map);
+
set_xen_guest_handle(exchange.in.extent_start, in_frames);
set_xen_guest_handle(exchange.out.extent_start, out_frames);
/* 0. Scrub the pages. */
for (i = 0, n = 0; i < 1U<<order ; i++) {
page = &pages[i];
- if (!(pfn_to_mfn(page_to_pfn(page)) >> (address_bits -
PAGE_SHIFT)))
- continue;
- __set_bit(i, limit_map);
+ if (address_bits) {
+ if (!(pfn_to_mfn(page_to_pfn(page)) >> (address_bits -
PAGE_SHIFT)))
+ continue;
+ __set_bit(i, limit_map);
+ }
if (!PageHighMem(page))
scrub_pages(page_address(page), 1);
@@ -497,7 +518,19 @@ int xen_limit_pages_to_max_mfn(
balloon_unlock(flags);
- return success ? 0 : -ENOMEM;
+ if (!success)
+ return -ENOMEM;
+
+ if (address_bits) {
+ if (order) {
+ BUILD_BUG_ON(sizeof(*limit_map) !=
sizeof(pages->index));
+ for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
+ pages[i + 1].index = limit_map[i];
+ }
+ SetPageForeign(pages, undo_limit_pages);
+ }
+
+ return 0;
}
EXPORT_SYMBOL_GPL(xen_limit_pages_to_max_mfn);
diff -r 6743af9fffc6 -r 17adc5c344fe arch/i386/mm/pgtable-xen.c
--- a/arch/i386/mm/pgtable-xen.c Wed Dec 03 11:38:32 2008 +0900
+++ b/arch/i386/mm/pgtable-xen.c Thu Dec 04 11:02:17 2008 +0900
@@ -152,6 +152,12 @@ pte_t *pte_alloc_one_kernel(struct mm_st
return pte;
}
+static void _pte_free(struct page *page, unsigned int order)
+{
+ BUG_ON(order);
+ pte_free(page);
+}
+
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
@@ -162,7 +168,7 @@ struct page *pte_alloc_one(struct mm_str
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
#endif
if (pte) {
- SetPageForeign(pte, pte_free);
+ SetPageForeign(pte, _pte_free);
init_page_count(pte);
}
return pte;
diff -r 6743af9fffc6 -r 17adc5c344fe arch/x86_64/kernel/io_apic-xen.c
--- a/arch/x86_64/kernel/io_apic-xen.c Wed Dec 03 11:38:32 2008 +0900
+++ b/arch/x86_64/kernel/io_apic-xen.c Thu Dec 04 11:02:17 2008 +0900
@@ -2054,6 +2054,8 @@ void __init setup_IO_APIC(void)
print_IO_APIC();
}
+#ifndef CONFIG_XEN
+
struct sysfs_ioapic_data {
struct sys_device dev;
struct IO_APIC_route_entry entry[0];
@@ -2107,10 +2109,8 @@ static int ioapic_resume(struct sys_devi
static struct sysdev_class ioapic_sysdev_class = {
set_kset_name("ioapic"),
-#ifndef CONFIG_XEN
.suspend = ioapic_suspend,
.resume = ioapic_resume,
-#endif
};
static int __init ioapic_init_sysfs(void)
@@ -2148,6 +2148,8 @@ static int __init ioapic_init_sysfs(void
device_initcall(ioapic_init_sysfs);
+#endif /* CONFIG_XEN */
+
/* --------------------------------------------------------------------------
ACPI-based IOAPIC Configuration
--------------------------------------------------------------------------
*/
diff -r 6743af9fffc6 -r 17adc5c344fe arch/x86_64/mm/pageattr-xen.c
--- a/arch/x86_64/mm/pageattr-xen.c Wed Dec 03 11:38:32 2008 +0900
+++ b/arch/x86_64/mm/pageattr-xen.c Thu Dec 04 11:02:17 2008 +0900
@@ -248,13 +248,19 @@ void _arch_exit_mmap(struct mm_struct *m
mm_unpin(mm);
}
+static void _pte_free(struct page *page, unsigned int order)
+{
+ BUG_ON(order);
+ pte_free(page);
+}
+
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
if (pte) {
- SetPageForeign(pte, pte_free);
+ SetPageForeign(pte, _pte_free);
init_page_count(pte);
}
return pte;
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/pci/msi-xen.c
--- a/drivers/pci/msi-xen.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/pci/msi-xen.c Thu Dec 04 11:02:17 2008 +0900
@@ -42,6 +42,8 @@ struct msi_dev_list {
struct list_head list;
spinlock_t pirq_list_lock;
struct list_head pirq_list_head;
+ /* Used for saving/restoring MSI-X tables */
+ void __iomem *mask_base;
};
struct msi_pirq_entry {
@@ -50,7 +52,6 @@ struct msi_pirq_entry {
int entry_nr;
#ifdef CONFIG_PM
/* PM save area for MSIX address/data */
- void __iomem *mask_base;
u32 address_hi_save;
u32 address_lo_save;
u32 data_save;
@@ -90,7 +91,7 @@ static struct msi_dev_list *get_msi_dev_
return ret;
}
-static int attach_pirq_entry(int pirq, int entry_nr, u64 table_base,
+static int attach_pirq_entry(int pirq, int entry_nr,
struct msi_dev_list *msi_dev_entry)
{
struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
@@ -100,9 +101,6 @@ static int attach_pirq_entry(int pirq, i
return -ENOMEM;
entry->pirq = pirq;
entry->entry_nr = entry_nr;
-#ifdef COMFIG_PM
- entry->mask_base = table_base;
-#endif
spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
@@ -381,17 +379,24 @@ int pci_save_msix_state(struct pci_dev *
unsigned long flags;
struct msi_dev_list *msi_dev_entry;
struct msi_pirq_entry *pirq_entry;
+ void __iomem *base;
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
if (pos <= 0 || dev->no_msi)
return 0;
-
- printk(KERN_CRIT "Saving MSIX cap\n");
/* save the capability */
pci_read_config_word(dev, msi_control_reg(pos), &control);
if (!(control & PCI_MSIX_FLAGS_ENABLE))
return 0;
+
+ msi_dev_entry = get_msi_dev_pirq_list(dev);
+ /* If we failed to map the MSI-X table at pci_enable_msix,
+ * We could not support saving them here.
+ */
+ if (!(base = msi_dev_entry->mask_base))
+ return -ENOMEM;
+
save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
GFP_KERNEL);
if (!save_state) {
@@ -400,19 +405,12 @@ int pci_save_msix_state(struct pci_dev *
}
*((u16 *)&save_state->data[0]) = control;
- msi_dev_entry = get_msi_dev_pirq_list(dev);
-
spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
int j;
- void __iomem *base;
/* save the table */
- base = pirq_entry->mask_base;
j = pirq_entry->entry_nr;
- printk(KERN_CRIT "Save msix table entry %d pirq %x base %p\n",
- j, pirq_entry->pirq, base);
-
pirq_entry->address_lo_save =
readl(base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
@@ -443,7 +441,6 @@ void pci_restore_msix_state(struct pci_d
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
if (!save_state)
return;
- printk(KERN_CRIT "Restoring MSIX cap\n");
save = *((u16 *)&save_state->data[0]);
pci_remove_saved_cap(save_state);
@@ -454,15 +451,12 @@ void pci_restore_msix_state(struct pci_d
return;
msi_dev_entry = get_msi_dev_pirq_list(dev);
+ base = msi_dev_entry->mask_base;
spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
/* route the table */
- base = pirq_entry->mask_base;
j = pirq_entry->entry_nr;
-
- printk(KERN_CRIT "Restore msix table entry %d pirq %x base
%p\n",
- j, pirq_entry->pirq, base);
writel(pirq_entry->address_lo_save,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
@@ -523,7 +517,8 @@ static int msix_capability_init(struct p
struct msix_entry *entries, int nvec)
{
u64 table_base;
- int pirq, i, j, mapped, pos;
+ u16 control;
+ int pirq, i, j, mapped, pos, nr_entries;
struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
struct msi_pirq_entry *pirq_entry;
@@ -534,6 +529,12 @@ static int msix_capability_init(struct p
table_base = find_table_base(dev, pos);
if (!table_base)
return -ENODEV;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ nr_entries = multi_msix_capable(control);
+ if (!msi_dev_entry->mask_base)
+ msi_dev_entry->mask_base =
+ ioremap_nocache(table_base, nr_entries *
PCI_MSIX_ENTRY_SIZE);
/* MSI-X Table Initialization */
for (i = 0; i < nvec; i++) {
@@ -554,7 +555,7 @@ static int msix_capability_init(struct p
pirq = msi_map_vector(dev, entries[i].entry, table_base);
if (pirq < 0)
break;
- attach_pirq_entry(pirq, entries[i].entry, table_base,
msi_dev_entry);
+ attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
(entries + i)->vector = pirq;
}
@@ -739,7 +740,7 @@ int pci_enable_msix(struct pci_dev* dev,
if (mapped)
continue;
irq = evtchn_map_pirq(-1, entries[i].vector);
- attach_pirq_entry(irq, entries[i].entry, 0,
msi_dev_entry);
+ attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
entries[i].vector = irq;
}
return 0;
@@ -857,18 +858,15 @@ void msi_remove_pci_irq_vectors(struct p
spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
if (!list_empty(&msi_dev_entry->pirq_list_head))
- {
- printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not
freed \
- before acquire again.\n", dev->bus->number,
PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn));
list_for_each_entry_safe(pirq_entry, tmp,
&msi_dev_entry->pirq_list_head, list) {
msi_unmap_pirq(dev, pirq_entry->pirq);
list_del(&pirq_entry->list);
kfree(pirq_entry);
}
- }
spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
+ iounmap(msi_dev_entry->mask_base);
+ msi_dev_entry->mask_base = NULL;
dev->irq = dev->irq_old;
}
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/pci/pci.h
--- a/drivers/pci/pci.h Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/pci/pci.h Thu Dec 04 11:02:17 2008 +0900
@@ -104,5 +104,4 @@ extern void pci_disable_bridge_window(st
extern void pci_disable_bridge_window(struct pci_dev *dev);
#else
#define is_reassigndev(dev) 0
-static inline void pci_disable_bridge_window(struct pci_dev *dev) {}
#endif
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/pci/quirks.c
--- a/drivers/pci/quirks.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/pci/quirks.c Thu Dec 04 11:02:17 2008 +0900
@@ -24,6 +24,7 @@
#include "pci.h"
+#ifdef CONFIG_PCI_REASSIGN
/*
* This quirk function disables the device and releases resources
* which is specified by kernel's boot parameter 'reassigndev'.
@@ -66,10 +67,10 @@ static void __devinit quirk_release_reso
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_disable_bridge_window(dev);
}
- return;
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_release_resources);
+#endif /* CONFIG_PCI_REASSIGN */
/* The Mellanox Tavor device gives false positive parity errors
* Mark this device with a broken_parity_status, to allow
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/pci/setup-bus.c Thu Dec 04 11:02:17 2008 +0900
@@ -355,7 +355,7 @@ pbus_size_mem(struct pci_bus *bus, unsig
continue;
r_size = r->end - r->start + 1;
- if (reassign)
+ if ((i < PCI_BRIDGE_RESOURCES) && reassign)
r_size = ALIGN(r_size, PAGE_SIZE);
/* For bridges size != alignment */
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/pci/setup-res.c Thu Dec 04 11:02:17 2008 +0900
@@ -234,6 +234,7 @@ pdev_sort_resources(struct pci_dev *dev,
pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
{
int i;
+ int reassigndev = is_reassigndev(dev);
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r;
@@ -245,6 +246,11 @@ pdev_sort_resources(struct pci_dev *dev,
if (!(r->flags) || r->parent)
continue;
+
+ if (i < PCI_BRIDGE_RESOURCES && (r->flags & IORESOURCE_MEM) &&
+ reassigndev)
+ r_align = ALIGN(r_align, PAGE_SIZE);
+
if (!r_align) {
printk(KERN_WARNING "PCI: Ignore bogus resource %d "
"[%llx:%llx] of %s\n",
@@ -263,6 +269,10 @@ pdev_sort_resources(struct pci_dev *dev,
align = (idx < PCI_BRIDGE_RESOURCES) ?
ln->res->end - ln->res->start + 1 :
ln->res->start;
+ if ((idx < PCI_BRIDGE_RESOURCES) &&
+ (ln->res->flags & IORESOURCE_MEM) &&
+ is_reassigndev(ln->dev))
+ align = ALIGN(align, PAGE_SIZE);
}
if (r_align > align) {
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/xen/blkback/blkback.c
--- a/drivers/xen/blkback/blkback.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/xen/blkback/blkback.c Thu Dec 04 11:02:17 2008 +0900
@@ -317,14 +317,14 @@ static int do_block_io_op(blkif_t *blkif
if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
break;
+ if (kthread_should_stop()) {
+ more_to_do = 1;
+ break;
+ }
+
pending_req = alloc_req();
if (NULL == pending_req) {
blkif->st_oo_req++;
- more_to_do = 1;
- break;
- }
-
- if (kthread_should_stop()) {
more_to_do = 1;
break;
}
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/xen/blktap/blktap.c
--- a/drivers/xen/blktap/blktap.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/xen/blktap/blktap.c Thu Dec 04 11:02:17 2008 +0900
@@ -1286,14 +1286,14 @@ static int do_block_io_op(blkif_t *blkif
break;
}
+ if (kthread_should_stop()) {
+ more_to_do = 1;
+ break;
+ }
+
pending_req = alloc_req();
if (NULL == pending_req) {
blkif->st_oo_req++;
- more_to_do = 1;
- break;
- }
-
- if (kthread_should_stop()) {
more_to_do = 1;
break;
}
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/xen/core/evtchn.c Thu Dec 04 11:02:17 2008 +0900
@@ -123,9 +123,6 @@ DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS])
/* Reference counts for bindings to IRQs. */
static int irq_bindcount[NR_IRQS];
-/* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
-static DECLARE_BITMAP(pirq_needs_eoi, NR_PIRQS);
-
#ifdef CONFIG_SMP
static u8 cpu_evtchn[NR_EVENT_CHANNELS];
@@ -756,16 +753,48 @@ static struct hw_interrupt_type dynirq_t
.retrigger = resend_irq_on_evtchn,
};
-static inline void pirq_unmask_notify(int irq)
+/* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
+static int pirq_eoi_does_unmask;
+static DECLARE_BITMAP(pirq_needs_eoi, ALIGN(NR_PIRQS, PAGE_SIZE * 8))
+ __attribute__ ((__section__(".bss.page_aligned"),
__aligned__(PAGE_SIZE)));
+
+static void pirq_unmask_and_notify(unsigned int evtchn, unsigned int irq)
{
struct physdev_eoi eoi = { .irq = evtchn_get_xen_pirq(irq) };
- if (unlikely(test_bit(irq - PIRQ_BASE, pirq_needs_eoi)))
- VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
+
+ if (pirq_eoi_does_unmask) {
+ if (test_bit(eoi.irq, pirq_needs_eoi))
+ VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
+ else
+ unmask_evtchn(evtchn);
+ } else if (test_bit(irq - PIRQ_BASE, pirq_needs_eoi)) {
+ if (smp_processor_id() != cpu_from_evtchn(evtchn)) {
+ struct evtchn_unmask unmask = { .port = evtchn };
+ struct multicall_entry mcl[2];
+
+ mcl[0].op = __HYPERVISOR_event_channel_op;
+ mcl[0].args[0] = EVTCHNOP_unmask;
+ mcl[0].args[1] = (unsigned long)&unmask;
+ mcl[1].op = __HYPERVISOR_physdev_op;
+ mcl[1].args[0] = PHYSDEVOP_eoi;
+ mcl[1].args[1] = (unsigned long)&eoi;
+
+ if (HYPERVISOR_multicall(mcl, 2))
+ BUG();
+ } else {
+ unmask_evtchn(evtchn);
+ VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
+ }
+ } else
+ unmask_evtchn(evtchn);
}
static inline void pirq_query_unmask(int irq)
{
struct physdev_irq_status_query irq_status;
+
+ if (pirq_eoi_does_unmask)
+ return;
irq_status.irq = evtchn_get_xen_pirq(irq);
if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
irq_status.flags = 0;
@@ -806,8 +835,7 @@ static unsigned int startup_pirq(unsigne
irq_info[irq] = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
out:
- unmask_evtchn(evtchn);
- pirq_unmask_notify(irq);
+ pirq_unmask_and_notify(evtchn, irq);
return 0;
}
@@ -859,10 +887,8 @@ static void end_pirq(unsigned int irq)
if ((irq_desc[irq].status & (IRQ_DISABLED|IRQ_PENDING)) ==
(IRQ_DISABLED|IRQ_PENDING)) {
shutdown_pirq(irq);
- } else if (VALID_EVTCHN(evtchn)) {
- unmask_evtchn(evtchn);
- pirq_unmask_notify(irq);
- }
+ } else if (VALID_EVTCHN(evtchn))
+ pirq_unmask_and_notify(evtchn, irq);
}
static struct hw_interrupt_type pirq_type = {
@@ -1011,6 +1037,15 @@ void irq_resume(void)
unsigned int cpu, irq, evtchn;
init_evtchn_cpu_bindings();
+
+ if (pirq_eoi_does_unmask) {
+ struct physdev_pirq_eoi_gmfn eoi_gmfn;
+
+ eoi_gmfn.gmfn = arbitrary_virt_to_machine(pirq_needs_eoi)
+ >> PAGE_SHIFT;
+ if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn))
+ BUG();
+ }
/* New event-channel space is not 'live' yet. */
for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
@@ -1098,8 +1133,15 @@ void __init xen_init_IRQ(void)
void __init xen_init_IRQ(void)
{
unsigned int i;
+ struct physdev_pirq_eoi_gmfn eoi_gmfn;
init_evtchn_cpu_bindings();
+
+ BUG_ON(!bitmap_empty(pirq_needs_eoi, PAGE_SIZE * 8));
+ eoi_gmfn.gmfn = arbitrary_virt_to_machine(pirq_needs_eoi)
+ >> PAGE_SHIFT;
+ if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
+ pirq_eoi_does_unmask = 1;
/* No event channels are 'live' right now. */
for (i = 0; i < NR_EVENT_CHANNELS; i++)
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/xen/core/gnttab.c
--- a/drivers/xen/core/gnttab.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/xen/core/gnttab.c Thu Dec 04 11:02:17 2008 +0900
@@ -505,8 +505,9 @@ static int gnttab_map(unsigned int start
return 0;
}
-static void gnttab_page_free(struct page *page)
-{
+static void gnttab_page_free(struct page *page, unsigned int order)
+{
+ BUG_ON(order);
ClearPageForeign(page);
gnttab_reset_grant_page(page);
put_page(page);
diff -r 6743af9fffc6 -r 17adc5c344fe drivers/xen/netback/netback.c
--- a/drivers/xen/netback/netback.c Wed Dec 03 11:38:32 2008 +0900
+++ b/drivers/xen/netback/netback.c Thu Dec 04 11:02:17 2008 +0900
@@ -55,7 +55,6 @@ struct netbk_tx_pending_inuse {
};
static void netif_idx_release(u16 pending_idx);
-static void netif_page_release(struct page *page);
static void make_tx_response(netif_t *netif,
netif_tx_request_t *txp,
s8 st);
@@ -1436,8 +1435,9 @@ static void netif_idx_release(u16 pendin
tasklet_schedule(&net_tx_tasklet);
}
-static void netif_page_release(struct page *page)
-{
+static void netif_page_release(struct page *page, unsigned int order)
+{
+ BUG_ON(order);
netif_idx_release(netif_page_index(page));
}
diff -r 6743af9fffc6 -r 17adc5c344fe include/asm-ia64/maddr.h
--- a/include/asm-ia64/maddr.h Wed Dec 03 11:38:32 2008 +0900
+++ b/include/asm-ia64/maddr.h Thu Dec 04 11:02:17 2008 +0900
@@ -99,6 +99,7 @@ mfn_to_local_pfn(unsigned long mfn)
#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT))
#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT)
#define virt_to_machine(virt) __pa(virt) /* for tpmfront.c */
+#define arbitrary_virt_to_machine(virt) virt_to_machine(ia64_imva(virt))
#define set_phys_to_machine(pfn, mfn) do { } while (0)
diff -r 6743af9fffc6 -r 17adc5c344fe include/linux/page-flags.h
--- a/include/linux/page-flags.h Wed Dec 03 11:38:32 2008 +0900
+++ b/include/linux/page-flags.h Thu Dec 04 11:02:17 2008 +0900
@@ -252,15 +252,15 @@
#define PageForeign(page) test_bit(PG_foreign, &(page)->flags)
#define SetPageForeign(_page, dtor) do { \
set_bit(PG_foreign, &(_page)->flags); \
- BUG_ON((dtor) == (void (*)(struct page *))0); \
+ BUG_ON((dtor) == (void (*)(struct page *, unsigned int))0); \
(_page)->index = (long)(dtor); \
} while (0)
#define ClearPageForeign(page) do { \
clear_bit(PG_foreign, &(page)->flags); \
(page)->index = 0; \
} while (0)
-#define PageForeignDestructor(_page) \
- ((void (*)(struct page *))(_page)->index)(_page)
+#define PageForeignDestructor(_page, order) \
+ ((void (*)(struct page *, unsigned int))(_page)->index)(_page, order)
struct page; /* forward declaration */
diff -r 6743af9fffc6 -r 17adc5c344fe include/xen/interface/physdev.h
--- a/include/xen/interface/physdev.h Wed Dec 03 11:38:32 2008 +0900
+++ b/include/xen/interface/physdev.h Thu Dec 04 11:02:17 2008 +0900
@@ -41,6 +41,21 @@ DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
/*
+ * Register a shared page for the hypervisor to indicate whether the guest
+ * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly
+ * once the guest used this function in that the associated event channel
+ * will automatically get unmasked. The page registered is used as a bit
+ * array indexed by Xen's PIRQ value.
+ */
+#define PHYSDEVOP_pirq_eoi_gmfn 17
+struct physdev_pirq_eoi_gmfn {
+ /* IN */
+ xen_pfn_t gmfn;
+};
+typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t);
+
+/*
* Query the status of an IRQ line.
* @arg == pointer to physdev_irq_status_query structure.
*/
diff -r 6743af9fffc6 -r 17adc5c344fe mm/page_alloc.c
--- a/mm/page_alloc.c Wed Dec 03 11:38:32 2008 +0900
+++ b/mm/page_alloc.c Thu Dec 04 11:02:17 2008 +0900
@@ -453,7 +453,7 @@ static void __free_pages_ok(struct page
#ifdef CONFIG_XEN
if (PageForeign(page)) {
- PageForeignDestructor(page);
+ PageForeignDestructor(page, order);
return;
}
#endif
@@ -737,7 +737,7 @@ static void fastcall free_hot_cold_page(
#ifdef CONFIG_XEN
if (PageForeign(page)) {
- PageForeignDestructor(page);
+ PageForeignDestructor(page, 0);
return;
}
#endif
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|