qubes-linux-kernel/patches.xen/xen3-patch-2.6.31
2011-04-19 22:09:59 +02:00

7755 lines
230 KiB
Plaintext

From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Linux: 2.6.31
Patch-mainline: 2.6.31
This patch contains the differences between 2.6.30 and 2.6.31.
Acked-by: Jeff Mahoney <jeffm@suse.com>
Automatically created from "patches.kernel.org/patch-2.6.31" by xen-port-patches.py
--- head-2011-03-17.orig/arch/x86/Kconfig 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/Kconfig 2011-02-01 14:50:44.000000000 +0100
@@ -21,7 +21,7 @@ config X86
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_IDE
select HAVE_OPROFILE
- select HAVE_PERF_EVENTS
+ select HAVE_PERF_EVENTS if !XEN
select HAVE_IRQ_WORK
select HAVE_IOREMAP_PROT
select HAVE_KPROBES
@@ -879,7 +879,7 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
config X86_MCE
bool "Machine Check / overheating reporting"
- depends on !X86_XEN && !XEN_UNPRIVILEGED_GUEST
+ depends on !XEN_UNPRIVILEGED_GUEST
---help---
Machine Check support allows the processor to notify the
kernel if it detects a problem (e.g. overheating, data corruption).
@@ -912,7 +912,7 @@ config X86_MCE_AMD
config X86_ANCIENT_MCE
bool "Support for old Pentium 5 / WinChip machine checks"
- depends on X86_32 && X86_MCE
+ depends on X86_32 && X86_MCE && !XEN
---help---
Include support for machine check handling on old Pentium 5 or WinChip
systems. These typically need to be enabled explicitely on the command
@@ -1609,6 +1609,7 @@ config KEXEC_JUMP
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP || XEN)
+ default 0x100000 if XEN
default "0x1000000"
---help---
This gives the physical address where the kernel is loaded.
--- head-2011-03-17.orig/arch/x86/ia32/ia32entry-xen.S 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/ia32/ia32entry-xen.S 2011-02-01 14:50:44.000000000 +0100
@@ -770,9 +770,11 @@ ia32_sys_call_table:
.quad compat_sys_signalfd4
.quad sys_eventfd2
.quad sys_epoll_create1
- .quad sys_dup3 /* 330 */
+ .quad sys_dup3 /* 330 */
.quad sys_pipe2
.quad sys_inotify_init1
.quad compat_sys_preadv
.quad compat_sys_pwritev
+ .quad compat_sys_rt_tgsigqueueinfo /* 335 */
+ .quad sys_perf_counter_open
ia32_syscall_end:
--- head-2011-03-17.orig/arch/x86/include/asm/hw_irq.h 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/arch/x86/include/asm/hw_irq.h 2011-02-01 14:50:44.000000000 +0100
@@ -142,6 +142,7 @@ extern asmlinkage void smp_invalidate_in
extern irqreturn_t smp_reschedule_interrupt(int, void *);
extern irqreturn_t smp_call_function_interrupt(int, void *);
extern irqreturn_t smp_call_function_single_interrupt(int, void *);
+extern irqreturn_t smp_reboot_interrupt(int, void *);
#endif
#endif
--- head-2011-03-17.orig/arch/x86/include/asm/required-features.h 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/arch/x86/include/asm/required-features.h 2011-02-01 14:50:44.000000000 +0100
@@ -48,7 +48,7 @@
#endif
#ifdef CONFIG_X86_64
-#ifdef CONFIG_PARAVIRT
+#if defined(CONFIG_PARAVIRT) || defined(CONFIG_XEN)
/* Paravirtualized systems may not have PSE or PGE available */
#define NEED_PSE 0
#define NEED_PGE 0
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/agp.h 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/agp.h 2011-02-01 14:50:44.000000000 +0100
@@ -48,6 +48,7 @@
/* Convert a physical address to an address suitable for the GART. */
#define phys_to_gart(x) phys_to_machine(x)
#define gart_to_phys(x) machine_to_phys(x)
+#define page_to_gart(x) phys_to_gart(page_to_pseudophys(x))
/* GATT allocation. Returns/accepts GATT kernel virtual address. */
#define alloc_gatt_pages(order) ({ \
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/desc.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/desc.h 2011-02-01 14:50:44.000000000 +0100
@@ -1,7 +1,6 @@
#ifndef _ASM_X86_DESC_H
#define _ASM_X86_DESC_H
-#ifndef __ASSEMBLY__
#include <asm/desc_defs.h>
#include <asm/ldt.h>
#include <asm/mmu.h>
@@ -406,29 +405,4 @@ static inline void set_system_intr_gate_
}
#endif
-#else
-/*
- * GET_DESC_BASE reads the descriptor base of the specified segment.
- *
- * Args:
- * idx - descriptor index
- * gdt - GDT pointer
- * base - 32bit register to which the base will be written
- * lo_w - lo word of the "base" register
- * lo_b - lo byte of the "base" register
- * hi_b - hi byte of the low word of the "base" register
- *
- * Example:
- * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
- */
-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
- movb idx * 8 + 4(gdt), lo_b; \
- movb idx * 8 + 7(gdt), hi_b; \
- shll $16, base; \
- movw idx * 8 + 2(gdt), lo_w;
-
-
-#endif /* __ASSEMBLY__ */
-
#endif /* _ASM_X86_DESC_H */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/fixmap.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/fixmap.h 2011-02-01 14:50:44.000000000 +0100
@@ -118,12 +118,9 @@ enum fixed_addresses {
#ifdef CONFIG_PARAVIRT
FIX_PARAVIRT_BOOTMAP,
#endif
- FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */
- FIX_TEXT_POKE1,
+ FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */
+ FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
__end_of_permanent_fixed_addresses,
-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
- FIX_OHCI1394_BASE,
-#endif
/*
* 256 temporary boot-time mappings, used by early_ioremap(),
* before ioremap() is functional.
@@ -136,6 +133,9 @@ enum fixed_addresses {
FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
(__end_of_permanent_fixed_addresses & 255),
FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+ FIX_OHCI1394_BASE,
+#endif
#ifdef CONFIG_X86_32
FIX_WP_TEST,
#endif
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/hypercall.h 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/hypercall.h 2011-02-01 14:50:44.000000000 +0100
@@ -265,7 +265,7 @@ HYPERVISOR_memory_op(
unsigned int cmd, void *arg)
{
if (arch_use_lazy_mmu_mode())
- xen_multicall_flush(false);
+ xen_multicall_flush();
return _hypercall2(int, memory_op, cmd, arg);
}
@@ -336,7 +336,7 @@ HYPERVISOR_grant_table_op(
int rc;
if (arch_use_lazy_mmu_mode())
- xen_multicall_flush(false);
+ xen_multicall_flush();
#ifdef GNTTABOP_map_grant_ref
if (cmd == GNTTABOP_map_grant_ref)
#endif
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/hypervisor.h 2011-03-11 11:13:19.000000000 +0100
@@ -144,7 +144,7 @@ void scrub_pages(void *, unsigned int);
DECLARE_PER_CPU(bool, xen_lazy_mmu);
-void xen_multicall_flush(bool);
+void xen_multicall_flush(void);
int __must_check xen_multi_update_va_mapping(unsigned long va, pte_t,
unsigned long flags);
@@ -162,7 +162,7 @@ static inline void arch_enter_lazy_mmu_m
static inline void arch_leave_lazy_mmu_mode(void)
{
percpu_write(xen_lazy_mmu, false);
- xen_multicall_flush(false);
+ xen_multicall_flush();
}
#define arch_use_lazy_mmu_mode() unlikely(percpu_read(xen_lazy_mmu))
@@ -176,13 +176,13 @@ static inline void arch_leave_lazy_mmu_m
static inline void arch_flush_lazy_mmu_mode(void)
{
if (arch_use_lazy_mmu_mode())
- xen_multicall_flush(false);
+ xen_multicall_flush();
}
#endif
#else /* !CONFIG_XEN || MODULE */
-static inline void xen_multicall_flush(bool ignore) {}
+static inline void xen_multicall_flush(void) {}
#define arch_use_lazy_mmu_mode() false
#define xen_multi_update_va_mapping(...) ({ BUG(); -ENOSYS; })
#define xen_multi_mmu_update(...) ({ BUG(); -ENOSYS; })
@@ -356,4 +356,9 @@ MULTI_grant_table_op(multicall_entry_t *
#define uvm_multi(cpumask) ((unsigned long)cpus_addr(cpumask) | UVMF_MULTI)
+#ifdef LINUX
+/* drivers/staging/ use Windows-style types, including VOID */
+#undef VOID
+#endif
+
#endif /* __HYPERVISOR_H__ */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/irq_vectors.h 2011-02-15 17:33:07.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/irq_vectors.h 2011-02-15 17:33:45.000000000 +0100
@@ -1,8 +1,11 @@
#ifndef _ASM_X86_IRQ_VECTORS_H
#define _ASM_X86_IRQ_VECTORS_H
+#define MCE_VECTOR 0x12
+
#ifdef CONFIG_X86_32
# define SYSCALL_VECTOR 0x80
+# define IA32_SYSCALL_VECTOR 0x80
#else
# define IA32_SYSCALL_VECTOR 0x80
#endif
@@ -11,7 +14,8 @@
#define CALL_FUNCTION_VECTOR 1
#define NMI_VECTOR 0x02
#define CALL_FUNC_SINGLE_VECTOR 3
-#define NR_IPIS 4
+#define REBOOT_VECTOR 4
+#define NR_IPIS 5
/*
* The maximum number of vectors supported by i386 processors
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pci.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pci.h 2011-02-01 14:50:44.000000000 +0100
@@ -97,7 +97,8 @@ extern void pci_iommu_alloc(void);
#define PCI_DMA_BUS_IS_PHYS 0
-#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG) || defined(CONFIG_SWIOTLB)
+#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG) \
+ || defined(CONFIG_SWIOTLB)
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
@@ -136,6 +137,7 @@ extern void pci_iommu_alloc(void);
/* generic pci stuff */
#include <asm-generic/pci.h>
+#define PCIBIOS_MAX_MEM_32 0xffffffff
#ifdef CONFIG_NUMA
/* Returns the node based on pci bus */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pgalloc.h 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pgalloc.h 2011-02-01 14:50:44.000000000 +0100
@@ -51,7 +51,13 @@ static inline void pte_free(struct mm_st
__pte_free(pte);
}
-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+extern void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
+ unsigned long address)
+{
+ ___pte_free_tlb(tlb, pte);
+}
static inline void pmd_populate_kernel(struct mm_struct *mm,
pmd_t *pmd, pte_t *pte)
@@ -92,7 +98,13 @@ static inline void pmd_free(struct mm_st
__pmd_free(virt_to_page(pmd));
}
-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+extern void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+
+static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+ unsigned long adddress)
+{
+ ___pmd_free_tlb(tlb, pmd);
+}
#ifdef CONFIG_X86_PAE
extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
@@ -145,7 +157,14 @@ static inline void pud_free(struct mm_st
__pmd_free(virt_to_page(pud));
}
-extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+extern void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+ unsigned long address)
+{
+ ___pud_free_tlb(tlb, pud);
+}
+
#endif /* PAGETABLE_LEVELS > 3 */
#endif /* PAGETABLE_LEVELS > 2 */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pgtable.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pgtable.h 2011-02-01 14:50:44.000000000 +0100
@@ -2,6 +2,7 @@
#define _ASM_X86_PGTABLE_H
#include <asm/page.h>
+#include <asm/e820.h>
#include <asm/pgtable_types.h>
@@ -78,6 +79,8 @@ static inline void __init paravirt_paget
#define pte_val(x) xen_pte_val(x)
#define __pte(x) xen_make_pte(x)
+#define arch_end_context_switch(prev) do {} while(0)
+
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
@@ -264,10 +267,17 @@ static inline pgprot_t pgprot_modify(pgp
#define canon_pgprot(p) __pgprot(massage_pgprot(p))
-static inline int is_new_memtype_allowed(unsigned long flags,
- unsigned long new_flags)
+static inline int is_new_memtype_allowed(u64 paddr, unsigned long size,
+ unsigned long flags,
+ unsigned long new_flags)
{
/*
+ * PAT type is always WB for ISA. So no need to check.
+ */
+ if (is_ISA_range(paddr, paddr + size - 1))
+ return 1;
+
+ /*
* Certain new memtypes are not allowed with certain
* requested memtype:
* - request is uncached, return cannot be write-back
@@ -312,6 +322,11 @@ static inline int pte_present(pte_t a)
return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
}
+static inline int pte_hidden(pte_t pte)
+{
+ return pte_flags(pte) & _PAGE_HIDDEN;
+}
+
static inline int pmd_present(pmd_t pmd)
{
#if CONFIG_XEN_COMPAT <= 0x030002
@@ -511,6 +526,8 @@ static inline int pgd_none(pgd_t pgd)
#ifndef __ASSEMBLY__
+#define direct_gbpages 0
+
/* local pte updates need not use xchg for locking */
static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
{
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pgtable_32.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pgtable_32.h 2011-02-01 14:50:44.000000000 +0100
@@ -48,13 +48,17 @@ extern void set_pmd_pfn(unsigned long, u
#endif
#if defined(CONFIG_HIGHPTE)
+#define __KM_PTE \
+ (in_nmi() ? KM_NMI_PTE : \
+ in_irq() ? KM_IRQ_PTE : \
+ KM_PTE0)
#define pte_offset_map(dir, address) \
- ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \
+ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), __KM_PTE) + \
pte_index((address)))
#define pte_offset_map_nested(dir, address) \
((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) + \
pte_index((address)))
-#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
+#define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
#else
#define pte_offset_map(dir, address) \
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pgtable_64.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pgtable_64.h 2011-02-01 14:50:44.000000000 +0100
@@ -33,10 +33,6 @@ extern pgd_t init_level4_pgt[];
extern void paging_init(void);
-#endif /* !__ASSEMBLY__ */
-
-#ifndef __ASSEMBLY__
-
#define pte_ERROR(e) \
printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n", \
__FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
@@ -142,8 +138,6 @@ static inline int pgd_large(pgd_t pgd) {
#define update_mmu_cache(vma, address, pte) do { } while (0)
-#define direct_gbpages 0
-
/* Encode and de-code a swap entry */
#if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
#define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
@@ -178,10 +172,7 @@ extern void cleanup_highmap(void);
/* fs/proc/kcore.c */
#define kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
-#define kc_offset_to_vaddr(o) \
- (((o) & (1UL << (__VIRTUAL_MASK_SHIFT - 1))) \
- ? ((o) | ~__VIRTUAL_MASK) \
- : (o))
+#define kc_offset_to_vaddr(o) ((o) | ~__VIRTUAL_MASK)
#define __HAVE_ARCH_PTE_SAME
#endif /* !__ASSEMBLY__ */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pgtable_64_types.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pgtable_64_types.h 2011-02-01 14:50:44.000000000 +0100
@@ -51,11 +51,12 @@ typedef union { pteval_t pte; unsigned i
#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE - 1))
+/* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */
#define MAX_PHYSMEM_BITS 43
#define MAXMEM _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
-#define VMALLOC_START _AC(0xffffc20000000000, UL)
-#define VMALLOC_END _AC(0xffffe1ffffffffff, UL)
-#define VMEMMAP_START _AC(0xffffe20000000000, UL)
+#define VMALLOC_START _AC(0xffffc90000000000, UL)
+#define VMALLOC_END _AC(0xffffe8ffffffffff, UL)
+#define VMEMMAP_START _AC(0xffffea0000000000, UL)
#define MODULES_VADDR _AC(0xffffffffa0000000, UL)
#define MODULES_END _AC(0xffffffffff000000, UL)
#define MODULES_LEN (MODULES_END - MODULES_VADDR)
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/pgtable_types.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/pgtable_types.h 2011-02-01 14:50:44.000000000 +0100
@@ -18,7 +18,7 @@
#define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
#define _PAGE_BIT_UNUSED1 9 /* available for programmer */
#define _PAGE_BIT_IOMAP 10 /* flag used to indicate IO mapping */
-#define _PAGE_BIT_UNUSED3 11
+#define _PAGE_BIT_HIDDEN 11 /* hidden by kmemcheck */
#define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */
#define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1
#define _PAGE_BIT_CPA_TEST _PAGE_BIT_UNUSED1
@@ -41,13 +41,18 @@
#define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
#define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
#define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
-#define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
#define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
#define _PAGE_SPECIAL (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
#define _PAGE_CPA_TEST (_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
#define __HAVE_ARCH_PTE_SPECIAL
+#ifdef CONFIG_KMEMCHECK
+#define _PAGE_HIDDEN (_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
+#else
+#define _PAGE_HIDDEN (_AT(pteval_t, 0))
+#endif
+
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX)
#else
@@ -330,7 +335,6 @@ typedef struct page *pgtable_t;
extern pteval_t __supported_pte_mask;
extern int nx_enabled;
-extern void set_nx(void);
#define pgprot_writecombine pgprot_writecombine
extern pgprot_t pgprot_writecombine(pgprot_t prot);
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/processor.h 2011-03-03 16:45:53.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/processor.h 2011-03-03 16:46:07.000000000 +0100
@@ -146,7 +146,8 @@ struct cpuinfo_x86 {
extern struct cpuinfo_x86 boot_cpu_data;
extern struct cpuinfo_x86 new_cpu_data;
-extern __u32 cleared_cpu_caps[NCAPINTS];
+extern __u32 cpu_caps_cleared[NCAPINTS];
+extern __u32 cpu_caps_set[NCAPINTS];
#ifdef CONFIG_SMP
DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
@@ -427,9 +428,6 @@ DECLARE_PER_CPU(unsigned long, stack_can
extern unsigned int xstate_size;
extern void free_thread_xstate(struct task_struct *);
extern struct kmem_cache *task_xstate_cachep;
-extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
-extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
-extern unsigned short num_cache_leaves;
struct thread_struct {
/* Cached TLS descriptors: */
@@ -444,8 +442,12 @@ struct thread_struct {
unsigned short fsindex;
unsigned short gsindex;
#endif
+#ifdef CONFIG_X86_32
unsigned long ip;
+#endif
+#ifdef CONFIG_X86_64
unsigned long fs;
+#endif
unsigned long gs;
/* Hardware debugging registers: */
unsigned long debugreg0;
@@ -474,14 +476,8 @@ struct thread_struct {
unsigned io_bitmap_max;
/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */
unsigned long debugctlmsr;
-#ifdef CONFIG_X86_DS
-/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */
+ /* Debug Store context; see asm/ds.h */
struct ds_context *ds_ctx;
-#endif /* CONFIG_X86_DS */
-#ifdef CONFIG_X86_PTRACE_BTS
-/* the signal to send on a bts buffer overflow */
- unsigned int bts_ovfl_signal;
-#endif /* CONFIG_X86_PTRACE_BTS */
};
static inline unsigned long xen_get_debugreg(int regno)
@@ -751,6 +747,21 @@ static inline unsigned long get_debugctl
return debugctlmsr;
}
+static inline unsigned long get_debugctlmsr_on_cpu(int cpu)
+{
+ u64 debugctlmsr = 0;
+ u32 val1, val2;
+
+#ifndef CONFIG_X86_DEBUGCTLMSR
+ if (boot_cpu_data.x86 < 6)
+ return 0;
+#endif
+ rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2);
+ debugctlmsr = val1 | ((u64)val2 << 32);
+
+ return debugctlmsr;
+}
+
static inline void update_debugctlmsr(unsigned long debugctlmsr)
{
#ifndef CONFIG_X86_DEBUGCTLMSR
@@ -760,6 +771,18 @@ static inline void update_debugctlmsr(un
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
}
+static inline void update_debugctlmsr_on_cpu(int cpu,
+ unsigned long debugctlmsr)
+{
+#ifndef CONFIG_X86_DEBUGCTLMSR
+ if (boot_cpu_data.x86 < 6)
+ return;
+#endif
+ wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR,
+ (u32)((u64)debugctlmsr),
+ (u32)((u64)debugctlmsr >> 32));
+}
+
/*
* from system description table in BIOS. Mostly for MCA use, but
* others may find it useful:
@@ -770,6 +793,7 @@ extern unsigned int BIOS_revision;
/* Boot loader type from the setup header: */
extern int bootloader_type;
+extern int bootloader_version;
extern char ignore_fpu_irq;
@@ -830,7 +854,6 @@ static inline void spin_lock_prefetch(co
.vm86_info = NULL, \
.sysenter_cs = __KERNEL_CS, \
.io_bitmap_ptr = NULL, \
- .fs = __KERNEL_PERCPU, \
}
/*
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/smp.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/smp.h 2011-02-01 14:50:44.000000000 +0100
@@ -198,7 +198,7 @@ extern unsigned disabled_cpus __cpuinitd
static inline int logical_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
- return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+ return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
}
#endif
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/spinlock.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/spinlock.h 2011-02-01 14:50:44.000000000 +0100
@@ -432,4 +432,8 @@ static inline void __raw_write_unlock(ra
#define _raw_read_relax(lock) cpu_relax()
#define _raw_write_relax(lock) cpu_relax()
+/* The {read|write|spin}_lock() on x86 are full memory barriers. */
+static inline void smp_mb__after_lock(void) { }
+#define ARCH_HAS_SMP_MB_AFTER_LOCK
+
#endif /* _ASM_X86_SPINLOCK_H */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/tlbflush.h 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/tlbflush.h 2011-02-01 14:50:44.000000000 +0100
@@ -111,6 +111,6 @@ static inline void flush_tlb_kernel_rang
flush_tlb_all();
}
-extern void zap_low_mappings(void);
+extern void zap_low_mappings(bool early);
#endif /* _ASM_X86_TLBFLUSH_H */
--- head-2011-03-17.orig/arch/x86/include/mach-xen/asm/xor.h 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/arch/x86/include/mach-xen/asm/xor.h 2011-02-01 14:50:44.000000000 +0100
@@ -1,4 +1,7 @@
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_KMEMCHECK
+/* kmemcheck doesn't handle MMX/SSE/SSE2 instructions */
+# include <asm-generic/xor.h>
+#elif defined(CONFIG_X86_32)
# include "../../asm/xor_32.h"
#else
# include "xor_64.h"
--- head-2011-03-17.orig/arch/x86/kernel/Makefile 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/Makefile 2011-02-01 14:50:44.000000000 +0100
@@ -128,6 +128,6 @@ ifeq ($(CONFIG_X86_64),y)
endif
disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
- i8259.o irqinit_$(BITS).o pci-swiotlb.o reboot.o smpboot.o tsc.o \
- tsc_sync.o uv_%.o vsmp_64.o
+ i8259.o irqinit.o pci-swiotlb.o reboot.o smpboot.o tsc.o tsc_sync.o \
+ uv_%.o vsmp_64.o
disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += probe_roms_32.o
--- head-2011-03-17.orig/arch/x86/kernel/acpi/sleep-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/acpi/sleep-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -107,7 +107,7 @@ int acpi_save_state_mem(void)
initial_gs = per_cpu_offset(smp_processor_id());
#endif
initial_code = (unsigned long)wakeup_long64;
- saved_magic = 0x123456789abcdef0;
+ saved_magic = 0x123456789abcdef0L;
#endif /* CONFIG_64BIT */
#endif
--- head-2011-03-17.orig/arch/x86/kernel/apic/io_apic-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/apic/io_apic-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -51,6 +51,7 @@
#include <asm/i8259.h>
#include <asm/nmi.h>
#include <asm/setup.h>
+#include <asm/hw_irq.h>
#include <asm/apic.h>
@@ -135,12 +136,9 @@ struct irq_pin_list {
struct irq_pin_list *next;
};
-static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
+static struct irq_pin_list *get_one_free_irq_2_pin(int node)
{
struct irq_pin_list *pin;
- int node;
-
- node = cpu_to_node(cpu);
pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
@@ -154,9 +152,6 @@ struct irq_cfg {
unsigned move_cleanup_count;
u8 vector;
u8 move_in_progress : 1;
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- u8 move_desc_pending : 1;
-#endif
};
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -188,16 +183,18 @@ int __init arch_early_irq_init(void)
struct irq_cfg *cfg;
struct irq_desc *desc;
int count;
+ int node;
int i;
cfg = irq_cfgx;
count = ARRAY_SIZE(irq_cfgx);
+ node= cpu_to_node(boot_cpu_id);
for (i = 0; i < count; i++) {
desc = irq_to_desc(i);
desc->chip_data = &cfg[i];
- alloc_bootmem_cpumask_var(&cfg[i].domain);
- alloc_bootmem_cpumask_var(&cfg[i].old_domain);
+ zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
+ zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
if (i < NR_IRQS_LEGACY)
cpumask_setall(cfg[i].domain);
}
@@ -218,12 +215,9 @@ static struct irq_cfg *irq_cfg(unsigned
return cfg;
}
-static struct irq_cfg *get_one_free_irq_cfg(int cpu)
+static struct irq_cfg *get_one_free_irq_cfg(int node)
{
struct irq_cfg *cfg;
- int node;
-
- node = cpu_to_node(cpu);
cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
if (cfg) {
@@ -244,13 +238,13 @@ static struct irq_cfg *get_one_free_irq_
return cfg;
}
-int arch_init_chip_data(struct irq_desc *desc, int cpu)
+int arch_init_chip_data(struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
cfg = desc->chip_data;
if (!cfg) {
- desc->chip_data = get_one_free_irq_cfg(cpu);
+ desc->chip_data = get_one_free_irq_cfg(node);
if (!desc->chip_data) {
printk(KERN_ERR "can not alloc irq_cfg\n");
BUG_ON(1);
@@ -260,10 +254,9 @@ int arch_init_chip_data(struct irq_desc
return 0;
}
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-
+/* for move_irq_desc */
static void
-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
+init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
{
struct irq_pin_list *old_entry, *head, *tail, *entry;
@@ -272,7 +265,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_
if (!old_entry)
return;
- entry = get_one_free_irq_2_pin(cpu);
+ entry = get_one_free_irq_2_pin(node);
if (!entry)
return;
@@ -282,7 +275,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_
tail = entry;
old_entry = old_entry->next;
while (old_entry) {
- entry = get_one_free_irq_2_pin(cpu);
+ entry = get_one_free_irq_2_pin(node);
if (!entry) {
entry = head;
while (entry) {
@@ -322,12 +315,12 @@ static void free_irq_2_pin(struct irq_cf
}
void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int cpu)
+ struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
struct irq_cfg *old_cfg;
- cfg = get_one_free_irq_cfg(cpu);
+ cfg = get_one_free_irq_cfg(node);
if (!cfg)
return;
@@ -338,7 +331,7 @@ void arch_init_copy_chip_data(struct irq
memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
- init_copy_irq_2_pin(old_cfg, cfg, cpu);
+ init_copy_irq_2_pin(old_cfg, cfg, node);
}
static void free_irq_cfg(struct irq_cfg *old_cfg)
@@ -362,19 +355,7 @@ void arch_free_chip_data(struct irq_desc
old_desc->chip_data = NULL;
}
}
-
-static void
-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
- struct irq_cfg *cfg = desc->chip_data;
-
- if (!cfg->move_in_progress) {
- /* it means that domain is not changed */
- if (!cpumask_intersects(desc->affinity, mask))
- cfg->move_desc_pending = 1;
- }
-}
-#endif
+/* end for move_irq_desc */
#else
static struct irq_cfg *irq_cfg(unsigned int irq)
@@ -384,13 +365,6 @@ static struct irq_cfg *irq_cfg(unsigned
#endif
-#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
-static inline void
-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
-}
-#endif
-
struct io_apic {
unsigned int index;
unsigned int unused[3];
@@ -522,7 +496,8 @@ static struct IO_APIC_route_entry ioapic
static void
__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
{
- union entry_union eu;
+ union entry_union eu = {{0, 0}};
+
eu.entry = e;
io_apic_write(apic, 0x11 + 2*pin, eu.w2);
io_apic_write(apic, 0x10 + 2*pin, eu.w1);
@@ -553,132 +528,18 @@ static void ioapic_mask_entry(int apic,
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-#ifdef CONFIG_SMP
-static void send_cleanup_vector(struct irq_cfg *cfg)
-{
- cpumask_var_t cleanup_mask;
-
- if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
- unsigned int i;
- cfg->move_cleanup_count = 0;
- for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
- cfg->move_cleanup_count++;
- for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
- apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
- } else {
- cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
- cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
- apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
- free_cpumask_var(cleanup_mask);
- }
- cfg->move_in_progress = 0;
-}
-
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
-{
- int apic, pin;
- struct irq_pin_list *entry;
- u8 vector = cfg->vector;
-
- entry = cfg->irq_2_pin;
- for (;;) {
- unsigned int reg;
-
- if (!entry)
- break;
-
- apic = entry->apic;
- pin = entry->pin;
- /*
- * With interrupt-remapping, destination information comes
- * from interrupt-remapping table entry.
- */
- if (!irq_remapped(irq))
- io_apic_write(apic, 0x11 + pin*2, dest);
- reg = io_apic_read(apic, 0x10 + pin*2);
- reg &= ~IO_APIC_REDIR_VECTOR_MASK;
- reg |= vector;
- io_apic_modify(apic, 0x10 + pin*2, reg);
- if (!entry->next)
- break;
- entry = entry->next;
- }
-}
-
-static int
-assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
-
-/*
- * Either sets desc->affinity to a valid value, and returns
- * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
- * leaves desc->affinity untouched.
- */
-static unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
-{
- struct irq_cfg *cfg;
- unsigned int irq;
-
- if (!cpumask_intersects(mask, cpu_online_mask))
- return BAD_APICID;
-
- irq = desc->irq;
- cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
- return BAD_APICID;
-
- /* check that before desc->addinity get updated */
- set_extra_move_desc(desc, mask);
-
- cpumask_copy(desc->affinity, mask);
-
- return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
-}
-
-static void
-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
- struct irq_cfg *cfg;
- unsigned long flags;
- unsigned int dest;
- unsigned int irq;
-
- irq = desc->irq;
- cfg = desc->chip_data;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- dest = set_desc_affinity(desc, mask);
- if (dest != BAD_APICID) {
- /* Only the high 8 bits are valid. */
- dest = SET_APIC_LOGICAL_ID(dest);
- __target_IO_APIC_irq(irq, dest, cfg);
- }
- spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void
-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
-{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
-
- set_ioapic_affinity_irq_desc(desc, mask);
-}
-#endif /* CONFIG_SMP */
-
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
* shared ISA-space IRQs, so we have to support them. We are super
* fast in the common case, and fast for shared ISA-space IRQs.
*/
-static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
+static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
struct irq_pin_list *entry;
entry = cfg->irq_2_pin;
if (!entry) {
- entry = get_one_free_irq_2_pin(cpu);
+ entry = get_one_free_irq_2_pin(node);
if (!entry) {
printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
apic, pin);
@@ -698,7 +559,7 @@ static void add_pin_to_irq_cpu(struct ir
entry = entry->next;
}
- entry->next = get_one_free_irq_2_pin(cpu);
+ entry->next = get_one_free_irq_2_pin(node);
entry = entry->next;
entry->apic = apic;
entry->pin = pin;
@@ -707,7 +568,7 @@ static void add_pin_to_irq_cpu(struct ir
/*
* Reroute an IRQ to a different pin.
*/
-static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
+static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
int oldapic, int oldpin,
int newapic, int newpin)
{
@@ -727,7 +588,7 @@ static void __init replace_pin_at_irq_cp
/* why? call replace before add? */
if (!replaced)
- add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
+ add_pin_to_irq_node(cfg, node, newapic, newpin);
}
static inline void io_apic_modify_irq(struct irq_cfg *cfg,
@@ -847,7 +708,7 @@ static void clear_IO_APIC (void)
clear_IO_APIC_pin(apic, pin);
}
#else
-#define add_pin_to_irq_cpu(cfg, cpu, apic, pin)
+#define add_pin_to_irq_node(cfg, node, apic, pin)
#endif /* !CONFIG_XEN */
#ifdef CONFIG_X86_32
@@ -888,7 +749,7 @@ static int __init ioapic_pirq_setup(char
__setup("pirq=", ioapic_pirq_setup);
#endif /* CONFIG_X86_32 */
-#ifdef CONFIG_INTR_REMAP
+#ifndef CONFIG_XEN
struct IO_APIC_route_entry **alloc_ioapic_entries(void)
{
int apic;
@@ -986,20 +847,6 @@ int restore_IO_APIC_setup(struct IO_APIC
return 0;
}
-void reinit_intr_remapped_IO_APIC(int intr_remapping,
- struct IO_APIC_route_entry **ioapic_entries)
-
-{
- /*
- * for now plain restore of previous settings.
- * TBD: In the case of OS enabling interrupt-remapping,
- * IO-APIC RTE's need to be setup to point to interrupt-remapping
- * table entries. for now, do a plain restore, and wait for
- * the setup_IO_APIC_irqs() to do proper initialization.
- */
- restore_IO_APIC_setup(ioapic_entries);
-}
-
void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
{
int apic;
@@ -1009,7 +856,7 @@ void free_ioapic_entries(struct IO_APIC_
kfree(ioapic_entries);
}
-#endif
+#endif /* CONFIG_XEN */
/*
* Find the IRQ entry number of a certain pin.
@@ -1072,54 +919,6 @@ static int __init find_isa_irq_apic(int
}
#endif
-/*
- * Find a specific PCI IRQ entry.
- * Not an __init, possibly needed by modules
- */
-static int pin_2_irq(int idx, int apic, int pin);
-
-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
-{
- int apic, i, best_guess = -1;
-
- apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
- bus, slot, pin);
- if (test_bit(bus, mp_bus_not_pci)) {
- apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
- return -1;
- }
- for (i = 0; i < mp_irq_entries; i++) {
- int lbus = mp_irqs[i].srcbus;
-
- for (apic = 0; apic < nr_ioapics; apic++)
- if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
- mp_irqs[i].dstapic == MP_APIC_ALL)
- break;
-
- if (!test_bit(lbus, mp_bus_not_pci) &&
- !mp_irqs[i].irqtype &&
- (bus == lbus) &&
- (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
- int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
-
- if (!(apic || IO_APIC_IRQ(irq)))
- continue;
-
- if (pin == (mp_irqs[i].srcbusirq & 3))
- return irq;
- /*
- * Use the first all-but-pin matching entry as a
- * best-guess fuzzy result for broken mptables.
- */
- if (best_guess < 0)
- best_guess = irq;
- }
- }
- return best_guess;
-}
-
-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
-
#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
/*
* EISA Edge/Level control register, ELCR
@@ -1338,6 +1137,64 @@ static int pin_2_irq(int idx, int apic,
return irq;
}
+/*
+ * Find a specific PCI IRQ entry.
+ * Not an __init, possibly needed by modules
+ */
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
+ struct io_apic_irq_attr *irq_attr)
+{
+ int apic, i, best_guess = -1;
+
+ apic_printk(APIC_DEBUG,
+ "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+ bus, slot, pin);
+ if (test_bit(bus, mp_bus_not_pci)) {
+ apic_printk(APIC_VERBOSE,
+ "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+ return -1;
+ }
+ for (i = 0; i < mp_irq_entries; i++) {
+ int lbus = mp_irqs[i].srcbus;
+
+ for (apic = 0; apic < nr_ioapics; apic++)
+ if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
+ mp_irqs[i].dstapic == MP_APIC_ALL)
+ break;
+
+ if (!test_bit(lbus, mp_bus_not_pci) &&
+ !mp_irqs[i].irqtype &&
+ (bus == lbus) &&
+ (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
+ int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+
+ if (!(apic || IO_APIC_IRQ(irq)))
+ continue;
+
+ if (pin == (mp_irqs[i].srcbusirq & 3)) {
+ set_io_apic_irq_attr(irq_attr, apic,
+ mp_irqs[i].dstirq,
+ irq_trigger(i),
+ irq_polarity(i));
+ return irq;
+ }
+ /*
+ * Use the first all-but-pin matching entry as a
+ * best-guess fuzzy result for broken mptables.
+ */
+ if (best_guess < 0) {
+ set_io_apic_irq_attr(irq_attr, apic,
+ mp_irqs[i].dstirq,
+ irq_trigger(i),
+ irq_polarity(i));
+ best_guess = irq;
+ }
+ }
+ }
+ return best_guess;
+}
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+
#ifndef CONFIG_XEN
void lock_vector_lock(void)
{
@@ -1609,6 +1466,9 @@ int setup_ioapic_entry(int apic_id, int
irte.vector = vector;
irte.dest_id = IRTE_DEST(destination);
+ /* Set source-id of interrupt request */
+ set_ioapic_sid(&irte, apic_id);
+
modify_irte(irq, &irte);
ir_entry->index2 = (index >> 15) & 0x1;
@@ -1684,63 +1544,75 @@ static void setup_IO_APIC_irq(int apic_i
ioapic_write_entry(apic_id, pin, entry);
}
+static struct {
+ DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
+} mp_ioapic_routing[MAX_IO_APICS];
+
static void __init setup_IO_APIC_irqs(void)
{
- int apic_id, pin, idx, irq;
+ int apic_id = 0, pin, idx, irq;
int notcon = 0;
struct irq_desc *desc;
struct irq_cfg *cfg;
- int cpu = boot_cpu_id;
+ int node = cpu_to_node(boot_cpu_id);
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
- for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
- for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+#ifdef CONFIG_ACPI
+ if (!acpi_disabled && acpi_ioapic) {
+ apic_id = mp_find_ioapic(0);
+ if (apic_id < 0)
+ apic_id = 0;
+ }
+#endif
- idx = find_irq_entry(apic_id, pin, mp_INT);
- if (idx == -1) {
- if (!notcon) {
- notcon = 1;
- apic_printk(APIC_VERBOSE,
- KERN_DEBUG " %d-%d",
- mp_ioapics[apic_id].apicid, pin);
- } else
- apic_printk(APIC_VERBOSE, " %d-%d",
- mp_ioapics[apic_id].apicid, pin);
- continue;
- }
- if (notcon) {
+ for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+ idx = find_irq_entry(apic_id, pin, mp_INT);
+ if (idx == -1) {
+ if (!notcon) {
+ notcon = 1;
apic_printk(APIC_VERBOSE,
- " (apicid-pin) not connected\n");
- notcon = 0;
- }
+ KERN_DEBUG " %d-%d",
+ mp_ioapics[apic_id].apicid, pin);
+ } else
+ apic_printk(APIC_VERBOSE, " %d-%d",
+ mp_ioapics[apic_id].apicid, pin);
+ continue;
+ }
+ if (notcon) {
+ apic_printk(APIC_VERBOSE,
+ " (apicid-pin) not connected\n");
+ notcon = 0;
+ }
- irq = pin_2_irq(idx, apic_id, pin);
+ irq = pin_2_irq(idx, apic_id, pin);
#ifdef CONFIG_XEN
- if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
- continue;
+ if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+ continue;
#else
- /*
- * Skip the timer IRQ if there's a quirk handler
- * installed and if it returns 1:
- */
- if (apic->multi_timer_check &&
- apic->multi_timer_check(apic_id, irq))
- continue;
+ /*
+ * Skip the timer IRQ if there's a quirk handler
+ * installed and if it returns 1:
+ */
+ if (apic->multi_timer_check &&
+ apic->multi_timer_check(apic_id, irq))
+ continue;
#endif
- desc = irq_to_desc_alloc_cpu(irq, cpu);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc for %d\n", irq);
- continue;
- }
- cfg = desc->chip_data;
- add_pin_to_irq_cpu(cfg, cpu, apic_id, pin);
-
- setup_IO_APIC_irq(apic_id, pin, irq, desc,
- irq_trigger(idx), irq_polarity(idx));
+ desc = irq_to_desc_alloc_node(irq, node);
+ if (!desc) {
+ printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+ continue;
}
+ cfg = desc->chip_data;
+ add_pin_to_irq_node(cfg, node, apic_id, pin);
+ /*
+ * don't mark it in pin_programmed, so later acpi could
+ * set it correctly when irq < 16
+ */
+ setup_IO_APIC_irq(apic_id, pin, irq, desc,
+ irq_trigger(idx), irq_polarity(idx));
}
if (notcon)
@@ -1908,36 +1780,30 @@ __apicdebuginit(void) print_IO_APIC(void
return;
}
-__apicdebuginit(void) print_APIC_bitfield(int base)
+__apicdebuginit(void) print_APIC_field(int base)
{
- unsigned int v;
- int i, j;
+ int i;
if (apic_verbosity == APIC_QUIET)
return;
- printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
- for (i = 0; i < 8; i++) {
- v = apic_read(base + i*0x10);
- for (j = 0; j < 32; j++) {
- if (v & (1<<j))
- printk("1");
- else
- printk("0");
- }
- printk("\n");
- }
+ printk(KERN_DEBUG);
+
+ for (i = 0; i < 8; i++)
+ printk(KERN_CONT "%08x", apic_read(base + i*0x10));
+
+ printk(KERN_CONT "\n");
}
__apicdebuginit(void) print_local_APIC(void *dummy)
{
- unsigned int v, ver, maxlvt;
+ unsigned int i, v, ver, maxlvt;
u64 icr;
if (apic_verbosity == APIC_QUIET)
return;
- printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
smp_processor_id(), hard_smp_processor_id());
v = apic_read(APIC_ID);
printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, read_apic_id());
@@ -1978,11 +1844,11 @@ __apicdebuginit(void) print_local_APIC(v
printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
printk(KERN_DEBUG "... APIC ISR field:\n");
- print_APIC_bitfield(APIC_ISR);
+ print_APIC_field(APIC_ISR);
printk(KERN_DEBUG "... APIC TMR field:\n");
- print_APIC_bitfield(APIC_TMR);
+ print_APIC_field(APIC_TMR);
printk(KERN_DEBUG "... APIC IRR field:\n");
- print_APIC_bitfield(APIC_IRR);
+ print_APIC_field(APIC_IRR);
if (APIC_INTEGRATED(ver)) { /* !82489DX */
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
@@ -2019,6 +1885,18 @@ __apicdebuginit(void) print_local_APIC(v
printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
v = apic_read(APIC_TDCR);
printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
+
+ if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
+ v = apic_read(APIC_EFEAT);
+ maxlvt = (v >> 16) & 0xff;
+ printk(KERN_DEBUG "... APIC EFEAT: %08x\n", v);
+ v = apic_read(APIC_ECTRL);
+ printk(KERN_DEBUG "... APIC ECTRL: %08x\n", v);
+ for (i = 0; i < maxlvt; i++) {
+ v = apic_read(APIC_EILVTn(i));
+ printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v);
+ }
+ }
printk("\n");
}
@@ -2067,6 +1945,11 @@ __apicdebuginit(void) print_PIC(void)
__apicdebuginit(int) print_all_ICs(void)
{
print_PIC();
+
+ /* don't print out if apic is not there */
+ if (!cpu_has_apic || disable_apic)
+ return 0;
+
print_all_local_APICs();
print_IO_APIC();
@@ -2188,7 +2071,9 @@ void disable_IO_APIC(void)
/*
* Use virtual wire A mode when interrupt remapping is enabled.
*/
- disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1);
+ if (cpu_has_apic)
+ disconnect_bsp_APIC(!intr_remapping_enabled &&
+ ioapic_i8259.pin != -1);
}
#ifdef CONFIG_X86_32
@@ -2427,7 +2312,119 @@ static int ioapic_retrigger_irq(unsigned
* races.
*/
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP
+static void send_cleanup_vector(struct irq_cfg *cfg)
+{
+ cpumask_var_t cleanup_mask;
+
+ if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+ unsigned int i;
+ cfg->move_cleanup_count = 0;
+ for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ cfg->move_cleanup_count++;
+ for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+ } else {
+ cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+ cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+ apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+ free_cpumask_var(cleanup_mask);
+ }
+ cfg->move_in_progress = 0;
+}
+
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+{
+ int apic, pin;
+ struct irq_pin_list *entry;
+ u8 vector = cfg->vector;
+
+ entry = cfg->irq_2_pin;
+ for (;;) {
+ unsigned int reg;
+
+ if (!entry)
+ break;
+
+ apic = entry->apic;
+ pin = entry->pin;
+ /*
+ * With interrupt-remapping, destination information comes
+ * from interrupt-remapping table entry.
+ */
+ if (!irq_remapped(irq))
+ io_apic_write(apic, 0x11 + pin*2, dest);
+ reg = io_apic_read(apic, 0x10 + pin*2);
+ reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+ reg |= vector;
+ io_apic_modify(apic, 0x10 + pin*2, reg);
+ if (!entry->next)
+ break;
+ entry = entry->next;
+ }
+}
+
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
+
+/*
+ * Either sets desc->affinity to a valid value, and returns
+ * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+ * leaves desc->affinity untouched.
+ */
+static unsigned int
+set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+{
+ struct irq_cfg *cfg;
+ unsigned int irq;
+
+ if (!cpumask_intersects(mask, cpu_online_mask))
+ return BAD_APICID;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
+ if (assign_irq_vector(irq, cfg, mask))
+ return BAD_APICID;
+
+ cpumask_copy(desc->affinity, mask);
+
+ return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+}
+
+static int
+set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+{
+ struct irq_cfg *cfg;
+ unsigned long flags;
+ unsigned int dest;
+ unsigned int irq;
+ int ret = -1;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ dest = set_desc_affinity(desc, mask);
+ if (dest != BAD_APICID) {
+ /* Only the high 8 bits are valid. */
+ dest = SET_APIC_LOGICAL_ID(dest);
+ __target_IO_APIC_irq(irq, dest, cfg);
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ return ret;
+}
+
+static int
+set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
+{
+ struct irq_desc *desc;
+
+ desc = irq_to_desc(irq);
+
+ return set_ioapic_affinity_irq_desc(desc, mask);
+}
#ifdef CONFIG_INTR_REMAP
@@ -2442,26 +2439,25 @@ static int ioapic_retrigger_irq(unsigned
* Real vector that is used for interrupting cpu will be coming from
* the interrupt-remapping table entry.
*/
-static void
+static int
migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
{
struct irq_cfg *cfg;
struct irte irte;
unsigned int dest;
unsigned int irq;
+ int ret = -1;
if (!cpumask_intersects(mask, cpu_online_mask))
- return;
+ return ret;
irq = desc->irq;
if (get_irte(irq, &irte))
- return;
+ return ret;
cfg = desc->chip_data;
if (assign_irq_vector(irq, cfg, mask))
- return;
-
- set_extra_move_desc(desc, mask);
+ return ret;
dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
@@ -2477,27 +2473,30 @@ migrate_ioapic_irq_desc(struct irq_desc
send_cleanup_vector(cfg);
cpumask_copy(desc->affinity, mask);
+
+ return 0;
}
/*
* Migrates the IRQ destination in the process context.
*/
-static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
const struct cpumask *mask)
{
- migrate_ioapic_irq_desc(desc, mask);
+ return migrate_ioapic_irq_desc(desc, mask);
}
-static void set_ir_ioapic_affinity_irq(unsigned int irq,
+static int set_ir_ioapic_affinity_irq(unsigned int irq,
const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
- set_ir_ioapic_affinity_irq_desc(desc, mask);
+ return set_ir_ioapic_affinity_irq_desc(desc, mask);
}
#else
-static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
const struct cpumask *mask)
{
+ return 0;
}
#endif
@@ -2559,86 +2558,19 @@ static void irq_complete_move(struct irq
struct irq_cfg *cfg = desc->chip_data;
unsigned vector, me;
- if (likely(!cfg->move_in_progress)) {
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- if (likely(!cfg->move_desc_pending))
- return;
-
- /* domain has not changed, but affinity did */
- me = smp_processor_id();
- if (cpumask_test_cpu(me, desc->affinity)) {
- *descp = desc = move_irq_desc(desc, me);
- /* get the new one */
- cfg = desc->chip_data;
- cfg->move_desc_pending = 0;
- }
-#endif
+ if (likely(!cfg->move_in_progress))
return;
- }
vector = ~get_irq_regs()->orig_ax;
me = smp_processor_id();
- if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
- *descp = desc = move_irq_desc(desc, me);
- /* get the new one */
- cfg = desc->chip_data;
-#endif
+ if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
send_cleanup_vector(cfg);
- }
}
#else
static inline void irq_complete_move(struct irq_desc **descp) {}
#endif
-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
-{
- int apic, pin;
- struct irq_pin_list *entry;
-
- entry = cfg->irq_2_pin;
- for (;;) {
-
- if (!entry)
- break;
-
- apic = entry->apic;
- pin = entry->pin;
- io_apic_eoi(apic, pin);
- entry = entry->next;
- }
-}
-
-static void
-eoi_ioapic_irq(struct irq_desc *desc)
-{
- struct irq_cfg *cfg;
- unsigned long flags;
- unsigned int irq;
-
- irq = desc->irq;
- cfg = desc->chip_data;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- __eoi_ioapic_irq(irq, cfg);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#ifdef CONFIG_X86_X2APIC
-static void ack_x2apic_level(unsigned int irq)
-{
- struct irq_desc *desc = irq_to_desc(irq);
- ack_x2APIC_irq();
- eoi_ioapic_irq(desc);
-}
-
-static void ack_x2apic_edge(unsigned int irq)
-{
- ack_x2APIC_irq();
-}
-#endif
-
static void ack_apic_edge(unsigned int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
@@ -2702,9 +2634,6 @@ static void ack_apic_level(unsigned int
*/
ack_APIC_irq();
- if (irq_remapped(irq))
- eoi_ioapic_irq(desc);
-
/* Now we can move and renable the irq */
if (unlikely(do_unmask_irq)) {
/* Only migrate the irq if the ack has been received.
@@ -2751,22 +2680,50 @@ static void ack_apic_level(unsigned int
}
#ifdef CONFIG_INTR_REMAP
+static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+ int apic, pin;
+ struct irq_pin_list *entry;
+
+ entry = cfg->irq_2_pin;
+ for (;;) {
+
+ if (!entry)
+ break;
+
+ apic = entry->apic;
+ pin = entry->pin;
+ io_apic_eoi(apic, pin);
+ entry = entry->next;
+ }
+}
+
+static void
+eoi_ioapic_irq(struct irq_desc *desc)
+{
+ struct irq_cfg *cfg;
+ unsigned long flags;
+ unsigned int irq;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ __eoi_ioapic_irq(irq, cfg);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
static void ir_ack_apic_edge(unsigned int irq)
{
-#ifdef CONFIG_X86_X2APIC
- if (x2apic_enabled())
- return ack_x2apic_edge(irq);
-#endif
- return ack_apic_edge(irq);
+ ack_APIC_irq();
}
static void ir_ack_apic_level(unsigned int irq)
{
-#ifdef CONFIG_X86_X2APIC
- if (x2apic_enabled())
- return ack_x2apic_level(irq);
-#endif
- return ack_apic_level(irq);
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ ack_APIC_irq();
+ eoi_ioapic_irq(desc);
}
#endif /* CONFIG_INTR_REMAP */
@@ -2977,7 +2934,7 @@ static inline void __init check_timer(vo
{
struct irq_desc *desc = irq_to_desc(0);
struct irq_cfg *cfg = desc->chip_data;
- int cpu = boot_cpu_id;
+ int node = cpu_to_node(boot_cpu_id);
int apic1, pin1, apic2, pin2;
unsigned long flags;
int no_pin1 = 0;
@@ -3043,7 +3000,7 @@ static inline void __init check_timer(vo
* Ok, does IRQ0 through the IOAPIC work?
*/
if (no_pin1) {
- add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
+ add_pin_to_irq_node(cfg, node, apic1, pin1);
setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
} else {
/* for edge trigger, setup_IO_APIC_irq already
@@ -3080,7 +3037,7 @@ static inline void __init check_timer(vo
/*
* legacy devices should be connected to IO APIC #0
*/
- replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
+ replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
enable_8259A_irq(0);
if (timer_irq_works()) {
@@ -3310,14 +3267,13 @@ static int nr_irqs_gsi = NR_IRQS_LEGACY;
/*
* Dynamic irq allocate and deallocation
*/
-unsigned int create_irq_nr(unsigned int irq_want)
+unsigned int create_irq_nr(unsigned int irq_want, int node)
{
/* Allocate an unused irq */
unsigned int irq;
unsigned int new;
unsigned long flags;
struct irq_cfg *cfg_new = NULL;
- int cpu = boot_cpu_id;
struct irq_desc *desc_new = NULL;
irq = 0;
@@ -3326,7 +3282,7 @@ unsigned int create_irq_nr(unsigned int
spin_lock_irqsave(&vector_lock, flags);
for (new = irq_want; new < nr_irqs; new++) {
- desc_new = irq_to_desc_alloc_cpu(new, cpu);
+ desc_new = irq_to_desc_alloc_node(new, node);
if (!desc_new) {
printk(KERN_INFO "can not get irq_desc for %d\n", new);
continue;
@@ -3335,6 +3291,9 @@ unsigned int create_irq_nr(unsigned int
if (cfg_new->vector != 0)
continue;
+
+ desc_new = move_irq_desc(desc_new, node);
+
if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
irq = new;
break;
@@ -3352,11 +3311,12 @@ unsigned int create_irq_nr(unsigned int
int create_irq(void)
{
+ int node = cpu_to_node(boot_cpu_id);
unsigned int irq_want;
int irq;
irq_want = nr_irqs_gsi;
- irq = create_irq_nr(irq_want);
+ irq = create_irq_nr(irq_want, node);
if (irq == 0)
irq = -1;
@@ -3422,6 +3382,9 @@ static int msi_compose_msg(struct pci_de
irte.vector = cfg->vector;
irte.dest_id = IRTE_DEST(dest);
+ /* Set source-id of interrupt request */
+ set_msi_sid(&irte, pdev);
+
modify_irte(irq, &irte);
msg->address_hi = MSI_ADDR_BASE_HI;
@@ -3459,7 +3422,7 @@ static int msi_compose_msg(struct pci_de
}
#ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3468,7 +3431,7 @@ static void set_msi_irq_affinity(unsigne
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
@@ -3480,13 +3443,15 @@ static void set_msi_irq_affinity(unsigne
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
write_msi_msg_desc(desc, &msg);
+
+ return 0;
}
#ifdef CONFIG_INTR_REMAP
/*
* Migrate the MSI irq to another cpumask. This migration is
* done in the process context using interrupt-remapping hardware.
*/
-static void
+static int
ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
@@ -3495,11 +3460,11 @@ ir_set_msi_irq_affinity(unsigned int irq
struct irte irte;
if (get_irte(irq, &irte))
- return;
+ return -1;
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
irte.vector = cfg->vector;
irte.dest_id = IRTE_DEST(dest);
@@ -3516,6 +3481,8 @@ ir_set_msi_irq_affinity(unsigned int irq
*/
if (cfg->move_in_progress)
send_cleanup_vector(cfg);
+
+ return 0;
}
#endif
@@ -3611,15 +3578,17 @@ int arch_setup_msi_irqs(struct pci_dev *
unsigned int irq_want;
struct intel_iommu *iommu = NULL;
int index = 0;
+ int node;
/* x86 doesn't support multiple MSI yet */
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
+ node = dev_to_node(&dev->dev);
irq_want = nr_irqs_gsi;
sub_handle = 0;
list_for_each_entry(msidesc, &dev->msi_list, list) {
- irq = create_irq_nr(irq_want);
+ irq = create_irq_nr(irq_want, node);
if (irq == 0)
return -1;
irq_want = irq + 1;
@@ -3669,7 +3638,7 @@ void arch_teardown_msi_irq(unsigned int
#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
#ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3678,7 +3647,7 @@ static void dmar_msi_set_affinity(unsign
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
@@ -3690,11 +3659,13 @@ static void dmar_msi_set_affinity(unsign
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
dmar_msi_write(irq, &msg);
+
+ return 0;
}
#endif /* CONFIG_SMP */
-struct irq_chip dmar_msi_type = {
+static struct irq_chip dmar_msi_type = {
.name = "DMAR_MSI",
.unmask = dmar_msi_unmask,
.mask = dmar_msi_mask,
@@ -3723,7 +3694,7 @@ int arch_setup_dmar_msi(unsigned int irq
#ifdef CONFIG_HPET_TIMER
#ifdef CONFIG_SMP
-static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3732,7 +3703,7 @@ static void hpet_msi_set_affinity(unsign
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
@@ -3744,6 +3715,8 @@ static void hpet_msi_set_affinity(unsign
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
hpet_msi_write(irq, &msg);
+
+ return 0;
}
#endif /* CONFIG_SMP */
@@ -3800,7 +3773,7 @@ static void target_ht_irq(unsigned int i
write_ht_irq_msg(irq, &msg);
}
-static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
@@ -3808,11 +3781,13 @@ static void set_ht_irq_affinity(unsigned
dest = set_desc_affinity(desc, mask);
if (dest == BAD_APICID)
- return;
+ return -1;
cfg = desc->chip_data;
target_ht_irq(irq, dest, cfg->vector);
+
+ return 0;
}
#endif
@@ -3887,6 +3862,8 @@ int arch_enable_uv_irq(char *irq_name, u
unsigned long flags;
int err;
+ BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
cfg = irq_cfg(irq);
err = assign_irq_vector(irq, cfg, eligible_cpu);
@@ -3900,19 +3877,20 @@ int arch_enable_uv_irq(char *irq_name, u
mmr_value = 0;
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
- BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
-
- entry->vector = cfg->vector;
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->polarity = 0;
- entry->trigger = 0;
- entry->mask = 0;
- entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
+ entry->vector = cfg->vector;
+ entry->delivery_mode = apic->irq_delivery_mode;
+ entry->dest_mode = apic->irq_dest_mode;
+ entry->polarity = 0;
+ entry->trigger = 0;
+ entry->mask = 0;
+ entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
mmr_pnode = uv_blade_to_pnode(mmr_blade);
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+ if (cfg->move_in_progress)
+ send_cleanup_vector(cfg);
+
return irq;
}
@@ -3926,10 +3904,10 @@ void arch_disable_uv_irq(int mmr_blade,
struct uv_IO_APIC_route_entry *entry;
int mmr_pnode;
+ BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
mmr_value = 0;
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
- BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
-
entry->mask = 1;
mmr_pnode = uv_blade_to_pnode(mmr_blade);
@@ -3995,14 +3973,85 @@ int __init arch_probe_nr_irqs(void)
#endif
#endif /* CONFIG_XEN */
+static int __io_apic_set_pci_routing(struct device *dev, int irq,
+ struct io_apic_irq_attr *irq_attr)
+{
+ struct irq_desc *desc;
+ struct irq_cfg *cfg;
+ int node;
+ int ioapic, pin;
+ int trigger, polarity;
+
+ ioapic = irq_attr->ioapic;
+#ifdef CONFIG_XEN
+ if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs) {
+ apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
+ ioapic, irq);
+ return -EINVAL;
+ }
+#endif
+ if (!IO_APIC_IRQ(irq)) {
+ apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+ ioapic);
+ return -EINVAL;
+ }
+
+ if (dev)
+ node = dev_to_node(dev);
+ else
+ node = cpu_to_node(boot_cpu_id);
+
+ desc = irq_to_desc_alloc_node(irq, node);
+ if (!desc) {
+ printk(KERN_INFO "can not get irq_desc %d\n", irq);
+ return 0;
+ }
+
+ pin = irq_attr->ioapic_pin;
+ trigger = irq_attr->trigger;
+ polarity = irq_attr->polarity;
+
+ /*
+ * IRQs < 16 are already in the irq_2_pin[] map
+ */
+ if (irq >= NR_IRQS_LEGACY) {
+ cfg = desc->chip_data;
+ add_pin_to_irq_node(cfg, node, ioapic, pin);
+ }
+
+ setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+
+ return 0;
+}
+
+int io_apic_set_pci_routing(struct device *dev, int irq,
+ struct io_apic_irq_attr *irq_attr)
+{
+ int ioapic, pin;
+ /*
+ * Avoid pin reprogramming. PRTs typically include entries
+ * with redundant pin->gsi mappings (but unique PCI devices);
+ * we only program the IOAPIC on the first.
+ */
+ ioapic = irq_attr->ioapic;
+ pin = irq_attr->ioapic_pin;
+ if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
+ pr_debug("Pin %d-%d already programmed\n",
+ mp_ioapics[ioapic].apicid, pin);
+ return 0;
+ }
+ set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
+
+ return __io_apic_set_pci_routing(dev, irq, irq_attr);
+}
+
/* --------------------------------------------------------------------------
ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI
-#ifdef CONFIG_X86_32
-#ifndef CONFIG_XEN
+#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
int __init io_apic_get_unique_id(int ioapic, int apic_id)
{
union IO_APIC_reg_00 reg_00;
@@ -4076,7 +4125,7 @@ int __init io_apic_get_unique_id(int ioa
return apic_id;
}
-#endif /* !CONFIG_XEN */
+#endif
int __init io_apic_get_version(int ioapic)
{
@@ -4089,47 +4138,6 @@ int __init io_apic_get_version(int ioapi
return reg_01.bits.version;
}
-#endif
-
-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
-{
- struct irq_desc *desc;
- struct irq_cfg *cfg;
- int cpu = boot_cpu_id;
-
-#ifdef CONFIG_XEN
- if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs) {
- apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
- ioapic, irq);
- return -EINVAL;
- }
-#endif
-
- if (!IO_APIC_IRQ(irq)) {
- apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
- ioapic);
- return -EINVAL;
- }
-
- desc = irq_to_desc_alloc_cpu(irq, cpu);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc %d\n", irq);
- return 0;
- }
-
- /*
- * IRQs < 16 are already in the irq_2_pin[] map
- */
- if (irq >= NR_IRQS_LEGACY) {
- cfg = desc->chip_data;
- add_pin_to_irq_cpu(cfg, cpu, ioapic, pin);
- }
-
- setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity);
-
- return 0;
-}
-
int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
{
@@ -4161,51 +4169,44 @@ int acpi_get_override_irq(int bus_irq, i
#ifdef CONFIG_SMP
void __init setup_ioapic_dest(void)
{
- int pin, ioapic, irq, irq_entry;
+ int pin, ioapic = 0, irq, irq_entry;
struct irq_desc *desc;
- struct irq_cfg *cfg;
const struct cpumask *mask;
if (skip_ioapic_setup == 1)
return;
- for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
- for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
- irq_entry = find_irq_entry(ioapic, pin, mp_INT);
- if (irq_entry == -1)
- continue;
- irq = pin_2_irq(irq_entry, ioapic, pin);
-
- /* setup_IO_APIC_irqs could fail to get vector for some device
- * when you have too many devices, because at that time only boot
- * cpu is online.
- */
- desc = irq_to_desc(irq);
- cfg = desc->chip_data;
- if (!cfg->vector) {
- setup_IO_APIC_irq(ioapic, pin, irq, desc,
- irq_trigger(irq_entry),
- irq_polarity(irq_entry));
- continue;
+#ifdef CONFIG_ACPI
+ if (!acpi_disabled && acpi_ioapic) {
+ ioapic = mp_find_ioapic(0);
+ if (ioapic < 0)
+ ioapic = 0;
+ }
+#endif
- }
+ for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+ irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+ if (irq_entry == -1)
+ continue;
+ irq = pin_2_irq(irq_entry, ioapic, pin);
- /*
- * Honour affinities which have been set in early boot
- */
- if (desc->status &
- (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
- mask = desc->affinity;
- else
- mask = apic->target_cpus();
+ desc = irq_to_desc(irq);
- if (intr_remapping_enabled)
- set_ir_ioapic_affinity_irq_desc(desc, mask);
- else
- set_ioapic_affinity_irq_desc(desc, mask);
- }
+ /*
+ * Honour affinities which have been set in early boot
+ */
+ if (desc->status &
+ (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+ mask = desc->affinity;
+ else
+ mask = apic->target_cpus();
+ if (intr_remapping_enabled)
+ set_ir_ioapic_affinity_irq_desc(desc, mask);
+ else
+ set_ioapic_affinity_irq_desc(desc, mask);
}
+
}
#endif
@@ -4288,29 +4289,21 @@ fake_ioapic_page:
}
}
-static int __init ioapic_insert_resources(void)
+void __init ioapic_insert_resources(void)
{
int i;
struct resource *r = ioapic_resources;
if (!r) {
- if (nr_ioapics > 0) {
+ if (nr_ioapics > 0)
printk(KERN_ERR
"IO APIC resources couldn't be allocated.\n");
- return -1;
- }
- return 0;
+ return;
}
for (i = 0; i < nr_ioapics; i++) {
insert_resource(&iomem_resource, r);
r++;
}
-
- return 0;
}
-
-/* Insert the IO APIC resources after PCI initialization has occured to handle
- * IO APICS that are mapped in on a BAR in PCI space. */
-late_initcall(ioapic_insert_resources);
#endif /* !CONFIG_XEN */
--- head-2011-03-17.orig/arch/x86/kernel/apic/probe_32-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/apic/probe_32-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -20,23 +20,12 @@
#include <asm/apic.h>
#include <asm/setup.h>
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <asm/mpspec.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
#include <linux/smp.h>
-#include <linux/init.h>
#include <asm/ipi.h>
-#include <linux/smp.h>
-#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/acpi.h>
#include <asm/e820.h>
-#include <asm/setup.h>
static int xen_phys_pkg_id(int cpuid_apic, int index_msb)
{
--- head-2011-03-17.orig/arch/x86/kernel/cpu/amd.c 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/cpu/amd.c 2011-02-01 14:50:44.000000000 +0100
@@ -415,7 +415,7 @@ static void __cpuinit early_init_amd(str
(c->x86_model == 8 && c->x86_mask >= 8))
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
#endif
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI) && !defined(CONFIG_XEN)
/* check CPU config space for extended APIC ID */
if (cpu_has_apic && c->x86 >= 0xf) {
unsigned int val;
--- head-2011-03-17.orig/arch/x86/kernel/cpu/common-xen.c 2011-03-17 14:42:07.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/cpu/common-xen.c 2011-03-17 14:42:17.000000000 +0100
@@ -13,6 +13,7 @@
#include <linux/io.h>
#include <asm/stackprotector.h>
+#include <asm/perf_counter.h>
#include <asm/mmu_context.h>
#include <asm/hypervisor.h>
#include <asm/processor.h>
@@ -66,7 +67,30 @@ void __init setup_cpu_local_masks(void)
#endif
}
-static const struct cpu_dev *this_cpu __cpuinitdata;
+static void __cpuinit default_init(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+ display_cacheinfo(c);
+#else
+ /* Not much we can do here... */
+ /* Check if at least it has cpuid */
+ if (c->cpuid_level == -1) {
+ /* No cpuid. It must be an ancient CPU */
+ if (c->x86 == 4)
+ strcpy(c->x86_model_id, "486");
+ else if (c->x86 == 3)
+ strcpy(c->x86_model_id, "386");
+ }
+#endif
+}
+
+static const struct cpu_dev __cpuinitconst default_cpu = {
+ .c_init = default_init,
+ .c_vendor = "Unknown",
+ .c_x86_vendor = X86_VENDOR_UNKNOWN,
+};
+
+static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
#ifdef CONFIG_X86_64
@@ -116,7 +140,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_p
/* data */
[GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },
- [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
+ [GDT_ENTRY_ESPFIX_SS] = { { { 0x0000ffff, 0x00cf9200 } } },
#endif
[GDT_ENTRY_PERCPU] = { { { 0x0000ffff, 0x00cf9200 } } },
GDT_STACK_CANARY_INIT
@@ -312,7 +336,8 @@ static const char *__cpuinit table_looku
return NULL; /* Not found */
}
-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
void load_percpu_segment(int cpu)
{
@@ -361,29 +386,6 @@ void switch_to_new_gdt(int cpu)
static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
-static void __cpuinit default_init(struct cpuinfo_x86 *c)
-{
-#ifdef CONFIG_X86_64
- display_cacheinfo(c);
-#else
- /* Not much we can do here... */
- /* Check if at least it has cpuid */
- if (c->cpuid_level == -1) {
- /* No cpuid. It must be an ancient CPU */
- if (c->x86 == 4)
- strcpy(c->x86_model_id, "486");
- else if (c->x86 == 3)
- strcpy(c->x86_model_id, "386");
- }
-#endif
-}
-
-static const struct cpu_dev __cpuinitconst default_cpu = {
- .c_init = default_init,
- .c_vendor = "Unknown",
- .c_x86_vendor = X86_VENDOR_UNKNOWN,
-};
-
static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
{
unsigned int *v;
@@ -516,7 +518,6 @@ out:
static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
- static int printed;
int i;
for (i = 0; i < X86_VENDOR_NUM; i++) {
@@ -533,13 +534,9 @@ static void __cpuinit get_cpu_vendor(str
}
}
- if (!printed) {
- printed++;
- printk(KERN_ERR
- "CPU: vendor_id '%s' unknown, using generic init.\n", v);
-
- printk(KERN_ERR "CPU: Your system may be unstable.\n");
- }
+ printk_once(KERN_ERR
+ "CPU: vendor_id '%s' unknown, using generic init.\n" \
+ "CPU: Your system may be unstable.\n", v);
c->x86_vendor = X86_VENDOR_UNKNOWN;
this_cpu = &default_cpu;
@@ -805,6 +802,12 @@ static void __cpuinit identify_cpu(struc
if (this_cpu->c_identify)
this_cpu->c_identify(c);
+ /* Clear/Set all flags overriden by options, after probe */
+ for (i = 0; i < NCAPINTS; i++) {
+ c->x86_capability[i] &= ~cpu_caps_cleared[i];
+ c->x86_capability[i] |= cpu_caps_set[i];
+ }
+
#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
#endif
@@ -850,6 +853,16 @@ static void __cpuinit identify_cpu(struc
#endif
init_hypervisor(c);
+
+ /*
+ * Clear/Set all flags overriden by options, need do it
+ * before following smp all cpus cap AND.
+ */
+ for (i = 0; i < NCAPINTS; i++) {
+ c->x86_capability[i] &= ~cpu_caps_cleared[i];
+ c->x86_capability[i] |= cpu_caps_set[i];
+ }
+
/*
* On SMP, boot_cpu_data holds the common feature set between
* all CPUs; so make sure that we indicate which features are
@@ -862,10 +875,6 @@ static void __cpuinit identify_cpu(struc
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
}
- /* Clear all flags overriden by options */
- for (i = 0; i < NCAPINTS; i++)
- c->x86_capability[i] &= ~cleared_cpu_caps[i];
-
#ifdef CONFIG_X86_MCE
/* Init Machine Check Exception if available. */
mcheck_init(c);
@@ -898,6 +907,7 @@ void __init identify_boot_cpu(void)
#else
vgetcpu_set_mode();
#endif
+ init_hw_perf_counters();
}
void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
--- head-2011-03-17.orig/arch/x86/kernel/cpu/mcheck/Makefile 2011-01-31 17:29:16.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/cpu/mcheck/Makefile 2011-02-01 14:50:44.000000000 +0100
@@ -11,5 +11,3 @@ obj-$(CONFIG_X86_MCE_INJECT) += mce-inje
obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
obj-$(CONFIG_ACPI_APEI) += mce-apei.o
-
-disabled-obj-$(CONFIG_XEN) := therm_throt.o
--- head-2011-03-17.orig/arch/x86/kernel/cpu/mcheck/mce.c 2011-01-31 14:53:50.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/cpu/mcheck/mce.c 2011-02-01 14:50:44.000000000 +0100
@@ -137,10 +137,12 @@ void mce_setup(struct mce *m)
m->time = get_seconds();
m->cpuvendor = boot_cpu_data.x86_vendor;
m->cpuid = cpuid_eax(1);
+#ifndef CONFIG_XEN
#ifdef CONFIG_SMP
m->socketid = cpu_data(m->extcpu).phys_proc_id;
#endif
m->apicid = cpu_data(m->extcpu).initial_apicid;
+#endif
rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
}
@@ -483,7 +485,9 @@ static inline void mce_get_rip(struct mc
*/
asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs)
{
+#ifndef CONFIG_XEN
ack_APIC_irq();
+#endif
exit_idle();
irq_enter();
mce_notify_irq();
@@ -506,7 +510,7 @@ static void mce_report_event(struct pt_r
return;
}
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
/*
* Without APIC do not notify. The event will be picked
* up eventually.
@@ -2167,7 +2171,7 @@ static __init int mcheck_init_device(voi
#ifdef CONFIG_X86_XEN_MCE
if (is_initial_xendomain()) {
/* Register vIRQ handler for MCE LOG processing */
- extern void bind_virq_for_mce(void);
+ extern int bind_virq_for_mce(void);
printk(KERN_DEBUG "MCE: bind virq for DOM0 logging\n");
bind_virq_for_mce();
--- head-2011-03-17.orig/arch/x86/kernel/cpu/mcheck/mce_dom0.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/cpu/mcheck/mce_dom0.c 2011-02-01 14:50:44.000000000 +0100
@@ -7,12 +7,17 @@
#include <asm/hypercall.h>
#include <asm/mce.h>
+static xen_mc_logical_cpu_t *g_physinfo;
+static unsigned int ncpus;
+
static int convert_log(struct mc_info *mi)
{
struct mcinfo_common *mic = NULL;
struct mcinfo_global *mc_global;
struct mcinfo_bank *mc_bank;
struct mce m;
+ unsigned int i;
+ bool found = false;
x86_mcinfo_lookup(mic, mi, MC_TYPE_GLOBAL);
if (mic == NULL)
@@ -21,9 +26,21 @@ static int convert_log(struct mc_info *m
return -1;
}
+ mce_setup(&m);
mc_global = (struct mcinfo_global*)mic;
m.mcgstatus = mc_global->mc_gstatus;
- m.cpu = mc_global->mc_coreid;/*for test*/
+ m.apicid = mc_global->mc_apicid;
+
+ for (i = 0; i < ncpus; i++)
+ if (g_physinfo[i].mc_apicid == m.apicid) {
+ found = true;
+ break;
+ }
+ WARN_ON_ONCE(!found);
+ m.socketid = mc_global->mc_socketid;
+ m.cpu = m.extcpu = g_physinfo[i].mc_cpunr;
+ m.cpuvendor = (__u8)g_physinfo[i].mc_vendor;
+
x86_mcinfo_lookup(mic, mi, MC_TYPE_BANK);
do
{
@@ -36,7 +53,6 @@ static int convert_log(struct mc_info *m
m.status = mc_bank->mc_status;
m.addr = mc_bank->mc_addr;
m.tsc = mc_bank->mc_tsc;
- m.res1 = mc_bank->mc_ctrl2;
m.bank = mc_bank->mc_bank;
printk(KERN_DEBUG "[CPU%d, BANK%d, addr %llx, state %llx]\n",
m.bank, m.cpu, m.addr, m.status);
@@ -116,18 +132,55 @@ end:
return IRQ_HANDLED;
}
-void bind_virq_for_mce(void)
+int __init bind_virq_for_mce(void)
{
int ret;
+ xen_mc_t mc_op;
+
+ g_mi = kmalloc(sizeof(*g_mi), GFP_KERNEL);
+ if (!g_mi)
+ return -ENOMEM;
+
+ /* fetch physical CPU count */
+ mc_op.cmd = XEN_MC_physcpuinfo;
+ mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
+ set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, NULL);
+ ret = HYPERVISOR_mca(&mc_op);
+ if (ret) {
+ pr_err("MCE: Failed to get physical CPU count\n");
+ kfree(g_mi);
+ return ret;
+ }
+
+ /* fetch CPU physical info for later reference */
+ ncpus = mc_op.u.mc_physcpuinfo.ncpus;
+ g_physinfo = kmalloc(sizeof(*g_physinfo) * ncpus, GFP_KERNEL);
+ if (!g_physinfo) {
+ kfree(g_mi);
+ return -ENOMEM;
+ }
+ set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
+ ret = HYPERVISOR_mca(&mc_op);
+ if (ret) {
+ pr_err("MCE: Failed to get physical CPUs' info\n");
+ kfree(g_mi);
+ kfree(g_physinfo);
+ return ret;
+ }
ret = bind_virq_to_irqhandler(VIRQ_MCA, 0,
mce_dom0_interrupt, 0, "mce", NULL);
- g_mi = kmalloc(sizeof(struct mc_info), GFP_KERNEL);
- if (ret < 0)
- pr_err("MCE_DOM0_LOG: bind_virq for DOM0 failed\n");
+ if (ret < 0) {
+ pr_err("MCE: Failed to bind vIRQ for Dom0\n");
+ kfree(g_mi);
+ kfree(g_physinfo);
+ return ret;
+ }
/* Log the machine checks left over from the previous reset. */
mce_dom0_interrupt(VIRQ_MCA, NULL);
+
+ return 0;
}
--- head-2011-03-17.orig/arch/x86/kernel/e820-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/e820-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -659,7 +659,7 @@ __init int e820_search_gap(unsigned long
*/
__init void e820_setup_gap(void)
{
- unsigned long gapstart, gapsize, round;
+ unsigned long gapstart, gapsize;
int found;
gapstart = 0x10000000;
@@ -668,24 +668,18 @@ __init void e820_setup_gap(void)
#ifdef CONFIG_X86_64
if (!found) {
- printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
- "address range\n"
- KERN_ERR "PCI: Unassigned devices with 32bit resource "
- "registers may break!\n");
+ printk(KERN_ERR
+ "PCI: Warning: Cannot find a gap in the 32bit address range\n"
+ "PCI: Unassigned devices with 32bit resource registers may break!\n");
found = e820_search_gap(&gapstart, &gapsize, MAX_GAP_END, 0);
WARN_ON(!found);
}
#endif
/*
- * See how much we want to round up: start off with
- * rounding to the next 1MB area.
+ * e820_reserve_resources_late protect stolen RAM already
*/
- round = 0x100000;
- while ((gapsize >> 4) > round)
- round += round;
- /* Fun with two's complement */
- pci_mem_start = (gapstart + round) & -round;
+ pci_mem_start = gapstart;
printk(KERN_INFO
"Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
@@ -1495,6 +1489,25 @@ void __init e820_reserve_resources(void)
}
}
+/* How much should we pad RAM ending depending on where it is? */
+static unsigned long ram_alignment(resource_size_t pos)
+{
+ unsigned long mb = pos >> 20;
+
+ /* To 64kB in the first megabyte */
+ if (!mb)
+ return 64*1024;
+
+ /* To 1MB in the first 16MB */
+ if (mb < 16)
+ return 1024*1024;
+
+ /* To 32MB for anything above that */
+ return 32*1024*1024;
+}
+
+#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
+
void __init e820_reserve_resources_late(void)
{
int i;
@@ -1506,6 +1519,26 @@ void __init e820_reserve_resources_late(
insert_resource_expand_to_fit(&iomem_resource, res);
res++;
}
+
+ /*
+ * Try to bump up RAM regions to reasonable boundaries to
+ * avoid stolen RAM:
+ */
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *entry = &e820.map[i];
+ u64 start, end;
+
+ if (entry->type != E820_RAM)
+ continue;
+ start = entry->addr + entry->size;
+ end = round_up(start, ram_alignment(start)) - 1;
+ if (end > MAX_RESOURCE_SIZE)
+ end = MAX_RESOURCE_SIZE;
+ if (start >= end)
+ continue;
+ reserve_region_with_split(&iomem_resource, start, end,
+ "RAM buffer");
+ }
}
#undef e820
--- head-2011-03-17.orig/arch/x86/kernel/entry_32-xen.S 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/entry_32-xen.S 2011-02-01 14:50:44.000000000 +0100
@@ -48,7 +48,6 @@
#include <asm/segment.h>
#include <asm/smp.h>
#include <asm/page_types.h>
-#include <asm/desc.h>
#include <asm/percpu.h>
#include <asm/dwarf2.h>
#include <asm/processor-flags.h>
@@ -88,7 +87,7 @@ NMI_MASK = 0x80000000
#define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
#else
#define preempt_stop(clobbers)
-#define resume_kernel restore_nocheck
+#define resume_kernel restore_all
#endif
.macro TRACE_IRQS_IRET
@@ -376,7 +375,7 @@ END(ret_from_exception)
ENTRY(resume_kernel)
DISABLE_INTERRUPTS(CLBR_ANY)
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
- jnz restore_nocheck
+ jnz restore_all
need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
@@ -569,6 +568,8 @@ syscall_exit:
jne syscall_exit_work
restore_all:
+ TRACE_IRQS_IRET
+restore_all_notrace:
#ifndef CONFIG_XEN
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
@@ -594,8 +595,6 @@ restore_nocheck:
CFI_REMEMBER_STATE
jnz restore_all_enable_events # != 0 => enable event delivery
#endif
- TRACE_IRQS_IRET
-restore_nocheck_notrace:
RESTORE_REGS 4 # skip orig_eax/error_code
CFI_ADJUST_CFA_OFFSET -4
irq_return:
@@ -632,22 +631,34 @@ ldt_ss:
jne restore_nocheck
#endif
- /* If returning to userspace with 16bit stack,
- * try to fix the higher word of ESP, as the CPU
- * won't restore it.
- * This is an "official" bug of all the x86-compatible
- * CPUs, which we can try to work around to make
- * dosemu and wine happy. */
- movl PT_OLDESP(%esp), %eax
- movl %esp, %edx
- call patch_espfix_desc
+/*
+ * Setup and switch to ESPFIX stack
+ *
+ * We're returning to userspace with a 16 bit stack. The CPU will not
+ * restore the high word of ESP for us on executing iret... This is an
+ * "official" bug of all the x86-compatible CPUs, which we can work
+ * around to make dosemu and wine happy. We do this by preloading the
+ * high word of ESP with the high word of the userspace ESP while
+ * compensating for the offset by changing to the ESPFIX segment with
+ * a base address that matches for the difference.
+ */
+ mov %esp, %edx /* load kernel esp */
+ mov PT_OLDESP(%esp), %eax /* load userspace esp */
+ mov %dx, %ax /* eax: new kernel esp */
+ sub %eax, %edx /* offset (low word is 0) */
+ PER_CPU(gdt_page, %ebx)
+ shr $16, %edx
+ mov %dl, GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx) /* bits 16..23 */
+ mov %dh, GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx) /* bits 24..31 */
pushl $__ESPFIX_SS
CFI_ADJUST_CFA_OFFSET 4
- pushl %eax
+ push %eax /* new kernel esp */
CFI_ADJUST_CFA_OFFSET 4
+ /* Disable interrupts, but do not irqtrace this section: we
+ * will soon execute iret and the tracer was already set to
+ * the irqstate after the iret */
DISABLE_INTERRUPTS(CLBR_EAX)
- TRACE_IRQS_OFF
- lss (%esp), %esp
+ lss (%esp), %esp /* switch to espfix segment */
CFI_ADJUST_CFA_OFFSET -8
jmp restore_nocheck
#else
@@ -786,15 +797,24 @@ PTREGSCALL(vm86old)
#ifndef CONFIG_XEN
.macro FIXUP_ESPFIX_STACK
- /* since we are on a wrong stack, we cant make it a C code :( */
+/*
+ * Switch back for ESPFIX stack to the normal zerobased stack
+ *
+ * We can't call C functions using the ESPFIX stack. This code reads
+ * the high word of the segment base from the GDT and swiches to the
+ * normal stack and adjusts ESP with the matching offset.
+ */
+ /* fixup the stack */
PER_CPU(gdt_page, %ebx)
- GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- addl %esp, %eax
+ mov GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx), %al /* bits 16..23 */
+ mov GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx), %ah /* bits 24..31 */
+ shl $16, %eax
+ addl %esp, %eax /* the adjusted stack pointer */
pushl $__KERNEL_DS
CFI_ADJUST_CFA_OFFSET 4
pushl %eax
CFI_ADJUST_CFA_OFFSET 4
- lss (%esp), %esp
+ lss (%esp), %esp /* switch to the normal stack segment */
CFI_ADJUST_CFA_OFFSET -8
.endm
.macro UNWIND_ESPFIX_STACK
@@ -1284,6 +1304,7 @@ ENTRY(ftrace_graph_caller)
pushl %edx
movl 0xc(%esp), %edx
lea 0x4(%ebp), %eax
+ movl (%ebp), %ecx
subl $MCOUNT_INSN_SIZE, %edx
call prepare_ftrace_return
popl %edx
@@ -1298,6 +1319,7 @@ return_to_handler:
pushl %eax
pushl %ecx
pushl %edx
+ movl %ebp, %eax
call ftrace_return_to_handler
movl %eax, 0xc(%esp)
popl %edx
@@ -1593,7 +1615,7 @@ nmi_stack_correct:
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
- jmp restore_nocheck_notrace
+ jmp restore_all_notrace
CFI_ENDPROC
nmi_stack_fixup:
--- head-2011-03-17.orig/arch/x86/kernel/entry_64.S 2011-02-16 16:02:30.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/entry_64.S 2011-02-16 16:02:54.000000000 +0100
@@ -1363,7 +1363,7 @@ apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
paranoidzeroentry_ist debug do_debug DEBUG_STACK
paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
paranoiderrorentry stack_segment do_stack_segment
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
zeroentry xen_debug do_debug
zeroentry xen_int3 do_int3
errorentry xen_stack_segment do_stack_segment
--- head-2011-03-17.orig/arch/x86/kernel/entry_64-xen.S 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/entry_64-xen.S 2011-02-01 14:50:44.000000000 +0100
@@ -139,6 +139,7 @@ ENTRY(ftrace_graph_caller)
leaq 8(%rbp), %rdi
movq 0x38(%rsp), %rsi
+ movq (%rbp), %rdx
subq $MCOUNT_INSN_SIZE, %rsi
call prepare_ftrace_return
@@ -151,27 +152,15 @@ END(ftrace_graph_caller)
GLOBAL(return_to_handler)
subq $80, %rsp
+ /* Save the return values */
movq %rax, (%rsp)
- movq %rcx, 8(%rsp)
- movq %rdx, 16(%rsp)
- movq %rsi, 24(%rsp)
- movq %rdi, 32(%rsp)
- movq %r8, 40(%rsp)
- movq %r9, 48(%rsp)
- movq %r10, 56(%rsp)
- movq %r11, 64(%rsp)
+ movq %rdx, 8(%rsp)
+ movq %rbp, %rdi
call ftrace_return_to_handler
movq %rax, 72(%rsp)
- movq 64(%rsp), %r11
- movq 56(%rsp), %r10
- movq 48(%rsp), %r9
- movq 40(%rsp), %r8
- movq 32(%rsp), %rdi
- movq 24(%rsp), %rsi
- movq 16(%rsp), %rdx
- movq 8(%rsp), %rcx
+ movq 8(%rsp), %rdx
movq (%rsp), %rax
addq $72, %rsp
retq
@@ -869,6 +858,8 @@ END(\sym)
#ifdef CONFIG_SMP
apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
+apicinterrupt REBOOT_VECTOR \
+ reboot_interrupt smp_reboot_interrupt
#endif
#ifdef CONFIG_X86_UV
@@ -900,10 +891,15 @@ apicinterrupt INVALIDATE_TLB_VECTOR_STAR
#endif
apicinterrupt THRESHOLD_APIC_VECTOR \
- threshold_interrupt mce_threshold_interrupt
+ threshold_interrupt smp_threshold_interrupt
apicinterrupt THERMAL_APIC_VECTOR \
thermal_interrupt smp_thermal_interrupt
+#ifdef CONFIG_X86_MCE
+apicinterrupt MCE_SELF_VECTOR \
+ mce_self_interrupt smp_mce_self_interrupt
+#endif
+
#ifdef CONFIG_SMP
apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
call_function_single_interrupt smp_call_function_single_interrupt
@@ -917,6 +913,11 @@ apicinterrupt ERROR_APIC_VECTOR \
error_interrupt smp_error_interrupt
apicinterrupt SPURIOUS_APIC_VECTOR \
spurious_interrupt smp_spurious_interrupt
+
+#ifdef CONFIG_PERF_COUNTERS
+apicinterrupt LOCAL_PENDING_VECTOR \
+ perf_pending_interrupt smp_perf_pending_interrupt
+#endif
#endif /* !CONFIG_XEN */
/*
@@ -1219,7 +1220,7 @@ paranoiderrorentry stack_segment do_stac
errorentry general_protection do_general_protection
errorentry page_fault do_page_fault
#ifdef CONFIG_X86_MCE
-paranoidzeroentry machine_check do_machine_check
+paranoidzeroentry machine_check *machine_check_vector(%rip)
#endif
#ifndef CONFIG_XEN
--- head-2011-03-17.orig/arch/x86/kernel/head_32-xen.S 2011-03-03 16:23:08.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/head_32-xen.S 2011-03-03 16:23:25.000000000 +0100
@@ -118,12 +118,6 @@ ENTRY(hypercall_page)
CFI_ENDPROC
/*
- * Real beginning of normal "text" segment
- */
-ENTRY(stext)
-ENTRY(_stext)
-
-/*
* BSS section
*/
.section ".bss.page_aligned","wa"
--- head-2011-03-17.orig/arch/x86/kernel/head_64-xen.S 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/head_64-xen.S 2011-02-01 14:50:44.000000000 +0100
@@ -15,7 +15,6 @@
#include <linux/threads.h>
#include <linux/init.h>
#include <linux/elfnote.h>
-#include <asm/desc.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/msr.h>
--- head-2011-03-17.orig/arch/x86/kernel/init_task.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/init_task.c 2011-02-01 14:50:44.000000000 +0100
@@ -31,6 +31,7 @@ union thread_union init_thread_union __i
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
+#ifndef CONFIG_X86_NO_TSS
/*
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
* no more per-task TSS's. The TSS size is kept cacheline-aligned
@@ -39,4 +40,4 @@ EXPORT_SYMBOL(init_task);
* on exact cacheline boundaries, to eliminate cacheline ping-pong.
*/
DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
-
+#endif
--- head-2011-03-17.orig/arch/x86/kernel/irq-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/irq-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -12,6 +12,8 @@
#include <asm/io_apic.h>
#include <asm/irq.h>
#include <asm/idle.h>
+#include <asm/mce.h>
+#include <asm/hw_irq.h>
atomic_t irq_err_count;
@@ -26,9 +28,10 @@ void (*generic_interrupt_extension)(void
*/
void ack_bad_irq(unsigned int irq)
{
- printk(KERN_ERR "unexpected IRQ trap at irq %02x\n", irq);
+ if (printk_ratelimit())
+ pr_err("unexpected IRQ trap at vector %02x\n", irq);
-#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+#ifndef CONFIG_XEN
/*
* Currently unexpected vectors happen only on SMP and APIC.
* We _must_ ack these because every local APIC has only N
@@ -38,8 +41,7 @@ void ack_bad_irq(unsigned int irq)
* completely.
* But only ack when the APIC is enabled -AK
*/
- if (cpu_has_apic)
- ack_APIC_irq();
+ ack_APIC_irq();
#endif
}
@@ -65,6 +67,14 @@ static int show_other_interrupts(struct
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
seq_printf(p, " Spurious interrupts\n");
+ seq_printf(p, "%*s: ", prec, "CNT");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
+ seq_printf(p, " Performance counter interrupts\n");
+ seq_printf(p, "%*s: ", prec, "PND");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
+ seq_printf(p, " Performance pending work\n");
#endif
#ifndef CONFIG_XEN
if (generic_interrupt_extension) {
@@ -95,17 +105,27 @@ static int show_other_interrupts(struct
seq_printf(p, " Spinlock wakeups\n");
#endif
#endif
-#ifdef CONFIG_X86_MCE
+#ifdef CONFIG_X86_THERMAL_VECTOR
seq_printf(p, "%*s: ", prec, "TRM");
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
seq_printf(p, " Thermal event interrupts\n");
-# ifdef CONFIG_X86_64
+#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
seq_printf(p, "%*s: ", prec, "THR");
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
seq_printf(p, " Threshold APIC interrupts\n");
-# endif
+#endif
+#ifdef CONFIG_X86_NEW_MCE
+ seq_printf(p, "%*s: ", prec, "MCE");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", per_cpu(mce_exception_count, j));
+ seq_printf(p, " Machine check exceptions\n");
+ seq_printf(p, "%*s: ", prec, "MCP");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
+ seq_printf(p, " Machine check polls\n");
#endif
seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
#if defined(CONFIG_X86_IO_APIC)
@@ -177,6 +197,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
#ifdef CONFIG_X86_LOCAL_APIC
sum += irq_stats(cpu)->apic_timer_irqs;
sum += irq_stats(cpu)->irq_spurious_count;
+ sum += irq_stats(cpu)->apic_perf_irqs;
+ sum += irq_stats(cpu)->apic_pending_irqs;
#endif
#ifndef CONFIG_XEN
if (generic_interrupt_extension)
@@ -191,11 +213,15 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += irq_stats(cpu)->irq_lock_count;
#endif
#endif
-#ifdef CONFIG_X86_MCE
+#ifdef CONFIG_X86_THERMAL_VECTOR
sum += irq_stats(cpu)->irq_thermal_count;
-# ifdef CONFIG_X86_64
+#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
sum += irq_stats(cpu)->irq_threshold_count;
#endif
+#ifdef CONFIG_X86_NEW_MCE
+ sum += per_cpu(mce_exception_count, cpu);
+ sum += per_cpu(mce_poll_count, cpu);
#endif
return sum;
}
@@ -231,14 +257,11 @@ unsigned int __irq_entry do_IRQ(struct p
irq = __get_cpu_var(vector_irq)[vector];
if (!handle_irq(irq, regs)) {
-#ifdef CONFIG_X86_64
- if (!disable_apic)
- ack_APIC_irq();
-#endif
+ ack_APIC_irq();
if (printk_ratelimit())
- printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
- __func__, smp_processor_id(), vector, irq);
+ pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
+ __func__, smp_processor_id(), vector, irq);
}
irq_exit();
--- head-2011-03-17.orig/arch/x86/kernel/microcode_core-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/microcode_core-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -22,27 +22,21 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/platform_device.h>
-#include <linux/capability.h>
#include <linux/miscdevice.h>
-#include <linux/firmware.h>
+#include <linux/capability.h>
#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/cpumask.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/fs.h>
#include <linux/mm.h>
+#include <linux/firmware.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
#include <asm/microcode.h>
#include <asm/processor.h>
-#include <asm/msr.h>
MODULE_DESCRIPTION("Microcode Update Driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
@@ -53,7 +47,18 @@ module_param(verbose, int, 0644);
#define MICROCODE_VERSION "2.00-xen"
-/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+/*
+ * Synchronization.
+ *
+ * All non cpu-hotplug-callback call sites use:
+ *
+ * - microcode_mutex to synchronize with each other;
+ * - get/put_online_cpus() to synchronize with
+ * the cpu-hotplug-callback call sites.
+ *
+ * We guarantee that only a single cpu is being
+ * updated at any particular moment of time.
+ */
static DEFINE_MUTEX(microcode_mutex);
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
@@ -90,18 +95,16 @@ static int microcode_open(struct inode *
static ssize_t microcode_write(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
- ssize_t ret;
+ ssize_t ret = -EINVAL;
if ((len >> PAGE_SHIFT) > num_physpages) {
- printk(KERN_ERR "microcode: too much data (max %ld pages)\n",
- num_physpages);
- return -EINVAL;
+ pr_err("microcode: too much data (max %ld pages)\n", num_physpages);
+ return ret;
}
mutex_lock(&microcode_mutex);
- ret = do_microcode_update(buf, len);
- if (!ret)
+ if (do_microcode_update(buf, len) == 0)
ret = (ssize_t)len;
mutex_unlock(&microcode_mutex);
@@ -110,15 +113,16 @@ static ssize_t microcode_write(struct fi
}
static const struct file_operations microcode_fops = {
- .owner = THIS_MODULE,
- .write = microcode_write,
- .open = microcode_open,
+ .owner = THIS_MODULE,
+ .write = microcode_write,
+ .open = microcode_open,
};
static struct miscdevice microcode_dev = {
- .minor = MICROCODE_MINOR,
- .name = "microcode",
- .fops = &microcode_fops,
+ .minor = MICROCODE_MINOR,
+ .name = "microcode",
+ .devnode = "cpu/microcode",
+ .fops = &microcode_fops,
};
static int __init microcode_dev_init(void)
@@ -127,9 +131,7 @@ static int __init microcode_dev_init(voi
error = misc_register(&microcode_dev);
if (error) {
- printk(KERN_ERR
- "microcode: can't misc_register on minor=%d\n",
- MICROCODE_MINOR);
+ pr_err("microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR);
return error;
}
@@ -188,38 +190,35 @@ static int __init microcode_init(void)
else if (c->x86_vendor == X86_VENDOR_AMD)
fw_name = "amd-ucode/microcode_amd.bin";
else {
- printk(KERN_ERR "microcode: no support for this CPU vendor\n");
+ pr_err("microcode: no support for this CPU vendor\n");
return -ENODEV;
}
- error = microcode_dev_init();
- if (error)
- return error;
microcode_pdev = platform_device_register_simple("microcode", -1,
NULL, 0);
if (IS_ERR(microcode_pdev)) {
- microcode_dev_exit();
return PTR_ERR(microcode_pdev);
}
+ error = microcode_dev_init();
+ if (error)
+ return error;
+
request_microcode(fw_name);
- printk(KERN_INFO
- "Microcode Update Driver: v" MICROCODE_VERSION
+ pr_info("Microcode Update Driver: v" MICROCODE_VERSION
" <tigran@aivazian.fsnet.co.uk>,"
" Peter Oruba\n");
return 0;
}
+module_init(microcode_init);
static void __exit microcode_exit(void)
{
microcode_dev_exit();
platform_device_unregister(microcode_pdev);
- printk(KERN_INFO
- "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
+ pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
}
-
-module_init(microcode_init);
module_exit(microcode_exit);
--- head-2011-03-17.orig/arch/x86/kernel/mpparse-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/mpparse-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -17,6 +17,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/smp.h>
+#include <linux/pci.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
@@ -904,24 +905,17 @@ static
inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
#endif /* CONFIG_X86_IO_APIC */
-static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
- int count)
+static int
+check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
{
- if (!mpc_new_phys) {
- pr_info("No spare slots, try to append...take your risk, "
- "new mpc_length %x\n", count);
- } else {
- if (count <= mpc_new_length)
- pr_info("No spare slots, try to append..., "
- "new mpc_length %x\n", count);
- else {
- pr_err("mpc_new_length %lx is too small\n",
- mpc_new_length);
- return -1;
- }
+ int ret = 0;
+
+ if (!mpc_new_phys || count <= mpc_new_length) {
+ WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
+ return -1;
}
- return 0;
+ return ret;
}
static int __init replace_intsrc_all(struct mpc_table *mpc,
@@ -980,7 +974,7 @@ static int __init replace_intsrc_all(st
} else {
struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
count += sizeof(struct mpc_intsrc);
- if (!check_slot(mpc_new_phys, mpc_new_length, count))
+ if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
goto out;
assign_to_mpc_intsrc(&mp_irqs[i], m);
mpc->length = count;
@@ -997,11 +991,14 @@ out:
return 0;
}
-static int __initdata enable_update_mptable;
+int enable_update_mptable;
static int __init update_mptable_setup(char *str)
{
enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+ pci_routeirq = 1;
+#endif
return 0;
}
early_param("update_mptable", update_mptable_setup);
@@ -1014,6 +1011,9 @@ static int __initdata alloc_mptable;
static int __init parse_alloc_mptable_opt(char *p)
{
enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+ pci_routeirq = 1;
+#endif
alloc_mptable = 1;
if (!p)
return 0;
--- head-2011-03-17.orig/arch/x86/kernel/pci-dma-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/pci-dma-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -32,6 +32,8 @@ int no_iommu __read_mostly;
/* Set this to 1 if there is a HW IOMMU in the system */
int iommu_detected __read_mostly = 0;
+int iommu_pass_through;
+
dma_addr_t bad_dma_address __read_mostly = 0;
EXPORT_SYMBOL(bad_dma_address);
@@ -264,6 +266,10 @@ static __init int iommu_setup(char *p)
if (!strncmp(p, "soft", 4))
swiotlb = 1;
#endif
+ if (!strncmp(p, "pt", 2)) {
+ iommu_pass_through = 1;
+ return 1;
+ }
gart_parse_options(p);
@@ -371,6 +377,8 @@ static int __init pci_iommu_init(void)
void pci_iommu_shutdown(void)
{
gart_iommu_shutdown();
+
+ amd_iommu_shutdown();
}
/* Must execute after PCI subsystem */
fs_initcall(pci_iommu_init);
--- head-2011-03-17.orig/arch/x86/kernel/process-xen.c 2011-03-03 16:06:40.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/process-xen.c 2011-03-03 16:07:25.000000000 +0100
@@ -8,12 +8,15 @@
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/clockchips.h>
+#include <linux/random.h>
#include <trace/power.h>
#include <asm/system.h>
#include <asm/apic.h>
+#include <asm/syscalls.h>
#include <asm/idle.h>
#include <asm/uaccess.h>
#include <asm/i387.h>
+#include <asm/ds.h>
#include <xen/evtchn.h>
unsigned long idle_halt;
@@ -46,6 +49,8 @@ void free_thread_xstate(struct task_stru
kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
tsk->thread.xstate = NULL;
}
+
+ WARN(tsk->thread.ds_ctx, "leaking DS context\n");
}
void free_thread_info(struct thread_info *ti)
@@ -59,7 +64,7 @@ void arch_task_cache_init(void)
task_xstate_cachep =
kmem_cache_create("task_xstate", xstate_size,
__alignof__(union thread_xstate),
- SLAB_PANIC, NULL);
+ SLAB_PANIC | SLAB_NOTRACK, NULL);
}
/*
@@ -85,8 +90,6 @@ void exit_thread(void)
t->io_bitmap_max = 0;
kfree(bp);
}
-
- ds_exit_thread(current);
}
void flush_thread(void)
@@ -471,16 +474,12 @@ static void c1e_idle(void)
if (!cpumask_test_cpu(cpu, c1e_mask)) {
cpumask_set_cpu(cpu, c1e_mask);
/*
- * Force broadcast so ACPI can not interfere. Needs
- * to run with interrupts enabled as it uses
- * smp_function_call.
+ * Force broadcast so ACPI can not interfere.
*/
- local_irq_enable();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
&cpu);
printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
cpu);
- local_irq_disable();
}
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
@@ -575,3 +574,16 @@ static int __init idle_setup(char *str)
}
early_param("idle", idle_setup);
+unsigned long arch_align_stack(unsigned long sp)
+{
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+ unsigned long range_end = mm->brk + 0x02000000;
+ return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+}
+
--- head-2011-03-17.orig/arch/x86/kernel/process_32-xen.c 2011-02-02 08:37:24.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/process_32-xen.c 2011-02-02 08:37:43.000000000 +0100
@@ -9,8 +9,6 @@
* This file handles the architecture-dependent parts of process handling..
*/
-#include <stdarg.h>
-
#include <linux/stackprotector.h>
#include <linux/cpu.h>
#include <linux/errno.h>
@@ -33,7 +31,6 @@
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
-#include <linux/random.h>
#include <linux/personality.h>
#include <linux/tick.h>
#include <linux/percpu.h>
@@ -297,7 +294,8 @@ int copy_thread(unsigned long clone_flag
p->thread.io_bitmap_max = 0;
}
- ds_copy_thread(p, current);
+ clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+ p->thread.ds_ctx = NULL;
clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
p->thread.debugctlmsr = 0;
@@ -468,7 +466,7 @@ __switch_to(struct task_struct *prev_p,
* done before math_state_restore, so the TS bit is up
* to date.
*/
- arch_leave_lazy_cpu_mode();
+ arch_end_context_switch(next_p);
/* If the task has used fpu the last 5 timeslices, just do a full
* restore of the math state immediately to avoid the trap; the
@@ -558,15 +556,3 @@ unsigned long get_wchan(struct task_stru
return 0;
}
-unsigned long arch_align_stack(unsigned long sp)
-{
- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= get_random_int() % 8192;
- return sp & ~0xf;
-}
-
-unsigned long arch_randomize_brk(struct mm_struct *mm)
-{
- unsigned long range_end = mm->brk + 0x02000000;
- return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
-}
--- head-2011-03-17.orig/arch/x86/kernel/process_64-xen.c 2011-02-02 08:37:17.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/process_64-xen.c 2011-02-02 08:37:47.000000000 +0100
@@ -17,8 +17,6 @@
* This file handles the architecture-dependent parts of process handling..
*/
-#include <stdarg.h>
-
#include <linux/stackprotector.h>
#include <linux/cpu.h>
#include <linux/errno.h>
@@ -35,7 +33,6 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/ptrace.h>
-#include <linux/random.h>
#include <linux/notifier.h>
#include <linux/kprobes.h>
#include <linux/kdebug.h>
@@ -344,7 +341,8 @@ int copy_thread(unsigned long clone_flag
}
p->thread.iopl = current->thread.iopl;
- ds_copy_thread(p, me);
+ clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+ p->thread.ds_ctx = NULL;
clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
p->thread.debugctlmsr = 0;
@@ -506,7 +504,7 @@ __switch_to(struct task_struct *prev_p,
* done before math_state_restore, so the TS bit is up
* to date.
*/
- arch_leave_lazy_cpu_mode();
+ arch_end_context_switch(next_p);
/*
* Switch FS and GS.
@@ -723,15 +721,3 @@ long sys_arch_prctl(int code, unsigned l
return do_arch_prctl(current, code, addr);
}
-unsigned long arch_align_stack(unsigned long sp)
-{
- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= get_random_int() % 8192;
- return sp & ~0xf;
-}
-
-unsigned long arch_randomize_brk(struct mm_struct *mm)
-{
- unsigned long range_end = mm->brk + 0x02000000;
- return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
-}
--- head-2011-03-17.orig/arch/x86/kernel/setup-xen.c 2011-03-03 16:22:49.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/setup-xen.c 2011-03-03 16:23:32.000000000 +0100
@@ -142,6 +142,14 @@ EXPORT_SYMBOL(xen_start_info);
#define ARCH_SETUP
#endif
+/*
+ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+ * apertures, ACPI and other tables without having to play with fixmaps.
+ */
+unsigned long max_low_pfn_mapped;
+unsigned long max_pfn_mapped;
+
RESERVE_BRK(dmi_alloc, 65536);
unsigned int boot_cpu_id __read_mostly;
@@ -247,8 +255,8 @@ unsigned long mmu_cr4_features;
unsigned long mmu_cr4_features = X86_CR4_PAE;
#endif
-/* Boot loader ID as an integer, for the benefit of proc_dointvec */
-int bootloader_type;
+/* Boot loader ID and version as integers, for the benefit of proc_dointvec */
+int bootloader_type, bootloader_version;
/*
* Setup options
@@ -316,6 +324,20 @@ void * __init extend_brk(size_t size, si
return ret;
}
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+static void __init init_gbpages(void)
+{
+ if (direct_gbpages && cpu_has_gbpages)
+ printk(KERN_INFO "Using GB pages for direct mapping\n");
+ else
+ direct_gbpages = 0;
+}
+#else
+static inline void init_gbpages(void)
+{
+}
+#endif
+
static void __init reserve_brk(void)
{
if (_brk_end > _brk_start)
@@ -328,15 +350,13 @@ static void __init reserve_brk(void)
#ifdef CONFIG_BLK_DEV_INITRD
-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
-
#define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)
static void __init relocate_initrd(void)
{
-
+#ifndef CONFIG_XEN
u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size;
- u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+ u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
u64 ramdisk_here;
unsigned long slop, clen, mapaddr;
char *p, *q;
@@ -391,8 +411,14 @@ static void __init relocate_initrd(void)
" %08llx - %08llx\n",
ramdisk_image, ramdisk_image + ramdisk_size - 1,
ramdisk_here, ramdisk_here + ramdisk_size - 1);
-}
+#else
+ printk(KERN_ERR "initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ __pa(xen_start_info->mod_start) + xen_start_info->mod_len,
+ max_low_pfn_mapped << PAGE_SHIFT);
+ initrd_start = 0;
#endif
+}
static void __init reserve_initrd(void)
{
@@ -400,7 +426,7 @@ static void __init reserve_initrd(void)
u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 ramdisk_end = ramdisk_image + ramdisk_size;
- u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+ u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
if (!boot_params.hdr.type_of_loader ||
!ramdisk_image || !ramdisk_size)
@@ -409,7 +435,7 @@ static void __init reserve_initrd(void)
unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
unsigned long ramdisk_size = xen_start_info->mod_len;
unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
- unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+ unsigned long end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
if (!xen_start_info->mod_start || !ramdisk_size)
return; /* No initrd provided by bootloader */
@@ -442,14 +468,8 @@ static void __init reserve_initrd(void)
return;
}
-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
relocate_initrd();
-#else
- printk(KERN_ERR "initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- ramdisk_end, end_of_lowmem);
- initrd_start = 0;
-#endif
+
free_early(ramdisk_image, ramdisk_end);
}
#else
@@ -721,6 +741,19 @@ static struct dmi_system_id __initdata b
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
},
},
+ {
+ /*
+ * AMI BIOS with low memory corruption was found on Intel DG45ID board.
+ * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+ * match only DMI_BOARD_NAME and see if there is more bad products
+ * with this vendor.
+ */
+ .callback = dmi_low_memory_corruption,
+ .ident = "AMI BIOS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
+ },
+ },
#endif
{}
};
@@ -788,6 +821,12 @@ void __init setup_arch(char **cmdline_p)
#endif
saved_video_mode = boot_params.hdr.vid_mode;
bootloader_type = boot_params.hdr.type_of_loader;
+ if ((bootloader_type >> 4) == 0xe) {
+ bootloader_type &= 0xf;
+ bootloader_type |= (boot_params.hdr.ext_loader_type+0x10) << 4;
+ }
+ bootloader_version = bootloader_type & 0xf;
+ bootloader_version |= boot_params.hdr.ext_loader_ver << 4;
#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
@@ -970,14 +1009,22 @@ void __init setup_arch(char **cmdline_p)
max_low_pfn = max_pfn;
high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+#ifndef CONFIG_XEN
+ max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
+#endif
#endif
#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
setup_bios_corruption_check();
#endif
+ printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
+ max_pfn_mapped<<PAGE_SHIFT);
+
reserve_brk();
+ init_gbpages();
+
/* max_pfn_mapped is updated here */
max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
max_pfn_mapped = max_low_pfn_mapped;
@@ -1219,24 +1266,6 @@ void __init setup_arch(char **cmdline_p)
#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
/**
- * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
- *
- * Description:
- * Perform any necessary interrupt initialisation prior to setting up
- * the "ordinary" interrupt call gates. For legacy reasons, the ISA
- * interrupts should be initialised here if the machine emulates a PC
- * in any way.
- **/
-void __init x86_quirk_pre_intr_init(void)
-{
- if (x86_quirks->arch_pre_intr_init) {
- if (x86_quirks->arch_pre_intr_init())
- return;
- }
- init_ISA_irqs();
-}
-
-/**
* x86_quirk_intr_init - post gate setup interrupt initialisation
*
* Description:
--- head-2011-03-17.orig/arch/x86/kernel/smp-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/smp-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -135,11 +135,36 @@ void xen_send_call_func_ipi(const struct
* this function calls the 'stop' function on all other CPUs in the system.
*/
+irqreturn_t smp_reboot_interrupt(int irq, void *dev_id)
+{
+ stop_this_cpu(NULL);
+
+ return IRQ_HANDLED;
+}
+
void xen_smp_send_stop(void)
{
unsigned long flags;
+ unsigned long wait;
+
+ /*
+ * Use an own vector here because smp_call_function
+ * does lots of things not suitable in a panic situation.
+ * On most systems we could also use an NMI here,
+ * but there are a few systems around where NMI
+ * is problematic so stay with an non NMI for now
+ * (this implies we cannot stop CPUs spinning with irq off
+ * currently)
+ */
+ if (num_online_cpus() > 1) {
+ xen_send_IPI_allbutself(REBOOT_VECTOR);
+
+ /* Don't wait longer than a second */
+ wait = USEC_PER_SEC;
+ while (num_online_cpus() > 1 && wait--)
+ udelay(1);
+ }
- smp_call_function(stop_this_cpu, NULL, 0);
local_irq_save(flags);
disable_all_local_evtchn();
local_irq_restore(flags);
--- head-2011-03-17.orig/arch/x86/kernel/traps-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/traps-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -45,6 +45,7 @@
#include <linux/edac.h>
#endif
+#include <asm/kmemcheck.h>
#include <asm/stacktrace.h>
#include <asm/processor.h>
#include <asm/debugreg.h>
@@ -53,6 +54,7 @@
#include <asm/traps.h>
#include <asm/desc.h>
#include <asm/i387.h>
+#include <asm/mce.h>
#include <asm/mach_traps.h>
@@ -64,8 +66,6 @@
#include <asm/setup.h>
#include <asm/traps.h>
-#include "cpu/mcheck/mce.h"
-
asmlinkage int system_call(void);
/* Do we ignore FPU interrupts ? */
@@ -347,6 +347,9 @@ io_check_error(unsigned char reason, str
printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
show_registers(regs);
+ if (panic_on_io_nmi)
+ panic("NMI IOCK error: Not continuing");
+
/* Re-enable the IOCK line, wait for a few seconds */
clear_io_check_error(reason);
}
@@ -527,6 +530,10 @@ dotraplinkage void __kprobes do_debug(st
get_debugreg(condition, 6);
+ /* Catch kmemcheck conditions first of all! */
+ if (condition & DR_STEP && kmemcheck_trap(regs))
+ return;
+
/*
* The processor cleared BTF, so don't mark that we need it set.
*/
@@ -792,15 +799,15 @@ unsigned long patch_espfix_desc(unsigned
return new_kesp;
}
-#else
+#endif
+
asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
{
}
-asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
{
}
-#endif
#endif /* CONFIG_XEN */
/*
@@ -834,9 +841,6 @@ asmlinkage void math_state_restore(void)
}
/* NB. 'clts' is done for us by Xen during virtual trap. */
-#ifdef CONFIG_X86_32
- restore_fpu(tsk);
-#else
/*
* Paranoid restore. send a SIGSEGV if we fail to restore the state.
*/
@@ -845,7 +849,7 @@ asmlinkage void math_state_restore(void)
force_sig(SIGSEGV, tsk);
return;
}
-#endif
+
thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
tsk->fpu_counter++;
}
--- head-2011-03-17.orig/arch/x86/kernel/vsyscall_64-xen.c 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/arch/x86/kernel/vsyscall_64-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -132,15 +132,7 @@ static __always_inline void do_vgettimeo
return;
}
- /*
- * Surround the RDTSC by barriers, to make sure it's not
- * speculated to outside the seqlock critical section and
- * does not cause time warps:
- */
- rdtsc_barrier();
now = vread();
- rdtsc_barrier();
-
base = __vsyscall_gtod_data.clock.cycle_last;
mask = __vsyscall_gtod_data.clock.mask;
mult = __vsyscall_gtod_data.clock.mult;
--- head-2011-03-17.orig/arch/x86/mm/dump_pagetables-xen.c 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/dump_pagetables-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -173,13 +173,14 @@ static void note_page(struct seq_file *m
st->current_address >= st->marker[1].start_address) {
const char *unit = units;
unsigned long delta;
+ int width = sizeof(unsigned long) * 2;
/*
* Now print the actual finished series
*/
- seq_printf(m, "0x%p-0x%p ",
- (void *)st->start_address,
- (void *)st->current_address);
+ seq_printf(m, "0x%0*lx-0x%0*lx ",
+ width, st->start_address,
+ width, st->current_address);
delta = (st->current_address - st->start_address) >> 10;
while (!(delta & 1023) && unit[1]) {
--- head-2011-03-17.orig/arch/x86/mm/fault-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/fault-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -3,40 +3,18 @@
* Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
* Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
*/
-#include <linux/interrupt.h>
-#include <linux/mmiotrace.h>
-#include <linux/bootmem.h>
-#include <linux/compiler.h>
-#include <linux/highmem.h>
-#include <linux/kprobes.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/vt_kern.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/errno.h>
-#include <linux/magic.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mman.h>
-#include <linux/tty.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
-
-#include <asm-generic/sections.h>
-
-#include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/proto.h>
-#include <asm/traps.h>
-#include <asm/desc.h>
+#include <linux/magic.h> /* STACK_END_MAGIC */
+#include <linux/sched.h> /* test_thread_flag(), ... */
+#include <linux/kdebug.h> /* oops_begin/end, ... */
+#include <linux/module.h> /* search_exception_table */
+#include <linux/bootmem.h> /* max_low_pfn */
+#include <linux/kprobes.h> /* __kprobes, ... */
+#include <linux/mmiotrace.h> /* kmmio_handler, ... */
+#include <linux/perf_counter.h> /* perf_swcounter_event */
+
+#include <asm/traps.h> /* dotraplinkage, ... */
+#include <asm/pgalloc.h> /* pgd_*(), ... */
+#include <asm/kmemcheck.h> /* kmemcheck_*(), ... */
/*
* Page fault error code bits:
@@ -228,10 +206,7 @@ static inline pmd_t *vmalloc_sync_one(pg
if (!pmd_present(*pmd_k))
return NULL;
- if (!pmd_present(*pmd)) {
- bool lazy = percpu_read(xen_lazy_mmu);
-
- percpu_write(xen_lazy_mmu, false);
+ if (!pmd_present(*pmd))
#if CONFIG_XEN_COMPAT > 0x030002
set_pmd(pmd, *pmd_k);
#else
@@ -241,10 +216,8 @@ static inline pmd_t *vmalloc_sync_one(pg
*/
set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
#endif
- percpu_write(xen_lazy_mmu, lazy);
- } else {
+ else
BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
- }
return pmd_k;
}
@@ -474,10 +447,11 @@ static noinline int vmalloc_fault(unsign
}
static const char errata93_warning[] =
-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
-KERN_ERR "******* Please consider a BIOS update.\n"
-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
+KERN_ERR
+"******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+"******* Working around it, but it may cause SEGVs or burn power.\n"
+"******* Please consider a BIOS update.\n"
+"******* Disabling USB legacy in the BIOS may also help.\n";
/*
* No vm86 mode in 64-bit mode:
@@ -562,8 +536,6 @@ bad:
static int is_errata93(struct pt_regs *regs, unsigned long address)
{
#ifdef CONFIG_X86_64
- static int once;
-
if (address != regs->ip)
return 0;
@@ -573,10 +545,7 @@ static int is_errata93(struct pt_regs *r
address |= 0xffffffffUL << 32;
if ((address >= (u64)_stext && address <= (u64)_etext) ||
(address >= MODULES_VADDR && address <= MODULES_END)) {
- if (!once) {
- printk(errata93_warning);
- once = 1;
- }
+ printk_once(errata93_warning);
regs->ip = address;
return 1;
}
@@ -749,7 +718,7 @@ show_signal_msg(struct pt_regs *regs, un
if (!printk_ratelimit())
return;
- printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+ printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
tsk->comm, task_pid_nr(tsk), address,
(void *)regs->ip, (void *)regs->sp, error_code);
@@ -1011,11 +980,17 @@ do_page_fault(struct pt_regs *regs, unsi
tsk = current;
mm = tsk->mm;
- prefetchw(&mm->mmap_sem);
-
/* Get the faulting address: */
address = read_cr2();
+ /*
+ * Detect and handle instructions that would cause a page fault for
+ * both a tracked kernel page and a userspace page.
+ */
+ if (kmemcheck_active(regs))
+ kmemcheck_hide(regs);
+ prefetchw(&mm->mmap_sem);
+
if (unlikely(kmmio_fault(regs, address)))
return;
@@ -1044,9 +1019,13 @@ do_page_fault(struct pt_regs *regs, unsi
return;
}
- if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
- vmalloc_fault(address) >= 0)
- return;
+ if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) {
+ if (vmalloc_fault(address) >= 0)
+ return;
+
+ if (kmemcheck_fault(regs, address, error_code))
+ return;
+ }
/* Can handle a stale RO->RW TLB: */
if (spurious_fault(error_code, address))
@@ -1085,6 +1064,8 @@ do_page_fault(struct pt_regs *regs, unsi
if (unlikely(error_code & PF_RSVD))
pgtable_bad(regs, error_code, address);
+ perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
/*
* If we're in an interrupt, have no user context or are running
* in an atomic region then we must not take the fault:
@@ -1171,17 +1152,22 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault:
*/
- fault = handle_mm_fault(mm, vma, address, write);
+ fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
if (unlikely(fault & VM_FAULT_ERROR)) {
mm_fault_error(regs, error_code, address, fault);
return;
}
- if (fault & VM_FAULT_MAJOR)
+ if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
- else
+ perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ regs, address);
+ } else {
tsk->min_flt++;
+ perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ regs, address);
+ }
check_v8086_mode(regs, address, tsk);
--- head-2011-03-17.orig/arch/x86/mm/highmem_32-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/highmem_32-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -44,7 +44,6 @@ void *kmap_atomic_prot(struct page *page
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
BUG_ON(!pte_none(*(kmap_pte-idx)));
set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
- /*arch_flush_lazy_mmu_mode();*/
return (void *)vaddr;
}
@@ -74,7 +73,6 @@ void kunmap_atomic(void *kvaddr, enum km
#endif
}
- /*arch_flush_lazy_mmu_mode();*/
pagefault_enable();
}
@@ -150,6 +148,7 @@ EXPORT_SYMBOL(kmap);
EXPORT_SYMBOL(kunmap);
EXPORT_SYMBOL(kmap_atomic);
EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_prot);
#ifdef CONFIG_HIGHPTE
EXPORT_SYMBOL(kmap_atomic_to_page);
#endif
--- head-2011-03-17.orig/arch/x86/mm/hypervisor.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/hypervisor.c 2011-02-01 14:50:44.000000000 +0100
@@ -116,8 +116,8 @@ static int _xen_multicall_flush(bool ret
return 0;
}
-void xen_multicall_flush(bool force) {
- if (force || use_lazy_mmu_mode())
+void xen_multicall_flush(void) {
+ if (use_lazy_mmu_mode())
_xen_multicall_flush(false);
}
--- head-2011-03-17.orig/arch/x86/mm/init-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/init-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -1,3 +1,4 @@
+#include <linux/initrd.h>
#include <linux/ioport.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
@@ -11,6 +12,10 @@
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+#include <asm/proto.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long __meminitdata e820_table_start;
unsigned long __meminitdata e820_table_end;
@@ -31,6 +36,69 @@ extern unsigned long extend_init_mapping
extern void xen_finish_init_mapping(void);
#endif
+int nx_enabled;
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+static int disable_nx __cpuinitdata;
+
+/*
+ * noexec = on|off
+ *
+ * Control non-executable mappings for processes.
+ *
+ * on Enable
+ * off Disable
+ */
+static int __init noexec_setup(char *str)
+{
+ if (!str)
+ return -EINVAL;
+ if (!strncmp(str, "on", 2)) {
+ __supported_pte_mask |= _PAGE_NX;
+ disable_nx = 0;
+ } else if (!strncmp(str, "off", 3)) {
+ disable_nx = 1;
+ __supported_pte_mask &= ~_PAGE_NX;
+ }
+ return 0;
+}
+early_param("noexec", noexec_setup);
+#endif
+
+#ifdef CONFIG_X86_PAE
+static void __init set_nx(void)
+{
+ unsigned int v[4], l, h;
+
+ if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+ cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+
+ if ((v[3] & (1 << 20)) && !disable_nx) {
+ rdmsr(MSR_EFER, l, h);
+ l |= EFER_NX;
+ wrmsr(MSR_EFER, l, h);
+ nx_enabled = 1;
+ __supported_pte_mask |= _PAGE_NX;
+ }
+ }
+}
+#else
+static inline void set_nx(void)
+{
+}
+#endif
+
+#ifdef CONFIG_X86_64
+void __cpuinit check_efer(void)
+{
+ unsigned long efer;
+
+ rdmsrl(MSR_EFER, efer);
+ if (!(efer & EFER_NX) || disable_nx)
+ __supported_pte_mask &= ~_PAGE_NX;
+}
+#endif
+
static void __init find_early_table_space(unsigned long end, int use_pse,
int use_gbpages)
{
@@ -127,20 +195,6 @@ static int __meminit save_mr(struct map_
return nr_range;
}
-#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
-static void __init init_gbpages(void)
-{
- if (direct_gbpages && cpu_has_gbpages)
- printk(KERN_INFO "Using GB pages for direct mapping\n");
- else
- direct_gbpages = 0;
-}
-#else
-static inline void init_gbpages(void)
-{
-}
-#endif
-
/*
* Setup the direct mapping of the physical memory at PAGE_OFFSET.
* This runs before bootmem is initialized and gets pages directly from
@@ -160,10 +214,7 @@ unsigned long __init_refok init_memory_m
printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
- if (!after_bootmem)
- init_gbpages();
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
/*
* For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
* This will simplify cpa(), which otherwise needs to support splitting
@@ -175,12 +226,9 @@ unsigned long __init_refok init_memory_m
use_gbpages = direct_gbpages;
#endif
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_X86_PAE
set_nx();
if (nx_enabled)
printk(KERN_INFO "NX (Execute Disable) protection: active\n");
-#endif
/* Enable PSE if available */
if (cpu_has_pse)
@@ -191,7 +239,6 @@ unsigned long __init_refok init_memory_m
set_in_cr4(X86_CR4_PGE);
__supported_pte_mask |= _PAGE_GLOBAL;
}
-#endif
if (use_gbpages)
page_size_mask |= 1 << PG_LEVEL_1G;
--- head-2011-03-17.orig/arch/x86/mm/init_32-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/init_32-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -52,12 +52,9 @@
#include <asm/swiotlb.h>
#include <asm/setup.h>
#include <asm/cacheflush.h>
+#include <asm/page_types.h>
#include <asm/init.h>
-unsigned long max_low_pfn_mapped;
-unsigned long max_pfn_mapped;
-
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long highstart_pfn, highend_pfn;
static noinline int do_test_wp_bit(void);
@@ -122,7 +119,7 @@ static pte_t * __init one_page_table_ini
pte_t *page_table = NULL;
if (after_bootmem) {
-#ifdef CONFIG_DEBUG_PAGEALLOC
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
#endif
if (!page_table)
@@ -569,7 +566,7 @@ static inline void save_pg_dir(void)
}
#endif /* !CONFIG_ACPI_SLEEP */
-void zap_low_mappings(void)
+void zap_low_mappings(bool early)
{
int i;
@@ -586,64 +583,16 @@ void zap_low_mappings(void)
set_pgd(swapper_pg_dir+i, __pgd(0));
#endif
}
- flush_tlb_all();
-}
-int nx_enabled;
+ if (early)
+ __flush_tlb();
+ else
+ flush_tlb_all();
+}
pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
EXPORT_SYMBOL_GPL(__supported_pte_mask);
-#ifdef CONFIG_X86_PAE
-
-static int disable_nx __initdata;
-
-/*
- * noexec = on|off
- *
- * Control non executable mappings.
- *
- * on Enable
- * off Disable
- */
-static int __init noexec_setup(char *str)
-{
- if (!str || !strcmp(str, "on")) {
- if (cpu_has_nx) {
- __supported_pte_mask |= _PAGE_NX;
- disable_nx = 0;
- }
- } else {
- if (!strcmp(str, "off")) {
- disable_nx = 1;
- __supported_pte_mask &= ~_PAGE_NX;
- } else {
- return -EINVAL;
- }
- }
-
- return 0;
-}
-early_param("noexec", noexec_setup);
-
-void __init set_nx(void)
-{
- unsigned int v[4], l, h;
-
- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
-
- if ((v[3] & (1 << 20)) && !disable_nx) {
- rdmsr(MSR_EFER, l, h);
- l |= EFER_NX;
- wrmsr(MSR_EFER, l, h);
- nx_enabled = 1;
- __supported_pte_mask |= _PAGE_NX;
- }
- }
-}
-#endif
-
/* user-defined highmem size */
static unsigned int highmem_pages = -1;
@@ -763,15 +712,15 @@ void __init initmem_init(unsigned long s
highstart_pfn = highend_pfn = max_pfn;
if (max_pfn > max_low_pfn)
highstart_pfn = max_low_pfn;
- memory_present(0, 0, highend_pfn);
e820_register_active_regions(0, 0, highend_pfn);
+ sparse_memory_present_with_active_regions(0);
printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
pages_to_mb(highend_pfn - highstart_pfn));
num_physpages = highend_pfn;
high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
#else
- memory_present(0, 0, max_low_pfn);
e820_register_active_regions(0, 0, max_low_pfn);
+ sparse_memory_present_with_active_regions(0);
num_physpages = max_low_pfn;
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
#endif
@@ -1074,7 +1023,7 @@ void __init mem_init(void)
test_wp_bit();
save_pg_dir();
- zap_low_mappings();
+ zap_low_mappings(true);
SetPagePinned(virt_to_page(init_mm.pgd));
}
--- head-2011-03-17.orig/arch/x86/mm/init_64-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/init_64-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -56,21 +56,11 @@
#include <xen/features.h>
-/*
- * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
- * The direct mapping extends to max_pfn_mapped, so that we can directly access
- * apertures, ACPI and other tables without having to play with fixmaps.
- */
-unsigned long max_low_pfn_mapped;
-unsigned long max_pfn_mapped;
-
#if CONFIG_XEN_COMPAT <= 0x030002
unsigned int __kernel_page_user;
EXPORT_SYMBOL(__kernel_page_user);
#endif
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
extern pmd_t level2_fixmap_pgt[PTRS_PER_PMD];
extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
@@ -151,39 +141,6 @@ early_param("gbpages", parse_direct_gbpa
pteval_t __supported_pte_mask __read_mostly = ~0UL;
EXPORT_SYMBOL_GPL(__supported_pte_mask);
-static int disable_nx __cpuinitdata;
-
-/*
- * noexec=on|off
- * Control non-executable mappings for 64-bit processes.
- *
- * on Enable (default)
- * off Disable
- */
-static int __init nonx_setup(char *str)
-{
- if (!str)
- return -EINVAL;
- if (!strncmp(str, "on", 2)) {
- __supported_pte_mask |= _PAGE_NX;
- disable_nx = 0;
- } else if (!strncmp(str, "off", 3)) {
- disable_nx = 1;
- __supported_pte_mask &= ~_PAGE_NX;
- }
- return 0;
-}
-early_param("noexec", nonx_setup);
-
-void __cpuinit check_efer(void)
-{
- unsigned long efer;
-
- rdmsrl(MSR_EFER, efer);
- if (!(efer & EFER_NX) || disable_nx)
- __supported_pte_mask &= ~_PAGE_NX;
-}
-
int force_personality32;
/*
@@ -213,7 +170,7 @@ static __ref void *spp_getpage(void)
void *ptr;
if (after_bootmem)
- ptr = (void *) get_zeroed_page(GFP_ATOMIC);
+ ptr = (void *) get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
else if (e820_table_end < e820_table_top) {
ptr = __va(e820_table_end << PAGE_SHIFT);
e820_table_end++;
@@ -399,7 +356,7 @@ static __ref void *alloc_low_page(unsign
void *adr;
if (after_bootmem) {
- adr = (void *)get_zeroed_page(GFP_ATOMIC);
+ adr = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
*phys = __pa(adr);
return adr;
@@ -804,7 +761,7 @@ void __init xen_finish_init_mapping(void
e820_table_top = e820_table_end;
}
-unsigned long __init
+unsigned long __meminit
kernel_physical_mapping_init(unsigned long start,
unsigned long end,
unsigned long page_size_mask)
@@ -873,6 +830,7 @@ void __init initmem_init(unsigned long s
early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
}
+#endif
void __init paging_init(void)
{
@@ -883,13 +841,21 @@ void __init paging_init(void)
max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
max_zone_pfns[ZONE_NORMAL] = max_pfn;
- memory_present(0, 0, max_pfn);
+ sparse_memory_present_with_active_regions(MAX_NUMNODES);
sparse_init();
+
+ /*
+ * clear the default setting with node 0
+ * note: don't use nodes_clear here, that is really clearing when
+ * numa support is not compiled in, and later node_set_state
+ * will not set it back.
+ */
+ node_clear_state(0, N_NORMAL_MEMORY);
+
free_area_init_nodes(max_zone_pfns);
SetPagePinned(virt_to_page(init_mm.pgd));
}
-#endif
/*
* Memory hotplug specific functions
@@ -1084,7 +1050,7 @@ int __init reserve_bootmem_generic(unsig
return ret;
#else
- reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ reserve_bootmem(phys, len, flags);
#endif
#ifndef CONFIG_XEN
--- head-2011-03-17.orig/arch/x86/mm/iomap_32-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/iomap_32-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -84,7 +84,6 @@ iounmap_atomic(void *kvaddr, enum km_typ
if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
kpte_clear_flush(kmap_pte-idx, vaddr);
- /*arch_flush_lazy_mmu_mode();*/
pagefault_enable();
}
EXPORT_SYMBOL_GPL(iounmap_atomic);
--- head-2011-03-17.orig/arch/x86/mm/pageattr-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/pageattr-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
+#include <linux/pfn.h>
#include <asm/e820.h>
#include <asm/processor.h>
@@ -486,7 +487,7 @@ static int split_large_page(pte_t *kpte,
if (!debug_pagealloc)
spin_unlock(&cpa_lock);
- base = alloc_pages(GFP_KERNEL, 0);
+ base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
if (!debug_pagealloc)
spin_lock(&cpa_lock);
if (!base)
@@ -610,9 +611,12 @@ static int __change_page_attr(struct cpa
unsigned int level;
pte_t *kpte, old_pte;
- if (cpa->flags & CPA_PAGES_ARRAY)
- address = (unsigned long)page_address(cpa->pages[cpa->curpage]);
- else if (cpa->flags & CPA_ARRAY)
+ if (cpa->flags & CPA_PAGES_ARRAY) {
+ struct page *page = cpa->pages[cpa->curpage];
+ if (unlikely(PageHighMem(page)))
+ return 0;
+ address = (unsigned long)page_address(page);
+ } else if (cpa->flags & CPA_ARRAY)
address = cpa->vaddr[cpa->curpage];
else
address = *cpa->vaddr;
@@ -702,8 +706,9 @@ static int __change_page_attr_set_clr(st
static int cpa_process_alias(struct cpa_data *cpa)
{
struct cpa_data alias_cpa;
- int ret = 0;
- unsigned long temp_cpa_vaddr, vaddr;
+ unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
+ unsigned long vaddr, remapped;
+ int ret;
if (cpa->pfn >= max_pfn_mapped)
return 0;
@@ -716,9 +721,12 @@ static int cpa_process_alias(struct cpa_
* No need to redo, when the primary call touched the direct
* mapping already:
*/
- if (cpa->flags & CPA_PAGES_ARRAY)
- vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]);
- else if (cpa->flags & CPA_ARRAY)
+ if (cpa->flags & CPA_PAGES_ARRAY) {
+ struct page *page = cpa->pages[cpa->curpage];
+ if (unlikely(PageHighMem(page)))
+ return 0;
+ vaddr = (unsigned long)page_address(page);
+ } else if (cpa->flags & CPA_ARRAY)
vaddr = cpa->vaddr[cpa->curpage];
else
vaddr = *cpa->vaddr;
@@ -727,42 +735,55 @@ static int cpa_process_alias(struct cpa_
PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
alias_cpa = *cpa;
- temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
- alias_cpa.vaddr = &temp_cpa_vaddr;
+ alias_cpa.vaddr = &laddr;
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
-
ret = __change_page_attr_set_clr(&alias_cpa, 0);
+ if (ret)
+ return ret;
}
#ifdef CONFIG_X86_64
- if (ret)
- return ret;
- /*
- * No need to redo, when the primary call touched the high
- * mapping already:
- */
- if (within(vaddr, (unsigned long) _text, _brk_end))
- return 0;
-
/*
- * If the physical address is inside the kernel map, we need
+ * If the primary call didn't touch the high mapping already
+ * and the physical address is inside the kernel map, we need
* to touch the high mapped kernel as well:
*/
- if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn()))
- return 0;
+ if (!within(vaddr, (unsigned long)_text, _brk_end) &&
+ within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) {
+ unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
+ __START_KERNEL_map;
+ alias_cpa = *cpa;
+ alias_cpa.vaddr = &temp_cpa_vaddr;
+ alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
- alias_cpa = *cpa;
- temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map;
- alias_cpa.vaddr = &temp_cpa_vaddr;
- alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+ /*
+ * The high mapping range is imprecise, so ignore the
+ * return value.
+ */
+ __change_page_attr_set_clr(&alias_cpa, 0);
+ }
+#endif
/*
- * The high mapping range is imprecise, so ignore the return value.
- */
- __change_page_attr_set_clr(&alias_cpa, 0);
-#endif
- return ret;
+ * If the PMD page was partially used for per-cpu remapping,
+ * the recycled area needs to be split and modified. Because
+ * the area is always proper subset of a PMD page
+ * cpa->numpages is guaranteed to be 1 for these areas, so
+ * there's no need to loop over and check for further remaps.
+ */
+ remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr);
+ if (remapped) {
+ WARN_ON(cpa->numpages > 1);
+ alias_cpa = *cpa;
+ alias_cpa.vaddr = &remapped;
+ alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+ ret = __change_page_attr_set_clr(&alias_cpa, 0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
@@ -860,15 +881,6 @@ static int change_page_attr_set_clr(unsi
vm_unmap_aliases();
- /*
- * If we're called with lazy mmu updates enabled, the
- * in-memory pte state may be stale. Flush pending updates to
- * bring them up to date.
- *
- arch_flush_lazy_mmu_mode();*/
- if (arch_use_lazy_mmu_mode())
- xen_multicall_flush(true);
-
cpa.vaddr = addr;
cpa.pages = pages;
cpa.numpages = numpages;
@@ -913,14 +925,6 @@ static int change_page_attr_set_clr(unsi
} else
cpa_flush_all(cache);
- /*
- * If we've been called with lazy mmu updates enabled, then
- * make sure that everything gets flushed out before we
- * return.
- *
- arch_flush_lazy_mmu_mode();*/
- WARN_ON_ONCE(arch_use_lazy_mmu_mode() && !irq_count());
-
out:
return ret;
}
@@ -1065,12 +1069,15 @@ EXPORT_SYMBOL(set_memory_array_uc);
int _set_memory_wc(unsigned long addr, int numpages)
{
int ret;
+ unsigned long addr_copy = addr;
+
ret = change_page_attr_set(&addr, numpages,
__pgprot(_PAGE_CACHE_UC_MINUS), 0);
-
if (!ret) {
- ret = change_page_attr_set(&addr, numpages,
- __pgprot(_PAGE_CACHE_WC), 0);
+ ret = change_page_attr_set_clr(&addr_copy, numpages,
+ __pgprot(_PAGE_CACHE_WC),
+ __pgprot(_PAGE_CACHE_MASK),
+ 0, 0, NULL);
}
return ret;
}
@@ -1187,7 +1194,9 @@ int set_pages_array_uc(struct page **pag
int free_idx;
for (i = 0; i < addrinarray; i++) {
- start = (unsigned long)page_address(pages[i]);
+ if (PageHighMem(pages[i]))
+ continue;
+ start = page_to_pfn(pages[i]) << PAGE_SHIFT;
end = start + PAGE_SIZE;
if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
goto err_out;
@@ -1200,7 +1209,9 @@ int set_pages_array_uc(struct page **pag
err_out:
free_idx = i;
for (i = 0; i < free_idx; i++) {
- start = (unsigned long)page_address(pages[i]);
+ if (PageHighMem(pages[i]))
+ continue;
+ start = page_to_pfn(pages[i]) << PAGE_SHIFT;
end = start + PAGE_SIZE;
free_memtype(start, end);
}
@@ -1229,7 +1240,9 @@ int set_pages_array_wb(struct page **pag
return retval;
for (i = 0; i < addrinarray; i++) {
- start = (unsigned long)page_address(pages[i]);
+ if (PageHighMem(pages[i]))
+ continue;
+ start = page_to_pfn(pages[i]) << PAGE_SHIFT;
end = start + PAGE_SIZE;
free_memtype(start, end);
}
--- head-2011-03-17.orig/arch/x86/mm/pat-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/pat-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -639,7 +639,8 @@ static int reserve_pfn_range(u64 paddr,
return ret;
if (flags != want_flags) {
- if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
+ if (strict_prot ||
+ !is_new_memtype_allowed(paddr, size, want_flags, flags)) {
free_memtype(paddr, paddr + size);
printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
" for %Lx-%Lx, got %s\n",
--- head-2011-03-17.orig/arch/x86/mm/pgtable-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/arch/x86/mm/pgtable-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -8,9 +8,11 @@
#include <asm/hypervisor.h>
#include <asm/mmu_context.h>
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ pte_t *pte = (pte_t *)__get_free_page(PGALLOC_GFP);
if (pte)
make_lowmem_page_readonly(pte, XENFEAT_writable_page_tables);
return pte;
@@ -27,9 +29,9 @@ pgtable_t pte_alloc_one(struct mm_struct
struct page *pte;
#ifdef CONFIG_HIGHPTE
- pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+ pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0);
#else
- pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+ pte = alloc_pages(PGALLOC_GFP, 0);
#endif
if (pte) {
pgtable_page_ctor(pte);
@@ -65,7 +67,7 @@ void __pte_free(pgtable_t pte)
__free_page(pte);
}
-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
{
pgtable_page_dtor(pte);
paravirt_release_pte(page_to_pfn(pte));
@@ -83,7 +85,7 @@ pmd_t *pmd_alloc_one(struct mm_struct *m
{
struct page *pmd;
- pmd = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+ pmd = alloc_pages(PGALLOC_GFP, 0);
if (!pmd)
return NULL;
SetPageForeign(pmd, _pmd_free);
@@ -107,14 +109,14 @@ void __pmd_free(pgtable_t pmd)
__free_page(pmd);
}
-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
{
paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
tlb_remove_page(tlb, virt_to_page(pmd));
}
#if PAGETABLE_LEVELS > 3
-void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
{
paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
tlb_remove_page(tlb, virt_to_page(pud));
@@ -609,7 +611,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
pmd_t *pmds[PREALLOCATED_PMDS];
unsigned long flags;
- pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
+ pgd = (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ORDER);
if (pgd == NULL)
goto out;
--- head-2011-03-17.orig/arch/x86/pci/i386.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/arch/x86/pci/i386.c 2011-02-01 14:50:44.000000000 +0100
@@ -239,12 +239,14 @@ void __init pcibios_resource_survey(void
pcibios_allocate_resources(1);
e820_reserve_resources_late();
+#ifndef CONFIG_XEN
/*
* Insert the IO APIC resources after PCI initialization has
* occured to handle IO APICS that are mapped in on a BAR in
* PCI space, but before trying to assign unassigned pci res.
*/
ioapic_insert_resources();
+#endif
}
/**
--- head-2011-03-17.orig/arch/x86/pci/irq-xen.c 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/arch/x86/pci/irq-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -895,6 +895,9 @@ static int pcibios_lookup_irq(struct pci
return 0;
}
+ if (io_apic_assign_pci_irqs)
+ return 0;
+
/* Find IRQ routing entry */
if (!pirq_table)
@@ -1045,56 +1048,15 @@ static void __init pcibios_fixup_irqs(vo
pirq_penalty[dev->irq]++;
}
+ if (io_apic_assign_pci_irqs)
+ return;
+
dev = NULL;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin)
continue;
-#ifdef CONFIG_X86_IO_APIC
- /*
- * Recalculate IRQ numbers if we use the I/O APIC.
- */
- if (io_apic_assign_pci_irqs) {
- int irq;
-
- /*
- * interrupt pins are numbered starting from 1
- */
- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
- PCI_SLOT(dev->devfn), pin - 1);
- /*
- * Busses behind bridges are typically not listed in the
- * MP-table. In this case we have to look up the IRQ
- * based on the parent bus, parent slot, and pin number.
- * The SMP code detects such bridged busses itself so we
- * should get into this branch reliably.
- */
- if (irq < 0 && dev->bus->parent) {
- /* go back to the bridge */
- struct pci_dev *bridge = dev->bus->self;
- int bus;
-
- pin = pci_swizzle_interrupt_pin(dev, pin);
- bus = bridge->bus->number;
- irq = IO_APIC_get_PCI_irq_vector(bus,
- PCI_SLOT(bridge->devfn), pin - 1);
- if (irq >= 0)
- dev_warn(&dev->dev,
- "using bridge %s INT %c to "
- "get IRQ %d\n",
- pci_name(bridge),
- 'A' + pin - 1, irq);
- }
- if (irq >= 0) {
- dev_info(&dev->dev,
- "PCI->APIC IRQ transform: INT %c "
- "-> IRQ %d\n",
- 'A' + pin - 1, irq);
- dev->irq = irq;
- }
- }
-#endif
/*
* Still no IRQ? Try to lookup one...
*/
@@ -1189,6 +1151,19 @@ int __init pcibios_irq_init(void)
pcibios_enable_irq = pirq_enable_irq;
pcibios_fixup_irqs();
+
+ if (io_apic_assign_pci_irqs && pci_routeirq) {
+ struct pci_dev *dev = NULL;
+ /*
+ * PCI IRQ routing is set up by pci_enable_device(), but we
+ * also do it here in case there are still broken drivers that
+ * don't use pci_enable_device().
+ */
+ printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+ for_each_pci_dev(dev)
+ pirq_enable_irq(dev);
+ }
+
return 0;
}
@@ -1219,16 +1194,23 @@ void pcibios_penalize_isa_irq(int irq, i
static int pirq_enable_irq(struct pci_dev *dev)
{
u8 pin;
- struct pci_dev *temp_dev;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+ if (pin && !pcibios_lookup_irq(dev, 1)) {
char *msg = "";
+ if (!io_apic_assign_pci_irqs && dev->irq)
+ return 0;
+
if (io_apic_assign_pci_irqs) {
+#ifdef CONFIG_X86_IO_APIC
+ struct pci_dev *temp_dev;
int irq;
+ struct io_apic_irq_attr irq_attr;
- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
+ irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+ PCI_SLOT(dev->devfn),
+ pin - 1, &irq_attr);
/*
* Busses behind bridges are typically not listed in the MP-table.
* In this case we have to look up the IRQ based on the parent bus,
@@ -1241,7 +1223,8 @@ static int pirq_enable_irq(struct pci_de
pin = pci_swizzle_interrupt_pin(dev, pin);
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
- PCI_SLOT(bridge->devfn), pin - 1);
+ PCI_SLOT(bridge->devfn),
+ pin - 1, &irq_attr);
if (irq >= 0)
dev_warn(&dev->dev, "using bridge %s "
"INT %c to get IRQ %d\n",
@@ -1251,12 +1234,15 @@ static int pirq_enable_irq(struct pci_de
}
dev = temp_dev;
if (irq >= 0) {
+ io_apic_set_pci_routing(&dev->dev, irq,
+ &irq_attr);
+ dev->irq = irq;
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
- dev->irq = irq;
return 0;
} else
msg = "; probably buggy MP table";
+#endif
} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
msg = "";
else
--- head-2011-03-17.orig/arch/x86/pci/pcifront.c 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/arch/x86/pci/pcifront.c 2011-02-01 14:50:44.000000000 +0100
@@ -6,6 +6,7 @@
*/
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/irq.h>
#include <linux/pci.h>
#include <asm/acpi.h>
#include <asm/pci_x86.h>
@@ -15,6 +16,8 @@ static int pcifront_enable_irq(struct pc
{
u8 irq;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+ if (!irq_to_desc_alloc_node(irq, numa_node_id()))
+ return -ENOMEM;
evtchn_register_pirq(irq);
dev->irq = irq;
--- head-2011-03-17.orig/arch/x86/vdso/vdso32-setup-xen.c 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/arch/x86/vdso/vdso32-setup-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -377,6 +377,8 @@ int arch_setup_additional_pages(struct l
}
}
+ current->mm->context.vdso = (void *)addr;
+
if (compat_uses_vma || !compat) {
/*
* MAYWRITE to allow gdb to COW and set breakpoints
@@ -397,11 +399,13 @@ int arch_setup_additional_pages(struct l
goto up_fail;
}
- current->mm->context.vdso = (void *)addr;
current_thread_info()->sysenter_return =
VDSO32_SYMBOL(addr, SYSENTER_RETURN);
up_fail:
+ if (ret)
+ current->mm->context.vdso = NULL;
+
up_write(&mm->mmap_sem);
return ret;
--- head-2011-03-17.orig/drivers/acpi/processor_driver.c 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/drivers/acpi/processor_driver.c 2011-02-01 14:50:44.000000000 +0100
@@ -340,7 +340,14 @@ static int acpi_processor_get_info(struc
* generated as the following format:
* CPU+CPU ID.
*/
- sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+ if (pr->id != -1)
+ sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+ else
+ snprintf(acpi_device_bid(device),
+ ARRAY_SIZE(acpi_device_bid(device)),
+ "#%0*X",
+ (int)ARRAY_SIZE(acpi_device_bid(device)) - 2,
+ pr->acpi_id);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
pr->acpi_id));
--- head-2011-03-17.orig/drivers/char/agp/intel-gtt.c 2011-03-11 10:53:08.000000000 +0100
+++ head-2011-03-17/drivers/char/agp/intel-gtt.c 2011-03-11 11:00:05.000000000 +0100
@@ -282,7 +282,11 @@ static struct agp_memory *alloc_agpphysm
new->page_count = pg_count;
new->num_scratch_pages = pg_count;
new->type = AGP_PHYS_MEMORY;
+#ifndef CONFIG_XEN
new->physical = page_to_phys(new->pages[0]);
+#else
+ new->physical = page_to_pseudophys(new->pages[0]);
+#endif
return new;
}
--- head-2011-03-17.orig/drivers/edac/Kconfig 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/drivers/edac/Kconfig 2011-02-01 14:50:44.000000000 +0100
@@ -77,6 +77,7 @@ config EDAC_MCE
config EDAC_AMD64
tristate "AMD64 (Opteron, Athlon64) K8, F10h"
depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
+ depends on !XEN
help
Support for error detection and correction of DRAM ECC errors on
the AMD64 families of memory controllers (K8 and F10h)
--- head-2011-03-17.orig/drivers/gpu/drm/ttm/ttm_bo.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/drivers/gpu/drm/ttm/ttm_bo.c 2011-02-01 14:50:44.000000000 +0100
@@ -1440,6 +1440,14 @@ int ttm_bo_global_init(struct drm_global
ret = -ENOMEM;
goto out_no_drp;
}
+#ifdef CONFIG_XEN
+ ret = xen_limit_pages_to_max_mfn(glob->dummy_read_page, 0, 32);
+ if (!ret)
+ clear_page(page_address(glob->dummy_read_page));
+ else
+ printk(KERN_WARNING
+ "Error restricting dummy read page: %d\n", ret);
+#endif
INIT_LIST_HEAD(&glob->swap_lru);
INIT_LIST_HEAD(&glob->device_list);
--- head-2011-03-17.orig/drivers/gpu/drm/ttm/ttm_bo_vm.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/drivers/gpu/drm/ttm/ttm_bo_vm.c 2011-03-02 11:54:22.000000000 +0100
@@ -169,7 +169,13 @@ static int ttm_bo_vm_fault(struct vm_are
if (bo->mem.bus.is_iomem) {
vma->vm_page_prot = ttm_io_prot(bo->mem.placement,
vma->vm_page_prot);
+#if defined(CONFIG_XEN) && defined(_PAGE_IOMAP)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_IOMAP;
+#endif
} else {
+#if defined(CONFIG_XEN) && defined(_PAGE_IOMAP)
+ pgprot_val(vma->vm_page_prot) &= ~_PAGE_IOMAP;
+#endif
ttm = bo->ttm;
vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ?
vm_get_page_prot(vma->vm_flags) :
--- head-2011-03-17.orig/drivers/pci/msi-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/drivers/pci/msi-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -54,22 +54,17 @@ int arch_msi_check_device(struct pci_dev
}
#endif
-static void __msi_set_enable(struct pci_dev *dev, int pos, int enable)
+static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
{
u16 control;
- if (pos) {
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
- control &= ~PCI_MSI_FLAGS_ENABLE;
- if (enable)
- control |= PCI_MSI_FLAGS_ENABLE;
- pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
- }
-}
+ BUG_ON(!pos);
-static void msi_set_enable(struct pci_dev *dev, int enable)
-{
- __msi_set_enable(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), enable);
+ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ control &= ~PCI_MSI_FLAGS_ENABLE;
+ if (enable)
+ control |= PCI_MSI_FLAGS_ENABLE;
+ pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
}
static void msix_set_enable(struct pci_dev *dev, int enable)
@@ -294,8 +289,11 @@ void pci_restore_msi_state(struct pci_de
return;
pci_intx_for_msi(dev, 0);
- if (dev->msi_enabled)
- msi_set_enable(dev, 0);
+ if (dev->msi_enabled) {
+ int pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+
+ msi_set_enable(dev, pos, 0);
+ }
if (dev->msix_enabled)
msix_set_enable(dev, 0);
@@ -322,9 +320,9 @@ static int msi_capability_init(struct pc
int pos, pirq;
u16 control;
- msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
-
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ msi_set_enable(dev, pos, 0); /* Disable MSI during set up */
+
pci_read_config_word(dev, msi_control_reg(pos), &control);
WARN_ON(nvec > 1); /* XXX */
@@ -334,7 +332,7 @@ static int msi_capability_init(struct pc
/* Set MSI enabled bits */
pci_intx_for_msi(dev, 0);
- msi_set_enable(dev, 1);
+ msi_set_enable(dev, pos, 1);
dev->msi_enabled = 1;
dev->irq = pirq;
@@ -356,6 +354,7 @@ static int msix_capability_init(struct p
{
u64 table_base;
int pirq, i, j, mapped, pos;
+ u16 control;
struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
struct msi_pirq_entry *pirq_entry;
@@ -365,11 +364,24 @@ static int msix_capability_init(struct p
msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+
+ /* Ensure MSI-X is disabled while it is set up */
+ control &= ~PCI_MSIX_FLAGS_ENABLE;
+ pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
table_base = find_table_base(dev, pos);
if (!table_base)
return -ENODEV;
- /* MSI-X Table Initialization */
+ /*
+ * Some devices require MSI-X to be enabled before we can touch the
+ * MSI-X registers. We need to mask all the vectors to prevent
+ * interrupts coming in before they're fully set up.
+ */
+ control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
+ pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
for (i = 0; i < nvec; i++) {
mapped = 0;
list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
@@ -406,10 +418,13 @@ static int msix_capability_init(struct p
return avail;
}
+ /* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
- msix_set_enable(dev, 1);
dev->msix_enabled = 1;
+ control &= ~PCI_MSIX_FLAGS_MASKALL;
+ pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
return 0;
}
@@ -531,7 +546,7 @@ EXPORT_SYMBOL(pci_enable_msi_block);
extern void pci_frontend_disable_msi(struct pci_dev* dev);
void pci_msi_shutdown(struct pci_dev *dev)
{
- int pirq;
+ int pirq, pos;
struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
if (!pci_msi_enable || !dev || !dev->msi_enabled)
@@ -553,7 +568,8 @@ void pci_msi_shutdown(struct pci_dev *de
msi_unmap_pirq(dev, pirq);
/* Disable MSI mode */
- msi_set_enable(dev, 0);
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ msi_set_enable(dev, pos, 0);
pci_intx_for_msi(dev, 1);
dev->msi_enabled = 0;
}
@@ -593,8 +609,8 @@ int pci_msix_table_size(struct pci_dev *
* indicates the successful configuration of MSI-X capability structure
* with new allocated MSI-X irqs. A return of < 0 indicates a failure.
* Or a return of > 0 indicates that driver request is exceeding the number
- * of irqs available. Driver should use the returned value to re-send
- * its request.
+ * of irqs or MSI-X vectors available. Driver should use the returned value to
+ * re-send its request.
**/
extern int pci_frontend_enable_msix(struct pci_dev *dev,
struct msix_entry *entries, int nvec);
@@ -650,7 +666,7 @@ int pci_enable_msix(struct pci_dev* dev,
nr_entries = pci_msix_table_size(dev);
if (nvec > nr_entries)
- return -EINVAL;
+ return nr_entries;
/* Check for any invalid entries */
for (i = 0; i < nvec; i++) {
--- head-2011-03-17.orig/drivers/staging/vt6655/ttype.h 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/drivers/staging/vt6655/ttype.h 2010-06-22 15:50:05.000000000 +0200
@@ -30,6 +30,9 @@
#ifndef __TTYPE_H__
#define __TTYPE_H__
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#endif
/******* Common definitions and typedefs ***********************************/
--- head-2011-03-17.orig/drivers/xen/Kconfig 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/drivers/xen/Kconfig 2011-02-02 15:37:23.000000000 +0100
@@ -371,7 +371,8 @@ config XEN_SCRUB_PAGES
config XEN_DEV_EVTCHN
tristate "Xen /dev/xen/evtchn device"
- default y
+ depends on XEN || PARAVIRT_XEN
+ default PARAVIRT_XEN || XEN_PRIVILEGED_GUEST || m
help
The evtchn driver allows a userspace process to triger event
channels and to receive notification of an event channel
@@ -411,7 +412,7 @@ config XEN_COMPAT_XENFS
config XEN_SYS_HYPERVISOR
bool "Create xen entries under /sys/hypervisor"
- depends on SYSFS
+ depends on PARAVIRT_XEN && SYSFS
select SYS_HYPERVISOR
default y
help
--- head-2011-03-17.orig/drivers/xen/Makefile 2011-02-24 14:09:54.000000000 +0100
+++ head-2011-03-17/drivers/xen/Makefile 2011-02-24 14:10:06.000000000 +0100
@@ -5,7 +5,6 @@ xen-balloon-$(CONFIG_PARAVIRT_XEN) := ba
xen-balloon-$(CONFIG_XEN) := balloon/
obj-$(CONFIG_XEN) += core/
obj-$(CONFIG_XEN) += console/
-obj-$(CONFIG_XEN) += evtchn/
obj-y += xenbus/
obj-$(CONFIG_XEN) += char/
@@ -15,7 +14,9 @@ obj-$(CONFIG_XEN) += features.o $(xen-
obj-$(CONFIG_HOTPLUG_CPU) += $(xen-hotplug-y)
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += $(xen-balloon-y)
+obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o
obj-$(CONFIG_XENFS) += xenfs/
+obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
obj-$(CONFIG_XEN_BLKDEV_TAP2) += blktap2/ blktap2-new/
--- head-2011-03-17.orig/drivers/xen/balloon/balloon.c 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/drivers/xen/balloon/balloon.c 2011-02-01 14:50:44.000000000 +0100
@@ -321,7 +321,7 @@ static int increase_reservation(unsigned
balloon_unlock(flags);
#ifndef MODULE
- setup_per_zone_pages_min();
+ setup_per_zone_wmarks();
if (rc > 0)
kswapd_run(0);
if (need_zonelists_rebuild)
--- head-2011-03-17.orig/drivers/xen/blkback/blkback.c 2011-01-31 18:01:51.000000000 +0100
+++ head-2011-03-17/drivers/xen/blkback/blkback.c 2011-02-01 14:50:44.000000000 +0100
@@ -495,7 +495,7 @@ static void dispatch_rw_block_io(blkif_t
for (i = 0; i < nseg; i++) {
if (((int)preq.sector_number|(int)seg[i].nsec) &
- ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
+ ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) {
DPRINTK("Misaligned I/O request from domain %d",
blkif->domid);
goto fail_put_bio;
--- head-2011-03-17.orig/drivers/xen/blkback/vbd.c 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/drivers/xen/blkback/vbd.c 2011-02-01 14:50:44.000000000 +0100
@@ -47,7 +47,7 @@ unsigned int vbd_info(struct vbd *vbd)
unsigned long vbd_secsize(struct vbd *vbd)
{
- return bdev_hardsect_size(vbd->bdev);
+ return bdev_logical_block_size(vbd->bdev);
}
int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
--- head-2011-03-17.orig/drivers/xen/blkback/xenbus.c 2011-01-31 17:49:31.000000000 +0100
+++ head-2011-03-17/drivers/xen/blkback/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -108,7 +108,7 @@ static void update_blkif_status(blkif_t
if (!get_device(_dev)) \
return ret; \
dev = to_xenbus_device(_dev); \
- if ((be = dev->dev.driver_data) != NULL) \
+ if ((be = dev_get_drvdata(&dev->dev)) != NULL) \
ret = sprintf(buf, format, ##args); \
put_device(_dev); \
return ret; \
@@ -173,7 +173,7 @@ void xenvbd_sysfs_delif(struct xenbus_de
static int blkback_remove(struct xenbus_device *dev)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
DPRINTK("");
@@ -194,7 +194,7 @@ static int blkback_remove(struct xenbus_
}
kfree(be);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
@@ -229,7 +229,7 @@ static int blkback_probe(struct xenbus_d
return -ENOMEM;
}
be->dev = dev;
- dev->dev.driver_data = be;
+ dev_set_drvdata(&dev->dev, be);
be->blkif = blkif_alloc(dev->otherend_id);
if (IS_ERR(be->blkif)) {
@@ -352,7 +352,7 @@ static void backend_changed(struct xenbu
static void frontend_changed(struct xenbus_device *dev,
enum xenbus_state frontend_state)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
int err;
DPRINTK("%s", xenbus_strstate(frontend_state));
--- head-2011-03-17.orig/drivers/xen/blkfront/blkfront.c 2011-02-01 14:39:24.000000000 +0100
+++ head-2011-03-17/drivers/xen/blkfront/blkfront.c 2011-02-01 14:50:44.000000000 +0100
@@ -119,12 +119,12 @@ static int blkfront_probe(struct xenbus_
/* Front end dir is a number, which is used as the id. */
info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
- dev->dev.driver_data = info;
+ dev_set_drvdata(&dev->dev, info);
err = talk_to_backend(dev, info);
if (err) {
kfree(info);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return err;
}
@@ -140,7 +140,7 @@ static int blkfront_probe(struct xenbus_
*/
static int blkfront_resume(struct xenbus_device *dev)
{
- struct blkfront_info *info = dev->dev.driver_data;
+ struct blkfront_info *info = dev_get_drvdata(&dev->dev);
int err;
DPRINTK("blkfront_resume: %s\n", dev->nodename);
@@ -265,7 +265,7 @@ fail:
static void backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
- struct blkfront_info *info = dev->dev.driver_data;
+ struct blkfront_info *info = dev_get_drvdata(&dev->dev);
struct block_device *bd;
DPRINTK("blkfront:backend_changed.\n");
@@ -433,7 +433,7 @@ static void blkfront_closing(struct blkf
static int blkfront_remove(struct xenbus_device *dev)
{
- struct blkfront_info *info = dev->dev.driver_data;
+ struct blkfront_info *info = dev_get_drvdata(&dev->dev);
DPRINTK("blkfront_remove: %s removed\n", dev->nodename);
@@ -682,7 +682,7 @@ static int blkif_queue_request(struct re
info->shadow[id].request = (unsigned long)req;
ring_req->id = id;
- ring_req->sector_number = (blkif_sector_t)req->sector;
+ ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
ring_req->handle = info->handle;
ring_req->operation = rq_data_dir(req) ?
@@ -738,25 +738,25 @@ void do_blkif_request(struct request_que
queued = 0;
- while ((req = elv_next_request(rq)) != NULL) {
+ while ((req = blk_peek_request(rq)) != NULL) {
info = req->rq_disk->private_data;
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
if (RING_FULL(&info->ring))
goto wait;
- DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
- "(%u/%li) buffer:%p [%s]\n",
- req, req->cmd, (long long)req->sector,
- req->current_nr_sectors,
- req->nr_sectors, req->buffer,
- rq_data_dir(req) ? "write" : "read");
+ blk_start_request(req);
+ if (!blk_fs_request(req)) {
+ __blk_end_request_all(req, -EIO);
+ continue;
+ }
+
+ DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
+ "(%u/%u) buffer:%p [%s]\n",
+ req, req->cmd, (long long)blk_rq_pos(req),
+ blk_rq_cur_sectors(req), blk_rq_sectors(req),
+ req->buffer, rq_data_dir(req) ? "write" : "read");
- blkdev_dequeue_request(req);
if (blkif_queue_request(req)) {
blk_requeue_request(rq, req);
wait:
@@ -822,8 +822,7 @@ static irqreturn_t blkif_int(int irq, vo
DPRINTK("Bad return from blkdev data "
"request: %x\n", bret->status);
- ret = __blk_end_request(req, ret, blk_rq_bytes(req));
- BUG_ON(ret);
+ __blk_end_request_all(req, ret);
break;
default:
BUG();
@@ -953,7 +952,7 @@ static int blkif_recover(struct blkfront
int blkfront_is_ready(struct xenbus_device *dev)
{
- struct blkfront_info *info = dev->dev.driver_data;
+ struct blkfront_info *info = dev_get_drvdata(&dev->dev);
return info->is_ready && info->xbdev;
}
--- head-2011-03-17.orig/drivers/xen/blkfront/vbd.c 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/drivers/xen/blkfront/vbd.c 2011-02-01 14:50:44.000000000 +0100
@@ -310,7 +310,7 @@ xlvbd_init_blk_queue(struct gendisk *gd,
#endif
/* Hard sector size and max sectors impersonate the equiv. hardware. */
- blk_queue_hardsect_size(rq, sector_size);
+ blk_queue_logical_block_size(rq, sector_size);
blk_queue_max_sectors(rq, 512);
/* Each segment in a request is up to an aligned page in size. */
@@ -499,7 +499,7 @@ static ssize_t show_media(struct device
struct device_attribute *attr, char *buf)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
- struct blkfront_info *info = xendev->dev.driver_data;
+ struct blkfront_info *info = dev_get_drvdata(&xendev->dev);
if (info->gd->flags & GENHD_FL_CD)
return sprintf(buf, "cdrom\n");
--- head-2011-03-17.orig/drivers/xen/blktap/blktap.c 2011-02-17 10:11:18.000000000 +0100
+++ head-2011-03-17/drivers/xen/blktap/blktap.c 2011-02-17 10:16:17.000000000 +0100
@@ -279,6 +279,15 @@ static inline unsigned int OFFSET_TO_SEG
} while(0)
+static char *blktap_nodename(struct device *dev)
+{
+ return kasprintf(GFP_KERNEL, "xen/blktap%u", MINOR(dev->devt));
+}
+
+static struct device_type blktap_type = {
+ .nodename = blktap_nodename
+};
+
/******************************************************************
* BLKTAP VM OPS
*/
@@ -438,7 +447,6 @@ static const struct file_operations blkt
static tap_blkif_t *get_next_free_dev(void)
{
- struct class *class;
tap_blkif_t *info;
int minor;
@@ -501,9 +509,9 @@ found:
wmb();
tapfds[minor] = info;
- if ((class = get_xen_class()) != NULL)
- device_create(class, NULL, MKDEV(blktap_major, minor),
- NULL, "blktap%d", minor);
+ xen_class_device_create(&blktap_type, NULL,
+ MKDEV(blktap_major, minor),
+ NULL, "blktap%d", minor);
}
out:
@@ -546,7 +554,8 @@ void signal_tapdisk(int idx)
return;
if (info->pid > 0) {
- ptask = find_task_by_pid_ns(info->pid, info->pid_ns);
+ ptask = pid_task(find_pid_ns(info->pid, info->pid_ns),
+ PIDTYPE_PID);
if (ptask)
info->status = CLEANSHUTDOWN;
}
@@ -1700,7 +1709,6 @@ static void make_response(blkif_t *blkif
static int __init blkif_init(void)
{
int i, ret;
- struct class *class;
if (!is_running_on_xen())
return -ENODEV;
@@ -1736,7 +1744,7 @@ static int __init blkif_init(void)
DPRINTK("Created misc_dev %d:0 [/dev/xen/blktap0]\n", ret);
/* Make sure the xen class exists */
- if ((class = get_xen_class()) != NULL) {
+ if (get_xen_class()) {
/*
* This will allow udev to create the blktap ctrl device.
* We only want to create blktap0 first. We don't want
@@ -1744,8 +1752,9 @@ static int __init blkif_init(void)
* We only create the device when a request of a new device is
* made.
*/
- device_create(class, NULL, MKDEV(blktap_major, 0), NULL,
- "blktap0");
+ xen_class_device_create(&blktap_type, NULL,
+ MKDEV(blktap_major, 0), NULL,
+ "blktap0");
} else {
/* this is bad, but not fatal */
WPRINTK("blktap: sysfs xen_class not created\n");
--- head-2011-03-17.orig/drivers/xen/blktap/xenbus.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/blktap/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -128,7 +128,7 @@ static int blktap_name(blkif_t *blkif, c
if (!get_device(_dev)) \
return ret; \
dev = to_xenbus_device(_dev); \
- if ((be = dev->dev.driver_data) != NULL) \
+ if ((be = dev_get_drvdata(&dev->dev)) != NULL) \
ret = sprintf(buf, format, ##args); \
put_device(_dev); \
return ret; \
@@ -158,7 +158,7 @@ static struct attribute_group tapstat_gr
int xentap_sysfs_addif(struct xenbus_device *dev)
{
int err;
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
err = sysfs_create_group(&dev->dev.kobj, &tapstat_group);
if (!err)
be->group_added = 1;
@@ -167,14 +167,14 @@ int xentap_sysfs_addif(struct xenbus_dev
void xentap_sysfs_delif(struct xenbus_device *dev)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
be->group_added = 0;
}
static int blktap_remove(struct xenbus_device *dev)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
if (be->group_added)
xentap_sysfs_delif(be->dev);
@@ -192,7 +192,7 @@ static int blktap_remove(struct xenbus_d
be->blkif = NULL;
}
kfree(be);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
@@ -261,7 +261,7 @@ static int blktap_probe(struct xenbus_de
}
be->dev = dev;
- dev->dev.driver_data = be;
+ dev_set_drvdata(&dev->dev, be);
be->xenbus_id = get_id(dev->nodename);
be->blkif = tap_alloc_blkif(dev->otherend_id);
@@ -351,7 +351,7 @@ static void blkif_disconnect(blkif_t *bl
static void tap_frontend_changed(struct xenbus_device *dev,
enum xenbus_state frontend_state)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
int err;
DPRINTK("fe_changed(%s,%d)\n", dev->nodename, frontend_state);
--- head-2011-03-17.orig/drivers/xen/blktap2/blktap.h 2011-01-31 18:07:35.000000000 +0100
+++ head-2011-03-17/drivers/xen/blktap2/blktap.h 2011-02-01 14:50:44.000000000 +0100
@@ -25,6 +25,8 @@ extern int blktap_debug_level;
#define BTWARN(_f, _a...) BTPRINTK(0, KERN_WARNING, 0, _f, ##_a)
#define BTERR(_f, _a...) BTPRINTK(0, KERN_ERR, 0, _f, ##_a)
+#define BLKTAP2_DEV_DIR "xen/blktap-2/"
+
#define MAX_BLKTAP_DEVICE 256
#define BLKTAP_CONTROL 1
--- head-2011-03-17.orig/drivers/xen/blktap2/control.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/blktap2/control.c 2011-02-01 14:50:44.000000000 +0100
@@ -154,6 +154,7 @@ static const struct file_operations blkt
static struct miscdevice blktap_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "blktap-control",
+ .devnode = BLKTAP2_DEV_DIR "control",
.fops = &blktap_control_file_operations,
};
--- head-2011-03-17.orig/drivers/xen/blktap2/device.c 2011-02-07 14:14:26.000000000 +0100
+++ head-2011-03-17/drivers/xen/blktap2/device.c 2011-02-01 14:50:44.000000000 +0100
@@ -206,13 +206,6 @@ flush_tlb_kernel_page(unsigned long kvad
#endif
}
-static void
-blktap_device_end_dequeued_request(struct request *req, int ret)
-{
- if (blk_end_request(req, ret, blk_rq_bytes(req)))
- BUG();
-}
-
/*
* tap->tap_sem held on entry
*/
@@ -378,7 +371,7 @@ blktap_device_fail_pending_requests(stru
blktap_unmap(tap, request);
req = (struct request *)(unsigned long)request->id;
- blktap_device_end_dequeued_request(req, -ENODEV);
+ blk_end_request_all(req, -ENODEV);
blktap_request_free(tap, request);
}
@@ -417,7 +410,7 @@ blktap_device_finish_request(struct blkt
if (unlikely(res->status != BLKIF_RSP_OKAY))
BTERR("Bad return from device data "
"request: %x\n", res->status);
- blktap_device_end_dequeued_request(req,
+ blk_end_request_all(req,
res->status == BLKIF_RSP_OKAY ? 0 : -EIO);
break;
default:
@@ -647,7 +640,7 @@ blktap_device_process_request(struct blk
ring = &tap->ring;
usr_idx = request->usr_idx;
blkif_req.id = usr_idx;
- blkif_req.sector_number = (blkif_sector_t)req->sector;
+ blkif_req.sector_number = (blkif_sector_t)blk_rq_pos(req);
blkif_req.handle = 0;
blkif_req.operation = rq_data_dir(req) ?
BLKIF_OP_WRITE : BLKIF_OP_READ;
@@ -844,20 +837,22 @@ blktap_device_run_queue(struct blktap *t
BTDBG("running queue for %d\n", tap->minor);
- while ((req = elv_next_request(rq)) != NULL) {
+ while ((req = blk_peek_request(rq)) != NULL) {
if (!blk_fs_request(req)) {
- end_request(req, 0);
+ blk_start_request(req);
+ __blk_end_request_all(req, -EIO);
continue;
}
if (blk_barrier_rq(req)) {
- end_request(req, 0);
+ blk_start_request(req);
+ __blk_end_request_all(req, -EOPNOTSUPP);
continue;
}
#ifdef ENABLE_PASSTHROUGH
if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
- blkdev_dequeue_request(req);
+ blk_start_request(req);
blktap_device_forward_request(tap, req);
continue;
}
@@ -877,13 +872,13 @@ blktap_device_run_queue(struct blktap *t
goto wait;
}
- BTDBG("req %p: dev %d cmd %p, sec 0x%llx, (0x%x/0x%lx) "
+ BTDBG("req %p: dev %d cmd %p, sec 0x%llx, (0x%x/0x%x) "
"buffer:%p [%s], pending: %p\n", req, tap->minor,
- req->cmd, (unsigned long long)req->sector,
- req->current_nr_sectors, req->nr_sectors, req->buffer,
+ req->cmd, (unsigned long long)blk_rq_pos(req),
+ blk_rq_cur_sectors(req), blk_rq_sectors(req), req->buffer,
rq_data_dir(req) ? "write" : "read", request);
- blkdev_dequeue_request(req);
+ blk_start_request(req);
spin_unlock_irq(&dev->lock);
down_write(&tap->tap_sem);
@@ -892,7 +887,7 @@ blktap_device_run_queue(struct blktap *t
if (!err)
queued++;
else {
- blktap_device_end_dequeued_request(req, err);
+ blk_end_request_all(req, err);
blktap_request_free(tap, request);
}
@@ -932,11 +927,12 @@ blktap_device_do_request(struct request_
return;
fail:
- while ((req = elv_next_request(rq))) {
+ while ((req = blk_fetch_request(rq))) {
BTERR("device closed: failing secs %llu - %llu\n",
- (unsigned long long)req->sector,
- (unsigned long long)req->sector + req->nr_sectors);
- end_request(req, 0);
+ (unsigned long long)blk_rq_pos(req),
+ (unsigned long long)blk_rq_pos(req)
+ + blk_rq_cur_sectors(req));
+ __blk_end_request_all(req, -EIO);
}
}
@@ -991,7 +987,7 @@ blktap_device_configure(struct blktap *t
set_capacity(dev->gd, tap->params.capacity);
/* Hard sector size and max sectors impersonate the equiv. hardware. */
- blk_queue_hardsect_size(rq, tap->params.sector_size);
+ blk_queue_logical_block_size(rq, tap->params.sector_size);
blk_queue_max_sectors(rq, 512);
/* Each segment in a request is up to an aligned page in size. */
@@ -1089,6 +1085,12 @@ blktap_device_destroy(struct blktap *tap
return 0;
}
+static char *blktap_nodename(struct gendisk *gd)
+{
+ return kasprintf(GFP_KERNEL, BLKTAP2_DEV_DIR "tapdev%u",
+ gd->first_minor);
+}
+
int
blktap_device_create(struct blktap *tap)
{
@@ -1125,6 +1127,7 @@ blktap_device_create(struct blktap *tap)
gd->major = blktap_device_major;
gd->first_minor = minor;
+ gd->nodename = blktap_nodename;
gd->fops = &blktap_device_file_operations;
gd->private_data = dev;
--- head-2011-03-17.orig/drivers/xen/blktap2/sysfs.c 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/drivers/xen/blktap2/sysfs.c 2011-02-01 14:50:44.000000000 +0100
@@ -436,6 +436,12 @@ blktap_sysfs_free(void)
class_destroy(class);
}
+static char *blktap_nodename(struct device *dev)
+{
+ return kasprintf(GFP_KERNEL, BLKTAP2_DEV_DIR "blktap%u",
+ MINOR(dev->devt));
+}
+
int __init
blktap_sysfs_init(void)
{
@@ -449,6 +455,8 @@ blktap_sysfs_init(void)
if (IS_ERR(cls))
return PTR_ERR(cls);
+ cls->nodename = blktap_nodename;
+
err = class_create_file(cls, &class_attr_verbosity);
if (!err) {
err = class_create_file(cls, &class_attr_devices);
--- head-2011-03-17.orig/drivers/xen/console/console.c 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/drivers/xen/console/console.c 2011-02-01 14:50:44.000000000 +0100
@@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/console.h>
-#include <linux/bootmem.h>
#include <linux/sysrq.h>
#include <linux/screen_info.h>
#include <linux/vt.h>
@@ -236,7 +235,7 @@ static int __init xen_console_init(void)
goto out;
}
- wbuf = alloc_bootmem(wbuf_size);
+ wbuf = kmalloc(wbuf_size, GFP_KERNEL);
register_console(&kcons_info);
@@ -632,8 +631,8 @@ static void xencons_close(struct tty_str
tty->closing = 1;
tty_wait_until_sent(tty, 0);
tty_driver_flush_buffer(tty);
- if (tty->ldisc.ops->flush_buffer != NULL)
- tty->ldisc.ops->flush_buffer(tty);
+ if (tty->ldisc->ops->flush_buffer)
+ tty->ldisc->ops->flush_buffer(tty);
tty->closing = 0;
spin_lock_irqsave(&xencons_lock, flags);
xencons_tty = NULL;
--- head-2011-03-17.orig/drivers/xen/core/evtchn.c 2011-02-09 13:57:45.000000000 +0100
+++ head-2011-03-17/drivers/xen/core/evtchn.c 2011-02-01 14:50:44.000000000 +0100
@@ -35,7 +35,6 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
-#include <linux/bootmem.h>
#include <linux/ftrace.h>
#include <linux/version.h>
#include <asm/atomic.h>
@@ -138,6 +137,12 @@ static inline unsigned int type_from_irq
return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND;
}
+unsigned int irq_from_evtchn(unsigned int port)
+{
+ return evtchn_to_irq[port];
+}
+EXPORT_SYMBOL_GPL(irq_from_evtchn);
+
/* IRQ <-> VIRQ mapping. */
DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
@@ -328,6 +333,8 @@ asmlinkage void __irq_entry evtchn_do_up
}
do {
+ bool handled = false;
+
masked_l2 = l2 & ((~0UL) << l2i);
if (masked_l2 == 0)
break;
@@ -338,13 +345,12 @@ asmlinkage void __irq_entry evtchn_do_up
mask_evtchn(port);
if ((irq = evtchn_to_irq[port]) != -1) {
clear_evtchn(port);
- if (!handle_irq(irq, regs)
- && printk_ratelimit())
- pr_emerg("No handler for "
- "irq %d (port %u)\n",
- irq, port);
- } else
- evtchn_device_upcall(port);
+ handled = handle_irq(irq, regs);
+ }
+ if (!handled && printk_ratelimit())
+ pr_emerg("No handler for irq %d"
+ " (port %u)\n",
+ irq, port);
l2i = (l2i + 1) % BITS_PER_LONG;
@@ -371,16 +377,26 @@ asmlinkage void __irq_entry evtchn_do_up
set_irq_regs(old_regs);
}
-static int find_unbound_irq(unsigned int cpu, struct irq_chip *chip)
+static int find_unbound_irq(unsigned int node, struct irq_chip *chip)
{
static int warned;
int irq;
for (irq = DYNIRQ_BASE; irq < nr_irqs; irq++) {
- struct irq_desc *desc = irq_to_desc_alloc_cpu(irq, cpu);
- struct irq_cfg *cfg = desc->chip_data;
+ struct irq_desc *desc;
+ struct irq_cfg *cfg;
- if (!cfg->bindcount) {
+ desc = irq_to_desc(irq);
+ if (!desc)
+ desc = irq_to_desc_alloc_node(irq, node);
+ else if (desc->chip != &no_irq_chip &&
+ desc->chip != &dynirq_chip)
+ continue;
+ if (!desc)
+ return -ENOMEM;
+
+ cfg = desc->chip_data;
+ if (cfg && !cfg->bindcount) {
desc->status |= IRQ_NOPROBE;
set_irq_chip_and_handler_name(irq, chip,
handle_fasteoi_irq,
@@ -407,7 +423,7 @@ static int bind_caller_port_to_irq(unsig
spin_lock(&irq_mapping_update_lock);
if ((irq = evtchn_to_irq[caller_port]) == -1) {
- if ((irq = find_unbound_irq(smp_processor_id(), &dynirq_chip)) < 0)
+ if ((irq = find_unbound_irq(numa_node_id(), &dynirq_chip)) < 0)
goto out;
evtchn_to_irq[caller_port] = irq;
@@ -430,9 +446,8 @@ static int bind_local_port_to_irq(unsign
BUG_ON(evtchn_to_irq[local_port] != -1);
- if ((irq = find_unbound_irq(smp_processor_id(), &dynirq_chip)) < 0) {
- struct evtchn_close close = { .port = local_port };
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+ if ((irq = find_unbound_irq(numa_node_id(), &dynirq_chip)) < 0) {
+ if (close_evtchn(local_port))
BUG();
goto out;
}
@@ -483,7 +498,8 @@ static int bind_virq_to_irq(unsigned int
spin_lock(&irq_mapping_update_lock);
if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
- if ((irq = find_unbound_irq(cpu, &dynirq_chip)) < 0)
+ if ((irq = find_unbound_irq(cpu_to_node(cpu),
+ &dynirq_chip)) < 0)
goto out;
bind_virq.virq = virq;
@@ -516,7 +532,8 @@ static int bind_ipi_to_irq(unsigned int
spin_lock(&irq_mapping_update_lock);
if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
- if ((irq = find_unbound_irq(cpu, &dynirq_chip)) < 0)
+ if ((irq = find_unbound_irq(cpu_to_node(cpu),
+ &dynirq_chip)) < 0)
goto out;
bind_ipi.vcpu = cpu;
@@ -542,16 +559,14 @@ static int bind_ipi_to_irq(unsigned int
static void unbind_from_irq(unsigned int irq)
{
- struct evtchn_close close;
unsigned int cpu;
int evtchn = evtchn_from_irq(irq);
spin_lock(&irq_mapping_update_lock);
if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) {
- close.port = evtchn;
if ((type_from_irq(irq) != IRQT_CALLER_PORT) &&
- HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+ close_evtchn(evtchn))
BUG();
switch (type_from_irq(irq)) {
@@ -732,9 +747,11 @@ static void rebind_irq_to_cpu(unsigned i
rebind_evtchn_to_cpu(evtchn, tcpu);
}
-static void set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int set_affinity_irq(unsigned int irq, const struct cpumask *dest)
{
rebind_irq_to_cpu(irq, cpumask_first(dest));
+
+ return 0;
}
#endif
@@ -908,7 +925,6 @@ static unsigned int startup_pirq(unsigne
static void shutdown_pirq(unsigned int irq)
{
- struct evtchn_close close;
int evtchn = evtchn_from_irq(irq);
if (!VALID_EVTCHN(evtchn))
@@ -916,8 +932,7 @@ static void shutdown_pirq(unsigned int i
mask_evtchn(evtchn);
- close.port = evtchn;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+ if (close_evtchn(evtchn))
BUG();
bind_evtchn_to_cpu(evtchn, 0);
@@ -1252,7 +1267,7 @@ int evtchn_map_pirq(int irq, int xen_pir
if (irq < 0) {
#ifdef CONFIG_SPARSE_IRQ
spin_lock(&irq_mapping_update_lock);
- irq = find_unbound_irq(smp_processor_id(), &pirq_chip);
+ irq = find_unbound_irq(numa_node_id(), &pirq_chip);
if (irq >= 0) {
struct irq_desc *desc;
struct irq_cfg *cfg;
@@ -1280,7 +1295,7 @@ int evtchn_map_pirq(int irq, int xen_pir
if (identity_mapped_irq(irq))
continue;
- desc = irq_to_desc_alloc_cpu(irq, smp_processor_id());
+ desc = irq_to_desc_alloc_node(irq, numa_node_id());
cfg = desc->chip_data;
if (!index_from_irq(irq)) {
BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
@@ -1340,8 +1355,9 @@ void __init xen_init_IRQ(void)
#else
i = nr_pirqs;
#endif
- pirq_needs_eoi = alloc_bootmem_pages(sizeof(unsigned long)
- * BITS_TO_LONGS(ALIGN(i, PAGE_SIZE * 8)));
+ i = get_order(sizeof(unsigned long) * BITS_TO_LONGS(i));
+ pirq_needs_eoi = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, i);
+ BUILD_BUG_ON(NR_PIRQS > PAGE_SIZE * 8);
eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
pirq_eoi_does_unmask = true;
--- head-2011-03-17.orig/drivers/xen/core/smpboot.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/drivers/xen/core/smpboot.c 2011-02-01 14:50:44.000000000 +0100
@@ -40,9 +40,11 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
static DEFINE_PER_CPU(int, resched_irq);
static DEFINE_PER_CPU(int, callfunc_irq);
static DEFINE_PER_CPU(int, call1func_irq);
+static DEFINE_PER_CPU(int, reboot_irq);
static char resched_name[NR_CPUS][15];
static char callfunc_name[NR_CPUS][15];
static char call1func_name[NR_CPUS][15];
+static char reboot_name[NR_CPUS][15];
void __init prefill_possible_map(void)
{
@@ -74,7 +76,7 @@ static int __cpuinit xen_smp_intr_init(u
int rc;
per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) =
- per_cpu(call1func_irq, cpu) = -1;
+ per_cpu(call1func_irq, cpu) = per_cpu(reboot_irq, cpu) = -1;
sprintf(resched_name[cpu], "resched%u", cpu);
rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
@@ -109,6 +111,17 @@ static int __cpuinit xen_smp_intr_init(u
goto fail;
per_cpu(call1func_irq, cpu) = rc;
+ sprintf(reboot_name[cpu], "reboot%u", cpu);
+ rc = bind_ipi_to_irqhandler(REBOOT_VECTOR,
+ cpu,
+ smp_reboot_interrupt,
+ IRQF_DISABLED|IRQF_NOBALANCING,
+ reboot_name[cpu],
+ NULL);
+ if (rc < 0)
+ goto fail;
+ per_cpu(reboot_irq, cpu) = rc;
+
rc = xen_spinlock_init(cpu);
if (rc < 0)
goto fail;
@@ -125,6 +138,8 @@ static int __cpuinit xen_smp_intr_init(u
unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
if (per_cpu(call1func_irq, cpu) >= 0)
unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
+ if (per_cpu(reboot_irq, cpu) >= 0)
+ unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
xen_spinlock_cleanup(cpu);
return rc;
}
@@ -138,6 +153,7 @@ static void __cpuinit xen_smp_intr_exit(
unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
+ unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
xen_spinlock_cleanup(cpu);
}
#endif
--- head-2011-03-17.orig/drivers/xen/evtchn.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/drivers/xen/evtchn.c 2011-02-01 14:50:44.000000000 +0100
@@ -48,10 +48,17 @@
#include <linux/mutex.h>
#include <linux/cpu.h>
+#ifdef CONFIG_PARAVIRT_XEN
#include <xen/xen.h>
#include <xen/events.h>
#include <xen/evtchn.h>
#include <asm/xen/hypervisor.h>
+#else
+#include <xen/evtchn.h>
+#include <xen/public/evtchn.h>
+#define xen_domain() is_running_on_xen()
+#define bind_evtchn_to_irqhandler bind_caller_port_to_irqhandler
+#endif
struct per_user_data {
struct mutex bind_mutex; /* serialize bind/unbind operations */
@@ -278,6 +285,9 @@ static void evtchn_unbind_from_user(stru
int irq = irq_from_evtchn(port);
unbind_from_irqhandler(irq, (void *)(unsigned long)port);
+#ifdef CONFIG_XEN
+ WARN_ON(close_evtchn(port));
+#endif
set_port_user(port, NULL);
}
@@ -450,7 +460,8 @@ static int evtchn_open(struct inode *ino
if (u == NULL)
return -ENOMEM;
- u->name = kasprintf(GFP_KERNEL, "evtchn:%s", current->comm);
+ u->name = kasprintf(GFP_KERNEL, "evtchn:%s[%d]",
+ current->comm, current->pid);
if (u->name == NULL) {
kfree(u);
return -ENOMEM;
@@ -519,6 +530,7 @@ static const struct file_operations evtc
static struct miscdevice evtchn_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "xen/evtchn",
+ .devnode = "xen/evtchn",
.fops = &evtchn_fops,
};
static int __init evtchn_init(void)
@@ -534,10 +546,10 @@ static int __init evtchn_init(void)
spin_lock_init(&port_user_lock);
- /* Create '/dev/misc/evtchn'. */
+ /* Create '/dev/xen/evtchn'. */
err = misc_register(&evtchn_miscdev);
if (err != 0) {
- printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+ pr_alert("Could not register /dev/xen/evtchn\n");
return err;
}
--- head-2011-03-17.orig/drivers/xen/fbfront/xenfb.c 2011-02-17 10:11:23.000000000 +0100
+++ head-2011-03-17/drivers/xen/fbfront/xenfb.c 2011-02-17 10:16:12.000000000 +0100
@@ -597,7 +597,7 @@ static int __devinit xenfb_probe(struct
fb_size = XENFB_DEFAULT_FB_LEN;
}
- dev->dev.driver_data = info;
+ dev_set_drvdata(&dev->dev, info);
info->xbdev = dev;
info->irq = -1;
info->x1 = info->y1 = INT_MAX;
@@ -701,7 +701,7 @@ static int __devinit xenfb_probe(struct
static int xenfb_resume(struct xenbus_device *dev)
{
- struct xenfb_info *info = dev->dev.driver_data;
+ struct xenfb_info *info = dev_get_drvdata(&dev->dev);
xenfb_disconnect_backend(info);
xenfb_init_shared_page(info, info->fb_info);
@@ -710,7 +710,7 @@ static int xenfb_resume(struct xenbus_de
static int xenfb_remove(struct xenbus_device *dev)
{
- struct xenfb_info *info = dev->dev.driver_data;
+ struct xenfb_info *info = dev_get_drvdata(&dev->dev);
del_timer(&info->refresh);
if (info->kthread)
@@ -819,7 +819,7 @@ static void xenfb_disconnect_backend(str
static void xenfb_backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
- struct xenfb_info *info = dev->dev.driver_data;
+ struct xenfb_info *info = dev_get_drvdata(&dev->dev);
int val;
switch (backend_state) {
--- head-2011-03-17.orig/drivers/xen/fbfront/xenkbd.c 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/drivers/xen/fbfront/xenkbd.c 2011-02-01 14:50:44.000000000 +0100
@@ -113,7 +113,7 @@ int __devinit xenkbd_probe(struct xenbus
xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
return -ENOMEM;
}
- dev->dev.driver_data = info;
+ dev_set_drvdata(&dev->dev, info);
info->xbdev = dev;
snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
@@ -186,7 +186,7 @@ int __devinit xenkbd_probe(struct xenbus
static int xenkbd_resume(struct xenbus_device *dev)
{
- struct xenkbd_info *info = dev->dev.driver_data;
+ struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
xenkbd_disconnect_backend(info);
info->page->in_cons = info->page->in_prod = 0;
@@ -196,7 +196,7 @@ static int xenkbd_resume(struct xenbus_d
static int xenkbd_remove(struct xenbus_device *dev)
{
- struct xenkbd_info *info = dev->dev.driver_data;
+ struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
xenkbd_disconnect_backend(info);
input_unregister_device(info->kbd);
@@ -262,7 +262,7 @@ static void xenkbd_disconnect_backend(st
static void xenkbd_backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
- struct xenkbd_info *info = dev->dev.driver_data;
+ struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
int ret, val;
switch (backend_state) {
--- head-2011-03-17.orig/drivers/xen/gntdev/gntdev.c 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/drivers/xen/gntdev/gntdev.c 2011-02-01 14:50:44.000000000 +0100
@@ -371,10 +371,18 @@ nomem_out:
/* Interface functions. */
+static char *gntdev_nodename(struct device *dev)
+{
+ return kstrdup("xen/" GNTDEV_NAME, GFP_KERNEL);
+}
+
+static struct device_type gntdev_type = {
+ .nodename = gntdev_nodename
+};
+
/* Initialises the driver. Called when the module is loaded. */
static int __init gntdev_init(void)
{
- struct class *class;
struct device *device;
if (!is_running_on_xen()) {
@@ -393,14 +401,9 @@ static int __init gntdev_init(void)
* device, and output the major number so that the device can be
* created manually using mknod.
*/
- if ((class = get_xen_class()) == NULL) {
- pr_err("Error setting up xen_class\n");
- pr_err("gntdev created, major number = %d\n", gntdev_major);
- return 0;
- }
-
- device = device_create(class, NULL, MKDEV(gntdev_major, 0),
- NULL, GNTDEV_NAME);
+ device = xen_class_device_create(&gntdev_type, NULL,
+ MKDEV(gntdev_major, 0),
+ NULL, GNTDEV_NAME);
if (IS_ERR(device)) {
pr_err("Error creating gntdev device in xen_class\n");
pr_err("gntdev created, major number = %d\n", gntdev_major);
--- head-2011-03-17.orig/drivers/xen/netback/accel.c 2011-01-31 17:29:16.000000000 +0100
+++ head-2011-03-17/drivers/xen/netback/accel.c 2011-02-01 14:50:44.000000000 +0100
@@ -103,7 +103,7 @@ static int netback_accelerator_probe_bac
struct xenbus_device *xendev = to_xenbus_device(dev);
if (!strcmp("vif", xendev->devicetype)) {
- struct backend_info *be = xendev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&xendev->dev);
if (match_accelerator(xendev, be, accelerator) &&
try_module_get(accelerator->hooks->owner)) {
@@ -124,7 +124,7 @@ static int netback_accelerator_remove_ba
(struct netback_accelerator *)arg;
if (!strcmp("vif", xendev->devicetype)) {
- struct backend_info *be = xendev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&xendev->dev);
if (be->accelerator == accelerator) {
be->accelerator->hooks->remove(xendev);
--- head-2011-03-17.orig/drivers/xen/netback/loopback.c 2011-03-01 11:52:05.000000000 +0100
+++ head-2011-03-17/drivers/xen/netback/loopback.c 2011-02-01 14:50:44.000000000 +0100
@@ -139,8 +139,8 @@ static int loopback_start_xmit(struct sk
return 0;
}
- dst_release(skb->dst);
- skb->dst = NULL;
+ dst_release(skb_dst(skb));
+ skb_dst_set(skb, NULL);
skb_orphan(skb);
--- head-2011-03-17.orig/drivers/xen/netback/xenbus.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/netback/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -38,7 +38,7 @@ static void netback_disconnect(struct de
static int netback_remove(struct xenbus_device *dev)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
netback_remove_accelerators(be, dev);
@@ -49,7 +49,7 @@ static int netback_remove(struct xenbus_
static void netback_disconnect(struct device *xbdev_dev, int clear)
{
- struct backend_info *be = xbdev_dev->driver_data;
+ struct backend_info *be = dev_get_drvdata(xbdev_dev);
if (be->netif)
kobject_uevent(&xbdev_dev->kobj, KOBJ_OFFLINE);
@@ -60,7 +60,7 @@ static void netback_disconnect(struct de
be->netif = NULL;
}
if (clear)
- xbdev_dev->driver_data = NULL;
+ dev_set_drvdata(xbdev_dev, NULL);
up_write(&teardown_sem);
}
@@ -84,7 +84,7 @@ static int netback_probe(struct xenbus_d
}
be->dev = dev;
- dev->dev.driver_data = be;
+ dev_set_drvdata(&dev->dev, be);
sg = 1;
if (netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB)
@@ -181,7 +181,7 @@ static int netback_uevent(struct xenbus_
kfree(val);
down_read(&teardown_sem);
- be = xdev->dev.driver_data;
+ be = dev_get_drvdata(&xdev->dev);
if (be && be->netif)
add_uevent_var(env, "vif=%s", be->netif->dev->name);
up_read(&teardown_sem);
@@ -224,7 +224,7 @@ static void backend_create_netif(struct
static void frontend_changed(struct xenbus_device *dev,
enum xenbus_state frontend_state)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
DPRINTK("%s", xenbus_strstate(frontend_state));
--- head-2011-03-17.orig/drivers/xen/netfront/netfront.c 2011-02-09 16:04:51.000000000 +0100
+++ head-2011-03-17/drivers/xen/netfront/netfront.c 2011-02-01 14:50:44.000000000 +0100
@@ -256,7 +256,7 @@ static int __devinit netfront_probe(stru
}
info = netdev_priv(netdev);
- dev->dev.driver_data = info;
+ dev_set_drvdata(&dev->dev, info);
err = register_netdev(info->netdev);
if (err) {
@@ -277,13 +277,13 @@ static int __devinit netfront_probe(stru
fail:
free_netdev(netdev);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return err;
}
static int __devexit netfront_remove(struct xenbus_device *dev)
{
- struct netfront_info *info = dev->dev.driver_data;
+ struct netfront_info *info = dev_get_drvdata(&dev->dev);
DPRINTK("%s\n", dev->nodename);
@@ -305,14 +305,14 @@ static int __devexit netfront_remove(str
static int netfront_suspend(struct xenbus_device *dev)
{
- struct netfront_info *info = dev->dev.driver_data;
+ struct netfront_info *info = dev_get_drvdata(&dev->dev);
return netfront_accelerator_suspend(info, dev);
}
static int netfront_suspend_cancel(struct xenbus_device *dev)
{
- struct netfront_info *info = dev->dev.driver_data;
+ struct netfront_info *info = dev_get_drvdata(&dev->dev);
return netfront_accelerator_suspend_cancel(info, dev);
}
@@ -325,7 +325,7 @@ static int netfront_suspend_cancel(struc
*/
static int netfront_resume(struct xenbus_device *dev)
{
- struct netfront_info *info = dev->dev.driver_data;
+ struct netfront_info *info = dev_get_drvdata(&dev->dev);
DPRINTK("%s\n", dev->nodename);
@@ -530,7 +530,7 @@ static int setup_device(struct xenbus_de
static void backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
- struct netfront_info *np = dev->dev.driver_data;
+ struct netfront_info *np = dev_get_drvdata(&dev->dev);
struct net_device *netdev = np->netdev;
DPRINTK("%s\n", xenbus_strstate(backend_state));
--- head-2011-03-17.orig/drivers/xen/pciback/xenbus.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/pciback/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -24,7 +24,7 @@ static struct pciback_device *alloc_pdev
dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
pdev->xdev = xdev;
- xdev->dev.driver_data = pdev;
+ dev_set_drvdata(&xdev->dev, pdev);
spin_lock_init(&pdev->dev_lock);
@@ -74,7 +74,7 @@ static void free_pdev(struct pciback_dev
pciback_release_devices(pdev);
- pdev->xdev->dev.driver_data = NULL;
+ dev_set_drvdata(&pdev->xdev->dev, NULL);
pdev->xdev = NULL;
kfree(pdev);
@@ -475,7 +475,7 @@ static int pciback_reconfigure(struct pc
static void pciback_frontend_changed(struct xenbus_device *xdev,
enum xenbus_state fe_state)
{
- struct pciback_device *pdev = xdev->dev.driver_data;
+ struct pciback_device *pdev = dev_get_drvdata(&xdev->dev);
dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
@@ -668,7 +668,7 @@ static int pciback_xenbus_probe(struct x
static int pciback_xenbus_remove(struct xenbus_device *dev)
{
- struct pciback_device *pdev = dev->dev.driver_data;
+ struct pciback_device *pdev = dev_get_drvdata(&dev->dev);
if (pdev != NULL)
free_pdev(pdev);
--- head-2011-03-17.orig/drivers/xen/pcifront/pci_op.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/pcifront/pci_op.c 2011-02-01 14:50:44.000000000 +0100
@@ -416,7 +416,7 @@ void pci_frontend_disable_msi(struct pci
#endif /* CONFIG_PCI_MSI */
/* Claim resources for the PCI frontend as-is, backend won't allow changes */
-static void pcifront_claim_resource(struct pci_dev *dev, void *data)
+static int pcifront_claim_resource(struct pci_dev *dev, void *data)
{
struct pcifront_device *pdev = data;
int i;
@@ -431,6 +431,8 @@ static void pcifront_claim_resource(stru
pci_claim_resource(dev, i);
}
}
+
+ return 0;
}
int __devinit pcifront_scan_root(struct pcifront_device *pdev,
--- head-2011-03-17.orig/drivers/xen/pcifront/xenbus.c 2011-01-31 17:32:29.000000000 +0100
+++ head-2011-03-17/drivers/xen/pcifront/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -34,7 +34,7 @@ static struct pcifront_device *alloc_pde
/*Flag for registering PV AER handler*/
set_bit(_XEN_PCIB_AERHANDLER, (void*)&pdev->sh_info->flags);
- xdev->dev.driver_data = pdev;
+ dev_set_drvdata(&xdev->dev, pdev);
pdev->xdev = xdev;
INIT_LIST_HEAD(&pdev->root_buses);
@@ -75,7 +75,7 @@ static void free_pdev(struct pcifront_de
else
free_page((unsigned long)pdev->sh_info);
- pdev->xdev->dev.driver_data = NULL;
+ dev_set_drvdata(&pdev->xdev->dev, NULL);
kfree(pdev);
}
@@ -394,7 +394,7 @@ static int pcifront_detach_devices(struc
static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
enum xenbus_state be_state)
{
- struct pcifront_device *pdev = xdev->dev.driver_data;
+ struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
switch (be_state) {
case XenbusStateUnknown:
@@ -446,8 +446,8 @@ static int pcifront_xenbus_probe(struct
static int pcifront_xenbus_remove(struct xenbus_device *xdev)
{
- if (xdev->dev.driver_data)
- free_pdev(xdev->dev.driver_data);
+ if (dev_get_drvdata(&xdev->dev))
+ free_pdev(dev_get_drvdata(&xdev->dev));
return 0;
}
--- head-2011-03-17.orig/drivers/xen/scsiback/scsiback.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/scsiback/scsiback.c 2011-02-01 14:50:44.000000000 +0100
@@ -224,7 +224,7 @@ static void scsiback_cmd_done(struct req
int errors;
sense_buffer = req->sense;
- resid = req->data_len;
+ resid = blk_rq_bytes(req);
errors = req->errors;
if (errors != 0) {
@@ -331,21 +331,6 @@ fail_flush:
return -ENOMEM;
}
-/* quoted scsi_lib.c/scsi_merge_bio */
-static int scsiback_merge_bio(struct request *rq, struct bio *bio)
-{
- struct request_queue *q = rq->q;
-
- bio->bi_flags &= ~(1 << BIO_SEG_VALID);
- if (rq_data_dir(rq) == WRITE)
- bio->bi_rw |= (1 << BIO_RW);
-
- blk_queue_bounce(q, &bio);
-
- return blk_rq_append_bio(q, rq, bio);
-}
-
-
/* quoted scsi_lib.c/scsi_bi_endio */
static void scsiback_bi_endio(struct bio *bio, int error)
{
@@ -355,29 +340,28 @@ static void scsiback_bi_endio(struct bio
/* quoted scsi_lib.c/scsi_req_map_sg . */
-static int request_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count)
+static struct bio *request_map_sg(pending_req_t *pending_req)
{
- struct request_queue *q = rq->q;
- int nr_pages;
- unsigned int nsegs = count;
- unsigned int data_len = 0, len, bytes, off;
+ struct request_queue *q = pending_req->sdev->request_queue;
+ unsigned int nsegs = (unsigned int)pending_req->nr_segments;
+ unsigned int i, len, bytes, off, nr_pages, nr_vecs = 0;
struct scatterlist *sg;
struct page *page;
- struct bio *bio = NULL;
- int i, err, nr_vecs = 0;
+ struct bio *bio = NULL, *bio_first = NULL, *bio_last = NULL;
+ int err;
for_each_sg (pending_req->sgl, sg, nsegs, i) {
page = sg_page(sg);
off = sg->offset;
len = sg->length;
- data_len += len;
nr_pages = (len + off + PAGE_SIZE - 1) >> PAGE_SHIFT;
while (len > 0) {
bytes = min_t(unsigned int, len, PAGE_SIZE - off);
if (!bio) {
- nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
+ nr_vecs = min_t(unsigned int, BIO_MAX_PAGES,
+ nr_pages);
nr_pages -= nr_vecs;
bio = bio_alloc(GFP_KERNEL, nr_vecs);
if (!bio) {
@@ -385,6 +369,11 @@ static int request_map_sg(struct request
goto free_bios;
}
bio->bi_end_io = scsiback_bi_endio;
+ if (bio_last)
+ bio_last->bi_next = bio;
+ else
+ bio_first = bio;
+ bio_last = bio;
}
if (bio_add_pc_page(q, bio, page, bytes, off) !=
@@ -395,11 +384,9 @@ static int request_map_sg(struct request
}
if (bio->bi_vcnt >= nr_vecs) {
- err = scsiback_merge_bio(rq, bio);
- if (err) {
- bio_endio(bio, 0);
- goto free_bios;
- }
+ bio->bi_flags &= ~(1 << BIO_SEG_VALID);
+ if (pending_req->sc_data_direction == WRITE)
+ bio->bi_rw |= (1 << BIO_RW);
bio = NULL;
}
@@ -409,21 +396,15 @@ static int request_map_sg(struct request
}
}
- rq->buffer = rq->data = NULL;
- rq->data_len = data_len;
-
- return 0;
+ return bio_first;
free_bios:
- while ((bio = rq->bio) != NULL) {
- rq->bio = bio->bi_next;
- /*
- * call endio instead of bio_put incase it was bounced
- */
- bio_endio(bio, 0);
+ while ((bio = bio_first) != NULL) {
+ bio_first = bio->bi_next;
+ bio_put(bio);
}
- return err;
+ return ERR_PTR(err);
}
@@ -431,7 +412,6 @@ void scsiback_cmd_exec(pending_req_t *pe
{
int cmd_len = (int)pending_req->cmd_len;
int data_dir = (int)pending_req->sc_data_direction;
- unsigned int nr_segments = (unsigned int)pending_req->nr_segments;
unsigned int timeout;
struct request *rq;
int write;
@@ -445,7 +425,30 @@ void scsiback_cmd_exec(pending_req_t *pe
timeout = VSCSIIF_TIMEOUT;
write = (data_dir == DMA_TO_DEVICE);
- rq = blk_get_request(pending_req->sdev->request_queue, write, GFP_KERNEL);
+ if (pending_req->nr_segments) {
+ struct bio *bio = request_map_sg(pending_req);
+
+ if (IS_ERR(bio)) {
+ pr_err("scsiback: SG Request Map Error\n");
+ return;
+ }
+
+ rq = blk_make_request(pending_req->sdev->request_queue, bio,
+ GFP_KERNEL);
+ if (IS_ERR(rq)) {
+ pr_err("scsiback: Make Request Error\n");
+ return;
+ }
+
+ rq->buffer = NULL;
+ } else {
+ rq = blk_get_request(pending_req->sdev->request_queue, write,
+ GFP_KERNEL);
+ if (unlikely(!rq)) {
+ pr_err("scsiback: Get Request Error\n");
+ return;
+ }
+ }
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->cmd_len = cmd_len;
@@ -460,14 +463,6 @@ void scsiback_cmd_exec(pending_req_t *pe
rq->timeout = timeout;
rq->end_io_data = pending_req;
- if (nr_segments) {
-
- if (request_map_sg(rq, pending_req, nr_segments)) {
- pr_err("scsiback: SG Request Map Error\n");
- return;
- }
- }
-
scsiback_get(pending_req->info);
blk_execute_rq_nowait(rq->q, NULL, rq, 1, scsiback_cmd_done);
--- head-2011-03-17.orig/drivers/xen/scsiback/xenbus.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/scsiback/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -226,7 +226,7 @@ static void scsiback_do_lun_hotplug(stru
static void scsiback_frontend_changed(struct xenbus_device *dev,
enum xenbus_state frontend_state)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
int err;
switch (frontend_state) {
@@ -283,7 +283,7 @@ static void scsiback_frontend_changed(st
static int scsiback_remove(struct xenbus_device *dev)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
if (be->info) {
scsiback_disconnect(be->info);
@@ -293,7 +293,7 @@ static int scsiback_remove(struct xenbus
}
kfree(be);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
@@ -316,7 +316,7 @@ static int scsiback_probe(struct xenbus_
return -ENOMEM;
}
be->dev = dev;
- dev->dev.driver_data = be;
+ dev_set_drvdata(&dev->dev, be);
be->info = vscsibk_info_alloc(dev->otherend_id);
if (IS_ERR(be->info)) {
--- head-2011-03-17.orig/drivers/xen/scsifront/xenbus.c 2011-02-08 10:04:06.000000000 +0100
+++ head-2011-03-17/drivers/xen/scsifront/xenbus.c 2011-02-08 10:05:30.000000000 +0100
@@ -189,7 +189,7 @@ static int scsifront_probe(struct xenbus
info->host = host;
- dev->dev.driver_data = info;
+ dev_set_drvdata(&dev->dev, info);
info->dev = dev;
for (i = 0; i < VSCSIIF_MAX_REQS; i++) {
@@ -243,7 +243,7 @@ free_sring:
static int scsifront_remove(struct xenbus_device *dev)
{
- struct vscsifrnt_info *info = dev->dev.driver_data;
+ struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename);
@@ -355,7 +355,7 @@ static void scsifront_do_lun_hotplug(str
static void scsifront_backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
- struct vscsifrnt_info *info = dev->dev.driver_data;
+ struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
DPRINTK("%p %u %u\n", dev, dev->state, backend_state);
--- head-2011-03-17.orig/drivers/xen/sfc_netback/accel_xenbus.c 2011-01-31 17:29:16.000000000 +0100
+++ head-2011-03-17/drivers/xen/sfc_netback/accel_xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -36,7 +36,7 @@
#define NODENAME_PATH_FMT "backend/vif/%d/%d"
#define NETBACK_ACCEL_FROM_XENBUS_DEVICE(_dev) (struct netback_accel *) \
- ((struct backend_info *)(_dev)->dev.driver_data)->netback_accel_priv
+ ((struct backend_info *)dev_get_drvdata(&(_dev)->dev))->netback_accel_priv
/* List of all the bends currently in existence. */
struct netback_accel *bend_list = NULL;
@@ -615,7 +615,7 @@ int netback_accel_probe(struct xenbus_de
mutex_lock(&bend->bend_mutex);
/* ...and store it where we can get at it */
- binfo = (struct backend_info *) dev->dev.driver_data;
+ binfo = dev_get_drvdata(&dev->dev);
binfo->netback_accel_priv = bend;
/* And vice-versa */
bend->hdev_data = dev;
@@ -729,7 +729,7 @@ int netback_accel_remove(struct xenbus_d
struct netback_accel *bend;
int frontend_state;
- binfo = (struct backend_info *) dev->dev.driver_data;
+ binfo = dev_get_drvdata(&dev->dev);
bend = (struct netback_accel *) binfo->netback_accel_priv;
DPRINTK("%s: dev %p bend %p\n", __FUNCTION__, dev, bend);
--- head-2011-03-17.orig/drivers/xen/sfc_netfront/accel_xenbus.c 2011-01-31 17:32:29.000000000 +0100
+++ head-2011-03-17/drivers/xen/sfc_netfront/accel_xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -727,8 +727,7 @@ int netfront_accel_probe(struct net_devi
int netfront_accel_remove(struct xenbus_device *dev)
{
- struct netfront_info *np =
- (struct netfront_info *)dev->dev.driver_data;
+ struct netfront_info *np = dev_get_drvdata(&dev->dev);
netfront_accel_vnic *vnic = (netfront_accel_vnic *)np->accel_priv;
DPRINTK("%s %s\n", __FUNCTION__, dev->nodename);
--- head-2011-03-17.orig/drivers/xen/sys-hypervisor.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/drivers/xen/sys-hypervisor.c 2011-02-01 14:50:44.000000000 +0100
@@ -20,6 +20,8 @@
#include <xen/interface/xen.h>
#include <xen/interface/version.h>
+#include "xenbus/xenbus_comms.h"
+
#define HYPERVISOR_ATTR_RO(_name) \
static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
@@ -118,9 +120,8 @@ static ssize_t uuid_show(struct hyp_sysf
{
char *vm, *val;
int ret;
- extern int xenstored_ready;
- if (!xenstored_ready)
+ if (!is_xenstored_ready())
return -EBUSY;
vm = xenbus_read(XBT_NIL, "vm", "", NULL);
--- head-2011-03-17.orig/drivers/xen/tpmback/xenbus.c 2011-01-31 17:32:22.000000000 +0100
+++ head-2011-03-17/drivers/xen/tpmback/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -54,7 +54,7 @@ long int tpmback_get_instance(struct bac
static int tpmback_remove(struct xenbus_device *dev)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
if (!be) return 0;
@@ -70,7 +70,7 @@ static int tpmback_remove(struct xenbus_
be->tpmif = NULL;
}
kfree(be);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
@@ -89,7 +89,7 @@ static int tpmback_probe(struct xenbus_d
be->is_instance_set = 0;
be->dev = dev;
- dev->dev.driver_data = be;
+ dev_set_drvdata(&dev->dev, be);
err = xenbus_watch_path2(dev, dev->nodename,
"instance", &be->backend_watch,
@@ -139,7 +139,7 @@ static void backend_changed(struct xenbu
static void frontend_changed(struct xenbus_device *dev,
enum xenbus_state frontend_state)
{
- struct backend_info *be = dev->dev.driver_data;
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
int err;
switch (frontend_state) {
--- head-2011-03-17.orig/drivers/xen/usbback/usbback.h 2011-01-31 17:49:31.000000000 +0100
+++ head-2011-03-17/drivers/xen/usbback/usbback.h 2011-02-01 14:50:44.000000000 +0100
@@ -63,6 +63,12 @@
struct usbstub;
+#ifndef BUS_ID_SIZE
+#define USBBACK_BUS_ID_SIZE 20
+#else
+#define USBBACK_BUS_ID_SIZE BUS_ID_SIZE
+#endif
+
#define USB_DEV_ADDR_SIZE 128
typedef struct usbif_st {
@@ -110,7 +116,7 @@ typedef struct usbif_st {
struct vusb_port_id {
struct list_head id_list;
- char phys_bus[BUS_ID_SIZE];
+ char phys_bus[USBBACK_BUS_ID_SIZE];
domid_t domid;
unsigned int handle;
int portnum;
--- head-2011-03-17.orig/drivers/xen/usbback/usbstub.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/drivers/xen/usbback/usbstub.c 2011-02-01 14:50:44.000000000 +0100
@@ -56,7 +56,7 @@ struct vusb_port_id *find_portid_by_busi
spin_lock_irqsave(&port_list_lock, flags);
list_for_each_entry(portid, &port_list, id_list) {
- if (!(strncmp(portid->phys_bus, busid, BUS_ID_SIZE))) {
+ if (!(strncmp(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE))) {
found = 1;
break;
}
@@ -110,7 +110,7 @@ int portid_add(const char *busid,
portid->handle = handle;
portid->portnum = portnum;
- strncpy(portid->phys_bus, busid, BUS_ID_SIZE);
+ strncpy(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE);
spin_lock_irqsave(&port_list_lock, flags);
list_add(&portid->id_list, &port_list);
@@ -228,7 +228,7 @@ static int usbstub_probe(struct usb_inte
usbbk_hotplug_notify(usbif, portid->portnum, udev->speed);
} else {
/* maybe already called and connected by other intf */
- if (strncmp(stub->portid->phys_bus, busid, BUS_ID_SIZE))
+ if (strncmp(stub->portid->phys_bus, busid, USBBACK_BUS_ID_SIZE))
goto out; /* invalid call */
}
--- head-2011-03-17.orig/drivers/xen/usbback/xenbus.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/usbback/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -112,7 +112,7 @@ again:
*/
portid = find_portid(usbif->domid, usbif->handle, i);
if (portid) {
- if ((strncmp(portid->phys_bus, busid, BUS_ID_SIZE)))
+ if ((strncmp(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE)))
xenbus_dev_fatal(dev, err,
"can't add port/%d, remove first", i);
else
@@ -142,7 +142,7 @@ abort:
static int usbback_remove(struct xenbus_device *dev)
{
- usbif_t *usbif = dev->dev.driver_data;
+ usbif_t *usbif = dev_get_drvdata(&dev->dev);
int i;
if (usbif->backend_watch.node) {
@@ -158,7 +158,7 @@ static int usbback_remove(struct xenbus_
usbif_disconnect(usbif);
usbif_free(usbif);;
}
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
@@ -182,7 +182,7 @@ static int usbback_probe(struct xenbus_d
return -ENOMEM;
}
usbif->xbdev = dev;
- dev->dev.driver_data = usbif;
+ dev_set_drvdata(&dev->dev, usbif);
err = xenbus_scanf(XBT_NIL, dev->nodename,
"num-ports", "%d", &num_ports);
@@ -260,7 +260,7 @@ static int connect_rings(usbif_t *usbif)
static void frontend_changed(struct xenbus_device *dev,
enum xenbus_state frontend_state)
{
- usbif_t *usbif = dev->dev.driver_data;
+ usbif_t *usbif = dev_get_drvdata(&dev->dev);
int err;
switch (frontend_state) {
--- head-2011-03-17.orig/drivers/xen/usbfront/xenbus.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/drivers/xen/usbfront/xenbus.c 2011-02-01 14:50:44.000000000 +0100
@@ -187,7 +187,7 @@ out:
static int connect(struct xenbus_device *dev)
{
- struct usbfront_info *info = dev->dev.driver_data;
+ struct usbfront_info *info = dev_get_drvdata(&dev->dev);
usbif_conn_request_t *req;
int i, idx, err;
@@ -299,7 +299,7 @@ static int usbfront_probe(struct xenbus_
}
info = hcd_to_info(hcd);
- dev->dev.driver_data = info;
+ dev_set_drvdata(&dev->dev, info);
err = usb_add_hcd(hcd, 0, 0);
if (err != 0) {
@@ -314,13 +314,13 @@ static int usbfront_probe(struct xenbus_
fail:
usb_put_hcd(hcd);
- dev->dev.driver_data = NULL;
+ dev_set_drvdata(&dev->dev, NULL);
return err;
}
static void usbfront_disconnect(struct xenbus_device *dev)
{
- struct usbfront_info *info = dev->dev.driver_data;
+ struct usbfront_info *info = dev_get_drvdata(&dev->dev);
struct usb_hcd *hcd = info_to_hcd(info);
usb_remove_hcd(hcd);
@@ -364,7 +364,7 @@ static void backend_changed(struct xenbu
static int usbfront_remove(struct xenbus_device *dev)
{
- struct usbfront_info *info = dev->dev.driver_data;
+ struct usbfront_info *info = dev_get_drvdata(&dev->dev);
struct usb_hcd *hcd = info_to_hcd(info);
destroy_rings(info);
--- head-2011-03-17.orig/drivers/xen/util.c 2011-01-31 17:56:27.000000000 +0100
+++ head-2011-03-17/drivers/xen/util.c 2011-02-01 14:50:44.000000000 +0100
@@ -1,20 +1,74 @@
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
#include <xen/driver_util.h>
-struct class *get_xen_class(void)
+static struct class *_get_xen_class(void)
{
static struct class *xen_class;
+ static DEFINE_MUTEX(xc_mutex);
- if (xen_class)
- return xen_class;
-
- xen_class = class_create(THIS_MODULE, "xen");
- if (IS_ERR(xen_class)) {
+ mutex_lock(&xc_mutex);
+ if (IS_ERR_OR_NULL(xen_class))
+ xen_class = class_create(THIS_MODULE, "xen");
+ mutex_unlock(&xc_mutex);
+ if (IS_ERR(xen_class))
pr_err("failed to create xen sysfs class\n");
- xen_class = NULL;
- }
return xen_class;
}
+
+struct class *get_xen_class(void)
+{
+ struct class *class = _get_xen_class();
+
+ return !IS_ERR(class) ? class : NULL;
+}
EXPORT_SYMBOL_GPL(get_xen_class);
+
+static void xcdev_release(struct device *dev)
+{
+ kfree(dev);
+}
+
+struct device *xen_class_device_create(struct device_type *type,
+ struct device *parent,
+ dev_t devt, void *drvdata,
+ const char *fmt, ...)
+{
+ struct device *dev;
+ int err;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev) {
+ va_list vargs;
+
+ va_start(vargs, fmt);
+ err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
+ va_end(vargs);
+ } else
+ err = -ENOMEM;
+
+ if (!err) {
+ dev->devt = devt;
+ dev->class = _get_xen_class();
+ if (IS_ERR(dev->class))
+ err = PTR_ERR(dev->class);
+ }
+
+ if (!err) {
+ dev->type = type;
+ dev->parent = parent;
+ dev_set_drvdata(dev, drvdata);
+ dev->release = xcdev_release;
+ err = device_register(dev);
+ if (!err)
+ return dev;
+ put_device(dev);
+ } else
+ kfree(dev);
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(xen_class_device_create);
--- head-2011-03-17.orig/drivers/xen/xenbus/xenbus_probe.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/drivers/xen/xenbus/xenbus_probe.c 2011-02-01 14:50:44.000000000 +0100
@@ -92,6 +92,11 @@ static int xenbus_probe_frontend(const c
static void xenbus_dev_shutdown(struct device *_dev);
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+static int xenbus_dev_suspend(struct device *dev, pm_message_t state);
+static int xenbus_dev_resume(struct device *dev);
+#endif
+
/* If something in array of ids matches this device, return it. */
static const struct xenbus_device_id *
match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
@@ -228,6 +233,10 @@ static struct xen_bus_type xenbus_fronte
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
.dev_attrs = xenbus_dev_attrs,
#endif
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+ .suspend = xenbus_dev_suspend,
+ .resume = xenbus_dev_resume,
+#endif
},
#if defined(CONFIG_XEN) || defined(MODULE)
.dev = {
@@ -767,6 +776,9 @@ void xenbus_dev_changed(const char *node
kfree(root);
}
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+EXPORT_SYMBOL_GPL(xenbus_dev_changed);
+#endif
static void frontend_changed(struct xenbus_watch *watch,
const char **vec, unsigned int len)
@@ -782,7 +794,11 @@ static struct xenbus_watch fe_watch = {
.callback = frontend_changed,
};
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
+#else
static int suspend_dev(struct device *dev, void *data)
+#endif
{
int err = 0;
struct xenbus_driver *drv;
@@ -795,13 +811,18 @@ static int suspend_dev(struct device *de
drv = to_xenbus_driver(dev->driver);
xdev = container_of(dev, struct xenbus_device, dev);
if (drv->suspend)
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+ err = drv->suspend(xdev, state);
+#else
err = drv->suspend(xdev);
+#endif
if (err)
pr_warning("xenbus: suspend %s failed: %i\n",
dev_name(dev), err);
return 0;
}
+#if defined(CONFIG_XEN) || defined(MODULE)
static int suspend_cancel_dev(struct device *dev, void *data)
{
int err = 0;
@@ -821,8 +842,13 @@ static int suspend_cancel_dev(struct dev
dev_name(dev), err);
return 0;
}
+#endif
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+static int xenbus_dev_resume(struct device *dev)
+#else
static int resume_dev(struct device *dev, void *data)
+#endif
{
int err;
struct xenbus_driver *drv;
@@ -864,6 +890,7 @@ static int resume_dev(struct device *dev
return 0;
}
+#if defined(CONFIG_XEN) || defined(MODULE)
void xenbus_suspend(void)
{
DPRINTK("");
@@ -893,6 +920,7 @@ void xenbus_suspend_cancel(void)
xenbus_backend_resume(suspend_cancel_dev);
}
EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
+#endif
/* A flag to determine if xenstored is 'ready' (i.e. has started) */
atomic_t xenbus_xsd_state = ATOMIC_INIT(XENBUS_XSD_UNCOMMITTED);
@@ -995,13 +1023,6 @@ static int xsd_port_read(char *page, cha
#endif
#if defined(CONFIG_XEN_XENBUS_DEV) || defined(MODULE)
-static int xb_free_port(evtchn_port_t port)
-{
- struct evtchn_close close;
- close.port = port;
- return HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
-}
-
int xenbus_conn(domid_t remote_dom, unsigned long *grant_ref, evtchn_port_t *local_port)
{
struct evtchn_alloc_unbound alloc_unbound;
@@ -1015,7 +1036,7 @@ int xenbus_conn(domid_t remote_dom, unsi
remove_xen_proc_entry("xsd_port");
#endif
- rc = xb_free_port(xen_store_evtchn);
+ rc = close_evtchn(xen_store_evtchn);
if (rc != 0)
goto fail0;
@@ -1041,7 +1062,7 @@ int xenbus_conn(domid_t remote_dom, unsi
return 0;
fail1:
- rc2 = xb_free_port(xen_store_evtchn);
+ rc2 = close_evtchn(xen_store_evtchn);
if (rc2 != 0)
pr_warning("XENBUS: Error freeing xenstore event channel:"
" %d\n", rc2);
--- head-2011-03-17.orig/drivers/xen/xenbus/xenbus_xs.c 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/drivers/xen/xenbus/xenbus_xs.c 2011-02-01 14:50:44.000000000 +0100
@@ -718,6 +718,10 @@ void xs_resume(void)
struct xenbus_watch *watch;
char token[sizeof(watch) * 2 + 1];
+#if !defined(CONFIG_XEN) && !defined(MODULE)
+ xb_init_comms();
+#endif
+
mutex_unlock(&xs_state.response_mutex);
mutex_unlock(&xs_state.request_mutex);
transaction_resume();
--- head-2011-03-17.orig/include/Kbuild 2011-02-01 14:38:38.000000000 +0100
+++ head-2011-03-17/include/Kbuild 2011-02-01 14:50:44.000000000 +0100
@@ -8,6 +8,5 @@ header-y += mtd/
header-y += rdma/
header-y += video/
header-y += drm/
-header-y += xen/public/
header-y += xen/
header-y += scsi/
--- head-2011-03-17.orig/include/xen/Kbuild 2011-01-31 14:31:28.000000000 +0100
+++ head-2011-03-17/include/xen/Kbuild 2011-02-01 14:50:44.000000000 +0100
@@ -1,3 +1,2 @@
-header-y += evtchn.h
header-y += privcmd.h
header-y += public/
--- head-2011-03-17.orig/include/xen/driver_util.h 2011-01-31 17:49:31.000000000 +0100
+++ head-2011-03-17/include/xen/driver_util.h 2011-02-01 14:50:44.000000000 +0100
@@ -1,8 +1,14 @@
#ifndef __XEN_DRIVER_UTIL_H__
#define __XEN_DRIVER_UTIL_H__
+#include <linux/compiler.h>
#include <linux/device.h>
extern struct class *get_xen_class(void);
+extern struct device *xen_class_device_create(struct device_type *,
+ struct device *parent,
+ dev_t devt, void *drvdata,
+ const char *fmt, ...)
+ __printf(5, 6);
#endif /* __XEN_DRIVER_UTIL_H__ */
--- head-2011-03-17.orig/include/xen/evtchn.h 2011-02-01 14:42:26.000000000 +0100
+++ head-2011-03-17/include/xen/evtchn.h 2011-02-01 14:50:44.000000000 +0100
@@ -113,9 +113,6 @@ void irq_resume(void);
/* Entry point for notifications into Linux subsystems. */
asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
-/* Entry point for notifications into the userland character device. */
-void evtchn_device_upcall(int port);
-
/* Mark a PIRQ as unavailable for dynamic allocation. */
void evtchn_register_pirq(int irq);
/* Map a Xen-supplied PIRQ to a dynamically allocated one. */
@@ -126,6 +123,7 @@ int evtchn_get_xen_pirq(int irq);
void mask_evtchn(int port);
void disable_all_local_evtchn(void);
void unmask_evtchn(int port);
+unsigned int irq_from_evtchn(unsigned int port);
#ifdef CONFIG_SMP
void rebind_evtchn_to_cpu(int port, unsigned int cpu);
@@ -163,6 +161,12 @@ static inline void notify_remote_via_evt
VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send));
}
+static inline int close_evtchn(int port)
+{
+ struct evtchn_close close = { .port = port };
+ return HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+}
+
/*
* Use these to access the event channel underlying the IRQ handle returned
* by bind_*_to_irqhandler().
--- head-2011-03-17.orig/include/xen/xenbus.h 2011-02-02 16:58:42.000000000 +0100
+++ head-2011-03-17/include/xen/xenbus.h 2011-02-02 16:59:07.000000000 +0100
@@ -104,8 +104,12 @@ struct xenbus_driver {
void (*otherend_changed)(struct xenbus_device *dev,
enum xenbus_state backend_state);
int (*remove)(struct xenbus_device *dev);
+#if !defined(CONFIG_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H)
+ int (*suspend)(struct xenbus_device *dev, pm_message_t state);
+#else
int (*suspend)(struct xenbus_device *dev);
int (*suspend_cancel)(struct xenbus_device *dev);
+#endif
int (*resume)(struct xenbus_device *dev);
int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *);
struct device_driver driver;
--- head-2011-03-17.orig/lib/swiotlb-xen.c 2011-02-01 14:44:12.000000000 +0100
+++ head-2011-03-17/lib/swiotlb-xen.c 2011-02-01 14:50:44.000000000 +0100
@@ -47,8 +47,8 @@ int swiotlb;
int swiotlb_force;
/*
- * Used to do a quick range check in swiotlb_unmap_single and
- * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
+ * Used to do a quick range check in unmap_single and
+ * sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
static char *io_tlb_start, *io_tlb_end;
@@ -167,7 +167,7 @@ dma_addr_t swiotlb_phys_to_bus(struct de
return phys_to_machine(paddr);
}
-phys_addr_t swiotlb_bus_to_phys(dma_addr_t baddr)
+phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
{
return machine_to_phys(baddr);
}
@@ -178,9 +178,15 @@ static dma_addr_t swiotlb_virt_to_bus(st
return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
}
-static void *swiotlb_bus_to_virt(dma_addr_t address)
+void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
{
- return phys_to_virt(swiotlb_bus_to_phys(address));
+ return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
+}
+
+int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
+ dma_addr_t addr, size_t size)
+{
+ return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
}
int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
@@ -315,7 +321,7 @@ static void swiotlb_bounce(phys_addr_t p
unsigned long flags;
while (size) {
- sz = min((size_t)(PAGE_SIZE - offset), size);
+ sz = min_t(size_t, PAGE_SIZE - offset, size);
local_irq_save(flags);
buffer = kmap_atomic(pfn_to_page(pfn),
@@ -449,7 +455,7 @@ found:
* dma_addr is the kernel virtual address of the bounce buffer to unmap.
*/
static void
-unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+do_unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
{
unsigned long flags;
int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
@@ -544,7 +550,7 @@ swiotlb_full(struct device *dev, size_t
* PCI address to use is returned.
*
* Once the device is given the dma address, the device owns this memory until
- * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
+ * either swiotlb_unmap_page or swiotlb_dma_sync_single is performed.
*/
dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
@@ -558,7 +564,7 @@ dma_addr_t swiotlb_map_page(struct devic
BUG_ON(dir == DMA_NONE);
/*
- * If the pointer passed in happens to be in the device's DMA window,
+ * If the address happens to be in the device's DMA window,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
@@ -583,23 +589,32 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
/*
* Unmap a single streaming mode DMA translation. The dma_addr and size must
- * match what was provided for in a previous swiotlb_map_single call. All
+ * match what was provided for in a previous swiotlb_map_page call. All
* other usages are undefined.
*
* After this call, reads by the cpu to the buffer are guaranteed to see
* whatever the device wrote there.
*/
+static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+ size_t size, int dir)
+{
+ char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
+
+ BUG_ON(dir == DMA_NONE);
+
+ if (is_swiotlb_buffer(dev_addr)) {
+ do_unmap_single(hwdev, dma_addr, size, dir);
+ return;
+ }
+
+ gnttab_dma_unmap_page(dev_addr);
+}
+
void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
- char *dma_addr = swiotlb_bus_to_virt(dev_addr);
-
- BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dev_addr))
- unmap_single(hwdev, dma_addr, size, dir);
- else
- gnttab_dma_unmap_page(dev_addr);
+ unmap_single(hwdev, dev_addr, size, dir);
}
EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
@@ -607,7 +622,7 @@ EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
* Make physical memory consistent for a single streaming mode DMA translation
* after a transfer.
*
- * If you perform a swiotlb_map_single() but wish to interrogate the buffer
+ * If you perform a swiotlb_map_page() but wish to interrogate the buffer
* using the cpu, yet do not wish to teardown the PCI dma mapping, you must
* call this function before doing so. At the next point you give the PCI dma
* address back to the card, you must first perform a
@@ -617,9 +632,10 @@ static void
swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, int dir, int target)
{
- char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
BUG_ON(dir == DMA_NONE);
+
if (is_swiotlb_buffer(dev_addr))
sync_single(hwdev, dma_addr, size, dir, target);
}
@@ -648,11 +664,7 @@ swiotlb_sync_single_range(struct device
unsigned long offset, size_t size,
int dir, int target)
{
- char *dma_addr = swiotlb_bus_to_virt(dev_addr);
-
- BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dev_addr))
- sync_single(hwdev, dma_addr + offset, size, dir, target);
+ swiotlb_sync_single(hwdev, dev_addr + offset, size, dir, target);
}
void
@@ -677,7 +689,7 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_ra
/*
* Map a set of buffers described by scatterlist in streaming mode for DMA.
- * This is the scatter-gather version of the above swiotlb_map_single
+ * This is the scatter-gather version of the above swiotlb_map_page
* interface. Here the scatter gather list elements are each tagged with the
* appropriate dma address and length. They are obtained via
* sg_dma_{address,length}(SG).
@@ -688,7 +700,7 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_ra
* The routine returns the number of addr/length pairs actually
* used, at most nents.
*
- * Device ownership issues as mentioned above for swiotlb_map_single are the
+ * Device ownership issues as mentioned above for swiotlb_map_page are the
* same here.
*/
int
@@ -741,7 +753,7 @@ EXPORT_SYMBOL(swiotlb_map_sg);
/*
* Unmap a set of streaming mode DMA translations. Again, cpu read rules
- * concerning calls here are the same as for swiotlb_unmap_single() above.
+ * concerning calls here are the same as for swiotlb_unmap_page() above.
*/
void
swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
@@ -752,13 +764,9 @@ swiotlb_unmap_sg_attrs(struct device *hw
BUG_ON(dir == DMA_NONE);
- for_each_sg(sgl, sg, nelems, i) {
- if (sg->dma_address != sg_phys(sg))
- unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
- sg->dma_length, dir);
- else
- gnttab_dma_unmap_page(sg->dma_address);
- }
+ for_each_sg(sgl, sg, nelems, i)
+ unmap_single(hwdev, sg->dma_address, sg->dma_length, dir);
+
}
EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
@@ -784,13 +792,9 @@ swiotlb_sync_sg(struct device *hwdev, st
struct scatterlist *sg;
int i;
- BUG_ON(dir == DMA_NONE);
-
- for_each_sg(sgl, sg, nelems, i) {
- if (sg->dma_address != sg_phys(sg))
- sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+ for_each_sg(sgl, sg, nelems, i)
+ swiotlb_sync_single(hwdev, sg->dma_address,
sg->dma_length, dir, target);
- }
}
void
--- head-2011-03-17.orig/mm/init-mm.c 2011-03-17 14:35:44.000000000 +0100
+++ head-2011-03-17/mm/init-mm.c 2011-02-01 14:50:44.000000000 +0100
@@ -13,6 +13,10 @@
#define INIT_MM_CONTEXT(name)
#endif
+#ifdef CONFIG_X86_XEN
+#define swapper_pg_dir ((pgd_t *)NULL)
+#endif
+
struct mm_struct init_mm = {
.mm_rb = RB_ROOT,
.pgd = swapper_pg_dir,
--- head-2011-03-17.orig/mm/memory.c 2011-01-31 18:01:51.000000000 +0100
+++ head-2011-03-17/mm/memory.c 2011-02-01 14:50:44.000000000 +0100
@@ -1522,7 +1522,7 @@ int __get_user_pages(struct task_struct
vmas[i] = vma;
i++;
start += PAGE_SIZE;
- len--;
+ nr_pages--;
continue;
}
}
--- head-2011-03-17.orig/mm/page_alloc.c 2011-02-08 10:05:20.000000000 +0100
+++ head-2011-03-17/mm/page_alloc.c 2011-02-01 14:50:44.000000000 +0100
@@ -649,6 +649,7 @@ static bool free_pages_prepare(struct pa
#ifdef CONFIG_XEN
if (PageForeign(page)) {
+ WARN_ON(wasMlocked);
PageForeignDestructor(page, order);
return;
}