[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, &ltype);
 +			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