[kernel] r6363 - in dists/trunk/linux-2.6/debian/patches: . series
Bastian Blank
waldi at costa.debian.org
Sun Apr 2 21:22:07 UTC 2006
Author: waldi
Date: Sun Apr 2 21:22:00 2006
New Revision: 6363
Added:
dists/trunk/linux-2.6/debian/patches/xen-tree-merge-22448.patch
- copied, changed from r6208, dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966.patch
Removed:
dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966.patch
Modified:
dists/trunk/linux-2.6/debian/patches/series/1-extra
dists/trunk/linux-2.6/debian/patches/series/3-extra
dists/trunk/linux-2.6/debian/patches/series/99experimental.1-extra
Log:
Update xen patch.
* debian/patches/series/1-extra, debian/patches/series/3-extra,
debian/patches/series/99experimental.1-extra: Update.
* debian/patches/xen-tree-merge-22448.patch: Remove.
* debian/patches/xen-tree-merge-21966.patch: Add.
Modified: dists/trunk/linux-2.6/debian/patches/series/1-extra
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1-extra (original)
+++ dists/trunk/linux-2.6/debian/patches/series/1-extra Sun Apr 2 21:22:00 2006
@@ -3,6 +3,5 @@
+ vserver-version.patch *_vserver *_xen-vserver
+ vserver-vs2.0.2-rc13.patch *_vserver *_xen-vserver
+ vserver-xen-clash.patch *_xen-vserver
-+ xen-tree-merge-21966.patch *_xen *_xen-vserver
+ mips-tulip.patch mipsel
+ mips-tulip_dc21143.patch mipsel
Modified: dists/trunk/linux-2.6/debian/patches/series/3-extra
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/3-extra (original)
+++ dists/trunk/linux-2.6/debian/patches/series/3-extra Sun Apr 2 21:22:00 2006
@@ -1 +1 @@
-+ vserver-vs2.0.2-rc14-update.patch *_vserver
++ vserver-vs2.0.2-rc14-update.patch *_vserver *_xen-vserver
Modified: dists/trunk/linux-2.6/debian/patches/series/99experimental.1-extra
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/99experimental.1-extra (original)
+++ dists/trunk/linux-2.6/debian/patches/series/99experimental.1-extra Sun Apr 2 21:22:00 2006
@@ -1 +1,2 @@
++ xen-tree-merge-22448.patch *_xen *_xen-vserver
+ xen-tls.patch *_xen *_xen-vserver
Copied: dists/trunk/linux-2.6/debian/patches/xen-tree-merge-22448.patch (from r6208, dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966.patch)
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966.patch (original)
+++ dists/trunk/linux-2.6/debian/patches/xen-tree-merge-22448.patch Sun Apr 2 21:22:00 2006
@@ -491,10 +491,10 @@
+endif
diff --git a/arch/i386/kernel/acpi/boot-xen.c b/arch/i386/kernel/acpi/boot-xen.c
new file mode 100644
-index 0000000..29b491e
+index 0000000..96e4525
--- /dev/null
+++ b/arch/i386/kernel/acpi/boot-xen.c
-@@ -0,0 +1,1163 @@
+@@ -0,0 +1,1161 @@
+/*
+ * boot.c - Architecture-Specific Low-Level ACPI Boot Support
+ *
@@ -543,6 +543,7 @@
+
+static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }
+
++
+#else /* X86 */
+
+#ifdef CONFIG_X86_LOCAL_APIC
@@ -1610,9 +1611,6 @@
+ disable_acpi();
+ return error;
+ }
-+#ifdef __i386__
-+ check_acpi_pci();
-+#endif
+
+ acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
+
@@ -1845,10 +1843,10 @@
+endif
diff --git a/arch/i386/kernel/cpu/common-xen.c b/arch/i386/kernel/cpu/common-xen.c
new file mode 100644
-index 0000000..2fc25e8
+index 0000000..db05bd0
--- /dev/null
+++ b/arch/i386/kernel/cpu/common-xen.c
-@@ -0,0 +1,723 @@
+@@ -0,0 +1,719 @@
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/delay.h>
@@ -1885,8 +1883,6 @@
+
+struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
+
-+extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c);
-+
+extern int disable_pse;
+
+static void default_init(struct cpuinfo_x86 * c)
@@ -2134,10 +2130,10 @@
+ c->x86_capability[4] = excap;
+ c->x86 = (tfms >> 8) & 15;
+ c->x86_model = (tfms >> 4) & 15;
-+ if (c->x86 == 0xf) {
++ if (c->x86 == 0xf)
+ c->x86 += (tfms >> 20) & 0xff;
++ if (c->x86 >= 0x6)
+ c->x86_model += ((tfms >> 16) & 0xF) << 4;
-+ }
+ c->x86_mask = tfms & 15;
+ } else {
+ /* Have CPUID level 0 only - unheard of */
@@ -2278,8 +2274,6 @@
+ c->x86_vendor, c->x86_model);
+ }
+
-+ machine_specific_modify_cpu_capabilities(c);
-+
+ /* Now the feature flags better reflect actual CPU features! */
+
+ printk(KERN_DEBUG "CPU: After all inits, caps:");
@@ -2602,10 +2596,10 @@
+endif
diff --git a/arch/i386/kernel/cpu/mtrr/main-xen.c b/arch/i386/kernel/cpu/mtrr/main-xen.c
new file mode 100644
-index 0000000..407cc78
+index 0000000..8f09bd7
--- /dev/null
+++ b/arch/i386/kernel/cpu/mtrr/main-xen.c
-@@ -0,0 +1,187 @@
+@@ -0,0 +1,196 @@
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
@@ -2616,6 +2610,8 @@
+#include <asm/mtrr.h>
+#include "mtrr.h"
+
++static DECLARE_MUTEX(mtrr_sem);
++
+void generic_get_mtrr(unsigned int reg, unsigned long *base,
+ unsigned int *size, mtrr_type * type)
+{
@@ -2671,12 +2667,15 @@
+ int error;
+ dom0_op_t op;
+
++ down(&mtrr_sem);
++
+ op.cmd = DOM0_ADD_MEMTYPE;
+ op.u.add_memtype.mfn = base;
+ op.u.add_memtype.nr_mfns = size;
+ op.u.add_memtype.type = type;
+ error = HYPERVISOR_dom0_op(&op);
+ if (error) {
++ up(&mtrr_sem);
+ BUG_ON(error > 0);
+ return error;
+ }
@@ -2684,6 +2683,8 @@
+ if (increment)
+ ++usage_table[op.u.add_memtype.reg];
+
++ up(&mtrr_sem);
++
+ return op.u.add_memtype.reg;
+}
+
@@ -2712,17 +2713,18 @@
+
+int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+{
-+ int i, max;
++ unsigned i;
+ mtrr_type ltype;
+ unsigned long lbase;
+ unsigned int lsize;
+ int error = -EINVAL;
+ dom0_op_t op;
+
-+ max = num_var_ranges;
++ down(&mtrr_sem);
++
+ if (reg < 0) {
+ /* Search for existing MTRR */
-+ for (i = 0; i < max; ++i) {
++ for (i = 0; i < num_var_ranges; ++i) {
+ mtrr_if->get(i, &lbase, &lsize, <ype);
+ if (lbase == base && lsize == size) {
+ reg = i;
@@ -2751,6 +2753,7 @@
+ }
+ error = reg;
+ out:
++ up(&mtrr_sem);
+ return error;
+}
+
@@ -2803,10 +2806,10 @@
+#include "../../x86_64/kernel/early_printk-xen.c"
diff --git a/arch/i386/kernel/entry-xen.S b/arch/i386/kernel/entry-xen.S
new file mode 100644
-index 0000000..a86e8f5
+index 0000000..ec17d1c
--- /dev/null
+++ b/arch/i386/kernel/entry-xen.S
-@@ -0,0 +1,857 @@
+@@ -0,0 +1,861 @@
+/*
+ * linux/arch/i386/entry.S
+ *
@@ -2888,6 +2891,10 @@
+/* Pseudo-eflags. */
+NMI_MASK = 0x80000000
+
++#ifndef CONFIG_XEN
++#define DISABLE_INTERRUPTS cli
++#define ENABLE_INTERRUPTS sti
++#else
+/* Offsets into shared_info_t. */
+#define evtchn_upcall_pending /* 0 */
+#define evtchn_upcall_mask 1
@@ -2895,33 +2902,24 @@
+#define sizeof_vcpu_shift 6
+
+#ifdef CONFIG_SMP
-+#define preempt_disable(reg) incl TI_preempt_count(reg)
-+#define preempt_enable(reg) decl TI_preempt_count(reg)
-+#define XEN_GET_VCPU_INFO(reg) preempt_disable(%ebp) ; \
-+ movl TI_cpu(%ebp),reg ; \
-+ shl $sizeof_vcpu_shift,reg ; \
-+ addl HYPERVISOR_shared_info,reg
-+#define XEN_PUT_VCPU_INFO(reg) preempt_enable(%ebp)
-+#define XEN_PUT_VCPU_INFO_fixup .byte 0xff,0xff,0xff
-+#else
-+#define XEN_GET_VCPU_INFO(reg) movl HYPERVISOR_shared_info,reg
-+#define XEN_PUT_VCPU_INFO(reg)
-+#define XEN_PUT_VCPU_INFO_fixup
++#define GET_VCPU_INFO movl TI_cpu(%ebp),%esi ; \
++ shl $sizeof_vcpu_shift,%esi ; \
++ addl HYPERVISOR_shared_info,%esi
++#else
++#define GET_VCPU_INFO movl HYPERVISOR_shared_info,%esi
+#endif
+
-+#define XEN_LOCKED_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg)
-+#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
-+#define XEN_BLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
-+ XEN_LOCKED_BLOCK_EVENTS(reg) ; \
-+ XEN_PUT_VCPU_INFO(reg)
-+#define XEN_UNBLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
-+ XEN_LOCKED_UNBLOCK_EVENTS(reg) ; \
-+ XEN_PUT_VCPU_INFO(reg)
-+#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
++#define __DISABLE_INTERRUPTS movb $1,evtchn_upcall_mask(%esi)
++#define __ENABLE_INTERRUPTS movb $0,evtchn_upcall_mask(%esi)
++#define DISABLE_INTERRUPTS GET_VCPU_INFO ; \
++ __DISABLE_INTERRUPTS
++#define ENABLE_INTERRUPTS GET_VCPU_INFO ; \
++ __ENABLE_INTERRUPTS
++#define __TEST_PENDING testb $0xFF,evtchn_upcall_pending(%esi)
++#endif
+
+#ifdef CONFIG_PREEMPT
-+#define preempt_stop GET_THREAD_INFO(%ebp) ; \
-+ XEN_BLOCK_EVENTS(%esi)
++#define preempt_stop cli
+#else
+#define preempt_stop
+#define resume_kernel restore_nocheck
@@ -2968,21 +2966,6 @@
+.previous
+
+
-+#define RESTORE_ALL \
-+ RESTORE_REGS \
-+ addl $4, %esp; \
-+1: iret; \
-+.section .fixup,"ax"; \
-+2: pushl $0; \
-+ pushl $do_iret_error; \
-+ jmp error_code; \
-+.previous; \
-+.section __ex_table,"a";\
-+ .align 4; \
-+ .long 1b,2b; \
-+.previous
-+
-+
+ENTRY(ret_from_fork)
+ pushl %eax
+ call schedule_tail
@@ -3008,7 +2991,7 @@
+ testl $(VM_MASK | 2), %eax
+ jz resume_kernel
+ENTRY(resume_userspace)
-+ XEN_BLOCK_EVENTS(%esi) # make sure we don't miss an interrupt
++ DISABLE_INTERRUPTS # make sure we don't miss an interrupt
+ # setting need_resched or sigpending
+ # between sampling and the iret
+ movl TI_flags(%ebp), %ecx
@@ -3019,15 +3002,15 @@
+
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
-+ XEN_BLOCK_EVENTS(%esi)
++ cli
+ cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
+ jnz restore_nocheck
+need_resched:
+ movl TI_flags(%ebp), %ecx # need_resched set ?
+ testb $_TIF_NEED_RESCHED, %cl
+ jz restore_all
-+ testb $0xFF,EVENT_MASK(%esp) # interrupts off (exception path) ?
-+ jnz restore_all
++ testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ?
++ jz restore_all
+ call preempt_schedule_irq
+ jmp need_resched
+#endif
@@ -3098,7 +3081,7 @@
+ call *sys_call_table(,%eax,4)
+ movl %eax,EAX(%esp) # store the return value
+syscall_exit:
-+ XEN_BLOCK_EVENTS(%esi) # make sure we don't miss an interrupt
++ DISABLE_INTERRUPTS # make sure we don't miss an interrupt
+ # setting need_resched or sigpending
+ # between sampling and the iret
+ movl TI_flags(%ebp), %ecx
@@ -3106,7 +3089,7 @@
+ jne syscall_exit_work
+
+restore_all:
-+#if 0 /* XEN */
++#ifndef CONFIG_XEN
+ movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
+ # Warning: OLDSS(%esp) contains the wrong/random values if we
+ # are returning to the kernel.
@@ -3116,22 +3099,26 @@
+ andl $(VM_MASK | (4 << 8) | 3), %eax
+ cmpl $((4 << 8) | 3), %eax
+ je ldt_ss # returning to user-space with LDT SS
-+#endif /* XEN */
++restore_nocheck:
++#else
+restore_nocheck:
+ testl $(VM_MASK|NMI_MASK), EFLAGS(%esp)
+ jnz hypervisor_iret
+ movb EVENT_MASK(%esp), %al
+ notb %al # %al == ~saved_mask
-+ XEN_GET_VCPU_INFO(%esi)
++ GET_VCPU_INFO
+ andb evtchn_upcall_mask(%esi),%al
+ andb $1,%al # %al == mask & ~saved_mask
+ jnz restore_all_enable_events # != 0 => reenable event delivery
-+ XEN_PUT_VCPU_INFO(%esi)
++#endif
+ RESTORE_REGS
+ addl $4, %esp
+1: iret
+.section .fixup,"ax"
+iret_exc:
++#ifndef CONFIG_XEN
++ sti
++#endif
+ pushl $0 # no error code
+ pushl $do_iret_error
+ jmp error_code
@@ -3141,13 +3128,7 @@
+ .long 1b,iret_exc
+.previous
+
-+hypervisor_iret:
-+ andl $~NMI_MASK, EFLAGS(%esp)
-+ RESTORE_REGS
-+ addl $4, %esp
-+ jmp hypercall_page + (__HYPERVISOR_iret * 32)
-+
-+#if 0 /* XEN */
++#ifndef CONFIG_XEN
+ldt_ss:
+ larl OLDSS(%esp), %eax
+ jnz restore_nocheck
@@ -3172,7 +3153,13 @@
+ .align 4
+ .long 1b,iret_exc
+.previous
-+#endif /* XEN */
++#else
++hypervisor_iret:
++ andl $~NMI_MASK, EFLAGS(%esp)
++ RESTORE_REGS
++ addl $4, %esp
++ jmp hypercall_page + (__HYPERVISOR_iret * 32)
++#endif
+
+ # perform work that needs to be done immediately before resumption
+ ALIGN
@@ -3181,7 +3168,7 @@
+ jz work_notifysig
+work_resched:
+ call schedule
-+ XEN_BLOCK_EVENTS(%esi) # make sure we don't miss an interrupt
++ DISABLE_INTERRUPTS # make sure we don't miss an interrupt
+ # setting need_resched or sigpending
+ # between sampling and the iret
+ movl TI_flags(%ebp), %ecx
@@ -3233,7 +3220,7 @@
+syscall_exit_work:
+ testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
+ jz work_pending
-+ XEN_UNBLOCK_EVENTS(%esi) # could let do_syscall_trace() call
++ ENABLE_INTERRUPTS # could let do_syscall_trace() call
+ # schedule() instead
+ movl %esp, %eax
+ movl $1, %edx
@@ -3253,7 +3240,7 @@
+ movl $-ENOSYS,EAX(%esp)
+ jmp resume_userspace
+
-+#if 0 /* XEN */
++#ifndef CONFIG_XEN
+#define FIXUP_ESPFIX_STACK \
+ movl %esp, %eax; \
+ /* switch to 32bit stack using the pointer on top of 16bit stack */ \
@@ -3312,7 +3299,9 @@
+
+/* The include is where all of the SMP etc. interrupts come from */
+#include "entry_arch.h"
-+#endif /* XEN */
++#else
++#define UNWIND_ESPFIX_STACK
++#endif
+
+ENTRY(divide_error)
+ pushl $0 # no error code
@@ -3331,7 +3320,7 @@
+ pushl %ebx
+ cld
+ pushl %es
-+# UNWIND_ESPFIX_STACK
++ UNWIND_ESPFIX_STACK
+ popl %ecx
+ movl ES(%esp), %edi # get the function address
+ movl ORIG_EAX(%esp), %edx # get the error code
@@ -3344,6 +3333,7 @@
+ call *%edi
+ jmp ret_from_exception
+
++#ifdef CONFIG_XEN
+# A note on the "critical region" in our callback handler.
+# We want to avoid stacking callback handlers due to events occurring
+# during handling of the last event. To do this, we keep events disabled
@@ -3370,14 +3360,23 @@
+
+ ALIGN
+restore_all_enable_events:
-+ XEN_LOCKED_UNBLOCK_EVENTS(%esi)
++ __ENABLE_INTERRUPTS
+scrit: /**** START OF CRITICAL REGION ****/
-+ XEN_TEST_PENDING(%esi)
++ __TEST_PENDING
+ jnz 14f # process more events if necessary...
-+ XEN_PUT_VCPU_INFO(%esi)
-+ RESTORE_ALL
-+14: XEN_LOCKED_BLOCK_EVENTS(%esi)
-+ XEN_PUT_VCPU_INFO(%esi)
++ RESTORE_REGS
++ addl $4, %esp
++1: iret
++.section .fixup,"ax"
++2: pushl $0
++ pushl $do_iret_error
++ jmp error_code
++.previous
++.section __ex_table,"a"
++ .align 4
++ .long 1b,2b
++.previous
++14: __DISABLE_INTERRUPTS
+ jmp 11b
+ecrit: /**** END OF CRITICAL REGION ****/
+# [How we do the fixup]. We want to merge the current stack frame with the
@@ -3393,7 +3392,6 @@
+ cmpb $0xff,%al # 0xff => vcpu_info critical region
+ jne 15f
+ GET_THREAD_INFO(%ebp)
-+ XEN_PUT_VCPU_INFO(%esi) # abort vcpu_info critical region
+ xorl %eax,%eax
+15: mov %esp,%esi
+ add %eax,%esi # %esi points at end of src region
@@ -3411,9 +3409,8 @@
+ jmp 11b
+
+critical_fixup_table:
-+ .byte 0xff,0xff,0xff # testb $0xff,(%esi) = XEN_TEST_PENDING
++ .byte 0xff,0xff,0xff # testb $0xff,(%esi) = __TEST_PENDING
+ .byte 0xff,0xff # jnz 14f
-+ XEN_PUT_VCPU_INFO_fixup
+ .byte 0x00 # pop %ebx
+ .byte 0x04 # pop %ecx
+ .byte 0x08 # pop %edx
@@ -3426,7 +3423,6 @@
+ .byte 0x24,0x24,0x24 # add $4,%esp
+ .byte 0x28 # iret
+ .byte 0xff,0xff,0xff,0xff # movb $1,1(%esi)
-+ XEN_PUT_VCPU_INFO_fixup
+ .byte 0x00,0x00 # jmp 11b
+
+# Hypervisor uses this for application faults while it executes.
@@ -3455,6 +3451,7 @@
+ .long 3b,8b; \
+ .long 4b,9b; \
+.previous
++#endif
+
+ENTRY(coprocessor_error)
+ pushl $0
@@ -3469,7 +3466,17 @@
+ENTRY(device_not_available)
+ pushl $-1 # mark this as an int
+ SAVE_ALL
-+ #preempt_stop /* This is already an interrupt gate on Xen. */
++#ifndef CONFIG_XEN
++ movl %cr0, %eax
++ testl $0x4, %eax # EM (math emulation bit)
++ je device_available_emulate
++ pushl $0 # temporary storage for ORIG_EIP
++ call math_emulate
++ addl $4, %esp
++ jmp ret_from_exception
++device_available_emulate:
++#endif
++ preempt_stop
+ call math_state_restore
+ jmp ret_from_exception
+
@@ -3512,16 +3519,7 @@
+ jmp ret_from_exception
+ .previous .text
+
-+ENTRY(nmi)
-+ pushl %eax
-+ SAVE_ALL
-+ xorl %edx,%edx # zero error code
-+ movl %esp,%eax # pt_regs pointer
-+ call do_nmi
-+ orl $NMI_MASK, EFLAGS(%esp)
-+ jmp restore_all
-+
-+#if 0 /* XEN */
++#ifndef CONFIG_XEN
+/*
+ * NMI is doubly nasty. It can happen _while_ we're handling
+ * a debug fault, and the debug fault hasn't yet been able to
@@ -3592,7 +3590,16 @@
+ .align 4
+ .long 1b,iret_exc
+.previous
-+#endif /* XEN */
++#else
++ENTRY(nmi)
++ pushl %eax
++ SAVE_ALL
++ xorl %edx,%edx # zero error code
++ movl %esp,%eax # pt_regs pointer
++ call do_nmi
++ orl $NMI_MASK, EFLAGS(%esp)
++ jmp restore_all
++#endif
+
+KPROBE_ENTRY(int3)
+ pushl $-1 # mark this as an int
@@ -3767,7 +3774,7 @@
+ */
diff --git a/arch/i386/kernel/head-xen.S b/arch/i386/kernel/head-xen.S
new file mode 100644
-index 0000000..3032a00
+index 0000000..23e62c0
--- /dev/null
+++ b/arch/i386/kernel/head-xen.S
@@ -0,0 +1,171 @@
@@ -3805,14 +3812,14 @@
+
+ /* get vendor info */
+ xorl %eax,%eax # call CPUID with 0 -> return vendor ID
-+ cpuid
++ XEN_CPUID
+ movl %eax,X86_CPUID # save CPUID level
+ movl %ebx,X86_VENDOR_ID # lo 4 chars
+ movl %edx,X86_VENDOR_ID+4 # next 4 chars
+ movl %ecx,X86_VENDOR_ID+8 # last 4 chars
+
+ movl $1,%eax # Use the CPUID instruction to get CPU type
-+ cpuid
++ XEN_CPUID
+ movb %al,%cl # save reg for future use
+ andb $0x0f,%ah # mask processor family
+ movb %ah,X86
@@ -4001,10 +4008,10 @@
+
diff --git a/arch/i386/kernel/io_apic-xen.c b/arch/i386/kernel/io_apic-xen.c
new file mode 100644
-index 0000000..5ef6513
+index 0000000..47edb05
--- /dev/null
+++ b/arch/i386/kernel/io_apic-xen.c
-@@ -0,0 +1,2746 @@
+@@ -0,0 +1,2747 @@
+/*
+ * Intel IO-APIC support for multi-Pentium hosts.
+ *
@@ -6338,7 +6345,8 @@
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ init_8259A(1);
+ timer_ack = 1;
-+ enable_8259A_irq(0);
++ if (timer_over_8254 > 0)
++ enable_8259A_irq(0);
+
+ pin1 = find_isa_irq_pin(0, mp_INT);
+ apic1 = find_isa_irq_apic(0, mp_INT);
@@ -7468,10 +7476,10 @@
+}
diff --git a/arch/i386/kernel/microcode-xen.c b/arch/i386/kernel/microcode-xen.c
new file mode 100644
-index 0000000..a0e1487
+index 0000000..07db5cc
--- /dev/null
+++ b/arch/i386/kernel/microcode-xen.c
-@@ -0,0 +1,164 @@
+@@ -0,0 +1,165 @@
+/*
+ * Intel CPU Microcode Update Driver for Linux
+ *
@@ -7499,6 +7507,7 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
++#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
@@ -10057,10 +10066,10 @@
+#endif
diff --git a/arch/i386/kernel/setup-xen.c b/arch/i386/kernel/setup-xen.c
new file mode 100644
-index 0000000..5368d2f
+index 0000000..1e0bd6f
--- /dev/null
+++ b/arch/i386/kernel/setup-xen.c
-@@ -0,0 +1,1874 @@
+@@ -0,0 +1,1878 @@
+/*
+ * linux/arch/i386/kernel/setup.c
+ *
@@ -11868,6 +11877,10 @@
+ op.u.set_iopl.iopl = 1;
+ HYPERVISOR_physdev_op(&op);
+
++#ifdef CONFIG_X86_IO_APIC
++ check_acpi_pci(); /* Checks more than just ACPI actually */
++#endif
++
+#ifdef CONFIG_ACPI
+ if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
+ printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
@@ -12650,10 +12663,10 @@
+ mb();
+}
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
-index eba7f53..378708c 100644
+index 7007e17..1008255 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
-@@ -1208,6 +1208,11 @@ static void __init smp_boot_cpus(unsigne
+@@ -1218,6 +1218,11 @@ static void __init smp_boot_cpus(unsigne
if (max_cpus <= cpucount+1)
continue;
@@ -12665,7 +12678,7 @@
if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
printk("CPU #%d not responding - cannot use it.\n",
apicid);
-@@ -1386,6 +1391,11 @@ int __devinit __cpu_up(unsigned int cpu)
+@@ -1396,6 +1401,11 @@ int __devinit __cpu_up(unsigned int cpu)
return -EIO;
}
@@ -13488,10 +13501,10 @@
+}
diff --git a/arch/i386/kernel/time-xen.c b/arch/i386/kernel/time-xen.c
new file mode 100644
-index 0000000..39cf69d
+index 0000000..197d785
--- /dev/null
+++ b/arch/i386/kernel/time-xen.c
-@@ -0,0 +1,1137 @@
+@@ -0,0 +1,1173 @@
+/*
+ * linux/arch/i386/kernel/time.c
+ *
@@ -13650,6 +13663,17 @@
+}
+__setup("independent_wallclock", __independent_wallclock);
+
++/* Permitted clock jitter, in nsecs, beyond which a warning will be printed. */
++static unsigned long permitted_clock_jitter = 10000000UL; /* 10ms */
++static int __init __permitted_clock_jitter(char *str)
++{
++ permitted_clock_jitter = simple_strtoul(str, NULL, 0);
++ return 1;
++}
++__setup("permitted_clock_jitter=", __permitted_clock_jitter);
++
++int tsc_disable __devinitdata = 0;
++
+#ifdef __i386__
+static void delay_tsc(unsigned long loops)
+{
@@ -13817,6 +13841,7 @@
+ src = &HYPERVISOR_shared_info->vcpu_info[cpu].time;
+ dst = &per_cpu(shadow_time, cpu);
+
++ rmb();
+ return (dst->version == src->version);
+}
+
@@ -14047,11 +14072,11 @@
+
+ do {
+ local_time_version = shadow->version;
-+ smp_rmb();
++ barrier();
+ time = shadow->system_timestamp + get_nsec_offset(shadow);
+ if (!time_values_up_to_date(cpu))
+ get_time_values_from_xen();
-+ smp_rmb();
++ barrier();
+ } while (local_time_version != shadow->version);
+
+ put_cpu();
@@ -14152,10 +14177,11 @@
+ } while (sched_time != runstate->state_entry_time);
+ } while (!time_values_up_to_date(cpu));
+
-+ if ((unlikely(delta < -1000000LL) || unlikely(delta_cpu < 0))
++ if ((unlikely(delta < -(s64)permitted_clock_jitter) ||
++ unlikely(delta_cpu < -(s64)permitted_clock_jitter))
+ && printk_ratelimit()) {
+ printk("Timer ISR/%d: Time went backwards: "
-+ "delta=%lld cpu_delta=%lld shadow=%lld "
++ "delta=%lld delta_cpu=%lld shadow=%lld "
+ "off=%lld processed=%lld cpu_processed=%lld\n",
+ cpu, delta, delta_cpu, shadow->system_timestamp,
+ (s64)get_nsec_offset(shadow),
@@ -14185,8 +14211,10 @@
+ * HACK: Passing NULL to account_steal_time()
+ * ensures that the ticks are accounted as stolen.
+ */
-+ if (stolen > 0) {
++ if ((stolen > 0) && (delta_cpu > 0)) {
+ delta_cpu -= stolen;
++ if (unlikely(delta_cpu < 0))
++ stolen += delta_cpu; /* clamp local-time progress */
+ do_div(stolen, NS_PER_TICK);
+ per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK;
+ per_cpu(processed_system_time, cpu) += stolen * NS_PER_TICK;
@@ -14198,8 +14226,10 @@
+ * HACK: Passing idle_task to account_steal_time()
+ * ensures that the ticks are accounted as idle/wait.
+ */
-+ if (blocked > 0) {
++ if ((blocked > 0) && (delta_cpu > 0)) {
+ delta_cpu -= blocked;
++ if (unlikely(delta_cpu < 0))
++ blocked += delta_cpu; /* clamp local-time progress */
+ do_div(blocked, NS_PER_TICK);
+ per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK;
+ per_cpu(processed_system_time, cpu) += blocked * NS_PER_TICK;
@@ -14397,9 +14427,9 @@
+ write_seqlock_irqsave(&xtime_lock, flags);
+ xtime.tv_sec = sec;
+ xtime.tv_nsec = 0;
-+ write_sequnlock_irqrestore(&xtime_lock, flags);
-+ jiffies += sleep_length;
++ jiffies_64 += sleep_length;
+ wall_jiffies += sleep_length;
++ write_sequnlock_irqrestore(&xtime_lock, flags);
+ touch_softlockup_watchdog();
+ return 0;
+}
@@ -14502,7 +14532,7 @@
+}
+
+/* Convert jiffies to system time. */
-+static inline u64 jiffies_to_st(unsigned long j)
++u64 jiffies_to_st(unsigned long j)
+{
+ unsigned long seq;
+ long delta;
@@ -14520,6 +14550,7 @@
+
+ return st;
+}
++EXPORT_SYMBOL(jiffies_to_st);
+
+/*
+ * stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
@@ -14605,13 +14636,31 @@
+ * now however.
+ */
+static ctl_table xen_subtable[] = {
-+ {1, "independent_wallclock", &independent_wallclock,
-+ sizeof(independent_wallclock), 0644, NULL, proc_dointvec},
-+ {0}
++ {
++ .ctl_name = 1,
++ .procname = "independent_wallclock",
++ .data = &independent_wallclock,
++ .maxlen = sizeof(independent_wallclock),
++ .mode = 0644,
++ .proc_handler = proc_dointvec
++ },
++ {
++ .ctl_name = 2,
++ .procname = "permitted_clock_jitter",
++ .data = &permitted_clock_jitter,
++ .maxlen = sizeof(permitted_clock_jitter),
++ .mode = 0644,
++ .proc_handler = proc_doulongvec_minmax
++ },
++ { 0 }
+};
+static ctl_table xen_table[] = {
-+ {123, "xen", NULL, 0, 0555, xen_subtable},
-+ {0}
++ {
++ .ctl_name = 123,
++ .procname = "xen",
++ .mode = 0555,
++ .child = xen_subtable},
++ { 0 }
+};
+static int __init xen_sysctl_init(void)
+{
@@ -16693,10 +16742,10 @@
+EXPORT_SYMBOL(kmap_atomic_to_page);
diff --git a/arch/i386/mm/hypervisor.c b/arch/i386/mm/hypervisor.c
new file mode 100644
-index 0000000..cfc359e
+index 0000000..de80a51
--- /dev/null
+++ b/arch/i386/mm/hypervisor.c
-@@ -0,0 +1,471 @@
+@@ -0,0 +1,424 @@
+/******************************************************************************
+ * mm/hypervisor.c
+ *
@@ -16704,8 +16753,11 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -16900,56 +16952,6 @@
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
-+void xen_pte_pin(unsigned long ptr)
-+{
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_PIN_L1_TABLE;
-+ op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
-+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
-+}
-+
-+void xen_pte_unpin(unsigned long ptr)
-+{
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_UNPIN_TABLE;
-+ op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
-+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
-+}
-+
-+#ifdef CONFIG_X86_64
-+void xen_pud_pin(unsigned long ptr)
-+{
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_PIN_L3_TABLE;
-+ op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
-+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
-+}
-+
-+void xen_pud_unpin(unsigned long ptr)
-+{
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_UNPIN_TABLE;
-+ op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
-+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
-+}
-+
-+void xen_pmd_pin(unsigned long ptr)
-+{
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_PIN_L2_TABLE;
-+ op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
-+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
-+}
-+
-+void xen_pmd_unpin(unsigned long ptr)
-+{
-+ struct mmuext_op op;
-+ op.cmd = MMUEXT_UNPIN_TABLE;
-+ op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
-+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
-+}
-+#endif /* CONFIG_X86_64 */
-+
+void xen_set_ldt(unsigned long ptr, unsigned long len)
+{
+ struct mmuext_op op;
@@ -17170,10 +17172,10 @@
+ */
diff --git a/arch/i386/mm/init-xen.c b/arch/i386/mm/init-xen.c
new file mode 100644
-index 0000000..b490dbd
+index 0000000..0e5661a
--- /dev/null
+++ b/arch/i386/mm/init-xen.c
-@@ -0,0 +1,846 @@
+@@ -0,0 +1,854 @@
+/*
+ * linux/arch/i386/mm/init.c
+ *
@@ -17205,6 +17207,8 @@
+#include <linux/efi.h>
+#include <linux/memory_hotplug.h>
+#include <linux/initrd.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
@@ -17218,6 +17222,7 @@
+#include <asm/tlbflush.h>
+#include <asm/sections.h>
+#include <asm/hypervisor.h>
++#include <asm/swiotlb.h>
+
+extern unsigned long *contiguous_bitmap;
+
@@ -17732,10 +17737,15 @@
+
+ kmap_init();
+
-+ /* Switch to the real shared_info page, and clear the dummy page. */
-+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
-+ HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
-+ memset(empty_zero_page, 0, sizeof(empty_zero_page));
++ if (!xen_feature(XENFEAT_auto_translated_physmap) ||
++ xen_start_info->shared_info >= xen_start_info->nr_pages) {
++ /* Switch to the real shared_info page, and clear the
++ * dummy page. */
++ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
++ HYPERVISOR_shared_info =
++ (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++ memset(empty_zero_page, 0, sizeof(empty_zero_page));
++ }
+
+ /* Setup mapping of lower 1st MB */
+ for (i = 0; i < NR_FIX_ISAMAPS; i++)
@@ -18022,10 +18032,10 @@
+#endif
diff --git a/arch/i386/mm/ioremap-xen.c b/arch/i386/mm/ioremap-xen.c
new file mode 100644
-index 0000000..a9a32ba
+index 0000000..05f3daa
--- /dev/null
+++ b/arch/i386/mm/ioremap-xen.c
-@@ -0,0 +1,462 @@
+@@ -0,0 +1,464 @@
+/*
+ * arch/i386/mm/ioremap.c
+ *
@@ -18060,13 +18070,13 @@
+#endif
+
+static int direct_remap_area_pte_fn(pte_t *pte,
-+ struct page *pte_page,
++ struct page *pmd_page,
+ unsigned long address,
+ void *data)
+{
+ mmu_update_t **v = (mmu_update_t **)data;
+
-+ (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pte_page)) <<
++ (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+ PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+ (*v)++;
+
@@ -18095,9 +18105,9 @@
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) {
+ /* Fill in the PTE pointers. */
-+ rc = generic_page_range(mm, start_address,
-+ address - start_address,
-+ direct_remap_area_pte_fn, &w);
++ rc = apply_to_page_range(mm, start_address,
++ address - start_address,
++ direct_remap_area_pte_fn, &w);
+ if (rc)
+ goto out;
+ w = u;
@@ -18121,8 +18131,9 @@
+
+ if (v != u) {
+ /* get the ptep's filled in */
-+ rc = generic_page_range(mm, start_address, address - start_address,
-+ direct_remap_area_pte_fn, &w);
++ rc = apply_to_page_range(mm, start_address,
++ address - start_address,
++ direct_remap_area_pte_fn, &w);
+ if (rc)
+ goto out;
+ rc = -EFAULT;
@@ -18170,11 +18181,11 @@
+EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
+
+static int lookup_pte_fn(
-+ pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
++ pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+ uint64_t *ptep = (uint64_t *)data;
+ if (ptep)
-+ *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pte_page)) <<
++ *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+ PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+ return 0;
+}
@@ -18183,13 +18194,14 @@
+ unsigned long address,
+ uint64_t *ptep)
+{
-+ return generic_page_range(mm, address, PAGE_SIZE, lookup_pte_fn, ptep);
++ return apply_to_page_range(mm, address, PAGE_SIZE,
++ lookup_pte_fn, ptep);
+}
+
+EXPORT_SYMBOL(create_lookup_pte_addr);
+
+static int noop_fn(
-+ pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
++ pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+ return 0;
+}
@@ -18198,7 +18210,7 @@
+ unsigned long address,
+ unsigned long size)
+{
-+ return generic_page_range(mm, address, size, noop_fn, NULL);
++ return apply_to_page_range(mm, address, size, noop_fn, NULL);
+}
+
+EXPORT_SYMBOL(touch_pte_range);
@@ -18488,12 +18500,25 @@
+ * tab-width: 8
+ * End:
+ */
+diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
+index d0cadb3..c749070 100644
+--- a/arch/i386/mm/pageattr.c
++++ b/arch/i386/mm/pageattr.c
+@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
+ unsigned long flags;
+
+ set_pte_atomic(kpte, pte); /* change init_mm */
+- if (PTRS_PER_PMD > 1)
++ if (HAVE_SHARED_KERNEL_PMD)
+ return;
+
+ spin_lock_irqsave(&pgd_lock, flags);
diff --git a/arch/i386/mm/pgtable-xen.c b/arch/i386/mm/pgtable-xen.c
new file mode 100644
-index 0000000..c2d97b5
+index 0000000..b6109de
--- /dev/null
+++ b/arch/i386/mm/pgtable-xen.c
-@@ -0,0 +1,646 @@
+@@ -0,0 +1,652 @@
+/*
+ * linux/arch/i386/mm/pgtable.c
+ */
@@ -19083,6 +19108,8 @@
+
+void mm_pin(struct mm_struct *mm)
+{
++ if (xen_feature(XENFEAT_writable_page_tables))
++ return;
+ spin_lock(&mm->page_table_lock);
+ __pgd_pin(mm->pgd);
+ spin_unlock(&mm->page_table_lock);
@@ -19090,6 +19117,8 @@
+
+void mm_unpin(struct mm_struct *mm)
+{
++ if (xen_feature(XENFEAT_writable_page_tables))
++ return;
+ spin_lock(&mm->page_table_lock);
+ __pgd_unpin(mm->pgd);
+ spin_unlock(&mm->page_table_lock);
@@ -19098,6 +19127,8 @@
+void mm_pin_all(void)
+{
+ struct page *page;
++ if (xen_feature(XENFEAT_writable_page_tables))
++ return;
+ for (page = pgd_list; page; page = (struct page *)page->index) {
+ if (!test_bit(PG_pinned, &page->flags))
+ __pgd_pin((pgd_t *)page_address(page));
@@ -20481,10 +20512,10 @@
+obj-$(CONFIG_ACPI_SLEEP) += cpu.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
-index a85ea9d..cea9e5c 100644
+index a85ea9d..3f6f231 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
-@@ -50,6 +50,53 @@ config GENERIC_IOMAP
+@@ -50,6 +50,60 @@ config GENERIC_IOMAP
bool
default y
@@ -20535,6 +20566,13 @@
+ help
+ Hack to turn off CONFIG_VT for domU
+
++config XEN_SYSFS
++ bool "Export Xen attributes in sysfs"
++ depends on XEN && SYSFS
++ default y
++ help
++ Xen hypervisor attributes will show up under /sys/hypervisor/.
++
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
@@ -20865,10 +20903,10 @@
+patched/reworked in drivers/xen to work with xenlinux/ia64.
diff --git a/arch/ia64/xen/drivers/coreMakefile b/arch/ia64/xen/drivers/coreMakefile
new file mode 100644
-index 0000000..40c4f13
+index 0000000..7a35e75
--- /dev/null
+++ b/arch/ia64/xen/drivers/coreMakefile
-@@ -0,0 +1,24 @@
+@@ -0,0 +1,26 @@
+#
+# Makefile for the linux kernel.
+#
@@ -20893,6 +20931,8 @@
+obj-$(CONFIG_SMP) += smp.o # setup_profiling_timer def'd in ia64
+obj-$(CONFIG_NET) += skbuff.o # until networking is up on ia64
+endif
++obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
++obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
diff --git a/arch/ia64/xen/drivers/evtchn_ia64.c b/arch/ia64/xen/drivers/evtchn_ia64.c
new file mode 100644
index 0000000..fa753e5
@@ -21432,10 +21472,10 @@
+#endif
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
new file mode 100644
-index 0000000..6fb0a90
+index 0000000..6a12ed9
--- /dev/null
+++ b/arch/ia64/xen/hypercall.S
-@@ -0,0 +1,323 @@
+@@ -0,0 +1,365 @@
+/*
+ * Support routines for Xen hypercalls
+ *
@@ -21692,7 +21732,6 @@
+ st8 [r11]=r10
+ ;;
+ br.ret.sptk.many rp
-+ ;;
+END(xen_set_rr)
+
+GLOBAL_ENTRY(xen_fc)
@@ -21702,7 +21741,16 @@
+(p7) fc r32;;
+(p7) br.ret.sptk.many rp
+ ;;
-+ ptc.e r96 // this is a "privified" fc r32
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_FC
++ ;;
++ st8 [r9]=r10
+ ;;
+ br.ret.sptk.many rp
+END(xen_fc)
@@ -21714,7 +21762,16 @@
+(p7) mov r8=cpuid[r32];;
+(p7) br.ret.sptk.many rp
+ ;;
-+ mov r72=rr[r32] // this is a "privified" mov r8=cpuid[r32]
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_GET_CPUID
++ ;;
++ st8 [r9]=r10
+ ;;
+ br.ret.sptk.many rp
+END(xen_get_cpuid)
@@ -21726,7 +21783,16 @@
+(p7) mov r8=pmd[r32];;
+(p7) br.ret.sptk.many rp
+ ;;
-+ mov r72=pmc[r32] // this is a "privified" mov r8=pmd[r32]
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_GET_PMD
++ ;;
++ st8 [r9]=r10
+ ;;
+ br.ret.sptk.many rp
+END(xen_get_pmd)
@@ -21739,10 +21805,20 @@
+(p7) mov r8=ar24;;
+(p7) br.ret.sptk.many rp
+ ;;
-+ mov ar24=r72 // this is a "privified" mov r8=ar.eflg
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_GET_EFLAG
++ ;;
++ st8 [r9]=r10
+ ;;
+ br.ret.sptk.many rp
+END(xen_get_eflag)
++
+// some bits aren't set if pl!=0, see SDM vol1 3.1.8
+GLOBAL_ENTRY(xen_set_eflag)
+ movl r8=running_on_xen;;
@@ -21751,13 +21827,19 @@
+(p7) mov ar24=r32
+(p7) br.ret.sptk.many rp
+ ;;
-+ // FIXME: this remains no-op'd because it generates
-+ // a privileged register (general exception) trap rather than
-+ // a privileged operation fault
-+ //mov ar24=r32
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_SET_EFLAG
++ ;;
++ st8 [r9]=r10
+ ;;
+ br.ret.sptk.many rp
-+END(xen_get_eflag)
++END(xen_set_eflag)
+#endif
diff --git a/arch/ia64/xen/xen_ksyms.c b/arch/ia64/xen/xen_ksyms.c
new file mode 100644
@@ -22685,10 +22767,10 @@
+
diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S
new file mode 100644
-index 0000000..d53b52a
+index 0000000..793d1b4
--- /dev/null
+++ b/arch/ia64/xen/xenivt.S
-@@ -0,0 +1,2044 @@
+@@ -0,0 +1,2032 @@
+/*
+ * arch/ia64/xen/ivt.S
+ *
@@ -23414,16 +23496,12 @@
+ movl r30=1f // load continuation point in case of nested fault
+ ;;
+#ifdef CONFIG_XEN
-+#if 1
+ mov r18=r8;
+ mov r8=r16;
+ XEN_HYPER_THASH;;
+ mov r17=r8;
+ mov r8=r18;;
+#else
-+ tak r17=r80 // "privified" thash
-+#endif
-+#else
+ thash r17=r16 // compute virtual address of L3 PTE
+#endif
+ mov r29=b0 // save b0 in case of nested fault
@@ -23503,16 +23581,12 @@
+#endif /* CONFIG_ITANIUM */
+ ;;
+#ifdef CONFIG_XEN
-+#if 1
+ mov r18=r8;
+ mov r8=r16;
+ XEN_HYPER_THASH;;
+ mov r17=r8;
+ mov r8=r18;;
+#else
-+ tak r17=r80 // "privified" thash
-+#endif
-+#else
+ thash r17=r16 // compute virtual address of L3 PTE
+#endif
+ mov r29=b0 // save b0 in case of nested fault)
@@ -23589,16 +23663,12 @@
+ movl r30=1f // load continuation point in case of nested fault
+ ;;
+#ifdef CONFIG_XEN
-+#if 1
+ mov r18=r8;
+ mov r8=r16;
+ XEN_HYPER_THASH;;
+ mov r17=r8;
+ mov r8=r18;;
+#else
-+ tak r17=r80 // "privified" thash
-+#endif
-+#else
+ thash r17=r16 // compute virtual address of L3 PTE
+#endif
+ mov r31=pr
@@ -25249,7 +25319,7 @@
int is_remapped(void *virt)
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
-index e18eb79..75e35a5 100644
+index e18eb79..a700ee7 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -119,6 +119,22 @@ config GENERIC_CPU
@@ -25311,7 +25381,7 @@
config MTRR
bool "MTRR (Memory Type Range Register) support"
-+ depends on !X86_64_XEN
++ depends on !XEN_UNPRIVILEGED_GUEST
---help---
On Intel P6 family processors (Pentium Pro, Pentium II and later)
the Memory Type Range Registers (MTRRs) may be used to control
@@ -26515,10 +26585,10 @@
+boot-$(CONFIG_XEN) := ../../../i386/kernel/acpi/boot-xen.o
diff --git a/arch/x86_64/kernel/apic-xen.c b/arch/x86_64/kernel/apic-xen.c
new file mode 100644
-index 0000000..f27b0e3
+index 0000000..3152b91
--- /dev/null
+++ b/arch/x86_64/kernel/apic-xen.c
-@@ -0,0 +1,200 @@
+@@ -0,0 +1,198 @@
+/*
+ * Local APIC handling, local APIC timers
+ *
@@ -26635,8 +26705,6 @@
+ irq_exit();
+}
+
-+int __initdata unsync_tsc_on_multicluster;
-+
+/*
+ * This interrupt should _never_ happen with our APIC/SMP architecture
+ */
@@ -27797,10 +27865,10 @@
+__setup("earlyprintk=", setup_early_printk);
diff --git a/arch/x86_64/kernel/entry-xen.S b/arch/x86_64/kernel/entry-xen.S
new file mode 100644
-index 0000000..dc41c56
+index 0000000..546d3a6
--- /dev/null
+++ b/arch/x86_64/kernel/entry-xen.S
-@@ -0,0 +1,1138 @@
+@@ -0,0 +1,1139 @@
+/*
+ * linux/arch/x86_64/entry.S
+ *
@@ -28619,7 +28687,7 @@
+ jmp error_exit
+
+#ifdef CONFIG_X86_LOCAL_APIC
-+ENTRY(nmi)
++KPROBE_ENTRY(nmi)
+ zeroentry do_nmi_callback
+ENTRY(do_nmi_callback)
+ addq $8, %rsp
@@ -28629,6 +28697,7 @@
+ XEN_BLOCK_EVENTS(%rsi)
+ GET_THREAD_INFO(%rcx)
+ jmp retint_restore_args
++ .previous .text
+#endif
+
+ ALIGN
@@ -34277,10 +34346,10 @@
+#endif
diff --git a/arch/x86_64/kernel/setup-xen.c b/arch/x86_64/kernel/setup-xen.c
new file mode 100644
-index 0000000..be0853d
+index 0000000..be3961b
--- /dev/null
+++ b/arch/x86_64/kernel/setup-xen.c
-@@ -0,0 +1,1619 @@
+@@ -0,0 +1,1647 @@
+/*
+ * linux/arch/x86-64/kernel/setup.c
+ *
@@ -34376,6 +34445,11 @@
+/* Allows setting of maximum possible memory size */
+unsigned long xen_override_max_pfn;
+
++static int xen_panic_event(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xen_panic_block = {
++ xen_panic_event, NULL, 0 /* try to go last */
++};
++
+unsigned long *phys_to_machine_mapping;
+unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[512];
+
@@ -34895,6 +34969,14 @@
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long kernel_end;
++#if defined(CONFIG_XEN) && defined(CONFIG_X86_LOCAL_APIC)
++ struct xennmi_callback cb;
++#endif
++
++#ifdef CONFIG_XEN
++ /* Register a call for panic conditions. */
++ notifier_chain_register(&panic_notifier_list, &xen_panic_block);
++#endif
+
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+ kernel_end = 0; /* dummy */
@@ -34932,6 +35014,13 @@
+#ifdef CONFIG_XEN
+ setup_xen_features();
+
++ if (xen_feature(XENFEAT_auto_translated_physmap) &&
++ xen_start_info->shared_info < xen_start_info->nr_pages) {
++ HYPERVISOR_shared_info =
++ (shared_info_t *)__va(xen_start_info->shared_info);
++ memset(empty_zero_page, 0, sizeof(empty_zero_page));
++ }
++
+ HYPERVISOR_vm_assist(VMASST_CMD_enable,
+ VMASST_TYPE_writable_pagetables);
+
@@ -34941,10 +35030,9 @@
+ (unsigned long) system_call);
+
+#ifdef CONFIG_X86_LOCAL_APIC
-+ HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi);
++ cb.handler_address = (unsigned long)&nmi;
++ HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+#endif
-+
-+ modify_cpu_capabilities(&boot_cpu_data);
+#endif
+
+ if (!MOUNT_ROOT_RDONLY)
@@ -35245,6 +35333,17 @@
+#endif /* !CONFIG_XEN */
+}
+
++#ifdef CONFIG_XEN
++static int
++xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
++{
++ HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash);
++ /* we're never actually going to get here... */
++ return NOTIFY_DONE;
++}
++#endif /* !CONFIG_XEN */
++
++
+static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+{
+ unsigned int *v;
@@ -35670,8 +35769,6 @@
+ select_idle_routine(c);
+ detect_ht(c);
+
-+ modify_cpu_capabilities(c);
-+
+ /*
+ * On SMP, boot_cpu_data holds the common feature set between
+ * all CPUs; so make sure that we indicate which features are
@@ -38988,10 +39085,10 @@
+__setup("pagefaulttrace", enable_pagefaulttrace);
diff --git a/arch/x86_64/mm/init-xen.c b/arch/x86_64/mm/init-xen.c
new file mode 100644
-index 0000000..0d09c4e
+index 0000000..edf63e8
--- /dev/null
+++ b/arch/x86_64/mm/init-xen.c
-@@ -0,0 +1,1107 @@
+@@ -0,0 +1,1101 @@
+/*
+ * linux/arch/x86_64/mm/init.c
+ *
@@ -39238,7 +39335,6 @@
+ if (pud_none(*pud)) {
+ pmd = (pmd_t *) spp_getpage();
+ make_page_readonly(pmd, XENFEAT_writable_page_tables);
-+ xen_pmd_pin(__pa(pmd));
+ set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+ if (pmd != pmd_offset(pud, 0)) {
+ printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0));
@@ -39249,7 +39345,6 @@
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) spp_getpage();
+ make_page_readonly(pte, XENFEAT_writable_page_tables);
-+ xen_pte_pin(__pa(pte));
+ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
+ if (pte != pte_offset_kernel(pmd, 0)) {
+ printk("PAGETABLE BUG #02!\n");
@@ -39291,7 +39386,6 @@
+
+ pmd = (pmd_t *) spp_getpage();
+ make_page_readonly(pmd, XENFEAT_writable_page_tables);
-+ xen_pmd_pin(__pa(pmd));
+
+ set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+
@@ -39305,7 +39399,6 @@
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) spp_getpage();
+ make_page_readonly(pte, XENFEAT_writable_page_tables);
-+ xen_pte_pin(__pa(pte));
+
+ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
+ if (pte != pte_offset_kernel(pmd, 0)) {
@@ -39455,7 +39548,6 @@
+ }
+ pte = pte_save;
+ early_make_page_readonly(pte, XENFEAT_writable_page_tables);
-+ xen_pte_pin(pte_phys);
+ set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE));
+ }
+}
@@ -39494,7 +39586,6 @@
+
+ pmd = alloc_static_page(&pmd_phys);
+ early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
-+ xen_pmd_pin(pmd_phys);
+ spin_lock(&init_mm.page_table_lock);
+ set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
+ phys_pmd_init(pmd, paddr, end);
@@ -39539,9 +39630,6 @@
+
+ xen_pgd_pin(__pa_symbol(init_level4_pgt));
+ xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
-+ xen_pud_pin(__pa_symbol(level3_kernel_pgt));
-+ xen_pud_pin(__pa_symbol(level3_user_pgt));
-+ xen_pmd_pin(__pa_symbol(level2_kernel_pgt));
+
+ set_pgd((pgd_t *)(init_level4_user_pgt + 511),
+ mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
@@ -39575,7 +39663,6 @@
+ pte_page = alloc_static_page(&phys);
+ early_make_page_readonly(
+ pte_page, XENFEAT_writable_page_tables);
-+ xen_pte_pin(phys);
+ set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
+ } else {
+ addr = page[pmd_index(va)];
@@ -39656,7 +39743,6 @@
+ pud = alloc_static_page(&pud_phys);
+ early_make_page_readonly(pud, XENFEAT_writable_page_tables);
+ }
-+ xen_pud_pin(pud_phys);
+ next = start + PGDIR_SIZE;
+ if (next > end)
+ next = end;
@@ -39751,10 +39837,16 @@
+ free_area_init_node(0, NODE_DATA(0), zones,
+ __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
+
-+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
-+ HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++ if (!xen_feature(XENFEAT_auto_translated_physmap) ||
++ xen_start_info->shared_info >= xen_start_info->nr_pages) {
++ /* Switch to the real shared_info page, and clear the
++ * dummy page. */
++ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
++ HYPERVISOR_shared_info =
++ (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++ memset(empty_zero_page, 0, sizeof(empty_zero_page));
++ }
+
-+ memset(empty_zero_page, 0, sizeof(empty_zero_page));
+ init_mm.context.pinned = 1;
+
+ /* Setup mapping of lower 1st MB */
@@ -39931,7 +40023,6 @@
+ ClearPageReserved(virt_to_page(addr));
+ set_page_count(virt_to_page(addr), 1);
+ memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE);
-+ xen_pte_unpin(__pa(addr));
+ make_page_writable(
+ __va(__pa(addr)), XENFEAT_writable_page_tables);
+ /*
@@ -40101,10 +40192,10 @@
+ */
diff --git a/arch/x86_64/mm/pageattr-xen.c b/arch/x86_64/mm/pageattr-xen.c
new file mode 100644
-index 0000000..a2305bc
+index 0000000..8ac6663
--- /dev/null
+++ b/arch/x86_64/mm/pageattr-xen.c
-@@ -0,0 +1,382 @@
+@@ -0,0 +1,391 @@
+/*
+ * Copyright 2002 Andi Kleen, SuSE Labs.
+ * Thanks to Ben LaHaise for precious feedback.
@@ -40178,6 +40269,9 @@
+
+void mm_pin(struct mm_struct *mm)
+{
++ if (xen_feature(XENFEAT_writable_page_tables))
++ return;
++
+ spin_lock(&mm->page_table_lock);
+
+ mm_walk(mm, PAGE_KERNEL_RO);
@@ -40201,6 +40295,9 @@
+
+void mm_unpin(struct mm_struct *mm)
+{
++ if (xen_feature(XENFEAT_writable_page_tables))
++ return;
++
+ spin_lock(&mm->page_table_lock);
+
+ xen_pgd_unpin(__pa(mm->pgd));
@@ -40223,6 +40320,9 @@
+
+void mm_pin_all(void)
+{
++ if (xen_feature(XENFEAT_writable_page_tables))
++ return;
++
+ while (!list_empty(&mm_unpinned))
+ mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
+ context.unpinned));
@@ -40572,6 +40672,22 @@
if (!rsdp) {
printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
return -ENODEV;
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index c314156..ae89ed5 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device
+ up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
++
++ if (err > 0) /* success */
++ err = count;
++ else if (err == 0) /* driver didn't accept device */
++ err = -ENODEV;
+ }
+ put_device(dev);
+ put_bus(bus);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 29c41f4..e65a3ef 100644
--- a/drivers/char/mem.c
@@ -42100,10 +42216,10 @@
/*
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
new file mode 100644
-index 0000000..7a6a569
+index 0000000..f452b2f
--- /dev/null
+++ b/drivers/xen/Kconfig
-@@ -0,0 +1,200 @@
+@@ -0,0 +1,210 @@
+#
+# This Kconfig describe xen options
+#
@@ -42136,12 +42252,14 @@
+ default !XEN_PRIVILEGED_GUEST
+
+config XEN_PCIDEV_BACKEND
-+ bool "PCI device backend driver"
-+ select PCI
-+ default y if XEN_PRIVILEGED_GUEST
++ tristate "PCI device backend driver"
++ depends PCI
++ default XEN_PRIVILEGED_GUEST
+ help
+ The PCI device backend driver allows the kernel to export arbitrary
-+ PCI devices to other guests.
++ PCI devices to other guests. If you select this to be a module, you
++ will need to make sure no other driver has bound to the device(s)
++ you want to make visible to other guests.
+
+choice
+ prompt "PCI Backend Mode"
@@ -42293,6 +42411,14 @@
+ Disable serial port drivers, allowing the Xen console driver
+ to provide a serial console at ttyS0.
+
++config XEN_SYSFS
++ tristate "Export Xen attributes in sysfs"
++ depends on XEN
++ depends on SYSFS
++ default y
++ help
++ Xen hypervisor attributes will show up under /sys/hypervisor/.
++
+endmenu
+
+config HAVE_ARCH_ALLOC_SKB
@@ -42342,10 +42468,10 @@
+obj-y += balloon.o
diff --git a/drivers/xen/balloon/balloon.c b/drivers/xen/balloon/balloon.c
new file mode 100644
-index 0000000..6a70087
+index 0000000..6f8039a
--- /dev/null
+++ b/drivers/xen/balloon/balloon.c
-@@ -0,0 +1,585 @@
+@@ -0,0 +1,592 @@
+/******************************************************************************
+ * balloon.c
+ *
@@ -42355,8 +42481,11 @@
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -42816,6 +42945,7 @@
+ return -1;
+
+ current_pages = min(xen_start_info->nr_pages, max_pfn);
++ totalram_pages = current_pages;
+ target_pages = current_pages;
+ balloon_low = 0;
+ balloon_high = 0;
@@ -42861,7 +42991,7 @@
+}
+
+static int dealloc_pte_fn(
-+ pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
++ pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+ unsigned long mfn = pte_mfn(*pte);
+ int ret;
@@ -42891,10 +43021,11 @@
+ scrub_pages(vstart, 1 << order);
+
+ balloon_lock(flags);
-+ ret = generic_page_range(
-+ &init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL);
++ ret = apply_to_page_range(&init_mm, vstart,
++ PAGE_SIZE << order, dealloc_pte_fn, NULL);
+ BUG_ON(ret);
+ current_pages -= 1UL << order;
++ totalram_pages = current_pages;
+ balloon_unlock(flags);
+
+ schedule_work(&balloon_worker);
@@ -42918,9 +43049,11 @@
+ schedule_work(&balloon_worker);
+}
+
-+EXPORT_SYMBOL(balloon_update_driver_allowance);
-+EXPORT_SYMBOL(balloon_alloc_empty_page_range);
-+EXPORT_SYMBOL(balloon_dealloc_empty_page_range);
++EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
++EXPORT_SYMBOL_GPL(balloon_alloc_empty_page_range);
++EXPORT_SYMBOL_GPL(balloon_dealloc_empty_page_range);
++
++MODULE_LICENSE("Dual BSD/GPL");
+
+/*
+ * Local variables:
@@ -42942,10 +43075,10 @@
+blkbk-y := blkback.o xenbus.o interface.o vbd.o
diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c
new file mode 100644
-index 0000000..d624caf
+index 0000000..2de5f1c
--- /dev/null
+++ b/drivers/xen/blkback/blkback.c
-@@ -0,0 +1,596 @@
+@@ -0,0 +1,620 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/main.c
+ *
@@ -42957,6 +43090,30 @@
+ *
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Copyright (c) 2005, Christopher Clark
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#include <linux/spinlock.h>
@@ -43544,10 +43701,35 @@
+ */
diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h
new file mode 100644
-index 0000000..aab5a9f
+index 0000000..502a02c
--- /dev/null
+++ b/drivers/xen/blkback/common.h
-@@ -0,0 +1,123 @@
+@@ -0,0 +1,148 @@
++/*
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
+
+#ifndef __BLKIF__BACKEND__COMMON_H__
+#define __BLKIF__BACKEND__COMMON_H__
@@ -43673,16 +43855,40 @@
+ */
diff --git a/drivers/xen/blkback/interface.c b/drivers/xen/blkback/interface.c
new file mode 100644
-index 0000000..090d107
+index 0000000..75b9f74
--- /dev/null
+++ b/drivers/xen/blkback/interface.c
-@@ -0,0 +1,164 @@
+@@ -0,0 +1,188 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/interface.c
+ *
+ * Block-device interface management.
+ *
+ * Copyright (c) 2004, Keir Fraser
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#include "common.h"
@@ -43843,16 +44049,40 @@
+ */
diff --git a/drivers/xen/blkback/vbd.c b/drivers/xen/blkback/vbd.c
new file mode 100644
-index 0000000..b2d0939
+index 0000000..d1d38dc
--- /dev/null
+++ b/drivers/xen/blkback/vbd.c
-@@ -0,0 +1,102 @@
+@@ -0,0 +1,126 @@
+/******************************************************************************
+ * blkback/vbd.c
+ *
+ * Routines for managing virtual block devices (VBDs).
+ *
+ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#include "common.h"
@@ -43951,10 +44181,10 @@
+ */
diff --git a/drivers/xen/blkback/xenbus.c b/drivers/xen/blkback/xenbus.c
new file mode 100644
-index 0000000..b1934d1
+index 0000000..82625a9
--- /dev/null
+++ b/drivers/xen/blkback/xenbus.c
-@@ -0,0 +1,421 @@
+@@ -0,0 +1,419 @@
+/* Xenbus code for blkif backend
+ Copyright (C) 2005 Rusty Russell <rusty at rustcorp.com.au>
+ Copyright (C) 2005 XenSource Ltd
@@ -44073,15 +44303,13 @@
+ const struct xenbus_device_id *id)
+{
+ int err;
-+ struct backend_info *be = kmalloc(sizeof(struct backend_info),
++ struct backend_info *be = kzalloc(sizeof(struct backend_info),
+ GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_fatal(dev, -ENOMEM,
+ "allocating backend structure");
+ return -ENOMEM;
+ }
-+ memset(be, 0, sizeof(*be));
-+
+ be->dev = dev;
+ dev->data = be;
+
@@ -44401,10 +44629,10 @@
+
diff --git a/drivers/xen/blkfront/blkfront.c b/drivers/xen/blkfront/blkfront.c
new file mode 100644
-index 0000000..c8c9dec
+index 0000000..6e29fa3
--- /dev/null
+++ b/drivers/xen/blkfront/blkfront.c
-@@ -0,0 +1,831 @@
+@@ -0,0 +1,821 @@
+/******************************************************************************
+ * blkfront.c
+ *
@@ -44497,26 +44725,21 @@
+ return err;
+ }
+
-+ info = kmalloc(sizeof(*info), GFP_KERNEL);
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+ return -ENOMEM;
+ }
++
+ info->xbdev = dev;
+ info->vdevice = vdevice;
+ info->connected = BLKIF_STATE_DISCONNECTED;
-+ info->mi = NULL;
-+ info->gd = NULL;
+ INIT_WORK(&info->work, blkif_restart_queue, (void *)info);
+
-+ info->shadow_free = 0;
-+ memset(info->shadow, 0, sizeof(info->shadow));
+ for (i = 0; i < BLK_RING_SIZE; i++)
+ info->shadow[i].req.id = i+1;
+ info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
-+ info->users = 0;
-+
+ /* Front end dir is a number, which is used as the id. */
+ info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
+ dev->data = info;
@@ -44759,11 +44982,7 @@
+
+ DPRINTK("blkfront_closing: %s removed\n", dev->nodename);
+
-+ if (info->mi) {
-+ DPRINTK("Calling xlvbd_del\n");
-+ xlvbd_del(info);
-+ info->mi = NULL;
-+ }
++ xlvbd_del(info);
+
+ xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
+}
@@ -45226,7 +45445,6 @@
+
+MODULE_LICENSE("Dual BSD/GPL");
+
-+
+/*
+ * Local variables:
+ * c-file-style: "linux"
@@ -45238,10 +45456,10 @@
+ */
diff --git a/drivers/xen/blkfront/block.h b/drivers/xen/blkfront/block.h
new file mode 100644
-index 0000000..ecede04
+index 0000000..d6a9314
--- /dev/null
+++ b/drivers/xen/blkfront/block.h
-@@ -0,0 +1,162 @@
+@@ -0,0 +1,165 @@
+/******************************************************************************
+ * block.h
+ *
@@ -45251,8 +45469,11 @@
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004-2005, Christian Limpach
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -45406,10 +45627,10 @@
+ */
diff --git a/drivers/xen/blkfront/vbd.c b/drivers/xen/blkfront/vbd.c
new file mode 100644
-index 0000000..d97f798
+index 0000000..830b3dd
--- /dev/null
+++ b/drivers/xen/blkfront/vbd.c
-@@ -0,0 +1,323 @@
+@@ -0,0 +1,327 @@
+/******************************************************************************
+ * vbd.c
+ *
@@ -45419,8 +45640,11 @@
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004-2005, Christian Limpach
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -45509,12 +45733,10 @@
+{
+ struct xlbd_major_info *ptr;
+
-+ ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
++ ptr = kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
+ if (ptr == NULL)
+ return NULL;
+
-+ memset(ptr, 0, sizeof(struct xlbd_major_info));
-+
+ ptr->major = major;
+
+ switch (index) {
@@ -45628,6 +45850,10 @@
+ int nr_minors = 1;
+ int err = -ENODEV;
+
++ BUG_ON(info->gd != NULL);
++ BUG_ON(info->mi != NULL);
++ BUG_ON(info->rq != NULL);
++
+ mi = xlbd_get_major_info(vdevice);
+ if (mi == NULL)
+ goto out;
@@ -45680,6 +45906,7 @@
+ out:
+ if (mi)
+ xlbd_put_major_info(mi);
++ info->mi = NULL;
+ return err;
+}
+
@@ -45706,22 +45933,20 @@
+void
+xlvbd_del(struct blkfront_info *info)
+{
-+ struct block_device *bd;
-+
-+ bd = bdget(info->dev);
-+ if (bd == NULL)
-+ return;
-+
-+ if (info->gd == NULL)
++ if (info->mi == NULL)
+ return;
+
++ BUG_ON(info->gd == NULL);
+ del_gendisk(info->gd);
+ put_disk(info->gd);
++ info->gd = NULL;
++
+ xlbd_put_major_info(info->mi);
+ info->mi = NULL;
-+ blk_cleanup_queue(info->rq);
+
-+ bdput(bd);
++ BUG_ON(info->rq == NULL);
++ blk_cleanup_queue(info->rq);
++ info->rq = NULL;
+}
+
+/*
@@ -46928,10 +47153,10 @@
+ */
diff --git a/drivers/xen/blktap/xenbus.c b/drivers/xen/blktap/xenbus.c
new file mode 100644
-index 0000000..3dc9167
+index 0000000..d97660d
--- /dev/null
+++ b/drivers/xen/blktap/xenbus.c
-@@ -0,0 +1,234 @@
+@@ -0,0 +1,233 @@
+/* Xenbus code for blkif tap
+
+ A Warfield.
@@ -47075,12 +47300,11 @@
+ char *frontend;
+ int err;
+
-+ be = kmalloc(sizeof(*be), GFP_KERNEL);
++ be = kzalloc(sizeof(*be), GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ return -ENOMEM;
+ }
-+ memset(be, 0, sizeof(*be));
+
+ frontend = NULL;
+ err = xenbus_gather(dev->nodename,
@@ -47382,10 +47606,10 @@
+obj-y := console.o xencons_ring.o
diff --git a/drivers/xen/console/console.c b/drivers/xen/console/console.c
new file mode 100644
-index 0000000..ae8255c
+index 0000000..360e550
--- /dev/null
+++ b/drivers/xen/console/console.c
-@@ -0,0 +1,643 @@
+@@ -0,0 +1,648 @@
+/******************************************************************************
+ * console.c
+ *
@@ -47393,8 +47617,11 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser.
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -48020,6 +48247,8 @@
+
+module_init(xencons_init);
+
++MODULE_LICENSE("Dual BSD/GPL");
++
+/*
+ * Local variables:
+ * c-file-style: "linux"
@@ -48031,10 +48260,36 @@
+ */
diff --git a/drivers/xen/console/xencons_ring.c b/drivers/xen/console/xencons_ring.c
new file mode 100644
-index 0000000..8abb0a4
+index 0000000..3bb5631
--- /dev/null
+++ b/drivers/xen/console/xencons_ring.c
-@@ -0,0 +1,125 @@
+@@ -0,0 +1,151 @@
++/*
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/errno.h>
@@ -48162,10 +48417,10 @@
+ */
diff --git a/drivers/xen/core/Makefile b/drivers/xen/core/Makefile
new file mode 100644
-index 0000000..1d57a5b
+index 0000000..a971d3c
--- /dev/null
+++ b/drivers/xen/core/Makefile
-@@ -0,0 +1,9 @@
+@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
@@ -48175,12 +48430,14 @@
+obj-$(CONFIG_PROC_FS) += xen_proc.o
+obj-$(CONFIG_NET) += skbuff.o
+obj-$(CONFIG_SMP) += smpboot.o
++obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
++obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
diff --git a/drivers/xen/core/evtchn.c b/drivers/xen/core/evtchn.c
new file mode 100644
-index 0000000..58f08c6
+index 0000000..5fbd1e0
--- /dev/null
+++ b/drivers/xen/core/evtchn.c
-@@ -0,0 +1,822 @@
+@@ -0,0 +1,863 @@
+/******************************************************************************
+ * evtchn.c
+ *
@@ -48188,8 +48445,11 @@
+ *
+ * Copyright (c) 2002-2005, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -48238,17 +48498,37 @@
+
+/* Packed IRQ information: binding type, sub-type index, and event channel. */
+static u32 irq_info[NR_IRQS];
++
+/* Binding types. */
+enum { IRQT_UNBOUND, IRQT_PIRQ, IRQT_VIRQ, IRQT_IPI, IRQT_EVTCHN };
++
+/* Constructor for packed IRQ information. */
-+#define mk_irq_info(type, index, evtchn) \
-+ (((u32)(type) << 24) | ((u32)(index) << 16) | (u32)(evtchn))
++static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn)
++{
++ return ((type << 24) | (index << 16) | evtchn);
++}
++
+/* Convenient shorthand for packed representation of an unbound IRQ. */
+#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
-+/* Accessor macros for packed IRQ information. */
-+#define evtchn_from_irq(irq) ((u16)(irq_info[irq]))
-+#define index_from_irq(irq) ((u8)(irq_info[irq] >> 16))
-+#define type_from_irq(irq) ((u8)(irq_info[irq] >> 24))
++
++/*
++ * Accessors for packed IRQ information.
++ */
++
++static inline unsigned int evtchn_from_irq(int irq)
++{
++ return (u16)(irq_info[irq]);
++}
++
++static inline unsigned int index_from_irq(int irq)
++{
++ return (u8)(irq_info[irq] >> 16);
++}
++
++static inline unsigned int type_from_irq(int irq)
++{
++ return (u8)(irq_info[irq] >> 24);
++}
+
+/* IRQ <-> VIRQ mapping. */
+DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]);
@@ -48270,10 +48550,13 @@
+static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
+
-+#define active_evtchns(cpu,sh,idx) \
-+ ((sh)->evtchn_pending[idx] & \
-+ cpu_evtchn_mask[cpu][idx] & \
-+ ~(sh)->evtchn_mask[idx])
++static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
++ unsigned int idx)
++{
++ return (sh->evtchn_pending[idx] &
++ cpu_evtchn_mask[cpu][idx] &
++ ~sh->evtchn_mask[idx]);
++}
+
+static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+{
@@ -48289,22 +48572,37 @@
+ memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
+}
+
-+#define cpu_from_evtchn(evtchn) (cpu_evtchn[evtchn])
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++ return cpu_evtchn[evtchn];
++}
+
+#else
+
-+#define active_evtchns(cpu,sh,idx) \
-+ ((sh)->evtchn_pending[idx] & \
-+ ~(sh)->evtchn_mask[idx])
-+#define bind_evtchn_to_cpu(chn,cpu) ((void)0)
-+#define init_evtchn_cpu_bindings() ((void)0)
-+#define cpu_from_evtchn(evtchn) (0)
++static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
++ unsigned int idx)
++{
++ return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]);
++}
+
-+#endif
++static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++{
++}
+
-+/* Upcall to generic IRQ layer. */
-+#ifdef CONFIG_X86
-+extern fastcall unsigned int do_IRQ(struct pt_regs *regs);
++static void init_evtchn_cpu_bindings(void)
++{
++}
++
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++ return 0;
++}
++
++#endif
++
++/* Upcall to generic IRQ layer. */
++#ifdef CONFIG_X86
++extern fastcall unsigned int do_IRQ(struct pt_regs *regs);
+#if defined (__i386__)
+static inline void exit_idle(void) {}
+#define IRQ_REG orig_eax
@@ -48330,7 +48628,7 @@
+{
+ (void)HYPERVISOR_xen_version(0, NULL);
+}
-+EXPORT_SYMBOL(force_evtchn_callback);
++EXPORT_SYMBOL_GPL(force_evtchn_callback);
+
+/* NB. Interrupts are disabled on entry. */
+asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
@@ -48506,7 +48804,7 @@
+
+ return irq;
+}
-+EXPORT_SYMBOL(bind_evtchn_to_irqhandler);
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
+
+int bind_virq_to_irqhandler(
+ unsigned int virq,
@@ -48528,7 +48826,7 @@
+
+ return irq;
+}
-+EXPORT_SYMBOL(bind_virq_to_irqhandler);
++EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
+
+int bind_ipi_to_irqhandler(
+ unsigned int ipi,
@@ -48550,14 +48848,14 @@
+
+ return irq;
+}
-+EXPORT_SYMBOL(bind_ipi_to_irqhandler);
++EXPORT_SYMBOL_GPL(bind_ipi_to_irqhandler);
+
+void unbind_from_irqhandler(unsigned int irq, void *dev_id)
+{
+ free_irq(irq, dev_id);
+ unbind_from_irq(irq);
+}
-+EXPORT_SYMBOL(unbind_from_irqhandler);
++EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
+
+#ifdef CONFIG_SMP
+static void do_nothing_function(void *ign)
@@ -48822,14 +49120,14 @@
+ if (VALID_EVTCHN(evtchn))
+ notify_remote_via_evtchn(evtchn);
+}
-+EXPORT_SYMBOL(notify_remote_via_irq);
++EXPORT_SYMBOL_GPL(notify_remote_via_irq);
+
+void mask_evtchn(int port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ synch_set_bit(port, &s->evtchn_mask[0]);
+}
-+EXPORT_SYMBOL(mask_evtchn);
++EXPORT_SYMBOL_GPL(mask_evtchn);
+
+void unmask_evtchn(int port)
+{
@@ -48860,7 +49158,7 @@
+ force_evtchn_callback();
+ }
+}
-+EXPORT_SYMBOL(unmask_evtchn);
++EXPORT_SYMBOL_GPL(unmask_evtchn);
+
+void irq_resume(void)
+{
@@ -49005,7 +49303,7 @@
+ */
diff --git a/drivers/xen/core/features.c b/drivers/xen/core/features.c
new file mode 100644
-index 0000000..297d13f
+index 0000000..ad1f0b4
--- /dev/null
+++ b/drivers/xen/core/features.c
@@ -0,0 +1,29 @@
@@ -49023,7 +49321,7 @@
+#include <xen/features.h>
+
+u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
-+EXPORT_SYMBOL(xen_features);
++EXPORT_SYMBOL_GPL(xen_features);
+
+void setup_xen_features(void)
+{
@@ -49040,10 +49338,10 @@
+}
diff --git a/drivers/xen/core/gnttab.c b/drivers/xen/core/gnttab.c
new file mode 100644
-index 0000000..0f1a295
+index 0000000..1049934
--- /dev/null
+++ b/drivers/xen/core/gnttab.c
-@@ -0,0 +1,426 @@
+@@ -0,0 +1,460 @@
+/******************************************************************************
+ * gnttab.c
+ *
@@ -49052,8 +49350,11 @@
+ * Copyright (c) 2005, Christopher Clark
+ * Copyright (c) 2004-2005, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -49077,6 +49378,8 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+#include <xen/interface/xen.h>
+#include <asm/fixmap.h>
@@ -49096,21 +49399,21 @@
+ printk(KERN_WARNING "xen_grant: " fmt, ##args)
+
+
-+EXPORT_SYMBOL(gnttab_grant_foreign_access);
-+EXPORT_SYMBOL(gnttab_end_foreign_access_ref);
-+EXPORT_SYMBOL(gnttab_end_foreign_access);
-+EXPORT_SYMBOL(gnttab_query_foreign_access);
-+EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
-+EXPORT_SYMBOL(gnttab_end_foreign_transfer_ref);
-+EXPORT_SYMBOL(gnttab_end_foreign_transfer);
-+EXPORT_SYMBOL(gnttab_alloc_grant_references);
-+EXPORT_SYMBOL(gnttab_free_grant_references);
-+EXPORT_SYMBOL(gnttab_free_grant_reference);
-+EXPORT_SYMBOL(gnttab_claim_grant_reference);
-+EXPORT_SYMBOL(gnttab_release_grant_reference);
-+EXPORT_SYMBOL(gnttab_request_free_callback);
-+EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
-+EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
++EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
++EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
++EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
++EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
++EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
++EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
++EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
+
+/* External tools reserve first few grant table entries. */
+#define NR_RESERVED_ENTRIES 8
@@ -49123,7 +49426,7 @@
+static grant_ref_t gnttab_free_head;
+static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED;
+
-+static grant_entry_t *shared;
++static grant_entry_t *shared = NULL;
+
+static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
+
@@ -49400,26 +49703,57 @@
+ spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+
++#ifndef __ia64__
++static int map_pte_fn(pte_t *pte, struct page *pmd_page,
++ unsigned long addr, void *data)
++{
++ unsigned long **frames = (unsigned long **)data;
++
++ set_pte_at(&init_mm, addr, pte, pfn_pte_ma((*frames)[0], PAGE_KERNEL));
++ (*frames)++;
++ return 0;
++}
++
++static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
++ unsigned long addr, void *data)
++{
++
++ set_pte_at(&init_mm, addr, pte, __pte(0));
++ return 0;
++}
++#endif
++
+int
+gnttab_resume(void)
+{
+ gnttab_setup_table_t setup;
-+ unsigned long frames[NR_GRANT_FRAMES];
-+ int i;
++ unsigned long frames[NR_GRANT_FRAMES];
++ int rc;
++#ifndef __ia64__
++ void *pframes = frames;
++ struct vm_struct *area;
++#endif
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = NR_GRANT_FRAMES;
+ setup.frame_list = frames;
+
-+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1));
-+ BUG_ON(setup.status != 0);
++ rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
++ BUG_ON(rc || setup.status);
+
-+#ifdef __ia64__
++#ifndef __ia64__
++ if (shared == NULL) {
++ area = get_vm_area(PAGE_SIZE * NR_GRANT_FRAMES, VM_IOREMAP);
++ BUG_ON(area == NULL);
++ shared = area->addr;
++ }
++ rc = apply_to_page_range(&init_mm, (unsigned long)shared,
++ PAGE_SIZE * NR_GRANT_FRAMES,
++ map_pte_fn, &pframes);
++ BUG_ON(rc);
++#else
+ shared = __va(frames[0] << PAGE_SHIFT);
+ printk("grant table at %p\n", shared);
-+#else
-+ for (i = 0; i < NR_GRANT_FRAMES; i++)
-+ set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
+#endif
+
+ return 0;
@@ -49428,10 +49762,12 @@
+int
+gnttab_suspend(void)
+{
-+ int i;
+
-+ for (i = 0; i < NR_GRANT_FRAMES; i++)
-+ clear_fixmap(FIX_GNTTAB_END - i);
++#ifndef __ia64__
++ apply_to_page_range(&init_mm, (unsigned long)shared,
++ PAGE_SIZE * NR_GRANT_FRAMES,
++ unmap_pte_fn, NULL);
++#endif
+
+ return 0;
+}
@@ -49446,10 +49782,6 @@
+
+ BUG_ON(gnttab_resume());
+
-+#ifndef __ia64__
-+ shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
-+#endif
-+
+ for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
+ gnttab_list[i] = i + 1;
+ gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
@@ -49470,12 +49802,75 @@
+ * tab-width: 8
+ * End:
+ */
+diff --git a/drivers/xen/core/hypervisor_sysfs.c b/drivers/xen/core/hypervisor_sysfs.c
+new file mode 100644
+index 0000000..f963902
+--- /dev/null
++++ b/drivers/xen/core/hypervisor_sysfs.c
+@@ -0,0 +1,57 @@
++/*
++ * copyright (c) 2006 IBM Corporation
++ * Authored by: Mike D. Day <ncmike at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/kobject.h>
++#include <xen/hypervisor_sysfs.h>
++
++decl_subsys(hypervisor, NULL, NULL);
++
++static ssize_t hyp_sysfs_show(struct kobject *kobj,
++ struct attribute *attr,
++ char *buffer)
++{
++ struct hyp_sysfs_attr *hyp_attr;
++ hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
++ if (hyp_attr->show)
++ return hyp_attr->show(hyp_attr, buffer);
++ return 0;
++}
++
++static ssize_t hyp_sysfs_store(struct kobject *kobj,
++ struct attribute *attr,
++ const char *buffer,
++ size_t len)
++{
++ struct hyp_sysfs_attr *hyp_attr;
++ hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
++ if (hyp_attr->store)
++ return hyp_attr->store(hyp_attr, buffer, len);
++ return 0;
++}
++
++struct sysfs_ops hyp_sysfs_ops = {
++ .show = hyp_sysfs_show,
++ .store = hyp_sysfs_store,
++};
++
++static struct kobj_type hyp_sysfs_kobj_type = {
++ .sysfs_ops = &hyp_sysfs_ops,
++};
++
++static int __init hypervisor_subsys_init(void)
++{
++ hypervisor_subsys.kset.kobj.ktype = &hyp_sysfs_kobj_type;
++ return subsystem_register(&hypervisor_subsys);
++}
++
++device_initcall(hypervisor_subsys_init);
++EXPORT_SYMBOL_GPL(hypervisor_subsys);
diff --git a/drivers/xen/core/reboot.c b/drivers/xen/core/reboot.c
new file mode 100644
-index 0000000..1fa1f56
+index 0000000..e63e404
--- /dev/null
+++ b/drivers/xen/core/reboot.c
-@@ -0,0 +1,441 @@
+@@ -0,0 +1,425 @@
+#define __KERNEL_SYSCALLS__
+#include <linux/version.h>
+#include <linux/kernel.h>
@@ -49503,9 +49898,10 @@
+EXPORT_SYMBOL(pm_power_off);
+#endif
+
++extern void ctrl_alt_del(void);
++
+#define SHUTDOWN_INVALID -1
+#define SHUTDOWN_POWEROFF 0
-+#define SHUTDOWN_REBOOT 1
+#define SHUTDOWN_SUSPEND 2
+/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
+ * report a crash, not be instructed to crash!
@@ -49600,7 +49996,7 @@
+ lock_cpu_hotplug();
+#ifdef CONFIG_SMP
+ /*
-+ * Take all other CPUs offline. We hold the hotplug semaphore to
++ * Take all other CPUs offline. We hold the hotplug mutex to
+ * avoid other processes bringing up CPUs under our feet.
+ */
+ cpus_clear(prev_online_cpus);
@@ -49712,33 +50108,19 @@
+{
+ static char *envp[] = { "HOME=/", "TERM=linux",
+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
-+ static char *restart_argv[] = { "/sbin/reboot", NULL };
+ static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
+
+ extern asmlinkage long sys_reboot(int magic1, int magic2,
+ unsigned int cmd, void *arg);
+
-+ daemonize("shutdown");
-+
-+ switch (shutting_down) {
-+ case SHUTDOWN_POWEROFF:
-+ case SHUTDOWN_HALT:
++ if ((shutting_down == SHUTDOWN_POWEROFF) ||
++ (shutting_down == SHUTDOWN_HALT)) {
+ if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) {
+ sys_reboot(LINUX_REBOOT_MAGIC1,
+ LINUX_REBOOT_MAGIC2,
+ LINUX_REBOOT_CMD_POWER_OFF,
+ NULL);
+ }
-+ break;
-+
-+ case SHUTDOWN_REBOOT:
-+ if (execve("/sbin/reboot", restart_argv, envp) < 0) {
-+ sys_reboot(LINUX_REBOOT_MAGIC1,
-+ LINUX_REBOOT_MAGIC2,
-+ LINUX_REBOOT_CMD_RESTART,
-+ NULL);
-+ }
-+ break;
+ }
+
+ shutting_down = SHUTDOWN_INVALID; /* could try again */
@@ -49809,7 +50191,7 @@
+ if (strcmp(str, "poweroff") == 0)
+ shutting_down = SHUTDOWN_POWEROFF;
+ else if (strcmp(str, "reboot") == 0)
-+ shutting_down = SHUTDOWN_REBOOT;
++ ctrl_alt_del();
+ else if (strcmp(str, "suspend") == 0)
+ shutting_down = SHUTDOWN_SUSPEND;
+ else if (strcmp(str, "halt") == 0)
@@ -49869,8 +50251,6 @@
+};
+#endif
+
-+static struct notifier_block xenstore_notifier;
-+
+static int setup_shutdown_watcher(struct notifier_block *notifier,
+ unsigned long event,
+ void *data)
@@ -49898,11 +50278,10 @@
+
+static int __init setup_shutdown_event(void)
+{
-+
-+ xenstore_notifier.notifier_call = setup_shutdown_watcher;
-+
++ static struct notifier_block xenstore_notifier = {
++ .notifier_call = setup_shutdown_watcher
++ };
+ register_xenstore_notifier(&xenstore_notifier);
-+
+ return 0;
+}
+
@@ -50572,6 +50951,323 @@
+ * tab-width: 8
+ * End:
+ */
+diff --git a/drivers/xen/core/xen_sysfs.c b/drivers/xen/core/xen_sysfs.c
+new file mode 100644
+index 0000000..e26ab7f
+--- /dev/null
++++ b/drivers/xen/core/xen_sysfs.c
+@@ -0,0 +1,311 @@
++/*
++ * copyright (c) 2006 IBM Corporation
++ * Authored by: Mike D. Day <ncmike at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <asm/hypervisor.h>
++#include <xen/features.h>
++#include <xen/hypervisor_sysfs.h>
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Mike D. Day <ncmike at us.ibm.com>");
++
++static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ return sprintf(buffer, "xen\n");
++}
++
++HYPERVISOR_ATTR_RO(type);
++
++static int __init xen_sysfs_type_init(void)
++{
++ return sysfs_create_file(&hypervisor_subsys.kset.kobj, &type_attr.attr);
++}
++
++static void xen_sysfs_type_destroy(void)
++{
++ sysfs_remove_file(&hypervisor_subsys.kset.kobj, &type_attr.attr);
++}
++
++/* xen version attributes */
++static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int version = HYPERVISOR_xen_version(XENVER_version, NULL);
++ if (version)
++ return sprintf(buffer, "%d\n", version >> 16);
++ return -ENODEV;
++}
++
++HYPERVISOR_ATTR_RO(major);
++
++static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int version = HYPERVISOR_xen_version(XENVER_version, NULL);
++ if (version)
++ return sprintf(buffer, "%d\n", version & 0xff);
++ return -ENODEV;
++}
++
++HYPERVISOR_ATTR_RO(minor);
++
++static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ char *extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
++ if (extra) {
++ ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
++ if (!ret)
++ return sprintf(buffer, "%s\n", extra);
++ kfree(extra);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(extra);
++
++static struct attribute *version_attrs[] = {
++ &major_attr.attr,
++ &minor_attr.attr,
++ &extra_attr.attr,
++ NULL
++};
++
++static struct attribute_group version_group = {
++ .name = "version",
++ .attrs = version_attrs,
++};
++
++static int __init xen_sysfs_version_init(void)
++{
++ return sysfs_create_group(&hypervisor_subsys.kset.kobj, &version_group);
++}
++
++static void xen_sysfs_version_destroy(void)
++{
++ sysfs_remove_group(&hypervisor_subsys.kset.kobj, &version_group);
++}
++
++/* xen compilation attributes */
++
++static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ struct xen_compile_info *info =
++ kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
++ if (info) {
++ ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
++ if (!ret)
++ ret = sprintf(buffer, "%s\n", info->compiler);
++ kfree(info);
++ } else
++ ret = -ENOMEM;
++
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(compiler);
++
++static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ struct xen_compile_info *info;
++
++ info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
++ if (info) {
++ ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
++ if (!ret)
++ ret = sprintf(buffer, "%s\n", info->compile_by);
++ kfree(info);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(compiled_by);
++
++static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ struct xen_compile_info *info;
++
++ info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
++ if (info) {
++ ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
++ if (!ret)
++ ret = sprintf(buffer, "%s\n", info->compile_date);
++ kfree(info);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(compile_date);
++
++static struct attribute *xen_compile_attrs[] = {
++ &compiler_attr.attr,
++ &compiled_by_attr.attr,
++ &compile_date_attr.attr,
++ NULL
++};
++
++static struct attribute_group xen_compilation_group = {
++ .name = "compilation",
++ .attrs = xen_compile_attrs,
++};
++
++int __init static xen_compilation_init(void)
++{
++ return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++ &xen_compilation_group);
++}
++
++static void xen_compilation_destroy(void)
++{
++ sysfs_remove_group(&hypervisor_subsys.kset.kobj,
++ &xen_compilation_group);
++}
++
++/* xen properties info */
++
++static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ char *caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
++ if (caps) {
++ ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
++ if (!ret)
++ ret = sprintf(buffer, "%s\n", caps);
++ kfree(caps);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(capabilities);
++
++static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ char *cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
++ if (cset) {
++ ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
++ if (!ret)
++ ret = sprintf(buffer, "%s\n", cset);
++ kfree(cset);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(changeset);
++
++static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ int ret;
++ struct xen_platform_parameters *parms =
++ kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
++ if (parms) {
++ ret = HYPERVISOR_xen_version(XENVER_platform_parameters, parms);
++ if (!ret)
++ ret = sprintf(buffer, "%lx\n", parms->virt_start);
++ kfree(parms);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++HYPERVISOR_ATTR_RO(virtual_start);
++
++/* eventually there will be several more features to export */
++static ssize_t xen_feature_show(int index, char *buffer)
++{
++ int ret;
++
++ struct xen_feature_info *info =
++ kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL);
++ if (info) {
++ info->submap_idx = index;
++ ret = HYPERVISOR_xen_version(XENVER_get_features, info);
++ if (!ret)
++ ret = sprintf(buffer, "%d\n", info->submap);
++ kfree(info);
++ } else
++ ret = -ENOMEM;
++ return ret;
++}
++
++static ssize_t writable_pt_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++ return xen_feature_show(XENFEAT_writable_page_tables, buffer);
++}
++
++HYPERVISOR_ATTR_RO(writable_pt);
++
++static struct attribute *xen_properties_attrs[] = {
++ &capabilities_attr.attr,
++ &changeset_attr.attr,
++ &virtual_start_attr.attr,
++ &writable_pt_attr.attr,
++ NULL
++};
++
++static struct attribute_group xen_properties_group = {
++ .name = "properties",
++ .attrs = xen_properties_attrs,
++};
++
++static int __init xen_properties_init(void)
++{
++ return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++ &xen_properties_group);
++}
++
++static void xen_properties_destroy(void)
++{
++ sysfs_remove_group(&hypervisor_subsys.kset.kobj, &xen_properties_group);
++}
++
++static int __init hyper_sysfs_init(void)
++{
++ int ret = xen_sysfs_type_init();
++ if (ret)
++ goto out;
++ ret = xen_sysfs_version_init();
++ if (ret)
++ goto version_out;
++ ret = xen_compilation_init();
++ if (ret)
++ goto comp_out;
++ ret = xen_properties_init();
++ if (!ret)
++ goto out;
++
++ xen_compilation_destroy();
++comp_out:
++ xen_sysfs_version_destroy();
++version_out:
++ xen_sysfs_type_destroy();
++out:
++ return ret;
++}
++
++static void hyper_sysfs_exit(void)
++{
++ xen_properties_destroy();
++ xen_compilation_destroy();
++ xen_sysfs_version_destroy();
++ xen_sysfs_type_destroy();
++
++}
++
++module_init(hyper_sysfs_init);
++module_exit(hyper_sysfs_exit);
diff --git a/drivers/xen/evtchn/Makefile b/drivers/xen/evtchn/Makefile
new file mode 100644
index 0000000..7b082a0
@@ -50582,10 +51278,10 @@
+obj-y := evtchn.o
diff --git a/drivers/xen/evtchn/evtchn.c b/drivers/xen/evtchn/evtchn.c
new file mode 100644
-index 0000000..7222429
+index 0000000..2975fe0
--- /dev/null
+++ b/drivers/xen/evtchn/evtchn.c
-@@ -0,0 +1,459 @@
+@@ -0,0 +1,464 @@
+/******************************************************************************
+ * evtchn.c
+ *
@@ -50594,8 +51290,11 @@
+ * Copyright (c) 2004-2005, K A Fraser
+ * Multi-process extensions Copyright (c) 2004, Steven Smith
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -51036,6 +51735,8 @@
+module_init(evtchn_init);
+module_exit(evtchn_cleanup);
+
++MODULE_LICENSE("Dual BSD/GPL");
++
+/*
+ * Local variables:
+ * c-file-style: "linux"
@@ -51047,19 +51748,21 @@
+ */
diff --git a/drivers/xen/net_driver_util.c b/drivers/xen/net_driver_util.c
new file mode 100644
-index 0000000..10688f9
+index 0000000..43b9fb7
--- /dev/null
+++ b/drivers/xen/net_driver_util.c
-@@ -0,0 +1,67 @@
+@@ -0,0 +1,68 @@
+/*****************************************************************************
+ *
+ * Utility functions for Xen network devices.
+ *
+ * Copyright (c) 2005 XenSource Ltd.
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following
-+ * license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this source file (the "Software"), to deal in the Software without
@@ -51080,7 +51783,6 @@
+ * DEALINGS IN THE SOFTWARE.
+ */
+
-+
+#include <linux/if_ether.h>
+#include <linux/err.h>
+#include <linux/module.h>
@@ -51107,7 +51809,7 @@
+ kfree(macstr);
+ return 0;
+}
-+EXPORT_SYMBOL(xen_net_read_mac);
++EXPORT_SYMBOL_GPL(xen_net_read_mac);
+
+/*
+ * Local variables:
@@ -51131,12 +51833,36 @@
+netloop-y := loopback.o
diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
new file mode 100644
-index 0000000..61f8d58
+index 0000000..ab52a03
--- /dev/null
+++ b/drivers/xen/netback/common.h
-@@ -0,0 +1,110 @@
+@@ -0,0 +1,134 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/common.h
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#ifndef __NETIF__BACKEND__COMMON_H__
@@ -51247,16 +51973,40 @@
+ */
diff --git a/drivers/xen/netback/interface.c b/drivers/xen/netback/interface.c
new file mode 100644
-index 0000000..a27533c
+index 0000000..79944d6
--- /dev/null
+++ b/drivers/xen/netback/interface.c
-@@ -0,0 +1,320 @@
+@@ -0,0 +1,344 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/interface.c
+ *
+ * Network-device interface management.
+ *
+ * Copyright (c) 2004-2005, Keir Fraser
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#include "common.h"
@@ -51573,10 +52323,10 @@
+ */
diff --git a/drivers/xen/netback/loopback.c b/drivers/xen/netback/loopback.c
new file mode 100644
-index 0000000..a5a11cc
+index 0000000..e9f354a
--- /dev/null
+++ b/drivers/xen/netback/loopback.c
-@@ -0,0 +1,231 @@
+@@ -0,0 +1,255 @@
+/******************************************************************************
+ * netback/loopback.c
+ *
@@ -51598,6 +52348,30 @@
+ * (to avoid confusing the Etherbridge).
+ *
+ * Copyright (c) 2005 K A Fraser
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
@@ -51810,10 +52584,10 @@
+ */
diff --git a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c
new file mode 100644
-index 0000000..64173fa
+index 0000000..41d4bf9
--- /dev/null
+++ b/drivers/xen/netback/netback.c
-@@ -0,0 +1,835 @@
+@@ -0,0 +1,859 @@
+/******************************************************************************
+ * drivers/xen/netback/netback.c
+ *
@@ -51824,6 +52598,30 @@
+ * drivers/xen/netfront/netfront.c
+ *
+ * Copyright (c) 2002-2005, K A Fraser
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
+ */
+
+#include "common.h"
@@ -52123,7 +52921,7 @@
+ if (make_rx_response(netif, id, status,
+ (unsigned long)skb->data & ~PAGE_MASK,
+ size, skb->proto_csum_valid ?
-+ NETRXF_csum_valid : 0) &&
++ NETRXF_data_validated : 0) &&
+ (rx_notify[irq] == 0)) {
+ rx_notify[irq] = 1;
+ notify_list[notify_nr++] = irq;
@@ -52651,7 +53449,7 @@
+ */
diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c
new file mode 100644
-index 0000000..64bebdb
+index 0000000..52a4fc9
--- /dev/null
+++ b/drivers/xen/netback/xenbus.c
@@ -0,0 +1,327 @@
@@ -52733,14 +53531,13 @@
+ const struct xenbus_device_id *id)
+{
+ int err;
-+ struct backend_info *be = kmalloc(sizeof(struct backend_info),
++ struct backend_info *be = kzalloc(sizeof(struct backend_info),
+ GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_fatal(dev, -ENOMEM,
+ "allocating backend structure");
+ return -ENOMEM;
+ }
-+ memset(be, 0, sizeof(*be));
+
+ be->dev = dev;
+ dev->data = be;
@@ -52871,7 +53668,8 @@
+ break;
+
+ case XenbusStateClosed:
-+ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
++ if (be->netif != NULL)
++ kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+ device_unregister(&dev->dev);
+ break;
+
@@ -53006,10 +53804,10 @@
+xennet-objs := netfront.o
diff --git a/drivers/xen/netfront/netfront.c b/drivers/xen/netfront/netfront.c
new file mode 100644
-index 0000000..79d8645
+index 0000000..220e9aa
--- /dev/null
+++ b/drivers/xen/netfront/netfront.c
-@@ -0,0 +1,1500 @@
+@@ -0,0 +1,1506 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
@@ -53080,21 +53878,12 @@
+#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
+#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
+
-+#ifndef __GFP_NOWARN
-+#define __GFP_NOWARN 0
-+#endif
-+#define alloc_xen_skb(_l) __dev_alloc_skb((_l), GFP_ATOMIC|__GFP_NOWARN)
-+
-+#define init_skb_shinfo(_skb) \
-+ do { \
-+ atomic_set(&(skb_shinfo(_skb)->dataref), 1); \
-+ skb_shinfo(_skb)->nr_frags = 0; \
-+ skb_shinfo(_skb)->frag_list = NULL; \
-+ } while (0)
-+
-+static unsigned long rx_pfn_array[NET_RX_RING_SIZE];
-+static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
-+static mmu_update_t rx_mmu[NET_RX_RING_SIZE];
++static inline void init_skb_shinfo(struct sk_buff *skb)
++{
++ atomic_set(&(skb_shinfo(skb)->dataref), 1);
++ skb_shinfo(skb)->nr_frags = 0;
++ skb_shinfo(skb)->frag_list = NULL;
++}
+
+struct netfront_info
+{
@@ -53149,16 +53938,28 @@
+ int tx_ring_ref;
+ int rx_ring_ref;
+ u8 mac[ETH_ALEN];
++
++ unsigned long rx_pfn_array[NET_RX_RING_SIZE];
++ multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
++ mmu_update_t rx_mmu[NET_RX_RING_SIZE];
+};
+
-+/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
-+#define ADD_ID_TO_FREELIST(_list, _id) \
-+ (_list)[(_id)] = (_list)[0]; \
-+ (_list)[0] = (void *)(unsigned long)(_id);
-+#define GET_ID_FROM_FREELIST(_list) \
-+ ({ unsigned long _id = (unsigned long)(_list)[0]; \
-+ (_list)[0] = (_list)[_id]; \
-+ (unsigned short)_id; })
++/*
++ * Access macros for acquiring freeing slots in {tx,rx}_skbs[].
++ */
++
++static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id)
++{
++ list[id] = list[0];
++ list[0] = (void *)(unsigned long)id;
++}
++
++static inline unsigned short get_id_from_freelist(struct sk_buff **list)
++{
++ unsigned int id = (unsigned int)(unsigned long)list[0];
++ list[0] = list[id];
++ return id;
++}
+
+#ifdef DEBUG
+static char *be_state_name[] = {
@@ -53499,7 +54300,7 @@
+ gnttab_release_grant_reference(
+ &np->gref_tx_head, np->grant_tx_ref[id]);
+ np->grant_tx_ref[id] = GRANT_INVALID_REF;
-+ ADD_ID_TO_FREELIST(np->tx_skbs, id);
++ add_id_to_freelist(np->tx_skbs, id);
+ dev_kfree_skb_irq(skb);
+ }
+
@@ -53560,9 +54361,10 @@
+ * Subtract dev_alloc_skb headroom (16 bytes) and shared info
+ * tailroom then round down to SKB_DATA_ALIGN boundary.
+ */
-+ skb = alloc_xen_skb(
++ skb = __dev_alloc_skb(
+ ((PAGE_SIZE - sizeof(struct skb_shared_info)) &
-+ (-SKB_DATA_ALIGN(1))) - 16);
++ (-SKB_DATA_ALIGN(1))) - 16,
++ GFP_ATOMIC|__GFP_NOWARN);
+ if (skb == NULL) {
+ /* Any skbuffs queued for refill? Force them out. */
+ if (i != 0)
@@ -53591,7 +54393,7 @@
+
+ skb->dev = dev;
+
-+ id = GET_ID_FROM_FREELIST(np->rx_skbs);
++ id = get_id_from_freelist(np->rx_skbs);
+
+ np->rx_skbs[id] = skb;
+
@@ -53603,13 +54405,13 @@
+ np->xbdev->otherend_id,
+ __pa(skb->head) >> PAGE_SHIFT);
+ RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref;
-+ rx_pfn_array[i] = virt_to_mfn(skb->head);
++ np->rx_pfn_array[i] = virt_to_mfn(skb->head);
+
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ /* Remove this page before passing back to Xen. */
+ set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
+ INVALID_P2M_ENTRY);
-+ MULTI_update_va_mapping(rx_mcl+i,
++ MULTI_update_va_mapping(np->rx_mcl+i,
+ (unsigned long)skb->head,
+ __pte(0), 0);
+ }
@@ -53618,7 +54420,7 @@
+ /* Tell the ballon driver what is going on. */
+ balloon_update_driver_allowance(i);
+
-+ reservation.extent_start = rx_pfn_array;
++ reservation.extent_start = np->rx_pfn_array;
+ reservation.nr_extents = i;
+ reservation.extent_order = 0;
+ reservation.address_bits = 0;
@@ -53626,19 +54428,19 @@
+
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ /* After all PTEs have been zapped, flush the TLB. */
-+ rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
++ np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
+ UVMF_TLB_FLUSH|UVMF_ALL;
+
+ /* Give away a batch of pages. */
-+ rx_mcl[i].op = __HYPERVISOR_memory_op;
-+ rx_mcl[i].args[0] = XENMEM_decrease_reservation;
-+ rx_mcl[i].args[1] = (unsigned long)&reservation;
++ np->rx_mcl[i].op = __HYPERVISOR_memory_op;
++ np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
++ np->rx_mcl[i].args[1] = (unsigned long)&reservation;
+
+ /* Zap PTEs and give away pages in one big multicall. */
-+ (void)HYPERVISOR_multicall(rx_mcl, i+1);
++ (void)HYPERVISOR_multicall(np->rx_mcl, i+1);
+
+ /* Check return status of HYPERVISOR_memory_op(). */
-+ if (unlikely(rx_mcl[i].result != i))
++ if (unlikely(np->rx_mcl[i].result != i))
+ panic("Unable to reduce memory reservation\n");
+ } else
+ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
@@ -53671,7 +54473,8 @@
+ if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >=
+ PAGE_SIZE)) {
+ struct sk_buff *nskb;
-+ if (unlikely((nskb = alloc_xen_skb(skb->len)) == NULL))
++ nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC|__GFP_NOWARN);
++ if (unlikely(nskb == NULL))
+ goto drop;
+ skb_put(nskb, skb->len);
+ memcpy(nskb->data, skb->data, skb->len);
@@ -53689,7 +54492,7 @@
+
+ i = np->tx.req_prod_pvt;
+
-+ id = GET_ID_FROM_FREELIST(np->tx_skbs);
++ id = get_id_from_freelist(np->tx_skbs);
+ np->tx_skbs[id] = skb;
+
+ tx = RING_GET_REQUEST(&np->tx, i);
@@ -53754,8 +54557,8 @@
+ struct sk_buff *skb, *nskb;
+ netif_rx_response_t *rx;
+ RING_IDX i, rp;
-+ mmu_update_t *mmu = rx_mmu;
-+ multicall_entry_t *mcl = rx_mcl;
++ mmu_update_t *mmu = np->rx_mmu;
++ multicall_entry_t *mcl = np->rx_mcl;
+ int work_done, budget, more_to_do = 1;
+ struct sk_buff_head rxq;
+ unsigned long flags;
@@ -53811,14 +54614,14 @@
+ np->grant_rx_ref[rx->id] = GRANT_INVALID_REF;
+
+ skb = np->rx_skbs[rx->id];
-+ ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
++ add_id_to_freelist(np->rx_skbs, rx->id);
+
+ /* NB. We handle skb overflow later. */
+ skb->data = skb->head + rx->offset;
+ skb->len = rx->status;
+ skb->tail = skb->data + skb->len;
+
-+ if (rx->flags & NETRXF_csum_valid)
++ if (rx->flags & NETRXF_data_validated)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ np->stats.rx_packets++;
@@ -53846,22 +54649,22 @@
+ balloon_update_driver_allowance(-work_done);
+
+ /* Do all the remapping work, and M2P updates, in one big hypercall. */
-+ if (likely((mcl - rx_mcl) != 0)) {
++ if (likely((mcl - np->rx_mcl) != 0)) {
+ mcl->op = __HYPERVISOR_mmu_update;
-+ mcl->args[0] = (unsigned long)rx_mmu;
-+ mcl->args[1] = mmu - rx_mmu;
++ mcl->args[0] = (unsigned long)np->rx_mmu;
++ mcl->args[1] = mmu - np->rx_mmu;
+ mcl->args[2] = 0;
+ mcl->args[3] = DOMID_SELF;
+ mcl++;
-+ (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
++ (void)HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
+ }
+
+ while ((skb = __skb_dequeue(&rxq)) != NULL) {
-+ if (skb->len > (dev->mtu + ETH_HLEN)) {
++ if (skb->len > (dev->mtu + ETH_HLEN + 4)) {
+ if (net_ratelimit())
+ printk(KERN_INFO "Received packet too big for "
+ "MTU (%d > %d)\n",
-+ skb->len - ETH_HLEN, dev->mtu);
++ skb->len - ETH_HLEN - 4, dev->mtu);
+ skb->len = 0;
+ skb->tail = skb->data;
+ init_skb_shinfo(skb);
@@ -53886,7 +54689,8 @@
+ 16 - (skb->data - skb->head));
+ }
+
-+ nskb = alloc_xen_skb(skb->len + 2);
++ nskb = __dev_alloc_skb(skb->len + 2,
++ GFP_ATOMIC|__GFP_NOWARN);
+ if (nskb != NULL) {
+ skb_reserve(nskb, 2);
+ skb_put(nskb, skb->len);
@@ -54512,26 +55316,26 @@
+ */
diff --git a/drivers/xen/pciback/Makefile b/drivers/xen/pciback/Makefile
new file mode 100644
-index 0000000..e031caa
+index 0000000..bfe77e6
--- /dev/null
+++ b/drivers/xen/pciback/Makefile
@@ -0,0 +1,10 @@
-+obj-y += pciback.o
++obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback.o
+
+pciback-y := pci_stub.o pciback_ops.o xenbus.o
+pciback-y += conf_space.o conf_space_header.o
-+pciback-${CONFIG_XEN_PCIDEV_BACKEND_VPCI} += vpci.o
-+pciback-${CONFIG_XEN_PCIDEV_BACKEND_PASS} += passthrough.o
++pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
++pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
+
+ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/xen/pciback/conf_space.c b/drivers/xen/pciback/conf_space.c
new file mode 100644
-index 0000000..f08eafa
+index 0000000..9d1fe1e
--- /dev/null
+++ b/drivers/xen/pciback/conf_space.c
-@@ -0,0 +1,324 @@
+@@ -0,0 +1,342 @@
+/*
+ * PCI Backend - Functions for creating a virtual configuration space for
+ * exported PCI Devices.
@@ -54548,6 +55352,9 @@
+#include "pciback.h"
+#include "conf_space.h"
+
++static int permissive = 0;
++module_param(permissive, bool, 0644);
++
+#define DEFINE_PCI_CONFIG(op,size,type) \
+int pciback_##op##_config_##size \
+(struct pci_dev *dev, int offset, type value, void *data) \
@@ -54732,7 +55539,7 @@
+
+int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
+{
-+ int err = 0;
++ int err = 0, handled = 0;
+ struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+ struct config_field_entry *cfg_entry;
+ struct config_field *field;
@@ -54767,6 +55574,21 @@
+ field_start - req_start);
+
+ err = conf_space_write(dev, cfg_entry, offset, tmp_val);
++ handled = 1;
++ }
++ }
++
++ if (!handled && !err && permissive) {
++ switch (size) {
++ case 1:
++ err = pci_write_config_byte(dev, offset, (u8)value);
++ break;
++ case 2:
++ err = pci_write_config_word(dev, offset, (u16)value);
++ break;
++ case 4:
++ err = pci_write_config_dword(dev, offset, (u32)value);
++ break;
+ }
+ }
+
@@ -54961,10 +55783,10 @@
+#endif /* __XEN_PCIBACK_CONF_SPACE_H__ */
diff --git a/drivers/xen/pciback/conf_space_header.c b/drivers/xen/pciback/conf_space_header.c
new file mode 100644
-index 0000000..17607d3
+index 0000000..0b9fce3
--- /dev/null
+++ b/drivers/xen/pciback/conf_space_header.c
-@@ -0,0 +1,269 @@
+@@ -0,0 +1,267 @@
+/*
+ * PCI Backend - Handles the virtual fields in the configuration space headers.
+ *
@@ -54991,21 +55813,19 @@
+ if (unlikely(verbose_request))
+ printk(KERN_DEBUG "pciback: %s: enable\n",
+ pci_name(dev));
-+ dev->is_enabled = 1;
-+ pcibios_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
++ pci_enable_device(dev);
+ } else if (dev->is_enabled && !is_enable_cmd(value)) {
+ if (unlikely(verbose_request))
+ printk(KERN_DEBUG "pciback: %s: disable\n",
+ pci_name(dev));
-+ pciback_disable_device(dev);
++ pci_disable_device(dev);
+ }
+
+ if (!dev->is_busmaster && is_master_cmd(value)) {
+ if (unlikely(verbose_request))
+ printk(KERN_DEBUG "pciback: %s: set bus master\n",
+ pci_name(dev));
-+ dev->is_busmaster = 1;
-+ pcibios_set_master(dev);
++ pci_set_master(dev);
+ }
+
+ if (value & PCI_COMMAND_INVALIDATE) {
@@ -55236,10 +56056,10 @@
+}
diff --git a/drivers/xen/pciback/passthrough.c b/drivers/xen/pciback/passthrough.c
new file mode 100644
-index 0000000..e5b7fbb
+index 0000000..5ee7638
--- /dev/null
+++ b/drivers/xen/pciback/passthrough.c
-@@ -0,0 +1,116 @@
+@@ -0,0 +1,157 @@
+/*
+ * PCI Backend - Provides restricted access to the real PCI bus topology
+ * to the frontend
@@ -55249,10 +56069,13 @@
+
+#include <linux/list.h>
+#include <linux/pci.h>
++#include <linux/spinlock.h>
+#include "pciback.h"
+
+struct passthrough_dev_data {
++ /* Access to dev_list must be protected by lock */
+ struct list_head dev_list;
++ spinlock_t lock;
+};
+
+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
@@ -55261,33 +56084,66 @@
+{
+ struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+ struct pci_dev_entry *dev_entry;
++ struct pci_dev *dev = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev_data->lock, flags);
+
+ list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
+ if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus)
+ && bus == (unsigned int)dev_entry->dev->bus->number
-+ && devfn == dev_entry->dev->devfn)
-+ return dev_entry->dev;
++ && devfn == dev_entry->dev->devfn) {
++ dev = dev_entry->dev;
++ break;
++ }
+ }
+
-+ return NULL;
++ spin_unlock_irqrestore(&dev_data->lock, flags);
++
++ return dev;
+}
+
-+/* Must hold pciback_device->dev_lock when calling this */
+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
+{
+ struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+ struct pci_dev_entry *dev_entry;
++ unsigned long flags;
+
+ dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
+ if (!dev_entry)
+ return -ENOMEM;
+ dev_entry->dev = dev;
+
++ spin_lock_irqsave(&dev_data->lock, flags);
+ list_add_tail(&dev_entry->list, &dev_data->dev_list);
++ spin_unlock_irqrestore(&dev_data->lock, flags);
+
+ return 0;
+}
+
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++{
++ struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
++ struct pci_dev_entry *dev_entry, *t;
++ struct pci_dev *found_dev = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev_data->lock, flags);
++
++ list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
++ if (dev_entry->dev == dev) {
++ list_del(&dev_entry->list);
++ found_dev = dev_entry->dev;
++ kfree(dev_entry);
++ }
++ }
++
++ spin_unlock_irqrestore(&dev_data->lock, flags);
++
++ if (found_dev)
++ pcistub_put_pci_dev(found_dev);
++}
++
+int pciback_init_devices(struct pciback_device *pdev)
+{
+ struct passthrough_dev_data *dev_data;
@@ -55296,6 +56152,8 @@
+ if (!dev_data)
+ return -ENOMEM;
+
++ spin_lock_init(&dev_data->lock);
++
+ INIT_LIST_HEAD(&dev_data->dev_list);
+
+ pdev->pci_dev_data = dev_data;
@@ -55313,6 +56171,8 @@
+ int found;
+ unsigned int domain, bus;
+
++ spin_lock(&dev_data->lock);
++
+ list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
+ /* Only publish this device as a root if none of its
+ * parent bridges are exported
@@ -55338,10 +56198,11 @@
+ }
+ }
+
++ spin_unlock(&dev_data->lock);
++
+ return err;
+}
+
-+/* Must hold pciback_device->dev_lock when calling this */
+void pciback_release_devices(struct pciback_device *pdev)
+{
+ struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
@@ -55358,10 +56219,10 @@
+}
diff --git a/drivers/xen/pciback/pci_stub.c b/drivers/xen/pciback/pci_stub.c
new file mode 100644
-index 0000000..aa76d75
+index 0000000..e0dc110
--- /dev/null
+++ b/drivers/xen/pciback/pci_stub.c
-@@ -0,0 +1,377 @@
+@@ -0,0 +1,695 @@
+/*
+ * PCI Stub Driver - Grabs devices in backend to be exported later
+ *
@@ -55371,110 +56232,190 @@
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
++#include <linux/kref.h>
+#include <asm/atomic.h>
+#include "pciback.h"
+
+static char *pci_devs_to_hide = NULL;
+module_param_named(hide, pci_devs_to_hide, charp, 0444);
+
-+struct pci_stub_device_id {
++struct pcistub_device_id {
+ struct list_head slot_list;
+ int domain;
+ unsigned char bus;
+ unsigned int devfn;
+};
-+LIST_HEAD(pci_stub_device_ids);
++static LIST_HEAD(pcistub_device_ids);
++static DEFINE_SPINLOCK(device_ids_lock);
+
-+struct pci_stub_device {
++struct pcistub_device {
++ struct kref kref;
+ struct list_head dev_list;
++ spinlock_t lock;
++
+ struct pci_dev *dev;
-+ atomic_t in_use;
++ struct pciback_device *pdev; /* non-NULL if struct pci_dev is in use */
+};
-+/* Access to pci_stub_devices & seized_devices lists and the initialize_devices
-+ * flag must be locked with pci_stub_devices_lock
++/* Access to pcistub_devices & seized_devices lists and the initialize_devices
++ * flag must be locked with pcistub_devices_lock
+ */
-+DEFINE_SPINLOCK(pci_stub_devices_lock);
-+LIST_HEAD(pci_stub_devices);
++static DEFINE_SPINLOCK(pcistub_devices_lock);
++static LIST_HEAD(pcistub_devices);
+
+/* wait for device_initcall before initializing our devices
+ * (see pcistub_init_devices_late)
+ */
+static int initialize_devices = 0;
-+LIST_HEAD(seized_devices);
++static LIST_HEAD(seized_devices);
+
-+static inline struct pci_dev *get_pci_dev(struct pci_stub_device *psdev)
++static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
+{
-+ if (atomic_dec_and_test(&psdev->in_use))
-+ return psdev->dev;
-+ else {
-+ atomic_inc(&psdev->in_use);
++ struct pcistub_device *psdev;
++
++ dev_dbg(&dev->dev, "pcistub_device_alloc\n");
++
++ psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC);
++ if (!psdev)
++ return NULL;
++
++ psdev->dev = pci_dev_get(dev);
++ if (!psdev->dev) {
++ kfree(psdev);
+ return NULL;
+ }
++
++ kref_init(&psdev->kref);
++ spin_lock_init(&psdev->lock);
++
++ return psdev;
+}
+
-+struct pci_dev *pcistub_get_pci_dev_by_slot(int domain, int bus,
++/* Don't call this directly as it's called by pcistub_device_put */
++static void pcistub_device_release(struct kref *kref)
++{
++ struct pcistub_device *psdev;
++
++ psdev = container_of(kref, struct pcistub_device, kref);
++
++ dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
++
++ /* Clean-up the device */
++ pciback_reset_device(psdev->dev);
++ pciback_config_free(psdev->dev);
++ kfree(pci_get_drvdata(psdev->dev));
++ pci_set_drvdata(psdev->dev, NULL);
++
++ pci_dev_put(psdev->dev);
++
++ kfree(psdev);
++}
++
++static inline void pcistub_device_get(struct pcistub_device *psdev)
++{
++ kref_get(&psdev->kref);
++}
++
++static inline void pcistub_device_put(struct pcistub_device *psdev)
++{
++ kref_put(&psdev->kref, pcistub_device_release);
++}
++
++static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
++ struct pcistub_device *psdev)
++{
++ struct pci_dev *pci_dev = NULL;
++ unsigned long flags;
++
++ pcistub_device_get(psdev);
++
++ spin_lock_irqsave(&psdev->lock, flags);
++ if (!psdev->pdev) {
++ psdev->pdev = pdev;
++ pci_dev = psdev->dev;
++ }
++ spin_unlock_irqrestore(&psdev->lock, flags);
++
++ if (!pci_dev)
++ pcistub_device_put(psdev);
++
++ return pci_dev;
++}
++
++struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
++ int domain, int bus,
+ int slot, int func)
+{
-+ struct pci_stub_device *psdev;
++ struct pcistub_device *psdev;
+ struct pci_dev *found_dev = NULL;
++ unsigned long flags;
+
-+ spin_lock(&pci_stub_devices_lock);
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
+
-+ list_for_each_entry(psdev, &pci_stub_devices, dev_list) {
++ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (psdev->dev != NULL
+ && domain == pci_domain_nr(psdev->dev->bus)
+ && bus == psdev->dev->bus->number
+ && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
-+ found_dev = get_pci_dev(psdev);
++ found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+ break;
+ }
+ }
+
-+ spin_unlock(&pci_stub_devices_lock);
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+ return found_dev;
+}
+
-+struct pci_dev *pcistub_get_pci_dev(struct pci_dev *dev)
++struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
++ struct pci_dev *dev)
+{
-+ struct pci_stub_device *psdev;
++ struct pcistub_device *psdev;
+ struct pci_dev *found_dev = NULL;
++ unsigned long flags;
+
-+ spin_lock(&pci_stub_devices_lock);
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
+
-+ list_for_each_entry(psdev, &pci_stub_devices, dev_list) {
++ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (psdev->dev == dev) {
-+ found_dev = get_pci_dev(psdev);
++ found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+ break;
+ }
+ }
+
-+ spin_unlock(&pci_stub_devices_lock);
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+ return found_dev;
+}
+
+void pcistub_put_pci_dev(struct pci_dev *dev)
+{
-+ struct pci_stub_device *psdev;
++ struct pcistub_device *psdev, *found_psdev = NULL;
++ unsigned long flags;
+
-+ spin_lock(&pci_stub_devices_lock);
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
+
-+ list_for_each_entry(psdev, &pci_stub_devices, dev_list) {
++ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (psdev->dev == dev) {
-+ /* Cleanup our device
-+ * (so it's ready for the next domain)
-+ */
-+ pciback_reset_device(psdev->dev);
-+
-+ atomic_inc(&psdev->in_use);
++ found_psdev = psdev;
+ break;
+ }
+ }
+
-+ spin_unlock(&pci_stub_devices_lock);
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++ /* Cleanup our device
++ * (so it's ready for the next domain)
++ */
++ pciback_reset_device(found_psdev->dev);
++ pciback_config_reset(found_psdev->dev);
++
++ spin_lock_irqsave(&found_psdev->lock, flags);
++ found_psdev->pdev = NULL;
++ spin_unlock_irqrestore(&found_psdev->lock, flags);
++
++ pcistub_device_put(found_psdev);
+}
+
-+static int __devinit pcistub_match(struct pci_dev *dev,
-+ struct pci_stub_device_id *pdev_id)
++static int __devinit pcistub_match_one(struct pci_dev *dev,
++ struct pcistub_device_id *pdev_id)
+{
+ /* Match the specified device by domain, bus, slot, func and also if
+ * any of the device's parent bridges match.
@@ -55489,23 +56430,44 @@
+ return 0;
+}
+
++static int __devinit pcistub_match(struct pci_dev *dev)
++{
++ struct pcistub_device_id *pdev_id;
++ unsigned long flags;
++ int found = 0;
++
++ spin_lock_irqsave(&device_ids_lock, flags);
++ list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
++ if (pcistub_match_one(dev, pdev_id)) {
++ found = 1;
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&device_ids_lock, flags);
++
++ return found;
++}
++
+static int __devinit pcistub_init_device(struct pci_dev *dev)
+{
+ struct pciback_dev_data *dev_data;
+ int err = 0;
+
++ dev_dbg(&dev->dev, "initializing...\n");
++
+ /* The PCI backend is not intended to be a module (or to work with
+ * removable PCI devices (yet). If it were, pciback_config_free()
+ * would need to be called somewhere to free the memory allocated
+ * here and then to call kfree(pci_get_drvdata(psdev->dev)).
+ */
-+ dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
++ dev_data = kmalloc(sizeof(*dev_data), GFP_ATOMIC);
+ if (!dev_data) {
+ err = -ENOMEM;
+ goto out;
+ }
+ pci_set_drvdata(dev, dev_data);
+
++ dev_dbg(&dev->dev, "initializing config\n");
+ err = pciback_config_init(dev);
+ if (err)
+ goto out;
@@ -55517,14 +56479,15 @@
+ * This makes the assumption that the device's resources won't
+ * change after this point (otherwise this code may break!)
+ */
++ dev_dbg(&dev->dev, "enabling device\n");
+ err = pci_enable_device(dev);
+ if (err)
+ goto config_release;
+
+ /* Now disable the device (this also ensures some private device
+ * data is setup before we export)
-+ * This calls pciback_config_reset(dev)
+ */
++ dev_dbg(&dev->dev, "reset device\n");
+ pciback_reset_device(dev);
+
+ return 0;
@@ -55546,62 +56509,82 @@
+ */
+static int __init pcistub_init_devices_late(void)
+{
-+ struct pci_stub_device *psdev, *t;
++ struct pcistub_device *psdev;
++ unsigned long flags;
+ int err = 0;
+
-+ spin_lock(&pci_stub_devices_lock);
++ pr_debug("pciback: pcistub_init_devices_late\n");
+
-+ list_for_each_entry_safe(psdev, t, &seized_devices, dev_list) {
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++ while (!list_empty(&seized_devices)) {
++ psdev = container_of(seized_devices.next,
++ struct pcistub_device, dev_list);
+ list_del(&psdev->dev_list);
++
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
+ err = pcistub_init_device(psdev->dev);
+ if (err) {
-+ printk(KERN_ERR
-+ "pciback: %s error %d initializing device\n",
-+ pci_name(psdev->dev), err);
++ dev_err(&psdev->dev->dev,
++ "error %d initializing device\n", err);
+ kfree(psdev);
-+ continue;
++ psdev = NULL;
+ }
+
-+ list_add_tail(&psdev->dev_list, &pci_stub_devices);
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++ if (psdev)
++ list_add_tail(&psdev->dev_list, &pcistub_devices);
+ }
+
+ initialize_devices = 1;
+
-+ spin_unlock(&pci_stub_devices_lock);
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+ return 0;
+}
+
-+device_initcall(pcistub_init_devices_late);
-+
+static int __devinit pcistub_seize(struct pci_dev *dev)
+{
-+ struct pci_stub_device *psdev;
++ struct pcistub_device *psdev;
++ unsigned long flags;
++ int initialize_devices_copy;
+ int err = 0;
+
-+ psdev = kmalloc(sizeof(*psdev), GFP_KERNEL);
++ psdev = pcistub_device_alloc(dev);
+ if (!psdev)
+ return -ENOMEM;
+
-+ psdev->dev = dev;
-+ atomic_set(&psdev->in_use, 1);
++ /* initialize_devices has to be accessed under a spin lock. But since
++ * it can only change from 0 -> 1, if it's already 1, we don't have to
++ * worry about it changing. That's why we can take a *copy* of
++ * initialize_devices and wait till we're outside of the lock to
++ * check if it's 1 (don't ever check if it's 0 outside of the lock)
++ */
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++ initialize_devices_copy = initialize_devices;
++
++ if (!initialize_devices_copy) {
++ dev_dbg(&dev->dev, "deferring initialization\n");
++ list_add(&psdev->dev_list, &seized_devices);
++ }
+
-+ spin_lock(&pci_stub_devices_lock);
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
-+ if (initialize_devices) {
++ if (initialize_devices_copy) {
++ /* don't want irqs disabled when calling pcistub_init_device */
+ err = pcistub_init_device(psdev->dev);
+ if (err)
+ goto out;
+
-+ list_add(&psdev->dev_list, &pci_stub_devices);
-+ } else
-+ list_add(&psdev->dev_list, &seized_devices);
++ list_add(&psdev->dev_list, &pcistub_devices);
++ }
+
+ out:
-+ spin_unlock(&pci_stub_devices_lock);
-+
+ if (err)
-+ kfree(psdev);
++ pcistub_device_put(psdev);
+
+ return err;
+}
@@ -55609,47 +56592,78 @@
+static int __devinit pcistub_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
-+ struct pci_stub_device_id *pdev_id;
-+ struct pci_dev *seized_dev;
+ int err = 0;
+
-+ list_for_each_entry(pdev_id, &pci_stub_device_ids, slot_list) {
++ dev_dbg(&dev->dev, "probing...\n");
+
-+ if (!pcistub_match(dev, pdev_id))
-+ continue;
++ if (pcistub_match(dev)) {
+
+ if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
+ && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
-+ printk(KERN_ERR
-+ "pciback: %s: can't export pci devices that "
-+ "don't have a normal (0) or bridge (1) "
-+ "header type!\n", pci_name(dev));
-+ break;
++ dev_err(&dev->dev, "can't export pci devices that "
++ "don't have a normal (0) or bridge (1) "
++ "header type!\n");
++ err = -ENODEV;
++ goto out;
+ }
+
-+ pr_info("pciback: seizing PCI device %s\n", pci_name(dev));
-+ seized_dev = pci_dev_get(dev);
++ dev_info(&dev->dev, "seizing device\n");
++ err = pcistub_seize(dev);
++ } else
++ /* Didn't find the device */
++ err = -ENODEV;
+
-+ if (seized_dev) {
-+ err = pcistub_seize(seized_dev);
-+ if (err) {
-+ pci_dev_put(dev);
-+ goto out;
-+ }
++ out:
++ return err;
++}
+
-+ /* Success! */
-+ goto out;
++static void pcistub_remove(struct pci_dev *dev)
++{
++ struct pcistub_device *psdev, *found_psdev = NULL;
++ unsigned long flags;
++
++ dev_dbg(&dev->dev, "removing\n");
++
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++ if (psdev->dev == dev) {
++ found_psdev = psdev;
++ break;
+ }
+ }
+
-+ /* Didn't find the device */
-+ err = -ENODEV;
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
-+ out:
-+ return err;
++ if (found_psdev) {
++ dev_dbg(&dev->dev, "found device to remove - in use? %p\n",
++ found_psdev->pdev);
++
++ if (found_psdev->pdev) {
++ printk(KERN_WARNING "pciback: ****** removing device "
++ "%s while still in-use! ******\n",
++ pci_name(found_psdev->dev));
++ printk(KERN_WARNING "pciback: ****** driver domain may "
++ "still access this device's i/o resources!\n");
++ printk(KERN_WARNING "pciback: ****** shutdown driver "
++ "domain before binding device\n");
++ printk(KERN_WARNING "pciback: ****** to other drivers "
++ "or domains\n");
++
++ pciback_release_pci_dev(found_psdev->pdev,
++ found_psdev->dev);
++ }
++
++ spin_lock_irqsave(&pcistub_devices_lock, flags);
++ list_del(&found_psdev->dev_list);
++ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++ /* the final put for releasing from the list */
++ pcistub_device_put(found_psdev);
++ }
+}
+
-+struct pci_device_id pcistub_ids[] = {
++static struct pci_device_id pcistub_ids[] = {
+ {
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
@@ -55664,16 +56678,152 @@
+ * for a normal device. I don't want it to be loaded automatically.
+ */
+
-+struct pci_driver pciback_pci_driver = {
++static struct pci_driver pciback_pci_driver = {
+ .name = "pciback",
+ .id_table = pcistub_ids,
+ .probe = pcistub_probe,
++ .remove = pcistub_remove,
+};
+
++static inline int str_to_slot(const char *buf, int *domain, int *bus,
++ int *slot, int *func)
++{
++ int err;
++
++ err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
++ if (err == 4)
++ return 0;
++ else if (err < 0)
++ return -EINVAL;
++
++ /* try again without domain */
++ *domain = 0;
++ err = sscanf(buf, " %x:%x.%x", bus, slot, func);
++ if (err == 3)
++ return 0;
++
++ return -EINVAL;
++}
++
++static int pcistub_device_id_add(int domain, int bus, int slot, int func)
++{
++ struct pcistub_device_id *pci_dev_id;
++ unsigned long flags;
++
++ pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
++ if (!pci_dev_id)
++ return -ENOMEM;
++
++ pci_dev_id->domain = domain;
++ pci_dev_id->bus = bus;
++ pci_dev_id->devfn = PCI_DEVFN(slot, func);
++
++ pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
++ domain, bus, slot, func);
++
++ spin_lock_irqsave(&device_ids_lock, flags);
++ list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
++ spin_unlock_irqrestore(&device_ids_lock, flags);
++
++ return 0;
++}
++
++static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
++{
++ struct pcistub_device_id *pci_dev_id, *t;
++ int devfn = PCI_DEVFN(slot, func);
++ int err = -ENOENT;
++ unsigned long flags;
++
++ spin_lock_irqsave(&device_ids_lock, flags);
++ list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, slot_list) {
++
++ if (pci_dev_id->domain == domain
++ && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) {
++ /* Don't break; here because it's possible the same
++ * slot could be in the list more than once
++ */
++ list_del(&pci_dev_id->slot_list);
++ kfree(pci_dev_id);
++
++ err = 0;
++
++ pr_debug("pciback: removed %04x:%02x:%02x.%01x from "
++ "seize list\n", domain, bus, slot, func);
++ }
++ }
++ spin_unlock_irqrestore(&device_ids_lock, flags);
++
++ return err;
++}
++
++static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
++ size_t count)
++{
++ int domain, bus, slot, func;
++ int err;
++
++ err = str_to_slot(buf, &domain, &bus, &slot, &func);
++ if (err)
++ goto out;
++
++ err = pcistub_device_id_add(domain, bus, slot, func);
++
++ out:
++ if (!err)
++ err = count;
++ return err;
++}
++
++DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add);
++
++static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf,
++ size_t count)
++{
++ int domain, bus, slot, func;
++ int err;
++
++ err = str_to_slot(buf, &domain, &bus, &slot, &func);
++ if (err)
++ goto out;
++
++ err = pcistub_device_id_remove(domain, bus, slot, func);
++
++ out:
++ if (!err)
++ err = count;
++ return err;
++}
++
++DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove);
++
++static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
++{
++ struct pcistub_device_id *pci_dev_id;
++ size_t count = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&device_ids_lock, flags);
++ list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) {
++ if (count >= PAGE_SIZE)
++ break;
++
++ count += scnprintf(buf + count, PAGE_SIZE - count,
++ "%04x:%02x:%02x.%01x\n",
++ pci_dev_id->domain, pci_dev_id->bus,
++ PCI_SLOT(pci_dev_id->devfn),
++ PCI_FUNC(pci_dev_id->devfn));
++ }
++ spin_unlock_irqrestore(&device_ids_lock, flags);
++
++ return count;
++}
++
++DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
++
+static int __init pcistub_init(void)
+{
+ int pos = 0;
-+ struct pci_stub_device_id *pci_dev_id;
+ int err = 0;
+ int domain, bus, slot, func;
+ int parsed;
@@ -55694,34 +56844,28 @@
+ goto parse_error;
+ }
+
-+ pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
-+ if (!pci_dev_id) {
-+ err = -ENOMEM;
++ err = pcistub_device_id_add(domain, bus, slot, func);
++ if (err)
+ goto out;
-+ }
-+
-+ pci_dev_id->domain = domain;
-+ pci_dev_id->bus = bus;
-+ pci_dev_id->devfn = PCI_DEVFN(slot, func);
-+
-+ pr_debug
-+ ("pciback: wants to seize %04x:%02x:%02x.%01x\n",
-+ domain, bus, slot, func);
-+
-+ list_add_tail(&pci_dev_id->slot_list,
-+ &pci_stub_device_ids);
+
+ /* if parsed<=0, we've reached the end of the string */
+ pos += parsed;
+ } while (parsed > 0 && pci_devs_to_hide[pos]);
-+
-+ /* If we're the first PCI Device Driver to register, we're the
-+ * first one to get offered PCI devices as they become
-+ * available (and thus we can be the first to grab them)
-+ */
-+ pci_register_driver(&pciback_pci_driver);
+ }
+
++ /* If we're the first PCI Device Driver to register, we're the
++ * first one to get offered PCI devices as they become
++ * available (and thus we can be the first to grab them)
++ */
++ err = pci_register_driver(&pciback_pci_driver);
++ if (err < 0)
++ goto out;
++
++ driver_create_file(&pciback_pci_driver.driver, &driver_attr_new_slot);
++ driver_create_file(&pciback_pci_driver.driver,
++ &driver_attr_remove_slot);
++ driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots);
++
+ out:
+ return err;
+
@@ -55731,6 +56875,7 @@
+ return -EINVAL;
+}
+
++#ifndef MODULE
+/*
+ * fs_initcall happens before device_initcall
+ * so pciback *should* get called first (b/c we
@@ -55739,12 +56884,46 @@
+ * driver to register)
+ */
+fs_initcall(pcistub_init);
++#endif
++
++static int __init pciback_init(void)
++{
++#ifdef MODULE
++ int err;
++
++ err = pcistub_init();
++ if (err < 0)
++ return err;
++#endif
++
++ pcistub_init_devices_late();
++ pciback_xenbus_register();
++
++ return 0;
++}
++
++static void __exit pciback_cleanup(void)
++{
++ pciback_xenbus_unregister();
++
++ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot);
++ driver_remove_file(&pciback_pci_driver.driver,
++ &driver_attr_remove_slot);
++ driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
++
++ pci_unregister_driver(&pciback_pci_driver);
++}
++
++module_init(pciback_init);
++module_exit(pciback_cleanup);
++
++MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/xen/pciback/pciback.h b/drivers/xen/pciback/pciback.h
new file mode 100644
-index 0000000..a1f408b
+index 0000000..aaa0d75
--- /dev/null
+++ b/drivers/xen/pciback/pciback.h
-@@ -0,0 +1,73 @@
+@@ -0,0 +1,78 @@
+/*
+ * PCI Backend Common Data Structures & Function Declarations
+ *
@@ -55784,13 +56963,14 @@
+};
+
+/* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
-+struct pci_dev *pcistub_get_pci_dev_by_slot(int domain, int bus,
++struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
++ int domain, int bus,
+ int slot, int func);
-+struct pci_dev *pcistub_get_pci_dev(struct pci_dev *dev);
++struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
++ struct pci_dev *dev);
+void pcistub_put_pci_dev(struct pci_dev *dev);
+
+/* Ensure a device is turned off or reset */
-+void pciback_disable_device(struct pci_dev *dev);
+void pciback_reset_device(struct pci_dev *pdev);
+
+/* Access a virtual configuration space for a PCI device */
@@ -55805,6 +56985,7 @@
+typedef int (*publish_pci_root_cb) (struct pciback_device * pdev,
+ unsigned int domain, unsigned int bus);
+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
+ unsigned int domain, unsigned int bus,
+ unsigned int devfn);
@@ -55816,14 +56997,17 @@
+/* Handles events from front-end */
+irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs);
+
++int pciback_xenbus_register(void);
++void pciback_xenbus_unregister(void);
++
+extern int verbose_request;
+#endif
diff --git a/drivers/xen/pciback/pciback_ops.c b/drivers/xen/pciback/pciback_ops.c
new file mode 100644
-index 0000000..9019608
+index 0000000..48305f5
--- /dev/null
+++ b/drivers/xen/pciback/pciback_ops.c
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,74 @@
+/*
+ * PCI Backend Operations - respond to PCI requests from Frontend
+ *
@@ -55831,26 +57015,15 @@
+ */
+#include <linux/module.h>
+#include <asm/bitops.h>
++#include <xen/evtchn.h>
+#include "pciback.h"
+
+int verbose_request = 0;
+module_param(verbose_request, int, 0644);
+
-+/* For those architectures without a pcibios_disable_device */
-+void __attribute__ ((weak)) pcibios_disable_device(struct pci_dev *dev) { }
-+
-+void pciback_disable_device(struct pci_dev *dev)
-+{
-+ if (dev->is_enabled) {
-+ dev->is_enabled = 0;
-+ pcibios_disable_device(dev);
-+ }
-+}
-+
+/* Ensure a device is "turned off" and ready to be exported.
-+ * This also sets up the device's private data to keep track of what should
-+ * be in the base address registers (BARs) so that we can keep the
-+ * client from manipulating them directly.
++ * (Also see pciback_config_reset to ensure virtual configuration space is
++ * ready to be re-exported)
+ */
+void pciback_reset_device(struct pci_dev *dev)
+{
@@ -55858,7 +57031,7 @@
+
+ /* Disable devices (but not bridges) */
+ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
-+ pciback_disable_device(dev);
++ pci_disable_device(dev);
+
+ pci_write_config_word(dev, PCI_COMMAND, 0);
+
@@ -55904,16 +57077,17 @@
+
+ wmb();
+ clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
++ notify_remote_via_irq(pdev->evtchn_irq);
+
+ out:
+ return IRQ_HANDLED;
+}
diff --git a/drivers/xen/pciback/vpci.c b/drivers/xen/pciback/vpci.c
new file mode 100644
-index 0000000..17d554d
+index 0000000..84bc4b9
--- /dev/null
+++ b/drivers/xen/pciback/vpci.c
-@@ -0,0 +1,163 @@
+@@ -0,0 +1,204 @@
+/*
+ * PCI Backend - Provides a Virtual PCI bus (with real devices)
+ * to the frontend
@@ -55924,12 +57098,15 @@
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
++#include <linux/spinlock.h>
+#include "pciback.h"
+
+#define PCI_SLOT_MAX 32
+
+struct vpci_dev_data {
++ /* Access to dev_list must be protected by lock */
+ struct list_head dev_list[PCI_SLOT_MAX];
++ spinlock_t lock;
+};
+
+static inline struct list_head *list_first(struct list_head *head)
@@ -55941,25 +57118,29 @@
+ unsigned int domain, unsigned int bus,
+ unsigned int devfn)
+{
-+ struct pci_dev_entry *dev_entry;
++ struct pci_dev_entry *entry;
++ struct pci_dev *dev = NULL;
+ struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++ unsigned long flags;
+
+ if (domain != 0 || bus != 0)
+ return NULL;
+
+ if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
-+ /* we don't need to lock the list here because once the backend
-+ * is in operation, it won't have any more devices addeded
-+ * (or removed).
-+ */
-+ list_for_each_entry(dev_entry,
++ spin_lock_irqsave(&vpci_dev->lock, flags);
++
++ list_for_each_entry(entry,
+ &vpci_dev->dev_list[PCI_SLOT(devfn)],
+ list) {
-+ if (PCI_FUNC(dev_entry->dev->devfn) == PCI_FUNC(devfn))
-+ return dev_entry->dev;
++ if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
++ dev = entry->dev;
++ break;
++ }
+ }
++
++ spin_unlock_irqrestore(&vpci_dev->lock, flags);
+ }
-+ return NULL;
++ return dev;
+}
+
+static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
@@ -55971,12 +57152,12 @@
+ return 0;
+}
+
-+/* Must hold pciback_device->dev_lock when calling this */
+int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
+{
+ int err = 0, slot;
+ struct pci_dev_entry *t, *dev_entry;
+ struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++ unsigned long flags;
+
+ if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
+ err = -EFAULT;
@@ -55995,6 +57176,8 @@
+
+ dev_entry->dev = dev;
+
++ spin_lock_irqsave(&vpci_dev->lock, flags);
++
+ /* Keep multi-function devices together on the virtual PCI bus */
+ for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+ if (!list_empty(&vpci_dev->dev_list[slot])) {
@@ -56008,7 +57191,7 @@
+ PCI_FUNC(dev->devfn));
+ list_add_tail(&dev_entry->list,
+ &vpci_dev->dev_list[slot]);
-+ goto out;
++ goto unlock;
+ }
+ }
+ }
@@ -56021,7 +57204,7 @@
+ pci_name(dev), slot);
+ list_add_tail(&dev_entry->list,
+ &vpci_dev->dev_list[slot]);
-+ goto out;
++ goto unlock;
+ }
+ }
+
@@ -56029,10 +57212,41 @@
+ xenbus_dev_fatal(pdev->xdev, err,
+ "No more space on root virtual PCI bus");
+
++ unlock:
++ spin_unlock_irqrestore(&vpci_dev->lock, flags);
+ out:
+ return err;
+}
+
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++{
++ int slot;
++ struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++ struct pci_dev *found_dev = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&vpci_dev->lock, flags);
++
++ for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++ struct pci_dev_entry *e, *tmp;
++ list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
++ list) {
++ if (e->dev == dev) {
++ list_del(&e->list);
++ found_dev = e->dev;
++ kfree(e);
++ goto out;
++ }
++ }
++ }
++
++ out:
++ spin_unlock_irqrestore(&vpci_dev->lock, flags);
++
++ if (found_dev)
++ pcistub_put_pci_dev(found_dev);
++}
++
+int pciback_init_devices(struct pciback_device *pdev)
+{
+ int slot;
@@ -56042,6 +57256,8 @@
+ if (!vpci_dev)
+ return -ENOMEM;
+
++ spin_lock_init(&vpci_dev->lock);
++
+ for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+ INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
+ }
@@ -56058,7 +57274,6 @@
+ return publish_cb(pdev, 0, 0);
+}
+
-+/* Must hold pciback_device->dev_lock when calling this */
+void pciback_release_devices(struct pciback_device *pdev)
+{
+ int slot;
@@ -56079,10 +57294,10 @@
+}
diff --git a/drivers/xen/pciback/xenbus.c b/drivers/xen/pciback/xenbus.c
new file mode 100644
-index 0000000..b3dc7fb
+index 0000000..f338de1
--- /dev/null
+++ b/drivers/xen/pciback/xenbus.c
-@@ -0,0 +1,439 @@
+@@ -0,0 +1,441 @@
+/*
+ * PCI Backend Xenbus Setup - handles setup with frontend and xend
+ *
@@ -56097,7 +57312,7 @@
+
+#define INVALID_EVTCHN_IRQ (-1)
+
-+struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
++static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
+{
+ struct pciback_device *pdev;
+
@@ -56123,7 +57338,7 @@
+ return pdev;
+}
+
-+void free_pdev(struct pciback_device *pdev)
++static void free_pdev(struct pciback_device *pdev)
+{
+ if (pdev->be_watching)
+ unregister_xenbus_watch(&pdev->be_watch);
@@ -56332,7 +57547,7 @@
+ dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
+ domain, bus, slot, func);
+
-+ dev = pcistub_get_pci_dev_by_slot(domain, bus, slot, func);
++ dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
+ if (!dev) {
+ err = -EINVAL;
+ xenbus_dev_fatal(pdev->xdev, err,
@@ -56515,13 +57730,15 @@
+ .otherend_changed = pciback_frontend_changed,
+};
+
-+static __init int pciback_xenbus_register(void)
++int __init pciback_xenbus_register(void)
+{
+ return xenbus_register_backend(&xenbus_pciback_driver);
+}
+
-+/* Must only initialize our xenbus driver after the pcistub driver */
-+device_initcall(pciback_xenbus_register);
++void __exit pciback_xenbus_unregister(void)
++{
++ xenbus_unregister_driver(&xenbus_pciback_driver);
++}
diff --git a/drivers/xen/pcifront/Makefile b/drivers/xen/pcifront/Makefile
new file mode 100644
index 0000000..621e988
@@ -56537,10 +57754,10 @@
+endif
diff --git a/drivers/xen/pcifront/pci.c b/drivers/xen/pcifront/pci.c
new file mode 100644
-index 0000000..d383410
+index 0000000..4239f00
--- /dev/null
+++ b/drivers/xen/pcifront/pci.c
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,46 @@
+/*
+ * PCI Frontend Operations - ensure only one PCI frontend runs at a time
+ *
@@ -56561,8 +57778,10 @@
+
+ spin_lock(&pcifront_dev_lock);
+
-+ if (!pcifront_dev)
++ if (!pcifront_dev) {
+ dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
++ pcifront_dev = pdev;
++ }
+ else {
+ dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n");
+ err = -EEXIST;
@@ -56587,10 +57806,10 @@
+}
diff --git a/drivers/xen/pcifront/pci_op.c b/drivers/xen/pcifront/pci_op.c
new file mode 100644
-index 0000000..9679192
+index 0000000..38906ad
--- /dev/null
+++ b/drivers/xen/pcifront/pci_op.c
-@@ -0,0 +1,245 @@
+@@ -0,0 +1,272 @@
+/*
+ * PCI Frontend Operations - Communicates with frontend
+ *
@@ -56601,6 +57820,7 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
++#include <linux/time.h>
+#include <xen/evtchn.h>
+#include "pcifront.h"
+
@@ -56634,8 +57854,9 @@
+ int err = 0;
+ struct xen_pci_op *active_op = &pdev->sh_info->op;
+ unsigned long irq_flags;
-+
-+ unsigned int volatile ttl = (1U << 29);
++ evtchn_port_t port = pdev->evtchn;
++ nsec_t ns, ns_timeout;
++ struct timeval tv;
+
+ spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
+
@@ -56644,14 +57865,27 @@
+ /* Go */
+ wmb();
+ set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
-+ notify_remote_via_evtchn(pdev->evtchn);
++ notify_remote_via_evtchn(port);
++
++ /*
++ * We set a poll timeout of 3 seconds but give up on return after
++ * 2 seconds. It is better to time out too late rather than too early
++ * (in the latter case we end up continually re-executing poll() with a
++ * timeout in the past). 1s difference gives plenty of slack for error.
++ */
++ do_gettimeofday(&tv);
++ ns_timeout = timeval_to_ns(&tv) + 2 * (nsec_t)NSEC_PER_SEC;
++
++ clear_evtchn(port);
+
-+ /* IRQs are disabled for the pci config. space reads/writes,
-+ * which means no event channel to notify us that the backend
-+ * is done so spin while waiting for the answer */
-+ while (test_bit
-+ (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) {
-+ if (!ttl) {
++ while (test_bit(_XEN_PCIF_active,
++ (unsigned long *)&pdev->sh_info->flags)) {
++ if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ))
++ BUG();
++ clear_evtchn(port);
++ do_gettimeofday(&tv);
++ ns = timeval_to_ns(&tv);
++ if (ns > ns_timeout) {
+ dev_err(&pdev->xdev->dev,
+ "pciback not responding!!!\n");
+ clear_bit(_XEN_PCIF_active,
@@ -56659,7 +57893,6 @@
+ err = XEN_PCI_ERR_dev_not_found;
+ goto out;
+ }
-+ ttl--;
+ }
+
+ memcpy(op, active_op, sizeof(struct xen_pci_op));
@@ -56752,7 +57985,7 @@
+
+ if (!r->parent && r->start && r->flags) {
+ dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
-+ pci_name(dev), i);
++ pci_name(dev), i);
+ pci_claim_resource(dev, i);
+ }
+ }
@@ -56813,25 +58046,38 @@
+ return err;
+}
+
++static void free_root_bus_devs(struct pci_bus *bus)
++{
++ struct pci_dev *dev;
++
++ spin_lock(&pci_bus_lock);
++ while (!list_empty(&bus->devices)) {
++ dev = container_of(bus->devices.next, struct pci_dev, bus_list);
++ spin_unlock(&pci_bus_lock);
++
++ dev_dbg(&dev->dev, "removing device\n");
++ pci_remove_bus_device(dev);
++
++ spin_lock(&pci_bus_lock);
++ }
++ spin_unlock(&pci_bus_lock);
++}
++
+void pcifront_free_roots(struct pcifront_device *pdev)
+{
+ struct pci_bus_entry *bus_entry, *t;
+
++ dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
++
+ list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
-+ /* TODO: Removing a PCI Bus is untested (as it normally
-+ * just goes away on domain shutdown)
-+ */
+ list_del(&bus_entry->list);
+
-+ spin_lock(&pci_bus_lock);
-+ list_del(&bus_entry->bus->node);
-+ spin_unlock(&pci_bus_lock);
++ free_root_bus_devs(bus_entry->bus);
+
+ kfree(bus_entry->bus->sysdata);
+
+ device_unregister(bus_entry->bus->bridge);
-+
-+ /* Do we need to free() the bus itself? */
++ pci_remove_bus(bus_entry->bus);
+
+ kfree(bus_entry);
+ }
@@ -56884,10 +58130,10 @@
+#endif /* __XEN_PCIFRONT_H__ */
diff --git a/drivers/xen/pcifront/xenbus.c b/drivers/xen/pcifront/xenbus.c
new file mode 100644
-index 0000000..c596ed4
+index 0000000..eed89eb
--- /dev/null
+++ b/drivers/xen/pcifront/xenbus.c
-@@ -0,0 +1,295 @@
+@@ -0,0 +1,297 @@
+/*
+ * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
+ *
@@ -56940,6 +58186,8 @@
+{
+ dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
+
++ pcifront_free_roots(pdev);
++
+ if (pdev->evtchn != INVALID_EVTCHN)
+ xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
+
@@ -58874,10 +60122,10 @@
+ */
diff --git a/drivers/xen/tpmback/xenbus.c b/drivers/xen/tpmback/xenbus.c
new file mode 100644
-index 0000000..9a2be8d
+index 0000000..6ce5f07
--- /dev/null
+++ b/drivers/xen/tpmback/xenbus.c
-@@ -0,0 +1,333 @@
+@@ -0,0 +1,331 @@
+/* Xenbus code for tpmif backend
+ Copyright (C) 2005 IBM Corporation
+ Copyright (C) 2005 Rusty Russell <rusty at rustcorp.com.au>
@@ -58947,7 +60195,7 @@
+ const struct xenbus_device_id *id)
+{
+ int err;
-+ struct backend_info *be = kmalloc(sizeof(struct backend_info),
++ struct backend_info *be = kzalloc(sizeof(struct backend_info),
+ GFP_KERNEL);
+
+ if (!be) {
@@ -58956,8 +60204,6 @@
+ return -ENOMEM;
+ }
+
-+ memset(be, 0, sizeof(*be));
-+
+ be->is_instance_set = 0;
+ be->dev = dev;
+ dev->data = be;
@@ -59221,10 +60467,10 @@
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront.o
diff --git a/drivers/xen/tpmfront/tpmfront.c b/drivers/xen/tpmfront/tpmfront.c
new file mode 100644
-index 0000000..62e3d56
+index 0000000..03a2ab9
--- /dev/null
+++ b/drivers/xen/tpmfront/tpmfront.c
-@@ -0,0 +1,728 @@
+@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2005, IBM Corporation
+ *
@@ -59235,9 +60481,12 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
-+ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
@@ -59267,8 +60516,7 @@
+#include <linux/init.h>
+#include <xen/tpmfe.h>
+#include <linux/err.h>
-+
-+#include <asm/semaphore.h>
++#include <linux/mutex.h>
+#include <asm/io.h>
+#include <xen/evtchn.h>
+#include <xen/interface/grant_table.h>
@@ -59377,8 +60625,8 @@
+
+**************************************************************/
+
-+static DECLARE_MUTEX(upperlayer_lock);
-+static DECLARE_MUTEX(suspend_lock);
++static DEFINE_MUTEX(upperlayer_lock);
++static DEFINE_MUTEX(suspend_lock);
+static struct tpmfe_device *upperlayer_tpmfe;
+
+/*
@@ -59388,9 +60636,9 @@
+{
+ int sent;
+
-+ down(&suspend_lock);
++ mutex_lock(&suspend_lock);
+ sent = tpm_xmit(tp, buf, count, 0, ptr);
-+ up(&suspend_lock);
++ mutex_unlock(&suspend_lock);
+
+ return sent;
+}
@@ -59403,7 +60651,7 @@
+{
+ int rc = 0;
+
-+ down(&upperlayer_lock);
++ mutex_lock(&upperlayer_lock);
+ if (NULL == upperlayer_tpmfe) {
+ upperlayer_tpmfe = tpmfe_dev;
+ tpmfe_dev->max_tx_size = TPMIF_TX_RING_SIZE * PAGE_SIZE;
@@ -59414,7 +60662,7 @@
+ } else {
+ rc = -EBUSY;
+ }
-+ up(&upperlayer_lock);
++ mutex_unlock(&upperlayer_lock);
+ return rc;
+}
+EXPORT_SYMBOL(tpm_fe_register_receiver);
@@ -59424,9 +60672,9 @@
+ */
+void tpm_fe_unregister_receiver(void)
+{
-+ down(&upperlayer_lock);
++ mutex_lock(&upperlayer_lock);
+ upperlayer_tpmfe = NULL;
-+ up(&upperlayer_lock);
++ mutex_unlock(&upperlayer_lock);
+}
+EXPORT_SYMBOL(tpm_fe_unregister_receiver);
+
@@ -59439,12 +60687,12 @@
+{
+ int rc = 0;
+
-+ down(&upperlayer_lock);
++ mutex_lock(&upperlayer_lock);
+
+ if (upperlayer_tpmfe && upperlayer_tpmfe->receive)
+ rc = upperlayer_tpmfe->receive(buf, count, ptr);
+
-+ up(&upperlayer_lock);
++ mutex_unlock(&upperlayer_lock);
+ return rc;
+}
+
@@ -59537,7 +60785,8 @@
+ goto abort_transaction;
+ }
+
-+ err = xenbus_switch_state(dev, xbt, XenbusStateInitialised);
++ err = xenbus_printf(xbt, dev->nodename,
++ "state", "%d", XenbusStateInitialised);
+ if (err) {
+ goto abort_transaction;
+ }
@@ -59638,7 +60887,7 @@
+ u32 ctr;
+
+ /* lock, so no app can send */
-+ down(&suspend_lock);
++ mutex_lock(&suspend_lock);
+ tp->is_suspended = 1;
+
+ for (ctr = 0; atomic_read(&tp->tx_busy) && ctr <= 25; ctr++) {
@@ -59870,7 +61119,7 @@
+ * Notify upper layer about the state of the connection
+ * to the BE.
+ */
-+ down(&upperlayer_lock);
++ mutex_lock(&upperlayer_lock);
+
+ if (upperlayer_tpmfe != NULL) {
+ if (tp->is_connected) {
@@ -59879,7 +61128,7 @@
+ upperlayer_tpmfe->status(0);
+ }
+ }
-+ up(&upperlayer_lock);
++ mutex_unlock(&upperlayer_lock);
+}
+
+
@@ -59888,21 +61137,21 @@
+ /*
+ * Don't notify upper layer if we are in suspend mode and
+ * should disconnect - assumption is that we will resume
-+ * The semaphore keeps apps from sending.
++ * The mutex keeps apps from sending.
+ */
+ if (is_connected == 0 && tp->is_suspended == 1) {
+ return;
+ }
+
+ /*
-+ * Unlock the semaphore if we are connected again
++ * Unlock the mutex if we are connected again
+ * after being suspended - now resuming.
+ * This also removes the suspend state.
+ */
+ if (is_connected == 1 && tp->is_suspended == 1) {
+ tp->is_suspended = 0;
+ /* unlock, so apps can resume sending */
-+ up(&suspend_lock);
++ mutex_unlock(&suspend_lock);
+ }
+
+ if (is_connected != tp->is_connected) {
@@ -60001,7 +61250,7 @@
+ */
diff --git a/drivers/xen/util.c b/drivers/xen/util.c
new file mode 100644
-index 0000000..7f76a39
+index 0000000..d7980f1
--- /dev/null
+++ b/drivers/xen/util.c
@@ -0,0 +1,80 @@
@@ -60013,9 +61262,9 @@
+#include <asm/uaccess.h>
+#include <xen/driver_util.h>
+
-+static int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
++static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
-+ /* generic_page_range() does all the hard work. */
++ /* apply_to_page_range() does all the hard work. */
+ return 0;
+}
+
@@ -60031,8 +61280,8 @@
+ * This ensures that page tables are constructed for this region
+ * of kernel virtual address space and mapped into init_mm.
+ */
-+ if (generic_page_range(&init_mm, (unsigned long)area->addr,
-+ area->size, f, NULL)) {
++ if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
++ area->size, f, NULL)) {
+ free_vm_area(area);
+ return NULL;
+ }
@@ -60101,10 +61350,10 @@
+xenbus-objs += xenbus_dev.o
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
new file mode 100644
-index 0000000..fea04d0
+index 0000000..8126705
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_client.c
-@@ -0,0 +1,405 @@
+@@ -0,0 +1,408 @@
+/******************************************************************************
+ * Client-facing interface for the Xenbus driver. In other words, the
+ * interface between the Xenbus and the device-specific code, be it the
@@ -60112,8 +61361,11 @@
+ *
+ * Copyright (C) 2005 XenSource Ltd
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -60165,7 +61417,7 @@
+
+ return err;
+}
-+EXPORT_SYMBOL(xenbus_watch_path);
++EXPORT_SYMBOL_GPL(xenbus_watch_path);
+
+
+int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
@@ -60185,7 +61437,7 @@
+ kfree(state);
+ return err;
+}
-+EXPORT_SYMBOL(xenbus_watch_path2);
++EXPORT_SYMBOL_GPL(xenbus_watch_path2);
+
+
+int xenbus_switch_state(struct xenbus_device *dev,
@@ -60222,7 +61474,7 @@
+
+ return 0;
+}
-+EXPORT_SYMBOL(xenbus_switch_state);
++EXPORT_SYMBOL_GPL(xenbus_switch_state);
+
+
+/**
@@ -60285,7 +61537,7 @@
+ _dev_error(dev, err, fmt, ap);
+ va_end(ap);
+}
-+EXPORT_SYMBOL(xenbus_dev_error);
++EXPORT_SYMBOL_GPL(xenbus_dev_error);
+
+
+void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
@@ -60299,7 +61551,7 @@
+
+ xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
+}
-+EXPORT_SYMBOL(xenbus_dev_fatal);
++EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
+
+
+int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
@@ -60309,7 +61561,7 @@
+ xenbus_dev_fatal(dev, err, "granting access to ring page");
+ return err;
+}
-+EXPORT_SYMBOL(xenbus_grant_ring);
++EXPORT_SYMBOL_GPL(xenbus_grant_ring);
+
+
+int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
@@ -60326,7 +61578,7 @@
+ *port = op.u.alloc_unbound.port;
+ return err;
+}
-+EXPORT_SYMBOL(xenbus_alloc_evtchn);
++EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
+
+
+int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
@@ -60345,7 +61597,7 @@
+ *port = op.u.bind_interdomain.local_port;
+ return err;
+}
-+EXPORT_SYMBOL(xenbus_bind_evtchn);
++EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
+
+
+int xenbus_free_evtchn(struct xenbus_device *dev, int port)
@@ -60397,7 +61649,7 @@
+ *vaddr = area->addr;
+ return 0;
+}
-+EXPORT_SYMBOL(xenbus_map_ring_valloc);
++EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
+
+
+int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
@@ -60421,7 +61673,7 @@
+
+ return op.status;
+}
-+EXPORT_SYMBOL(xenbus_map_ring);
++EXPORT_SYMBOL_GPL(xenbus_map_ring);
+
+
+/* Based on Rusty Russell's skeleton driver's unmap_page */
@@ -60466,7 +61718,7 @@
+
+ return op.status;
+}
-+EXPORT_SYMBOL(xenbus_unmap_ring_vfree);
++EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
+
+
+int xenbus_unmap_ring(struct xenbus_device *dev,
@@ -60486,7 +61738,7 @@
+
+ return op.status;
+}
-+EXPORT_SYMBOL(xenbus_unmap_ring);
++EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
+
+
+XenbusState xenbus_read_driver_state(const char *path)
@@ -60498,7 +61750,7 @@
+
+ return result;
+}
-+EXPORT_SYMBOL(xenbus_read_driver_state);
++EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
+
+
+/*
@@ -60512,10 +61764,10 @@
+ */
diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c
new file mode 100644
-index 0000000..6d06b4d
+index 0000000..041b7db
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_comms.c
-@@ -0,0 +1,211 @@
+@@ -0,0 +1,218 @@
+/******************************************************************************
+ * xenbus_comms.c
+ *
@@ -60523,8 +61775,11 @@
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -60624,8 +61879,10 @@
+ cons = intf->req_cons;
+ prod = intf->req_prod;
+ mb();
-+ if (!check_indexes(cons, prod))
++ if (!check_indexes(cons, prod)) {
++ intf->req_cons = intf->req_prod = 0;
+ return -EIO;
++ }
+
+ dst = get_output_chunk(cons, prod, intf->req, &avail);
+ if (avail == 0)
@@ -60668,8 +61925,10 @@
+ cons = intf->rsp_cons;
+ prod = intf->rsp_prod;
+ mb();
-+ if (!check_indexes(cons, prod))
++ if (!check_indexes(cons, prod)) {
++ intf->rsp_cons = intf->rsp_prod = 0;
+ return -EIO;
++ }
+
+ src = get_input_chunk(cons, prod, intf->rsp, &avail);
+ if (avail == 0)
@@ -60729,17 +61988,20 @@
+ */
diff --git a/drivers/xen/xenbus/xenbus_comms.h b/drivers/xen/xenbus/xenbus_comms.h
new file mode 100644
-index 0000000..59ca0d3
+index 0000000..a378b2d
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_comms.h
-@@ -0,0 +1,50 @@
+@@ -0,0 +1,53 @@
+/*
+ * Private include for xenbus communications.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -60785,10 +62047,10 @@
+ */
diff --git a/drivers/xen/xenbus/xenbus_dev.c b/drivers/xen/xenbus/xenbus_dev.c
new file mode 100644
-index 0000000..cdab7e8
+index 0000000..282cdaf
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_dev.c
-@@ -0,0 +1,238 @@
+@@ -0,0 +1,252 @@
+/*
+ * xenbus_dev.c
+ *
@@ -60798,8 +62060,11 @@
+ * Copyright (c) 2005, Christian Limpach
+ * Copyright (c) 2005, Rusty Russell, IBM Corporation
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -60827,6 +62092,7 @@
+#include <linux/notifier.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
++#include <linux/poll.h>
+
+#include "xenbus_comms.h"
+
@@ -60970,11 +62236,10 @@
+
+ nonseekable_open(inode, filp);
+
-+ u = kmalloc(sizeof(*u), GFP_KERNEL);
++ u = kzalloc(sizeof(*u), GFP_KERNEL);
+ if (u == NULL)
+ return -ENOMEM;
+
-+ memset(u, 0, sizeof(*u));
+ INIT_LIST_HEAD(&u->transactions);
+ init_waitqueue_head(&u->read_waitq);
+
@@ -60999,11 +62264,22 @@
+ return 0;
+}
+
++static unsigned int xenbus_dev_poll(struct file *file, poll_table *wait)
++{
++ struct xenbus_dev_data *u = file->private_data;
++
++ poll_wait(file, &u->read_waitq, wait);
++ if (u->read_cons != u->read_prod)
++ return POLLIN | POLLRDNORM;
++ return 0;
++}
++
+static struct file_operations xenbus_dev_file_ops = {
+ .read = xenbus_dev_read,
+ .write = xenbus_dev_write,
+ .open = xenbus_dev_open,
+ .release = xenbus_dev_release,
++ .poll = xenbus_dev_poll,
+};
+
+static int __init
@@ -61029,10 +62305,10 @@
+ */
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
new file mode 100644
-index 0000000..d43f9fb
+index 0000000..61158a6
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_probe.c
-@@ -0,0 +1,1081 @@
+@@ -0,0 +1,1069 @@
+/******************************************************************************
+ * Talks to Xen Store to figure out what devices we have.
+ *
@@ -61040,8 +62316,11 @@
+ * Copyright (C) 2005 Mike Wray, Hewlett-Packard
+ * Copyright (C) 2005 XenSource Ltd
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -61084,9 +62363,7 @@
+
+#include "xenbus_comms.h"
+
-+extern struct semaphore xenwatch_mutex;
-+
-+#define streq(a, b) (strcmp((a), (b)) == 0)
++extern struct mutex xenwatch_mutex;
+
+static struct notifier_block *xenstore_chain;
+
@@ -61094,8 +62371,8 @@
+static const struct xenbus_device_id *
+match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
+{
-+ for (; !streq(arr->devicetype, ""); arr++) {
-+ if (streq(arr->devicetype, dev->devicetype))
++ for (; *arr->devicetype != '\0'; arr++) {
++ if (!strcmp(arr->devicetype, dev->devicetype))
+ return arr;
+ }
+ return NULL;
@@ -61141,6 +62418,23 @@
+}
+
+
++static void free_otherend_details(struct xenbus_device *dev)
++{
++ kfree(dev->otherend);
++ dev->otherend = NULL;
++}
++
++
++static void free_otherend_watch(struct xenbus_device *dev)
++{
++ if (dev->otherend_watch.node) {
++ unregister_xenbus_watch(&dev->otherend_watch);
++ kfree(dev->otherend_watch.node);
++ dev->otherend_watch.node = NULL;
++ }
++}
++
++
+static int read_otherend_details(struct xenbus_device *xendev,
+ char *id_node, char *path_node)
+{
@@ -61158,8 +62452,7 @@
+ !xenbus_exists(XBT_NULL, xendev->otherend, "")) {
+ xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
+ xendev->nodename);
-+ kfree(xendev->otherend);
-+ xendev->otherend = NULL;
++ free_otherend_details(xendev);
+ return -ENOENT;
+ }
+
@@ -61179,23 +62472,6 @@
+}
+
+
-+static void free_otherend_details(struct xenbus_device *dev)
-+{
-+ kfree(dev->otherend);
-+ dev->otherend = NULL;
-+}
-+
-+
-+static void free_otherend_watch(struct xenbus_device *dev)
-+{
-+ if (dev->otherend_watch.node) {
-+ unregister_xenbus_watch(&dev->otherend_watch);
-+ kfree(dev->otherend_watch.node);
-+ dev->otherend_watch.node = NULL;
-+ }
-+}
-+
-+
+/* Bus type for frontend drivers. */
+static int xenbus_probe_frontend(const char *type, const char *name);
+static struct xen_bus_type xenbus_frontend = {
@@ -61431,9 +62707,9 @@
+ drv->driver.probe = xenbus_dev_probe;
+ drv->driver.remove = xenbus_dev_remove;
+
-+ down(&xenwatch_mutex);
++ mutex_lock(&xenwatch_mutex);
+ ret = driver_register(&drv->driver);
-+ up(&xenwatch_mutex);
++ mutex_unlock(&xenwatch_mutex);
+ return ret;
+}
+
@@ -61443,7 +62719,7 @@
+
+ return xenbus_register_driver_common(drv, &xenbus_frontend);
+}
-+EXPORT_SYMBOL(xenbus_register_frontend);
++EXPORT_SYMBOL_GPL(xenbus_register_frontend);
+
+int xenbus_register_backend(struct xenbus_driver *drv)
+{
@@ -61451,13 +62727,13 @@
+
+ return xenbus_register_driver_common(drv, &xenbus_backend);
+}
-+EXPORT_SYMBOL(xenbus_register_backend);
++EXPORT_SYMBOL_GPL(xenbus_register_backend);
+
+void xenbus_unregister_driver(struct xenbus_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
-+EXPORT_SYMBOL(xenbus_unregister_driver);
++EXPORT_SYMBOL_GPL(xenbus_unregister_driver);
+
+struct xb_find_info
+{
@@ -61470,7 +62746,7 @@
+ struct xenbus_device *xendev = to_xenbus_device(dev);
+ struct xb_find_info *info = data;
+
-+ if (streq(xendev->nodename, info->nodename)) {
++ if (!strcmp(xendev->nodename, info->nodename)) {
+ info->dev = xendev;
+ get_device(dev);
+ return 1;
@@ -61522,15 +62798,10 @@
+ } while (info.dev);
+}
+
-+static void xenbus_dev_free(struct xenbus_device *xendev)
-+{
-+ kfree(xendev);
-+}
-+
+static void xenbus_dev_release(struct device *dev)
+{
+ if (dev)
-+ xenbus_dev_free(to_xenbus_device(dev));
++ kfree(to_xenbus_device(dev));
+}
+
+/* Simplified asprintf. */
@@ -61587,10 +62858,9 @@
+ }
+
+ stringlen = strlen(nodename) + 1 + strlen(type) + 1;
-+ xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
++ xendev = kzalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
+ if (!xendev)
+ return -ENOMEM;
-+ memset(xendev, 0, sizeof(*xendev));
+
+ /* Copy the strings into the extra space. */
+
@@ -61620,7 +62890,7 @@
+
+ return 0;
+fail:
-+ xenbus_dev_free(xendev);
++ kfree(xendev);
+ return err;
+}
+
@@ -61881,7 +63151,7 @@
+ bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
+ xs_suspend();
+}
-+EXPORT_SYMBOL(xenbus_suspend);
++EXPORT_SYMBOL_GPL(xenbus_suspend);
+
+void xenbus_resume(void)
+{
@@ -61890,7 +63160,7 @@
+ bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
+ bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
+}
-+EXPORT_SYMBOL(xenbus_resume);
++EXPORT_SYMBOL_GPL(xenbus_resume);
+
+
+/* A flag to determine if xenstored is 'ready' (i.e. has started) */
@@ -61908,13 +63178,13 @@
+
+ return ret;
+}
-+EXPORT_SYMBOL(register_xenstore_notifier);
++EXPORT_SYMBOL_GPL(register_xenstore_notifier);
+
+void unregister_xenstore_notifier(struct notifier_block *nb)
+{
+ notifier_chain_unregister(&xenstore_chain, nb);
+}
-+EXPORT_SYMBOL(unregister_xenstore_notifier);
++EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
+
+
+static int all_devices_ready_(struct device *dev, void *data)
@@ -61992,9 +63262,8 @@
+ if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0))
+ return -EINVAL;
+
-+ vma->vm_pgoff = mfn_to_pfn(xen_start_info->store_mfn);
-+
-+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++ if (remap_pfn_range(vma, vma->vm_start,
++ mfn_to_pfn(xen_start_info->store_mfn),
+ size, vma->vm_page_prot))
+ return -EAGAIN;
+
@@ -62056,10 +63325,6 @@
+ if (!page)
+ return -ENOMEM;
+
-+ /* We don't refcnt properly, so set reserved on page.
-+ * (this allocation is permanent) */
-+ SetPageReserved(virt_to_page(page));
-+
+ xen_start_info->store_mfn =
+ pfn_to_mfn(virt_to_phys((void *)page) >>
+ PAGE_SHIFT);
@@ -62074,7 +63339,7 @@
+ xen_start_info->store_evtchn = op.u.alloc_unbound.port;
+
+ /* And finally publish the above info in /proc/xen */
-+ xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0400);
++ xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0600);
+ if (xsd_kva_intf) {
+ memcpy(&xsd_kva_fops, xsd_kva_intf->proc_fops,
+ sizeof(xsd_kva_fops));
@@ -62085,7 +63350,8 @@
+ xsd_port_intf = create_xen_proc_entry("xsd_port", 0400);
+ if (xsd_port_intf)
+ xsd_port_intf->read_proc = xsd_port_read;
-+ }
++ } else
++ xenstored_ready = 1;
+
+ /* Initialize the interface to xenstore. */
+ err = xs_init();
@@ -62095,10 +63361,8 @@
+ return err;
+ }
+
-+ if (!dom0) {
-+ xenstored_ready = 1;
++ if (!dom0)
+ xenbus_probe(NULL);
-+ }
+
+ return 0;
+}
@@ -62116,10 +63380,10 @@
+ */
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
new file mode 100644
-index 0000000..ad43b0c
+index 0000000..7e343ef
--- /dev/null
+++ b/drivers/xen/xenbus/xenbus_xs.c
-@@ -0,0 +1,830 @@
+@@ -0,0 +1,839 @@
+/******************************************************************************
+ * xenbus_xs.c
+ *
@@ -62128,8 +63392,11 @@
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -62160,14 +63427,13 @@
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/kthread.h>
++#include <linux/rwsem.h>
+#include <xen/xenbus.h>
+#include "xenbus_comms.h"
+
+/* xenbus_probe.c */
+extern char *kasprintf(const char *fmt, ...);
+
-+#define streq(a, b) (strcmp((a), (b)) == 0)
-+
+struct xs_stored_msg {
+ struct list_head list;
+
@@ -62195,7 +63461,7 @@
+ wait_queue_head_t reply_waitq;
+
+ /* One request at a time. */
-+ struct semaphore request_mutex;
++ struct mutex request_mutex;
+
+ /* Protect transactions against save/restore. */
+ struct rw_semaphore suspend_mutex;
@@ -62218,14 +63484,14 @@
+ * carrying out work.
+ */
+static pid_t xenwatch_pid;
-+/* static */ DECLARE_MUTEX(xenwatch_mutex);
++/* static */ DEFINE_MUTEX(xenwatch_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);
+
+static int get_error(const char *errorstring)
+{
+ unsigned int i;
+
-+ for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
++ for (i = 0; strcmp(errorstring, xsd_errors[i].errstring) != 0; i++) {
+ if (i == ARRAY_SIZE(xsd_errors) - 1) {
+ printk(KERN_WARNING
+ "XENBUS xen store gave: unknown error %s",
@@ -62275,12 +63541,12 @@
+ msg.type = XS_DEBUG;
+ msg.len = sizeof("print") + count + 1;
+
-+ down(&xs_state.request_mutex);
++ mutex_lock(&xs_state.request_mutex);
+ xb_write(&msg, sizeof(msg));
+ xb_write("print", sizeof("print"));
+ xb_write(str, count);
+ xb_write("", 1);
-+ up(&xs_state.request_mutex);
++ mutex_unlock(&xs_state.request_mutex);
+}
+
+void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
@@ -62292,7 +63558,7 @@
+ if (req_msg.type == XS_TRANSACTION_START)
+ down_read(&xs_state.suspend_mutex);
+
-+ down(&xs_state.request_mutex);
++ mutex_lock(&xs_state.request_mutex);
+
+ err = xb_write(msg, sizeof(*msg) + msg->len);
+ if (err) {
@@ -62301,7 +63567,7 @@
+ } else
+ ret = read_reply(&msg->type, &msg->len);
+
-+ up(&xs_state.request_mutex);
++ mutex_unlock(&xs_state.request_mutex);
+
+ if ((msg->type == XS_TRANSACTION_END) ||
+ ((req_msg.type == XS_TRANSACTION_START) &&
@@ -62330,25 +63596,25 @@
+ for (i = 0; i < num_vecs; i++)
+ msg.len += iovec[i].iov_len;
+
-+ down(&xs_state.request_mutex);
++ mutex_lock(&xs_state.request_mutex);
+
+ err = xb_write(&msg, sizeof(msg));
+ if (err) {
-+ up(&xs_state.request_mutex);
++ mutex_unlock(&xs_state.request_mutex);
+ return ERR_PTR(err);
+ }
+
+ for (i = 0; i < num_vecs; i++) {
+ err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
+ if (err) {
-+ up(&xs_state.request_mutex);
++ mutex_unlock(&xs_state.request_mutex);
+ return ERR_PTR(err);
+ }
+ }
+
+ ret = read_reply(&msg.type, len);
+
-+ up(&xs_state.request_mutex);
++ mutex_unlock(&xs_state.request_mutex);
+
+ if (IS_ERR(ret))
+ return ret;
@@ -62359,7 +63625,14 @@
+ return ERR_PTR(-err);
+ }
+
-+ BUG_ON(msg.type != type);
++ if (msg.type != type) {
++ if (printk_ratelimit())
++ printk(KERN_WARNING
++ "XENBUS unexpected type [%d], expected [%d]\n",
++ msg.type, type);
++ kfree(ret);
++ return ERR_PTR(-EINVAL);
++ }
+ return ret;
+}
+
@@ -62448,7 +63721,7 @@
+
+ return split(strings, len, num);
+}
-+EXPORT_SYMBOL(xenbus_directory);
++EXPORT_SYMBOL_GPL(xenbus_directory);
+
+/* Check if a path exists. Return 1 if it does. */
+int xenbus_exists(xenbus_transaction_t t,
@@ -62463,7 +63736,7 @@
+ kfree(d);
+ return 1;
+}
-+EXPORT_SYMBOL(xenbus_exists);
++EXPORT_SYMBOL_GPL(xenbus_exists);
+
+/* Get the value of a single file.
+ * Returns a kmalloced value: call free() on it after use.
@@ -62483,7 +63756,7 @@
+ kfree(path);
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_read);
++EXPORT_SYMBOL_GPL(xenbus_read);
+
+/* Write the value of a single file.
+ * Returns -err on failure.
@@ -62508,7 +63781,7 @@
+ kfree(path);
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_write);
++EXPORT_SYMBOL_GPL(xenbus_write);
+
+/* Create a new directory. */
+int xenbus_mkdir(xenbus_transaction_t t,
@@ -62525,7 +63798,7 @@
+ kfree(path);
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_mkdir);
++EXPORT_SYMBOL_GPL(xenbus_mkdir);
+
+/* Destroy a file or directory (directories must be empty). */
+int xenbus_rm(xenbus_transaction_t t, const char *dir, const char *node)
@@ -62541,7 +63814,7 @@
+ kfree(path);
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_rm);
++EXPORT_SYMBOL_GPL(xenbus_rm);
+
+/* Start a transaction: changes by others will not be seen during this
+ * transaction, and changes will not be visible to others until end.
@@ -62562,7 +63835,7 @@
+ kfree(id_str);
+ return 0;
+}
-+EXPORT_SYMBOL(xenbus_transaction_start);
++EXPORT_SYMBOL_GPL(xenbus_transaction_start);
+
+/* End a transaction.
+ * If abandon is true, transaction is discarded instead of committed.
@@ -62583,7 +63856,7 @@
+
+ return err;
+}
-+EXPORT_SYMBOL(xenbus_transaction_end);
++EXPORT_SYMBOL_GPL(xenbus_transaction_end);
+
+/* Single read and scanf: returns -errno or num scanned. */
+int xenbus_scanf(xenbus_transaction_t t,
@@ -62606,7 +63879,7 @@
+ return -ERANGE;
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_scanf);
++EXPORT_SYMBOL_GPL(xenbus_scanf);
+
+/* Single printf and write: returns -errno or 0. */
+int xenbus_printf(xenbus_transaction_t t,
@@ -62632,7 +63905,7 @@
+
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_printf);
++EXPORT_SYMBOL_GPL(xenbus_printf);
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xenbus_gather(xenbus_transaction_t t, const char *dir, ...)
@@ -62662,7 +63935,7 @@
+ va_end(ap);
+ return ret;
+}
-+EXPORT_SYMBOL(xenbus_gather);
++EXPORT_SYMBOL_GPL(xenbus_gather);
+
+static int xs_watch(const char *path, const char *token)
+{
@@ -62732,7 +64005,7 @@
+
+ return err;
+}
-+EXPORT_SYMBOL(register_xenbus_watch);
++EXPORT_SYMBOL_GPL(register_xenbus_watch);
+
+void unregister_xenbus_watch(struct xenbus_watch *watch)
+{
@@ -62770,16 +64043,16 @@
+
+ /* Flush any currently-executing callback, unless we are it. :-) */
+ if (current->pid != xenwatch_pid) {
-+ down(&xenwatch_mutex);
-+ up(&xenwatch_mutex);
++ mutex_lock(&xenwatch_mutex);
++ mutex_unlock(&xenwatch_mutex);
+ }
+}
-+EXPORT_SYMBOL(unregister_xenbus_watch);
++EXPORT_SYMBOL_GPL(unregister_xenbus_watch);
+
+void xs_suspend(void)
+{
+ down_write(&xs_state.suspend_mutex);
-+ down(&xs_state.request_mutex);
++ mutex_lock(&xs_state.request_mutex);
+}
+
+void xs_resume(void)
@@ -62787,7 +64060,7 @@
+ struct xenbus_watch *watch;
+ char token[sizeof(watch) * 2 + 1];
+
-+ up(&xs_state.request_mutex);
++ mutex_unlock(&xs_state.request_mutex);
+
+ /* No need for watches_lock: the suspend_mutex is sufficient. */
+ list_for_each_entry(watch, &watches, list) {
@@ -62810,7 +64083,7 @@
+ if (kthread_should_stop())
+ break;
+
-+ down(&xenwatch_mutex);
++ mutex_lock(&xenwatch_mutex);
+
+ spin_lock(&watch_events_lock);
+ ent = watch_events.next;
@@ -62828,7 +64101,7 @@
+ kfree(msg);
+ }
+
-+ up(&xenwatch_mutex);
++ mutex_unlock(&xenwatch_mutex);
+ }
+
+ return 0;
@@ -62921,7 +64194,7 @@
+ spin_lock_init(&xs_state.reply_lock);
+ init_waitqueue_head(&xs_state.reply_waitq);
+
-+ init_MUTEX(&xs_state.request_mutex);
++ mutex_init(&xs_state.request_mutex);
+ init_rwsem(&xs_state.suspend_mutex);
+
+ /* Initialize the shared memory rings to talk to xenstored */
@@ -63711,10 +64984,10 @@
if (IO_APIC_IRQ(i))
diff --git a/include/asm-i386/hypercall.h b/include/asm-i386/hypercall.h
new file mode 100644
-index 0000000..1b2605e
+index 0000000..f920d4b
--- /dev/null
+++ b/include/asm-i386/hypercall.h
-@@ -0,0 +1,329 @@
+@@ -0,0 +1,357 @@
+/******************************************************************************
+ * hypercall.h
+ *
@@ -63722,8 +64995,11 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -63754,6 +65030,7 @@
+#include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
+#include <xen/interface/nmi.h>
++#include <linux/errno.h>
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
@@ -63890,6 +65167,31 @@
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
++static inline int
++HYPERVISOR_sched_op_new(
++ int cmd, void *arg)
++{
++ return _hypercall2(int, sched_op_new, cmd, arg);
++}
++
++static inline int
++HYPERVISOR_poll(
++ evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
++{
++ struct sched_poll sched_poll = {
++ .ports = ports,
++ .nr_ports = nr_ports,
++ .timeout = jiffies_to_st(timeout)
++ };
++
++ int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
++
++ if (rc == -ENOSYS)
++ rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
++
++ return rc;
++}
++
+static inline long
+HYPERVISOR_set_timer_op(
+ u64 timeout)
@@ -64025,8 +65327,7 @@
+
+static inline int
+HYPERVISOR_nmi_op(
-+ unsigned long op,
-+ unsigned long arg)
++ unsigned long op, void *arg)
+{
+ return _hypercall2(int, nmi_op, op, arg);
+}
@@ -64046,7 +65347,7 @@
+ */
diff --git a/include/asm-i386/hypervisor.h b/include/asm-i386/hypervisor.h
new file mode 100644
-index 0000000..021e2de
+index 0000000..f721acc
--- /dev/null
+++ b/include/asm-i386/hypervisor.h
@@ -0,0 +1,168 @@
@@ -64057,8 +65358,11 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -64134,12 +65438,6 @@
+void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */
+void xen_pgd_pin(unsigned long ptr);
+void xen_pgd_unpin(unsigned long ptr);
-+void xen_pud_pin(unsigned long ptr); /* x86_64 only */
-+void xen_pud_unpin(unsigned long ptr); /* x86_64 only */
-+void xen_pmd_pin(unsigned long ptr); /* x86_64 only */
-+void xen_pmd_unpin(unsigned long ptr); /* x86_64 only */
-+void xen_pte_pin(unsigned long ptr);
-+void xen_pte_unpin(unsigned long ptr);
+
+void xen_set_ldt(unsigned long ptr, unsigned long bytes);
+void xen_machphys_update(unsigned long mfn, unsigned long pfn);
@@ -64158,6 +65456,9 @@
+void xen_destroy_contiguous_region(
+ unsigned long vstart, unsigned int order);
+
++/* Turn jiffies into Xen system time. */
++u64 jiffies_to_st(unsigned long jiffies);
++
+#include <asm/hypercall.h>
+
+#if defined(CONFIG_X86_64)
@@ -64532,13 +65833,19 @@
+#endif /* __ASM_MACH_PAGE_H */
diff --git a/include/asm-i386/mach-default/mach_pgtable.h b/include/asm-i386/mach-default/mach_pgtable.h
new file mode 100644
-index 0000000..118b32c
+index 0000000..9dccb55
--- /dev/null
+++ b/include/asm-i386/mach-default/mach_pgtable.h
-@@ -0,0 +1,45 @@
+@@ -0,0 +1,51 @@
+#ifndef __ASM_MACH_PGTABLE_H
+#define __ASM_MACH_PGTABLE_H
+
++#ifdef CONFIG_X86_PAE
++#define HAVE_SHARED_KERNEL_PMD 1
++#else
++#define HAVE_SHARED_KERNEL_PMD 0
++#endif
++
+extern pgd_t swapper_pg_dir[1024];
+
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
@@ -64583,32 +65890,17 @@
+#endif /* __ASM_MACH_PGTABLE_H */
diff --git a/include/asm-i386/mach-default/mach_processor.h b/include/asm-i386/mach-default/mach_processor.h
new file mode 100644
-index 0000000..7d6b3b2
+index 0000000..708e572
--- /dev/null
+++ b/include/asm-i386/mach-default/mach_processor.h
-@@ -0,0 +1,53 @@
+@@ -0,0 +1,38 @@
+#ifndef __ASM_MACH_PROCESSOR_H
+#define __ASM_MACH_PROCESSOR_H
+
-+static inline void set_in_cr4(unsigned long mask)
-+{
-+ unsigned cr4;
-+ mmu_cr4_features |= mask;
-+ cr4 = read_cr4();
-+ cr4 |= mask;
-+ write_cr4(cr4);
-+}
-+
-+static inline void clear_in_cr4(unsigned long mask)
-+{
-+ unsigned cr4;
-+ mmu_cr4_features &= ~mask;
-+ cr4 = read_cr4();
-+ cr4 &= ~mask;
-+ write_cr4(cr4);
-+}
++#define CPUID_STR "cpuid"
+
-+static inline void mach_load_esp0(struct tss_struct *tss, struct thread_struct *thread)
++static inline void mach_update_kernel_stack(unsigned long esp0,
++ unsigned short ss0)
+{
+}
+
@@ -65586,45 +66878,23 @@
+#endif /* __ASM_MACH_PGTABLE_H */
diff --git a/include/asm-i386/mach-xen/mach_processor.h b/include/asm-i386/mach-xen/mach_processor.h
new file mode 100644
-index 0000000..4080373
+index 0000000..dffd6c5
--- /dev/null
+++ b/include/asm-i386/mach-xen/mach_processor.h
-@@ -0,0 +1,57 @@
+@@ -0,0 +1,35 @@
+#ifndef __ASM_MACH_PROCESSOR_H
+#define __ASM_MACH_PROCESSOR_H
+
-+#include <xen/interface/physdev.h>
-+
-+static inline void __unsupported_cr4(void)
-+{
-+ const char *msg = "Xen unsupported cr4 update\n";
-+
-+ (void)HYPERVISOR_console_io(
-+ CONSOLEIO_write, __builtin_strlen(msg), (char *)msg);
-+ BUG();
-+}
++#define CPUID_STR XEN_CPUID
+
-+static inline void set_in_cr4(unsigned long mask)
-+{
-+ mmu_cr4_features |= mask;
-+ switch (mask) {
-+ case X86_CR4_OSFXSR:
-+ case X86_CR4_OSXMMEXCPT:
-+ break;
-+ default:
-+ __unsupported_cr4();
-+ }
-+}
++#include <xen/interface/physdev.h>
+
-+static inline void clear_in_cr4(unsigned long mask)
++static inline void mach_update_kernel_stack(unsigned long esp0,
++ unsigned short ss0)
+{
-+ mmu_cr4_features &= ~mask;
-+ __unsupported_cr4();
++ HYPERVISOR_stack_switch(ss0, esp0);
+}
+
-+#define mach_load_esp0(tss, thread) \
-+ HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)
-+
+/*
+ * These special macros can be used to get or set a debugging register
+ */
@@ -65902,10 +67172,10 @@
+#endif /* !_MACH_TRAPS_H */
diff --git a/include/asm-i386/mach-xen/setup_arch_post.h b/include/asm-i386/mach-xen/setup_arch_post.h
new file mode 100644
-index 0000000..49c3f2a
+index 0000000..646cf78
--- /dev/null
+++ b/include/asm-i386/mach-xen/setup_arch_post.h
-@@ -0,0 +1,50 @@
+@@ -0,0 +1,45 @@
+/**
+ * machine_specific_memory_setup - Hook for machine specific memory setup.
+ *
@@ -65924,18 +67194,6 @@
+ return "Xen";
+}
+
-+void __devinit machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c)
-+{
-+ clear_bit(X86_FEATURE_VME, c->x86_capability);
-+ clear_bit(X86_FEATURE_DE, c->x86_capability);
-+ clear_bit(X86_FEATURE_PSE, c->x86_capability);
-+ clear_bit(X86_FEATURE_PGE, c->x86_capability);
-+ clear_bit(X86_FEATURE_SEP, c->x86_capability);
-+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
-+ clear_bit(X86_FEATURE_MTRR, c->x86_capability);
-+ c->hlt_works_ok = 0;
-+}
-+
+extern void hypervisor_callback(void);
+extern void failsafe_callback(void);
+extern void nmi(void);
@@ -65943,14 +67201,21 @@
+static void __init machine_specific_arch_setup(void)
+{
+ struct xen_platform_parameters pp;
++ struct xennmi_callback cb;
++
++ if (xen_feature(XENFEAT_auto_translated_physmap) &&
++ xen_start_info->shared_info < xen_start_info->nr_pages) {
++ HYPERVISOR_shared_info =
++ (shared_info_t *)__va(xen_start_info->shared_info);
++ memset(empty_zero_page, 0, sizeof(empty_zero_page));
++ }
+
+ HYPERVISOR_set_callbacks(
+ __KERNEL_CS, (unsigned long)hypervisor_callback,
+ __KERNEL_CS, (unsigned long)failsafe_callback);
+
-+ HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi);
-+
-+ machine_specific_modify_cpu_capabilities(&boot_cpu_data);
++ cb.handler_address = (unsigned long)&nmi;
++ HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+
+ if (HYPERVISOR_xen_version(XENVER_platform_parameters,
+ &pp) == 0)
@@ -66335,7 +67600,7 @@
pgprot_val(pgprot)) & __supported_pte_mask);
}
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
-index 088a945..d933743 100644
+index 088a945..956bd43 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -34,7 +34,6 @@ struct vm_area_struct;
@@ -66364,7 +67629,24 @@
static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
-@@ -278,7 +276,8 @@ static inline pte_t ptep_get_and_clear_f
+@@ -269,7 +267,16 @@ static inline pte_t ptep_get_and_clear_f
+ pte_t pte;
+ if (full) {
+ pte = *ptep;
++#ifdef CONFIG_X86_PAE
++ /* Cannot do this in a single step, as the compiler may
++ issue the two stores in either order, but the hypervisor
++ must not see the high part before the low one. */
++ ptep->pte_low = 0;
++ barrier();
++ ptep->pte_high = 0;
++#else
+ *ptep = __pte(0);
++#endif
+ } else {
+ pte = ptep_get_and_clear(mm, addr, ptep);
+ }
+@@ -278,7 +285,8 @@ static inline pte_t ptep_get_and_clear_f
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
@@ -66374,7 +67656,7 @@
}
/*
-@@ -399,9 +398,9 @@ extern void noexec_setup(const char *str
+@@ -399,9 +407,9 @@ extern void noexec_setup(const char *str
#if defined(CONFIG_HIGHPTE)
#define pte_offset_map(dir, address) \
@@ -66386,7 +67668,7 @@
#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
#else
-@@ -423,14 +422,6 @@ extern void noexec_setup(const char *str
+@@ -423,14 +431,6 @@ extern void noexec_setup(const char *str
* bit at the same time.
*/
#define update_mmu_cache(vma,address,pte) do { } while (0)
@@ -66401,7 +67683,7 @@
#endif /* !__ASSEMBLY__ */
-@@ -438,9 +429,6 @@ extern void noexec_setup(const char *str
+@@ -438,9 +438,6 @@ extern void noexec_setup(const char *str
#define kern_addr_valid(addr) (1)
#endif /* CONFIG_FLATMEM */
@@ -66412,10 +67694,18 @@
#define GET_IOSPACE(pfn) 0
#define GET_PFN(pfn) (pfn)
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
-index feca5d9..2e7bec8 100644
+index feca5d9..36eff94 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
-@@ -90,8 +90,10 @@ struct cpuinfo_x86 {
+@@ -20,6 +20,7 @@
+ #include <linux/config.h>
+ #include <linux/threads.h>
+ #include <asm/percpu.h>
++#include <mach_processor.h>
+
+ /* flag for disabling the tsc */
+ extern int tsc_disable;
+@@ -90,8 +91,10 @@ struct cpuinfo_x86 {
extern struct cpuinfo_x86 boot_cpu_data;
extern struct cpuinfo_x86 new_cpu_data;
@@ -66426,32 +67716,61 @@
#ifdef CONFIG_SMP
extern struct cpuinfo_x86 cpu_data[];
-@@ -232,24 +234,6 @@ static inline unsigned int cpuid_edx(uns
+@@ -143,7 +146,7 @@ static inline void detect_ht(struct cpui
*/
- extern unsigned long mmu_cr4_features;
+ static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
+ {
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+@@ -155,7 +158,7 @@ static inline void cpuid(unsigned int op
+ static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+ {
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+@@ -170,7 +173,7 @@ static inline unsigned int cpuid_eax(uns
+ {
+ unsigned int eax;
--static inline void set_in_cr4 (unsigned long mask)
--{
-- unsigned cr4;
-- mmu_cr4_features |= mask;
-- cr4 = read_cr4();
-- cr4 |= mask;
-- write_cr4(cr4);
--}
--
--static inline void clear_in_cr4 (unsigned long mask)
--{
-- unsigned cr4;
-- mmu_cr4_features &= ~mask;
-- cr4 = read_cr4();
-- cr4 &= ~mask;
-- write_cr4(cr4);
--}
--
- /*
- * NSC/Cyrix CPU configuration register indexes
- */
-@@ -333,7 +317,9 @@ extern int bootloader_type;
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax)
+ : "0" (op)
+ : "bx", "cx", "dx");
+@@ -180,7 +183,7 @@ static inline unsigned int cpuid_ebx(uns
+ {
+ unsigned int eax, ebx;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax), "=b" (ebx)
+ : "0" (op)
+ : "cx", "dx" );
+@@ -190,7 +193,7 @@ static inline unsigned int cpuid_ecx(uns
+ {
+ unsigned int eax, ecx;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax), "=c" (ecx)
+ : "0" (op)
+ : "bx", "dx" );
+@@ -200,7 +203,7 @@ static inline unsigned int cpuid_edx(uns
+ {
+ unsigned int eax, edx;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax), "=d" (edx)
+ : "0" (op)
+ : "bx", "cx");
+@@ -333,7 +336,9 @@ extern int bootloader_type;
#define IO_BITMAP_BITS 65536
#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
@@ -66461,7 +67780,7 @@
#define INVALID_IO_BITMAP_OFFSET 0x8000
#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
-@@ -391,6 +377,7 @@ typedef struct {
+@@ -391,6 +396,7 @@ typedef struct {
struct thread_struct;
@@ -66469,7 +67788,7 @@
struct tss_struct {
unsigned short back_link,__blh;
unsigned long esp0;
-@@ -436,6 +423,7 @@ struct tss_struct {
+@@ -436,6 +442,7 @@ struct tss_struct {
*/
unsigned long stack[64];
} __attribute__((packed));
@@ -66477,17 +67796,15 @@
#define ARCH_MIN_TASKALIGN 16
-@@ -472,6 +460,9 @@ struct thread_struct {
+@@ -472,6 +479,7 @@ struct thread_struct {
.io_bitmap_ptr = NULL, \
}
-+#include <mach_processor.h>
-+
+#ifndef CONFIG_X86_NO_TSS
/*
* Note that the .io_bitmap member must be extra-big. This is because
* the CPU will access an additional byte beyond the end of the IO
-@@ -486,15 +477,25 @@ struct thread_struct {
+@@ -486,15 +494,25 @@ struct thread_struct {
.io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \
}
@@ -66507,14 +67824,14 @@
+#define __load_esp0(tss, thread)
+#endif
+
-+#define load_esp0(tss, thread) do { \
-+ __load_esp0(tss, thread); \
-+ mach_load_esp0(tss, thread); \
++#define load_esp0(tss, thread) do { \
++ __load_esp0(tss, thread); \
++ mach_update_kernel_stack((thread)->esp0, __KERNEL_DS); \
+} while (0)
#define start_thread(regs, new_eip, new_esp) do { \
__asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0)); \
-@@ -507,33 +508,6 @@ static inline void load_esp0(struct tss_
+@@ -507,33 +525,6 @@ static inline void load_esp0(struct tss_
regs->esp = new_esp; \
} while (0)
@@ -67655,10 +68972,10 @@
#endif /* _ASM_IA64_GCC_INTRIN_H */
diff --git a/include/asm-ia64/hypercall.h b/include/asm-ia64/hypercall.h
new file mode 100644
-index 0000000..fd57868
+index 0000000..b260c56
--- /dev/null
+++ b/include/asm-ia64/hypercall.h
-@@ -0,0 +1,253 @@
+@@ -0,0 +1,283 @@
+/******************************************************************************
+ * hypercall.h
+ *
@@ -67666,8 +68983,11 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -67693,6 +69013,8 @@
+
+#include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
++#include <xen/interface/dom0_ops.h>
++#include <linux/errno.h>
+
+/* FIXME: temp place to hold these page related macros */
+#include <asm/page.h>
@@ -67826,6 +69148,31 @@
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
++static inline int
++HYPERVISOR_sched_op_new(
++ int cmd, void *arg)
++{
++ return _hypercall2(int, sched_op_new, cmd, arg);
++}
++
++static inline int
++HYPERVISOR_poll(
++ evtchn_port_t *ports, unsigned int nr_ports, unsigned long timeout)
++{
++ struct sched_poll sched_poll = {
++ .ports = ports,
++ .nr_ports = nr_ports,
++ .timeout = jiffies_to_st(timeout)
++ };
++
++ int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
++
++ if (rc == -ENOSYS)
++ rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
++
++ return rc;
++}
++
+static inline long
+HYPERVISOR_set_timer_op(
+ u64 timeout)
@@ -67914,10 +69261,10 @@
+#endif /* __HYPERCALL_H__ */
diff --git a/include/asm-ia64/hypervisor.h b/include/asm-ia64/hypervisor.h
new file mode 100644
-index 0000000..4771111
+index 0000000..4a5f424
--- /dev/null
+++ b/include/asm-ia64/hypervisor.h
-@@ -0,0 +1,70 @@
+@@ -0,0 +1,78 @@
+/******************************************************************************
+ * hypervisor.h
+ *
@@ -67925,8 +69272,11 @@
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -67964,6 +69314,11 @@
+
+void force_evtchn_callback(void);
+
++int xen_init(void);
++
++/* Turn jiffies into Xen system time. XXX Implement me. */
++#define jiffies_to_st(j) 0
++
+#include <asm/hypercall.h>
+
+// for drivers/xen/privcmd/privcmd.c
@@ -68314,10 +69669,10 @@
({ \
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
new file mode 100644
-index 0000000..235197b
+index 0000000..af1685b
--- /dev/null
+++ b/include/asm-ia64/xen/privop.h
-@@ -0,0 +1,272 @@
+@@ -0,0 +1,277 @@
+#ifndef _ASM_IA64_XEN_PRIVOP_H
+#define _ASM_IA64_XEN_PRIVOP_H
+
@@ -68353,6 +69708,11 @@
+#define XEN_HYPER_GET_RR break 0x10
+#define XEN_HYPER_SET_RR break 0x11
+#define XEN_HYPER_SET_KR break 0x12
++#define XEN_HYPER_FC break 0x13
++#define XEN_HYPER_GET_CPUID break 0x14
++#define XEN_HYPER_GET_PMD break 0x15
++#define XEN_HYPER_GET_EFLAG break 0x16
++#define XEN_HYPER_SET_EFLAG break 0x17
+#endif
+
+#ifndef __ASSEMBLY__
@@ -68982,7 +70342,7 @@
+
#endif /* _X8664_DMA_MAPPING_H */
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
-index 7b286bd..beaf264 100644
+index 7b286bd..315b124 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -17,6 +17,10 @@
@@ -68996,7 +70356,7 @@
/*
* Here we define all the compile-time 'special' virtual
-@@ -45,6 +49,18 @@ enum fixed_addresses {
+@@ -45,6 +49,16 @@ enum fixed_addresses {
FIX_IO_APIC_BASE_0,
FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
#endif
@@ -69006,8 +70366,6 @@
+ FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+#endif
+ FIX_SHARED_INFO,
-+ FIX_GNTTAB_BEGIN,
-+ FIX_GNTTAB_END = FIX_GNTTAB_BEGIN + NR_GRANT_FRAMES - 1,
+#define NR_FIX_ISAMAPS 256
+ FIX_ISAMAP_END,
+ FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
@@ -69015,7 +70373,7 @@
__end_of_fixed_addresses
};
-@@ -59,6 +75,9 @@ extern void __set_fixmap (enum fixed_add
+@@ -59,6 +73,9 @@ extern void __set_fixmap (enum fixed_add
#define set_fixmap_nocache(idx, phys) \
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
@@ -69214,10 +70572,10 @@
send_IPI_self(IO_APIC_VECTOR(i));
diff --git a/include/asm-x86_64/hypercall.h b/include/asm-x86_64/hypercall.h
new file mode 100644
-index 0000000..87bbfb4
+index 0000000..9fb2016
--- /dev/null
+++ b/include/asm-x86_64/hypercall.h
-@@ -0,0 +1,323 @@
+@@ -0,0 +1,352 @@
+/******************************************************************************
+ * hypercall.h
+ *
@@ -69229,8 +70587,11 @@
+ * Benjamin Liu <benjamin.liu at intel.com>
+ * Jun Nakajima <jun.nakajima at intel.com>
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -69256,6 +70617,8 @@
+
+#include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
++#include <xen/interface/nmi.h>
++#include <linux/errno.h>
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
@@ -69393,6 +70756,31 @@
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
++static inline int
++HYPERVISOR_sched_op_new(
++ int cmd, void *arg)
++{
++ return _hypercall2(int, sched_op_new, cmd, arg);
++}
++
++static inline int
++HYPERVISOR_poll(
++ evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
++{
++ struct sched_poll sched_poll = {
++ .ports = ports,
++ .nr_ports = nr_ports,
++ .timeout = jiffies_to_st(timeout)
++ };
++
++ int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
++
++ if (rc == -ENOSYS)
++ rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
++
++ return rc;
++}
++
+static inline long
+HYPERVISOR_set_timer_op(
+ u64 timeout)
@@ -69524,8 +70912,7 @@
+
+static inline int
+HYPERVISOR_nmi_op(
-+ unsigned long op,
-+ unsigned long arg)
++ unsigned long op, void *arg)
+{
+ return _hypercall2(int, nmi_op, op, arg);
+}
@@ -70018,6 +71405,73 @@
#define deactivate_mm(tsk,mm) do { \
load_gs_index(0); \
asm volatile("movl %0,%%fs"::"r"(0)); \
+diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
+index 10f8b51..cc34004 100644
+--- a/include/asm-x86_64/msr.h
++++ b/include/asm-x86_64/msr.h
+@@ -79,10 +79,16 @@
+ : "=a" (low), "=d" (high) \
+ : "c" (counter))
+
++#ifndef CONFIG_XEN
++#define CPUID_STR "cpuid"
++#else
++#define CPUID_STR XEN_CPUID
++#endif
++
+ static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+ {
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+@@ -94,7 +100,7 @@ static inline void cpuid(int op, unsigne
+ static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+ {
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+@@ -109,7 +115,7 @@ static inline unsigned int cpuid_eax(uns
+ {
+ unsigned int eax;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax)
+ : "0" (op)
+ : "bx", "cx", "dx");
+@@ -119,7 +125,7 @@ static inline unsigned int cpuid_ebx(uns
+ {
+ unsigned int eax, ebx;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax), "=b" (ebx)
+ : "0" (op)
+ : "cx", "dx" );
+@@ -129,7 +135,7 @@ static inline unsigned int cpuid_ecx(uns
+ {
+ unsigned int eax, ecx;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax), "=c" (ecx)
+ : "0" (op)
+ : "bx", "dx" );
+@@ -139,7 +145,7 @@ static inline unsigned int cpuid_edx(uns
+ {
+ unsigned int eax, edx;
+
+- __asm__("cpuid"
++ __asm__(CPUID_STR
+ : "=a" (eax), "=d" (edx)
+ : "0" (op)
+ : "bx", "cx");
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 615e3e4..e62161d 100644
--- a/include/asm-x86_64/page.h
@@ -70348,7 +71802,7 @@
} ____cacheline_aligned_in_smp;
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h
-index 08cad24..ada72f7 100644
+index 08cad24..e838545 100644
--- a/include/asm-x86_64/pgalloc.h
+++ b/include/asm-x86_64/pgalloc.h
@@ -6,26 +6,90 @@
@@ -70539,12 +71993,11 @@
}
/* Should really implement gc for free page table pages. This could be
-@@ -89,17 +198,33 @@ static inline struct page *pte_alloc_one
+@@ -89,17 +198,32 @@ static inline struct page *pte_alloc_one
static inline void pte_free_kernel(pte_t *pte)
{
BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+#ifdef CONFIG_XEN
-+ xen_pte_unpin(__pa(pte));
+ make_page_writable(pte, XENFEAT_writable_page_tables);
+#endif
free_page((unsigned long)pte);
@@ -70960,7 +72413,7 @@
#define MK_IOSPACE_PFN(space, pfn) (pfn)
#define GET_IOSPACE(pfn) 0
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
-index 8c8d88c..78cd5a3 100644
+index 8c8d88c..76eafaf 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -138,27 +138,51 @@ extern unsigned int init_intel_cacheinfo
@@ -71089,24 +72542,6 @@
struct task_struct;
struct mm_struct;
-@@ -479,4 +520,17 @@ extern int bootloader_type;
-
- #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
-
-+static inline void modify_cpu_capabilities(struct cpuinfo_x86 *c)
-+{
-+#ifdef CONFIG_XEN
-+ clear_bit(X86_FEATURE_VME, c->x86_capability);
-+ clear_bit(X86_FEATURE_DE, c->x86_capability);
-+ clear_bit(X86_FEATURE_PSE, c->x86_capability);
-+ clear_bit(X86_FEATURE_PGE, c->x86_capability);
-+ clear_bit(X86_FEATURE_SEP, c->x86_capability);
-+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
-+ clear_bit(X86_FEATURE_MTRR, c->x86_capability);
-+#endif
-+}
-+
- #endif /* __ASM_X86_64_PROCESSOR_H */
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 9ccbb2c..c838964 100644
--- a/include/asm-x86_64/smp.h
@@ -71556,7 +72991,7 @@
#ifdef CONFIG_GENERIC_HARDIRQS
extern cpumask_t irq_affinity[NR_IRQS];
diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 498ff87..4a05b8d 100644
+index 498ff87..946f3e5 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -166,6 +166,9 @@ extern unsigned int kobjsize(const void
@@ -71584,10 +73019,10 @@
#define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */
+#ifdef CONFIG_XEN
-+typedef int (*pte_fn_t)(pte_t *pte, struct page *pte_page, unsigned long addr,
-+ void *data);
-+extern int generic_page_range(struct mm_struct *mm, unsigned long address,
-+ unsigned long size, pte_fn_t fn, void *data);
++typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr,
++ void *data);
++extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
++ unsigned long size, pte_fn_t fn, void *data);
+#endif
+
#ifdef CONFIG_PROC_FS
@@ -71641,10 +73076,10 @@
/**
diff --git a/include/xen/balloon.h b/include/xen/balloon.h
new file mode 100644
-index 0000000..7f2be02
+index 0000000..d9637ef
--- /dev/null
+++ b/include/xen/balloon.h
-@@ -0,0 +1,70 @@
+@@ -0,0 +1,73 @@
+/******************************************************************************
+ * balloon.h
+ *
@@ -71653,8 +73088,11 @@
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -71749,10 +73187,10 @@
+ */
diff --git a/include/xen/evtchn.h b/include/xen/evtchn.h
new file mode 100644
-index 0000000..594c1a6
+index 0000000..100eb1c
--- /dev/null
+++ b/include/xen/evtchn.h
-@@ -0,0 +1,123 @@
+@@ -0,0 +1,126 @@
+/******************************************************************************
+ * evtchn.h
+ *
@@ -71761,8 +73199,11 @@
+ *
+ * Copyright (c) 2004-2005, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -71950,10 +73391,10 @@
+ */
diff --git a/include/xen/gnttab.h b/include/xen/gnttab.h
new file mode 100644
-index 0000000..58aeb49
+index 0000000..584a5db
--- /dev/null
+++ b/include/xen/gnttab.h
-@@ -0,0 +1,120 @@
+@@ -0,0 +1,123 @@
+/******************************************************************************
+ * gnttab.h
+ *
@@ -71965,8 +73406,11 @@
+ * Copyright (c) 2004-2005, K A Fraser
+ * Copyright (c) 2005, Christopher Clark
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -72074,6 +73518,44 @@
+ * tab-width: 8
+ * End:
+ */
+diff --git a/include/xen/hypervisor_sysfs.h b/include/xen/hypervisor_sysfs.h
+new file mode 100644
+index 0000000..706fb7f
+--- /dev/null
++++ b/include/xen/hypervisor_sysfs.h
+@@ -0,0 +1,32 @@
++/*
++ * copyright (c) 2006 IBM Corporation
++ * Authored by: Mike D. Day <ncmike at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _HYP_SYSFS_H_
++#define _HYP_SYSFS_H_
++
++#include <linux/kobject.h>
++#include <linux/sysfs.h>
++
++#define HYPERVISOR_ATTR_RO(_name) \
++static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
++
++#define HYPERVISOR_ATTR_RW(_name) \
++static struct hyp_sysfs_attr _name##_attr = \
++ __ATTR(_name, 0644, _name##_show, _name##_store)
++
++extern struct subsystem hypervisor_subsys;
++
++struct hyp_sysfs_attr {
++ struct attribute attr;
++ ssize_t (*show)(struct hyp_sysfs_attr *, char *);
++ ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
++ void *hyp_attr_data;
++};
++
++#endif /* _HYP_SYSFS_H_ */
diff --git a/include/xen/interface/acm.h b/include/xen/interface/acm.h
new file mode 100644
index 0000000..a7a5a57
@@ -72263,10 +73745,10 @@
+ */
diff --git a/include/xen/interface/acm_ops.h b/include/xen/interface/acm_ops.h
new file mode 100644
-index 0000000..76c35db
+index 0000000..b4ce11f
--- /dev/null
+++ b/include/xen/interface/acm_ops.h
-@@ -0,0 +1,96 @@
+@@ -0,0 +1,98 @@
+/*
+ * acm_ops.h: Xen access control module hypervisor commands
+ *
@@ -72279,6 +73761,7 @@
+
+#include "xen.h"
+#include "sched_ctl.h"
++#include "acm.h"
+
+/*
+ * Make sure you increment the interface version whenever you modify this file!
@@ -72340,7 +73823,7 @@
+ int acm_decision; /* out */
+};
+
-+struct acm_op {
++typedef struct acm_op {
+ uint32_t cmd;
+ uint32_t interface_version; /* ACM_INTERFACE_VERSION */
+ union {
@@ -72350,7 +73833,8 @@
+ struct acm_getssid getssid;
+ struct acm_getdecision getdecision;
+ } u;
-+};
++} acm_op_t;
++DEFINE_GUEST_HANDLE(acm_op_t);
+
+#endif /* __XEN_PUBLIC_ACM_OPS_H__ */
+
@@ -72365,10 +73849,10 @@
+ */
diff --git a/include/xen/interface/arch-ia64.h b/include/xen/interface/arch-ia64.h
new file mode 100644
-index 0000000..316df5c
+index 0000000..ef33916
--- /dev/null
+++ b/include/xen/interface/arch-ia64.h
-@@ -0,0 +1,302 @@
+@@ -0,0 +1,337 @@
+/******************************************************************************
+ * arch-ia64/hypervisor-if.h
+ *
@@ -72431,6 +73915,33 @@
+
+#define INVALID_MFN (~0UL)
+
++#define MEM_G (1UL << 30)
++#define MEM_M (1UL << 20)
++
++#define MMIO_START (3 * MEM_G)
++#define MMIO_SIZE (512 * MEM_M)
++
++#define VGA_IO_START 0xA0000UL
++#define VGA_IO_SIZE 0x20000
++
++#define LEGACY_IO_START (MMIO_START + MMIO_SIZE)
++#define LEGACY_IO_SIZE (64*MEM_M)
++
++#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
++#define IO_PAGE_SIZE PAGE_SIZE
++
++#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
++#define STORE_PAGE_SIZE PAGE_SIZE
++
++#define IO_SAPIC_START 0xfec00000UL
++#define IO_SAPIC_SIZE 0x100000
++
++#define PIB_START 0xfee00000UL
++#define PIB_SIZE 0x100000
++
++#define GFW_START (4*MEM_G -16*MEM_M)
++#define GFW_SIZE (16*MEM_M)
++
+/*
+ * NB. This may become a 64-bit count with no shift. If this happens then the
+ * structure size will still be 8 bytes, so no other alignments will change.
@@ -72615,7 +74126,7 @@
+ int interrupt_delivery_enabled; // virtual psr.i
+ int pending_interruption;
+ int incomplete_regframe; // see SDM vol2 6.8
-+ unsigned long delivery_mask[4];
++ unsigned long reserved5_1[4];
+ int metaphysical_mode; // 1 = use metaphys mapping, 0 = use virtual
+ int banknum; // 0 or 1, which virtual register bank is active
+ unsigned long rrs[8]; // region registers
@@ -72642,6 +74153,12 @@
+ unsigned long start_info_pfn;
+} arch_shared_info_t;
+
++typedef struct {
++ unsigned long start;
++ unsigned long size;
++} arch_initrd_info_t;
++
++#define IA64_COMMAND_LINE_SIZE 512
+typedef struct vcpu_guest_context {
+#define VGCF_FPU_VALID (1<<0)
+#define VGCF_VMX_GUEST (1<<1)
@@ -72655,6 +74172,8 @@
+ cpu_user_regs_t regs;
+ arch_vcpu_info_t vcpu;
+ arch_shared_info_t shared;
++ arch_initrd_info_t initrd;
++ char cmdline[IA64_COMMAND_LINE_SIZE];
+} vcpu_guest_context_t;
+DEFINE_GUEST_HANDLE(vcpu_guest_context_t);
+
@@ -72673,10 +74192,10 @@
+ */
diff --git a/include/xen/interface/arch-x86_32.h b/include/xen/interface/arch-x86_32.h
new file mode 100644
-index 0000000..f7079eb
+index 0000000..1ae2df6
--- /dev/null
+++ b/include/xen/interface/arch-x86_32.h
-@@ -0,0 +1,181 @@
+@@ -0,0 +1,195 @@
+/******************************************************************************
+ * arch-x86_32.h
+ *
@@ -72781,6 +74300,7 @@
+ uint16_t cs; /* code selector */
+ unsigned long address; /* code offset */
+} trap_info_t;
++DEFINE_GUEST_HANDLE(trap_info_t);
+
+typedef struct cpu_user_regs {
+ uint32_t ebx;
@@ -72804,6 +74324,7 @@
+ uint16_t fs, _pad4;
+ uint16_t gs, _pad5;
+} cpu_user_regs_t;
++DEFINE_GUEST_HANDLE(cpu_user_regs_t);
+
+typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+
@@ -72815,7 +74336,7 @@
+ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
+ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
+#define VGCF_I387_VALID (1<<0)
-+#define VGCF_VMX_GUEST (1<<1)
++#define VGCF_HVM_GUEST (1<<1)
+#define VGCF_IN_KERNEL (1<<2)
+ unsigned long flags; /* VGCF_* flags */
+ cpu_user_regs_t user_regs; /* User-level CPU registers */
@@ -72847,6 +74368,18 @@
+
+#endif /* !__ASSEMBLY__ */
+
++/*
++ * Prefix forces emulation of some non-trapping instructions.
++ * Currently only CPUID.
++ */
++#ifdef __ASSEMBLY__
++#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
++#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
++#else
++#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
++#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
++#endif
++
+#endif
+
+/*
@@ -72860,10 +74393,10 @@
+ */
diff --git a/include/xen/interface/arch-x86_64.h b/include/xen/interface/arch-x86_64.h
new file mode 100644
-index 0000000..f0ea2f5
+index 0000000..98948c4
--- /dev/null
+++ b/include/xen/interface/arch-x86_64.h
-@@ -0,0 +1,266 @@
+@@ -0,0 +1,271 @@
+/******************************************************************************
+ * arch-x86_64.h
+ *
@@ -73002,15 +74535,6 @@
+ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
+ /* Bottom of iret stack frame. */
+};
-+/*
-+ * For compatibility with HYPERVISOR_switch_to_user which is the old
-+ * name for HYPERVISOR_iret.
-+ */
-+struct switch_to_user {
-+ /* Top of stack (%rsp at point of hypercall). */
-+ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
-+ /* Bottom of iret stack frame. */
-+};
+
+/*
+ * Send an array of these to HYPERVISOR_set_trap_table().
@@ -73032,6 +74556,7 @@
+ uint16_t cs; /* code selector */
+ unsigned long address; /* code offset */
+} trap_info_t;
++DEFINE_GUEST_HANDLE(trap_info_t);
+
+#ifdef __GNUC__
+/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
@@ -73071,6 +74596,7 @@
+ uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
+ uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
+} cpu_user_regs_t;
++DEFINE_GUEST_HANDLE(cpu_user_regs_t);
+
+#undef __DECL_REG
+
@@ -73084,7 +74610,7 @@
+ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
+ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
+#define VGCF_I387_VALID (1<<0)
-+#define VGCF_VMX_GUEST (1<<1)
++#define VGCF_HVM_GUEST (1<<1)
+#define VGCF_IN_KERNEL (1<<2)
+ unsigned long flags; /* VGCF_* flags */
+ cpu_user_regs_t user_regs; /* User-level CPU registers */
@@ -73119,6 +74645,18 @@
+
+#endif /* !__ASSEMBLY__ */
+
++/*
++ * Prefix forces emulation of some non-trapping instructions.
++ * Currently only CPUID.
++ */
++#ifdef __ASSEMBLY__
++#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
++#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
++#else
++#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
++#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
++#endif
++
+#endif
+
+/*
@@ -73668,10 +75206,10 @@
+ */
diff --git a/include/xen/interface/event_channel.h b/include/xen/interface/event_channel.h
new file mode 100644
-index 0000000..03d2039
+index 0000000..c556163
--- /dev/null
+++ b/include/xen/interface/event_channel.h
-@@ -0,0 +1,203 @@
+@@ -0,0 +1,205 @@
+/******************************************************************************
+ * event_channel.h
+ *
@@ -73684,6 +75222,7 @@
+#define __XEN_PUBLIC_EVENT_CHANNEL_H__
+
+typedef uint32_t evtchn_port_t;
++DEFINE_GUEST_HANDLE(evtchn_port_t);
+
+/*
+ * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
@@ -73863,6 +75402,7 @@
+ evtchn_unmask_t unmask;
+ } u;
+} evtchn_op_t;
++DEFINE_GUEST_HANDLE(evtchn_op_t);
+
+#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
+
@@ -73936,10 +75476,10 @@
+ */
diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
new file mode 100644
-index 0000000..e137953
+index 0000000..47a033e
--- /dev/null
+++ b/include/xen/interface/grant_table.h
-@@ -0,0 +1,306 @@
+@@ -0,0 +1,311 @@
+/******************************************************************************
+ * grant_table.h
+ *
@@ -74109,6 +75649,7 @@
+ grant_handle_t handle;
+ uint64_t dev_bus_addr;
+} gnttab_map_grant_ref_t;
++DEFINE_GUEST_HANDLE(gnttab_map_grant_ref_t);
+
+/*
+ * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
@@ -74130,6 +75671,7 @@
+ /* OUT parameters. */
+ int16_t status; /* GNTST_* */
+} gnttab_unmap_grant_ref_t;
++DEFINE_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
+
+/*
+ * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
@@ -74147,8 +75689,9 @@
+ uint32_t nr_frames;
+ /* OUT parameters. */
+ int16_t status; /* GNTST_* */
-+ unsigned long *frame_list;
++ GUEST_HANDLE(ulong) frame_list;
+} gnttab_setup_table_t;
++DEFINE_GUEST_HANDLE(gnttab_setup_table_t);
+
+/*
+ * GNTTABOP_dump_table: Dump the contents of the grant table to the
@@ -74161,6 +75704,7 @@
+ /* OUT parameters. */
+ int16_t status; /* GNTST_* */
+} gnttab_dump_table_t;
++DEFINE_GUEST_HANDLE(gnttab_dump_table_t);
+
+/*
+ * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
@@ -74179,6 +75723,7 @@
+ /* OUT parameters. */
+ int16_t status;
+} gnttab_transfer_t;
++DEFINE_GUEST_HANDLE(gnttab_transfer_t);
+
+/*
+ * Bitfield values for update_pin_status.flags.
@@ -74610,10 +76155,10 @@
+ */
diff --git a/include/xen/interface/io/netif.h b/include/xen/interface/io/netif.h
new file mode 100644
-index 0000000..dcb9b46
+index 0000000..c9bcc77
--- /dev/null
+++ b/include/xen/interface/io/netif.h
-@@ -0,0 +1,76 @@
+@@ -0,0 +1,84 @@
+/******************************************************************************
+ * netif.h
+ *
@@ -74636,8 +76181,12 @@
+ */
+
+/* Protocol checksum field is blank in the packet (hardware offload)? */
-+#define _NETTXF_csum_blank (0)
-+#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank)
++#define _NETTXF_csum_blank (0)
++#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank)
++
++/* Packet data has been validated against protocol checksum. */
++#define _NETTXF_data_validated (1)
++#define NETTXF_data_validated (1U<<_NETTXF_data_validated)
+
+typedef struct netif_tx_request {
+ grant_ref_t gref; /* Reference to buffer page */
@@ -74657,9 +76206,13 @@
+ grant_ref_t gref; /* Reference to incoming granted frame */
+} netif_rx_request_t;
+
-+/* Protocol checksum already validated (e.g., performed by hardware)? */
-+#define _NETRXF_csum_valid (0)
-+#define NETRXF_csum_valid (1U<<_NETRXF_csum_valid)
++/* Packet data has been validated against protocol checksum. */
++#define _NETRXF_data_validated (0)
++#define NETRXF_data_validated (1U<<_NETRXF_data_validated)
++
++/* Protocol checksum field is blank in the packet (hardware offload)? */
++#define _NETRXF_csum_blank (1)
++#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank)
+
+typedef struct {
+ uint16_t id;
@@ -75084,161 +76637,6 @@
+ * indent-tabs-mode: nil
+ * End:
+ */
-diff --git a/include/xen/interface/io/vmx_vlapic.h b/include/xen/interface/io/vmx_vlapic.h
-new file mode 100644
-index 0000000..f63a9aa
---- /dev/null
-+++ b/include/xen/interface/io/vmx_vlapic.h
-@@ -0,0 +1,58 @@
-+#ifndef _VMX_VLAPIC_H
-+#define _VMX_VLAPIC_H
-+
-+/*
-+ We extended one bit for PIC type
-+ */
-+#define VLAPIC_DELIV_MODE_FIXED 0x0
-+#define VLAPIC_DELIV_MODE_LPRI 0x1
-+#define VLAPIC_DELIV_MODE_SMI 0x2
-+#define VLAPIC_DELIV_MODE_NMI 0x4
-+#define VLAPIC_DELIV_MODE_INIT 0x5
-+#define VLAPIC_DELIV_MODE_STARTUP 0x6
-+#define VLAPIC_DELIV_MODE_EXT 0x7
-+#define VLAPIC_DELIV_MODE_MASK 0x8
-+
-+#define VLAPIC_MSG_LEVEL 4
-+
-+#define INTR_EXT 0
-+#define INTR_APIC 1
-+#define INTR_LAPIC 2
-+
-+#define VL_STATE_EOI 1
-+#define VL_STATE_EXT_LOCK 2
-+#define VL_STATE_MSG_LOCK 3
-+#define VL_STATE_EOI_LOCK 3
-+
-+#define VLOCAL_APIC_MAX_INTS 256
-+#define VLAPIC_INT_COUNT (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(uint64_t)))
-+#define VLAPIC_INT_COUNT_32 (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(uint32_t)))
-+
-+typedef struct {
-+ /* interrupt for PIC and ext type IOAPIC interrupt */
-+ uint64_t vl_ext_intr[VLAPIC_INT_COUNT];
-+ uint64_t vl_ext_intr_mask[VLAPIC_INT_COUNT];
-+ uint64_t vl_apic_intr[VLAPIC_INT_COUNT];
-+ uint64_t vl_apic_tmr[VLAPIC_INT_COUNT];
-+ uint64_t vl_eoi[VLAPIC_INT_COUNT];
-+ uint32_t vl_lapic_id;
-+ uint32_t direct_intr;
-+ uint32_t vl_apr;
-+ uint32_t vl_logical_dest;
-+ uint32_t vl_dest_format;
-+ uint32_t vl_arb_id;
-+ uint32_t vl_state;
-+ uint32_t apic_msg_count;
-+} vlapic_info;
-+
-+#endif /* _VMX_VLAPIC_H_ */
-+
-+/*
-+ * Local variables:
-+ * mode: C
-+ * c-set-style: "BSD"
-+ * c-basic-offset: 4
-+ * tab-width: 4
-+ * indent-tabs-mode: nil
-+ * End:
-+ */
-diff --git a/include/xen/interface/io/vmx_vpic.h b/include/xen/interface/io/vmx_vpic.h
-new file mode 100644
-index 0000000..256ac87
---- /dev/null
-+++ b/include/xen/interface/io/vmx_vpic.h
-@@ -0,0 +1,85 @@
-+/*
-+ * QEMU System Emulator header
-+ *
-+ * Copyright (c) 2003 Fabrice Bellard
-+ * Copyright (c) 2005 Intel Corp
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+ * THE SOFTWARE.
-+ */
-+
-+#ifndef _VMX_VPIC_H
-+#define _VMX_VPIC_H
-+
-+#define hw_error(x) do {} while (0);
-+
-+
-+/* i8259.c */
-+typedef struct IOAPICState IOAPICState;
-+typedef struct PicState {
-+ uint8_t last_irr; /* edge detection */
-+ uint8_t irr; /* interrupt request register */
-+ uint8_t imr; /* interrupt mask register */
-+ uint8_t isr; /* interrupt service register */
-+ uint8_t priority_add; /* highest irq priority */
-+ uint8_t irq_base;
-+ uint8_t read_reg_select;
-+ uint8_t poll;
-+ uint8_t special_mask;
-+ uint8_t init_state;
-+ uint8_t auto_eoi;
-+ uint8_t rotate_on_auto_eoi;
-+ uint8_t special_fully_nested_mode;
-+ uint8_t init4; /* true if 4 byte init */
-+ uint8_t elcr; /* PIIX edge/trigger selection*/
-+ uint8_t elcr_mask;
-+ struct vmx_virpic *pics_state;
-+} PicState;
-+
-+struct vmx_virpic {
-+ /* 0 is master pic, 1 is slave pic */
-+ /* XXX: better separation between the two pics */
-+ PicState pics[2];
-+ void (*irq_request)(int *opaque, int level);
-+ void *irq_request_opaque;
-+ /* IOAPIC callback support */
-+ void (*alt_irq_func)(void *opaque, int irq_num, int level);
-+ void *alt_irq_opaque;
-+};
-+
-+
-+void pic_set_irq(struct vmx_virpic *s, int irq, int level);
-+void pic_set_irq_new(void *opaque, int irq, int level);
-+void pic_init(struct vmx_virpic *s,
-+ void (*irq_request)(),
-+ void *irq_request_opaque);
-+void pic_set_alt_irq_func(struct vmx_virpic *s,
-+ void(*alt_irq_func)(),
-+ void *alt_irq_opaque);
-+int pic_read_irq(struct vmx_virpic *s);
-+void pic_update_irq(struct vmx_virpic *s);
-+uint32_t pic_intack_read(struct vmx_virpic *s);
-+void register_pic_io_hook (void);
-+int cpu_get_pic_interrupt(struct vcpu *v, int *type);
-+int is_pit_irq(struct vcpu *v, int irq, int type);
-+int is_irq_enabled(struct vcpu *v, int irq);
-+void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
-+void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
-+
-+/* APIC */
-+#endif /* _VMX_VPIC_H */
diff --git a/include/xen/interface/io/xenbus.h b/include/xen/interface/io/xenbus.h
new file mode 100644
index 0000000..472079c
@@ -75392,10 +76790,10 @@
+ */
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
new file mode 100644
-index 0000000..f3f16fe
+index 0000000..f2a5c1c
--- /dev/null
+++ b/include/xen/interface/memory.h
-@@ -0,0 +1,153 @@
+@@ -0,0 +1,155 @@
+/******************************************************************************
+ * memory.h
+ *
@@ -75495,25 +76893,27 @@
+DEFINE_GUEST_HANDLE(xen_machphys_mfn_list_t);
+
+/*
-+ * Returns the base and size of the specified reserved 'RAM hole' in the
-+ * specified guest's pseudophysical address space.
-+ * arg == addr of xen_reserved_phys_area_t.
-+ */
-+#define XENMEM_reserved_phys_area 7
-+typedef struct xen_reserved_phys_area {
-+ /* Which domain to report about? */
++ * Sets the GPFN at which a particular page appears in the specified guest's
++ * pseudophysical address space.
++ * arg == addr of xen_add_to_physmap_t.
++ */
++#define XENMEM_add_to_physmap 7
++typedef struct xen_add_to_physmap {
++ /* Which domain to change the mapping for. */
+ domid_t domid;
+
-+ /*
-+ * Which reserved area to report? Out-of-range request reports
-+ * -ESRCH. Currently no architecture will have more than one reserved area.
-+ */
-+ unsigned int idx;
-+
-+ /* Base and size of the specified reserved area. */
-+ unsigned long first_gpfn, nr_gpfns;
-+} xen_reserved_phys_area_t;
-+DEFINE_GUEST_HANDLE(xen_reserved_phys_area_t);
++ /* Source mapping space. */
++#define XENMAPSPACE_shared_info 0 /* shared info page */
++#define XENMAPSPACE_grant_table 1 /* grant table page */
++ unsigned int space;
++
++ /* Index into source mapping space. */
++ unsigned long idx;
++
++ /* GPFN where the source mapping page should appear. */
++ unsigned long gpfn;
++} xen_add_to_physmap_t;
++DEFINE_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/*
+ * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
@@ -75551,10 +76951,10 @@
+ */
diff --git a/include/xen/interface/nmi.h b/include/xen/interface/nmi.h
new file mode 100644
-index 0000000..0c0c67b
+index 0000000..a938ef8
--- /dev/null
+++ b/include/xen/interface/nmi.h
-@@ -0,0 +1,54 @@
+@@ -0,0 +1,59 @@
+/******************************************************************************
+ * nmi.h
+ *
@@ -75588,9 +76988,14 @@
+/*
+ * Register NMI callback for this (calling) VCPU. Currently this only makes
+ * sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
-+ * arg == address of callback function.
++ * arg == pointer to xennmi_callback structure.
+ */
+#define XENNMI_register_callback 0
++typedef struct xennmi_callback {
++ unsigned long handler_address;
++ unsigned long pad;
++} xennmi_callback_t;
++DEFINE_GUEST_HANDLE(xennmi_callback_t);
+
+/*
+ * Deregister NMI callback for this (calling) VCPU.
@@ -75611,10 +77016,10 @@
+ */
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
new file mode 100644
-index 0000000..2df68b4
+index 0000000..b003af7
--- /dev/null
+++ b/include/xen/interface/physdev.h
-@@ -0,0 +1,70 @@
+@@ -0,0 +1,71 @@
+
+#ifndef __XEN_PUBLIC_PHYSDEV_H__
+#define __XEN_PUBLIC_PHYSDEV_H__
@@ -75673,6 +77078,7 @@
+ physdevop_irq_t irq_op;
+ } u;
+} physdev_op_t;
++DEFINE_GUEST_HANDLE(physdev_op_t);
+
+#endif /* __XEN_PUBLIC_PHYSDEV_H__ */
+
@@ -75687,10 +77093,10 @@
+ */
diff --git a/include/xen/interface/sched.h b/include/xen/interface/sched.h
new file mode 100644
-index 0000000..a1a03de
+index 0000000..bebdb1c
--- /dev/null
+++ b/include/xen/interface/sched.h
-@@ -0,0 +1,60 @@
+@@ -0,0 +1,87 @@
+/******************************************************************************
+ * sched.h
+ *
@@ -75702,16 +77108,26 @@
+#ifndef __XEN_PUBLIC_SCHED_H__
+#define __XEN_PUBLIC_SCHED_H__
+
++#include "event_channel.h"
++
+/*
-+ * Prototype for this hypercall is:
-+ * int sched_op(int cmd, unsigned long arg)
++ * The prototype for this hypercall is:
++ * long sched_op_new(int cmd, void *arg)
++ * @cmd == SCHEDOP_??? (scheduler operation).
++ * @arg == Operation-specific extra argument(s), as described below.
++ *
++ * **NOTE**:
++ * Versions of Xen prior to 3.0.2 provide only the following legacy version
++ * of this hypercall, supporting only the commands yield, block and shutdown:
++ * long sched_op(int cmd, unsigned long arg)
+ * @cmd == SCHEDOP_??? (scheduler operation).
-+ * @arg == Operation-specific extra argument(s).
++ * @arg == 0 (SCHEDOP_yield and SCHEDOP_block)
++ * == SHUTDOWN_* code (SCHEDOP_shutdown)
+ */
+
+/*
+ * Voluntarily yield the CPU.
-+ * @arg == 0.
++ * @arg == NULL.
+ */
+#define SCHEDOP_yield 0
+
@@ -75720,18 +77136,35 @@
+ * If called with event upcalls masked, this operation will atomically
+ * reenable event delivery and check for pending events before blocking the
+ * VCPU. This avoids a "wakeup waiting" race.
-+ * @arg == 0.
++ * @arg == NULL.
+ */
+#define SCHEDOP_block 1
+
+/*
+ * Halt execution of this domain (all VCPUs) and notify the system controller.
-+ * @arg == SHUTDOWN_??? (reason for shutdown).
++ * @arg == pointer to sched_shutdown structure.
+ */
+#define SCHEDOP_shutdown 2
++typedef struct sched_shutdown {
++ unsigned int reason; /* SHUTDOWN_* */
++} sched_shutdown_t;
++DEFINE_GUEST_HANDLE(sched_shutdown_t);
++
++/*
++ * Poll a set of event-channel ports. Return when one or more are pending. An
++ * optional timeout may be specified.
++ * @arg == pointer to sched_poll structure.
++ */
++#define SCHEDOP_poll 3
++typedef struct sched_poll {
++ GUEST_HANDLE(evtchn_port_t) ports;
++ unsigned int nr_ports;
++ uint64_t timeout;
++} sched_poll_t;
++DEFINE_GUEST_HANDLE(sched_poll_t);
+
+/*
-+ * Reason codes for SCHEDOP_shutdown. These may be interpreted by controller
++ * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
+ * software to determine the appropriate action. For the most part, Xen does
+ * not care about the shutdown code.
+ */
@@ -75823,10 +77256,10 @@
+ */
diff --git a/include/xen/interface/trace.h b/include/xen/interface/trace.h
new file mode 100644
-index 0000000..cba4b26
+index 0000000..8fc009d
--- /dev/null
+++ b/include/xen/interface/trace.h
-@@ -0,0 +1,90 @@
+@@ -0,0 +1,86 @@
+/******************************************************************************
+ * include/public/trace.h
+ *
@@ -75853,7 +77286,6 @@
+#define TRC_VMXTIMER 0x00082000 /* VMX timer trace */
+#define TRC_VMXINT 0x00084000 /* VMX interrupt trace */
+#define TRC_VMXIO 0x00088000 /* VMX io emulation trace */
-+#define TRC_VMEXIT_HANDLER 0x00090000 /* VMX handler trace */
+
+/* Trace events per class */
+
@@ -75879,15 +77311,12 @@
+
+/* trace events per subclass */
+#define TRC_VMX_VMEXIT (TRC_VMXEXIT + 1)
-+#define TRC_VMX_VECTOR (TRC_VMXEXIT + 2)
++#define TRC_VMX_VMENTRY (TRC_VMXEXIT + 2)
+
+#define TRC_VMX_TIMER_INTR (TRC_VMXTIMER + 1)
+
+#define TRC_VMX_INT (TRC_VMXINT + 1)
+
-+#define TRC_VMEXIT (TRC_VMEXIT_HANDLER + 1)
-+#define TRC_VMENTRY (TRC_VMEXIT_HANDLER + 2)
-+
+
+/* This structure represents a single trace buffer record. */
+struct t_rec {
@@ -76114,10 +77543,10 @@
+ */
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
new file mode 100644
-index 0000000..6e1f366
+index 0000000..5d88c9c
--- /dev/null
+++ b/include/xen/interface/xen.h
-@@ -0,0 +1,447 @@
+@@ -0,0 +1,449 @@
+/******************************************************************************
+ * xen.h
+ *
@@ -76174,13 +77603,12 @@
+#define __HYPERVISOR_vm_assist 21
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_iret 23 /* x86 only */
-+#define __HYPERVISOR_switch_vm86 23 /* x86/32 only (obsolete name) */
-+#define __HYPERVISOR_switch_to_user 23 /* x86/64 only (obsolete name) */
+#define __HYPERVISOR_vcpu_op 24
+#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op 26
+#define __HYPERVISOR_acm_op 27
+#define __HYPERVISOR_nmi_op 28
++#define __HYPERVISOR_sched_op_new 29
+
+/*
+ * VIRTUAL INTERRUPTS
@@ -76282,7 +77710,7 @@
+#define MMUEXT_NEW_USER_BASEPTR 15
+
+#ifndef __ASSEMBLY__
-+struct mmuext_op {
++typedef struct mmuext_op {
+ unsigned int cmd;
+ union {
+ /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */
@@ -76296,7 +77724,8 @@
+ /* TLB_FLUSH_MULTI, INVLPG_MULTI */
+ void *vcpumask;
+ } arg2;
-+};
++} mmuext_op_t;
++DEFINE_GUEST_HANDLE(mmuext_op_t);
+#endif
+
+/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
@@ -76363,6 +77792,7 @@
+ uint64_t ptr; /* Machine address of PTE. */
+ uint64_t val; /* New contents of PTE. */
+} mmu_update_t;
++DEFINE_GUEST_HANDLE(mmu_update_t);
+
+/*
+ * Send an array of these to HYPERVISOR_multicall().
@@ -76372,6 +77802,7 @@
+ unsigned long op, result;
+ unsigned long args[6];
+} multicall_entry_t;
++DEFINE_GUEST_HANDLE(multicall_entry_t);
+
+/*
+ * Event channel endpoints per domain:
@@ -76567,19 +77998,21 @@
+ */
diff --git a/include/xen/net_driver_util.h b/include/xen/net_driver_util.h
new file mode 100644
-index 0000000..130b4f0
+index 0000000..9054452
--- /dev/null
+++ b/include/xen/net_driver_util.h
-@@ -0,0 +1,56 @@
+@@ -0,0 +1,58 @@
+/*****************************************************************************
+ *
+ * Utility functions for Xen network devices.
+ *
+ * Copyright (c) 2005 XenSource Ltd.
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following
-+ * license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this source file (the "Software"), to deal in the Software without
@@ -76674,10 +78107,10 @@
+#endif /* __XEN_ASM_PCIFRONT_H__ */
diff --git a/include/xen/public/evtchn.h b/include/xen/public/evtchn.h
new file mode 100644
-index 0000000..456f246
+index 0000000..5ba554b
--- /dev/null
+++ b/include/xen/public/evtchn.h
-@@ -0,0 +1,98 @@
+@@ -0,0 +1,101 @@
+/******************************************************************************
+ * evtchn.h
+ *
@@ -76685,8 +78118,11 @@
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -76778,10 +78214,10 @@
+ */
diff --git a/include/xen/public/privcmd.h b/include/xen/public/privcmd.h
new file mode 100644
-index 0000000..074d66c
+index 0000000..a7da522
--- /dev/null
+++ b/include/xen/public/privcmd.h
-@@ -0,0 +1,91 @@
+@@ -0,0 +1,94 @@
+/******************************************************************************
+ * privcmd.h
+ *
@@ -76789,8 +78225,11 @@
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -76950,10 +78389,10 @@
+ */
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
new file mode 100644
-index 0000000..27b08d5
+index 0000000..1224805
--- /dev/null
+++ b/include/xen/xenbus.h
-@@ -0,0 +1,298 @@
+@@ -0,0 +1,301 @@
+/******************************************************************************
+ * xenbus.h
+ *
@@ -76962,8 +78401,11 @@
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * Copyright (C) 2005 XenSource Ltd.
+ *
-+ * This file may be distributed separately from the Linux kernel, or
-+ * incorporated into other software packages, subject to the following license:
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
@@ -76989,7 +78431,7 @@
+
+#include <linux/device.h>
+#include <linux/notifier.h>
-+#include <asm/semaphore.h>
++#include <linux/mutex.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/xenbus.h>
@@ -77272,19 +78714,6 @@
+int xencons_ring_send(const char *data, unsigned len);
+
+#endif /* __ASM_XENCONS_H__ */
-diff --git a/init/Kconfig b/init/Kconfig
-index 38416a1..2c3ece9 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -224,7 +224,7 @@ config UID16
- This enables the legacy 16-bit UID syscall wrappers.
-
- config VM86
-- depends X86
-+ depends on X86
- default y
- bool "Enable VM86 support" if EMBEDDED
- help
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index 0b46a5d..17ab322 100644
--- a/kernel/Kconfig.preempt
@@ -77496,7 +78925,7 @@
{
unsigned long vaddr;
diff --git a/mm/memory.c b/mm/memory.c
-index 9abc600..351b316 100644
+index 85e80a5..f91d3ba 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -405,7 +405,8 @@ struct page *vm_normal_page(struct vm_ar
@@ -77509,7 +78938,7 @@
return NULL;
}
-@@ -1019,6 +1020,23 @@ int get_user_pages(struct task_struct *t
+@@ -1020,6 +1021,23 @@ int get_user_pages(struct task_struct *t
continue;
}
@@ -77533,41 +78962,44 @@
if (!vma || (vma->vm_flags & (VM_IO | VM_PFNMAP))
|| !(vm_flags & vma->vm_flags))
return i ? : -EFAULT;
-@@ -1358,6 +1376,98 @@ int remap_pfn_range(struct vm_area_struc
+@@ -1359,6 +1377,102 @@ int remap_pfn_range(struct vm_area_struc
}
EXPORT_SYMBOL(remap_pfn_range);
+#ifdef CONFIG_XEN
-+static inline int generic_pte_range(struct mm_struct *mm, pmd_t *pmd,
-+ unsigned long addr, unsigned long end,
-+ pte_fn_t fn, void *data)
++static inline int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
++ unsigned long addr, unsigned long end,
++ pte_fn_t fn, void *data)
+{
+ pte_t *pte;
+ int err;
-+ struct page *pte_page;
++ struct page *pmd_page;
++ spinlock_t *ptl;
+
+ pte = (mm == &init_mm) ?
+ pte_alloc_kernel(pmd, addr) :
-+ pte_alloc_map(mm, pmd, addr);
++ pte_alloc_map_lock(mm, pmd, addr, &ptl);
+ if (!pte)
+ return -ENOMEM;
+
-+ pte_page = pmd_page(*pmd);
++ BUG_ON(pmd_huge(*pmd));
++
++ pmd_page = pmd_page(*pmd);
+
+ do {
-+ err = fn(pte, pte_page, addr, data);
++ err = fn(pte, pmd_page, addr, data);
+ if (err)
+ break;
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+
+ if (mm != &init_mm)
-+ pte_unmap(pte-1);
++ pte_unmap_unlock(pte-1, ptl);
+ return err;
+}
+
-+static inline int generic_pmd_range(struct mm_struct *mm, pud_t *pud,
-+ unsigned long addr, unsigned long end,
-+ pte_fn_t fn, void *data)
++static inline int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
++ unsigned long addr, unsigned long end,
++ pte_fn_t fn, void *data)
+{
+ pmd_t *pmd;
+ unsigned long next;
@@ -77578,16 +79010,16 @@
+ return -ENOMEM;
+ do {
+ next = pmd_addr_end(addr, end);
-+ err = generic_pte_range(mm, pmd, addr, next, fn, data);
++ err = apply_to_pte_range(mm, pmd, addr, next, fn, data);
+ if (err)
+ break;
+ } while (pmd++, addr = next, addr != end);
+ return err;
+}
+
-+static inline int generic_pud_range(struct mm_struct *mm, pgd_t *pgd,
-+ unsigned long addr, unsigned long end,
-+ pte_fn_t fn, void *data)
++static inline int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd,
++ unsigned long addr, unsigned long end,
++ pte_fn_t fn, void *data)
+{
+ pud_t *pud;
+ unsigned long next;
@@ -77598,7 +79030,7 @@
+ return -ENOMEM;
+ do {
+ next = pud_addr_end(addr, end);
-+ err = generic_pmd_range(mm, pud, addr, next, fn, data);
++ err = apply_to_pmd_range(mm, pud, addr, next, fn, data);
+ if (err)
+ break;
+ } while (pud++, addr = next, addr != end);
@@ -77609,8 +79041,8 @@
+ * Scan a region of virtual memory, filling in page tables as necessary
+ * and calling a provided function on each leaf page table.
+ */
-+int generic_page_range(struct mm_struct *mm, unsigned long addr,
-+ unsigned long size, pte_fn_t fn, void *data)
++int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
++ unsigned long size, pte_fn_t fn, void *data)
+{
+ pgd_t *pgd;
+ unsigned long next;
@@ -77621,12 +79053,13 @@
+ pgd = pgd_offset(mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
-+ err = generic_pud_range(mm, pgd, addr, next, fn, data);
++ err = apply_to_pud_range(mm, pgd, addr, next, fn, data);
+ if (err)
+ break;
+ } while (pgd++, addr = next, addr != end);
+ return err;
+}
++EXPORT_SYMBOL_GPL(apply_to_page_range);
+#endif
+
/*
@@ -77835,6 +79268,49 @@
C(pkt_type);
C(ip_summed);
C(priority);
+diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
+index a3d1407..425c926 100644
+--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
++++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
+@@ -129,10 +129,14 @@ tcp_manip_pkt(struct sk_buff **pskb,
+ if (hdrsize < sizeof(*hdr))
+ return 1;
+
+- hdr->check = ip_nat_cheat_check(~oldip, newip,
++ if ((*pskb)->proto_csum_blank) {
++ hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
++ } else {
++ hdr->check = ip_nat_cheat_check(~oldip, newip,
+ ip_nat_cheat_check(oldport ^ 0xFFFF,
+ newport,
+ hdr->check));
++ }
+ return 1;
+ }
+
+diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
+index ec6053f..1d760fe 100644
+--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
++++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
+@@ -113,11 +113,16 @@ udp_manip_pkt(struct sk_buff **pskb,
+ newport = tuple->dst.u.udp.port;
+ portptr = &hdr->dest;
+ }
+- if (hdr->check) /* 0 is a special case meaning no checksum */
+- hdr->check = ip_nat_cheat_check(~oldip, newip,
++ if (hdr->check) { /* 0 is a special case meaning no checksum */
++ if ((*pskb)->proto_csum_blank) {
++ hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
++ } else {
++ hdr->check = ip_nat_cheat_check(~oldip, newip,
+ ip_nat_cheat_check(*portptr ^ 0xFFFF,
+ newport,
+ hdr->check));
++ }
++ }
+ *portptr = newport;
+ return 1;
+ }
diff --git a/scripts/Makefile.xen b/scripts/Makefile.xen
new file mode 100644
index 0000000..b3ec53a
More information about the Kernel-svn-changes
mailing list