[kernel] r6128 - in dists/trunk/linux-2.6/debian/patches: . series
Bastian Blank
waldi at costa.debian.org
Sat Mar 11 18:10:27 UTC 2006
Author: waldi
Date: Sat Mar 11 18:10:24 2006
New Revision: 6128
Added:
dists/trunk/linux-2.6/debian/patches/series/0experimental.2-extra
dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966-update.patch (contents, props changed)
Log:
Update xen patch.
* debian/patches/series/0experimental.2-extra: Update.
* debian/patches/xen-tree-merge-21966-update.patch: Add.
Added: dists/trunk/linux-2.6/debian/patches/series/0experimental.2-extra
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/series/0experimental.2-extra Sat Mar 11 18:10:24 2006
@@ -0,0 +1 @@
++ xen-tree-merge-21966-update.patch *_xen
Added: dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966-update.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/xen-tree-merge-21966-update.patch Sat Mar 11 18:10:24 2006
@@ -0,0 +1,10168 @@
+diff -r c75ede70c907 -r f6bd46559b93 arch/i386/kernel/entry-xen.S
+--- a/arch/i386/kernel/entry-xen.S Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/i386/kernel/entry-xen.S Mon Mar 6 17:57:34 2006 +0000
+@@ -560,7 +560,7 @@ 11: push %esp
+ jmp ret_from_intr
+
+ ALIGN
+-restore_all_enable_events:
++restore_all_enable_events:
+ XEN_LOCKED_UNBLOCK_EVENTS(%esi)
+ scrit: /**** START OF CRITICAL REGION ****/
+ XEN_TEST_PENDING(%esi)
+@@ -577,7 +577,7 @@ ecrit: /**** END OF CRITICAL REGION ***
+ # registers are in each frame. We do this quickly using the lookup table
+ # 'critical_fixup_table'. For each byte offset in the critical region, it
+ # provides the number of bytes which have already been popped from the
+-# interrupted stack frame.
++# interrupted stack frame.
+ critical_region_fixup:
+ addl $critical_fixup_table-scrit,%eax
+ movzbl (%eax),%eax # %eax contains num bytes popped
+diff -r c75ede70c907 -r f6bd46559b93 arch/i386/kernel/head-xen.S
+--- a/arch/i386/kernel/head-xen.S Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/i386/kernel/head-xen.S Mon Mar 6 17:57:34 2006 +0000
+@@ -29,8 +29,6 @@ ENTRY(startup_32)
+
+ /* Set up the stack pointer */
+ movl $(init_thread_union+THREAD_SIZE),%esp
+-
+-checkCPUtype:
+
+ /* get vendor info */
+ xorl %eax,%eax # call CPUID with 0 -> return vendor ID
+diff -r c75ede70c907 -r f6bd46559b93 arch/i386/kernel/io_apic-xen.c
+--- a/arch/i386/kernel/io_apic-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/i386/kernel/io_apic-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -61,8 +61,8 @@ static inline unsigned int xen_io_apic_r
+ int ret;
+
+ op.cmd = PHYSDEVOP_APIC_READ;
+- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
+- op.u.apic_op.offset = reg;
++ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++ op.u.apic_op.reg = reg;
+ ret = HYPERVISOR_physdev_op(&op);
+ if (ret)
+ return ret;
+@@ -74,8 +74,8 @@ static inline void xen_io_apic_write(uns
+ physdev_op_t op;
+
+ op.cmd = PHYSDEVOP_APIC_WRITE;
+- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
+- op.u.apic_op.offset = reg;
++ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++ op.u.apic_op.reg = reg;
+ op.u.apic_op.value = value;
+ HYPERVISOR_physdev_op(&op);
+ }
+diff -r c75ede70c907 -r f6bd46559b93 arch/i386/kernel/process-xen.c
+--- a/arch/i386/kernel/process-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/i386/kernel/process-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -107,9 +107,9 @@ void xen_idle(void)
+ {
+ local_irq_disable();
+
+- if (need_resched()) {
++ if (need_resched())
+ local_irq_enable();
+- } else {
++ else {
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb__after_clear_bit();
+ stop_hz_timer();
+diff -r c75ede70c907 -r f6bd46559b93 arch/i386/kernel/time-xen.c
+--- a/arch/i386/kernel/time-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/i386/kernel/time-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -160,13 +160,12 @@ static void delay_tsc(unsigned long loop
+ static void delay_tsc(unsigned long loops)
+ {
+ unsigned long bclock, now;
+-
++
+ rdtscl(bclock);
+- do
+- {
++ do {
+ rep_nop();
+ rdtscl(now);
+- } while ((now-bclock) < loops);
++ } while ((now - bclock) < loops);
+ }
+
+ static struct timer_opts timer_tsc = {
+@@ -187,7 +186,7 @@ static inline u64 scale_delta(u64 delta,
+ u32 tmp1, tmp2;
+ #endif
+
+- if ( shift < 0 )
++ if (shift < 0)
+ delta >>= -shift;
+ else
+ delta <<= shift;
+@@ -226,7 +225,7 @@ void init_cpu_khz(void)
+ struct vcpu_time_info *info;
+ info = &HYPERVISOR_shared_info->vcpu_info[0].time;
+ do_div(__cpu_khz, info->tsc_to_system_mul);
+- if ( info->tsc_shift < 0 )
++ if (info->tsc_shift < 0)
+ cpu_khz = __cpu_khz << -info->tsc_shift;
+ else
+ cpu_khz = __cpu_khz >> info->tsc_shift;
+@@ -284,8 +283,7 @@ static void update_wallclock(void)
+ shadow_tv.tv_sec = s->wc_sec;
+ shadow_tv.tv_nsec = s->wc_nsec;
+ rmb();
+- }
+- while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
++ } while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
+
+ if (!independent_wallclock)
+ __update_wallclock(shadow_tv.tv_sec, shadow_tv.tv_nsec);
+@@ -312,8 +310,7 @@ static void get_time_values_from_xen(voi
+ dst->tsc_to_nsec_mul = src->tsc_to_system_mul;
+ dst->tsc_shift = src->tsc_shift;
+ rmb();
+- }
+- while ((src->version & 1) | (dst->version ^ src->version));
++ } while ((src->version & 1) | (dst->version ^ src->version));
+
+ dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
+ }
+@@ -324,7 +321,7 @@ static inline int time_values_up_to_date
+ struct shadow_time_info *dst;
+
+ src = &HYPERVISOR_shared_info->vcpu_info[cpu].time;
+- dst = &per_cpu(shadow_time, cpu);
++ dst = &per_cpu(shadow_time, cpu);
+
+ return (dst->version == src->version);
+ }
+@@ -456,7 +453,7 @@ int do_settimeofday(struct timespec *tv)
+ * overflows. If that were to happen then our shadow time values would
+ * be stale, so we can retry with fresh ones.
+ */
+- for ( ; ; ) {
++ for (;;) {
+ nsec = tv->tv_nsec - get_nsec_offset(shadow);
+ if (time_values_up_to_date(cpu))
+ break;
+@@ -640,7 +637,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ get_time_values_from_xen();
+
+ /* Obtain a consistent snapshot of elapsed wallclock cycles. */
+- delta = delta_cpu =
++ delta = delta_cpu =
+ shadow->system_timestamp + get_nsec_offset(shadow);
+ delta -= processed_system_time;
+ delta_cpu -= per_cpu(processed_system_time, cpu);
+@@ -659,8 +656,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ per_cpu(processed_blocked_time, cpu);
+ barrier();
+ } while (sched_time != runstate->state_entry_time);
+- }
+- while (!time_values_up_to_date(cpu));
++ } while (!time_values_up_to_date(cpu));
+
+ if ((unlikely(delta < -1000000LL) || unlikely(delta_cpu < 0))
+ && printk_ratelimit()) {
+@@ -1012,7 +1008,7 @@ void __init time_init(void)
+ }
+
+ /* Convert jiffies to system time. */
+-static inline u64 jiffies_to_st(unsigned long j)
++static inline u64 jiffies_to_st(unsigned long j)
+ {
+ unsigned long seq;
+ long delta;
+@@ -1023,7 +1019,7 @@ static inline u64 jiffies_to_st(unsigned
+ delta = j - jiffies;
+ /* NB. The next check can trigger in some wrap-around cases,
+ * but that's ok: we'll just end up with a shorter timeout. */
+- if (delta < 1)
++ if (delta < 1)
+ delta = 1;
+ st = processed_system_time + (delta * (u64)NS_PER_TICK);
+ } while (read_seqretry(&xtime_lock, seq));
+@@ -1039,7 +1035,7 @@ void stop_hz_timer(void)
+ {
+ unsigned int cpu = smp_processor_id();
+ unsigned long j;
+-
++
+ /* We must do this /before/ checking rcu_pending(). */
+ cpu_set(cpu, nohz_cpu_mask);
+ smp_mb();
+@@ -1086,7 +1082,7 @@ void local_setup_timer(unsigned int cpu)
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ /* Use cpu0 timestamp: cpu's shadow is not initialised yet. */
+- per_cpu(processed_system_time, cpu) =
++ per_cpu(processed_system_time, cpu) =
+ per_cpu(shadow_time, 0).system_timestamp;
+ init_missing_ticks_accounting(cpu);
+ } while (read_seqretry(&xtime_lock, seq));
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/Kconfig
+--- a/arch/ia64/Kconfig Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/Kconfig Mon Mar 6 17:57:34 2006 +0000
+@@ -49,6 +49,53 @@ config GENERIC_IOMAP
+ config GENERIC_IOMAP
+ bool
+ default y
++
++config XEN
++ bool
++ default y
++ help
++ Enable Xen hypervisor support. Resulting kernel runs
++ both as a guest OS on Xen and natively on hardware.
++
++config ARCH_XEN
++ bool
++ default y
++ help
++ TEMP ONLY. Needs to be on for drivers/xen to build.
++
++config XEN_PRIVILEGED_GUEST
++ bool "Privileged Guest"
++ default n
++ help
++ Used in drivers/xen/privcmd.c. Should go away?
++
++config XEN_BLKDEV_GRANT
++ depends on XEN
++ bool
++ default y
++
++config XEN_BLKDEV_FRONTEND
++ depends on XEN
++ bool
++ default y
++
++config XEN_BLKDEV_BACKEND
++ depends on XEN
++ bool
++ default y
++
++config XEN_VT
++ bool "Override for turning on CONFIG_VT for domU"
++ default y
++ help
++ Hack to turn off CONFIG_VT for domU
++
++config VT
++ bool
++ default y if XEN && XEN_VT
++ default n if XEN && !XEN_VT
++ help
++ Hack to turn off CONFIG_VT for domU
+
+ config SCHED_NO_NO_OMIT_FRAME_POINTER
+ bool
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/Makefile
+--- a/arch/ia64/Makefile Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -52,9 +52,15 @@ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/
+ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
+ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
+ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
++core-$(CONFIG_XEN) += arch/ia64/xen/
+
+ drivers-$(CONFIG_PCI) += arch/ia64/pci/
++ifneq ($(CONFIG_XEN),y)
+ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
++endif
++ifneq ($(CONFIG_IA64_GENERIC),y)
++drivers-$(CONFIG_XEN) += arch/ia64/hp/sim/
++endif
+ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
+ drivers-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
+ drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/
+@@ -67,6 +73,8 @@ all: compressed unwcheck
+ all: compressed unwcheck
+
+ compressed: vmlinux.gz
++
++vmlinuz: vmlinux.gz
+
+ vmlinux.gz: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $@
+@@ -82,7 +90,7 @@ boot: lib/lib.a vmlinux
+ boot: lib/lib.a vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $@
+
+-install: vmlinux.gz
++install:
+ sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
+
+ define archhelp
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/hp/sim/Makefile
+--- a/arch/ia64/hp/sim/Makefile Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/hp/sim/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -14,3 +14,5 @@ obj-$(CONFIG_HP_SIMSERIAL) += simserial.
+ obj-$(CONFIG_HP_SIMSERIAL) += simserial.o
+ obj-$(CONFIG_HP_SIMSERIAL_CONSOLE) += hpsim_console.o
+ obj-$(CONFIG_HP_SIMSCSI) += simscsi.o
++obj-$(CONFIG_XEN) += simserial.o
++obj-$(CONFIG_XEN) += hpsim_console.o
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/kernel/entry.S
+--- a/arch/ia64/kernel/entry.S Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/kernel/entry.S Mon Mar 6 17:57:34 2006 +0000
+@@ -181,7 +181,7 @@ END(sys_clone)
+ * called. The code starting at .map relies on this. The rest of the code
+ * doesn't care about the interrupt masking status.
+ */
+-GLOBAL_ENTRY(ia64_switch_to)
++GLOBAL_ENTRY(__ia64_switch_to)
+ .prologue
+ alloc r16=ar.pfs,1,0,0,0
+ DO_SAVE_SWITCH_STACK
+@@ -235,7 +235,7 @@ GLOBAL_ENTRY(ia64_switch_to)
+ ;;
+ srlz.d
+ br.cond.sptk .done
+-END(ia64_switch_to)
++END(__ia64_switch_to)
+
+ /*
+ * Note that interrupts are enabled during save_switch_stack and load_switch_stack. This
+@@ -376,7 +376,7 @@ END(save_switch_stack)
+ * - b7 holds address to return to
+ * - must not touch r8-r11
+ */
+-ENTRY(load_switch_stack)
++GLOBAL_ENTRY(load_switch_stack)
+ .prologue
+ .altrp b7
+
+@@ -511,7 +511,7 @@ END(clone)
+ * because some system calls (such as ia64_execve) directly
+ * manipulate ar.pfs.
+ */
+-GLOBAL_ENTRY(ia64_trace_syscall)
++GLOBAL_ENTRY(__ia64_trace_syscall)
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * We need to preserve the scratch registers f6-f11 in case the system
+@@ -583,7 +583,7 @@ strace_error:
+ (p6) mov r10=-1
+ (p6) mov r8=r9
+ br.cond.sptk .strace_save_retval
+-END(ia64_trace_syscall)
++END(__ia64_trace_syscall)
+
+ /*
+ * When traced and returning from sigreturn, we invoke syscall_trace but then
+@@ -636,8 +636,11 @@ GLOBAL_ENTRY(ia64_ret_from_syscall)
+ adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
+ mov r10=r0 // clear error indication in r10
+ (p7) br.cond.spnt handle_syscall_error // handle potential syscall failure
++ ;;
++ // don't fall through, ia64_leave_syscall may be #define'd
++ br.cond.sptk.few ia64_leave_syscall
++ ;;
+ END(ia64_ret_from_syscall)
+- // fall through
+ /*
+ * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
+ * need to switch to bank 0 and doesn't restore the scratch registers.
+@@ -682,7 +685,7 @@ END(ia64_ret_from_syscall)
+ * ar.csd: cleared
+ * ar.ssd: cleared
+ */
+-ENTRY(ia64_leave_syscall)
++GLOBAL_ENTRY(__ia64_leave_syscall)
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * work.need_resched etc. mustn't get changed by this CPU before it returns to
+@@ -790,7 +793,7 @@ ENTRY(ia64_leave_syscall)
+ mov.m ar.ssd=r0 // M2 clear ar.ssd
+ mov f11=f0 // F clear f11
+ br.cond.sptk.many rbs_switch // B
+-END(ia64_leave_syscall)
++END(__ia64_leave_syscall)
+
+ #ifdef CONFIG_IA32_SUPPORT
+ GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
+@@ -802,10 +805,13 @@ GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
+ st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
+ .mem.offset 8,0
+ st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
++ ;;
++ // don't fall through, ia64_leave_kernel may be #define'd
++ br.cond.sptk.few ia64_leave_kernel
++ ;;
+ END(ia64_ret_from_ia32_execve)
+- // fall through
+ #endif /* CONFIG_IA32_SUPPORT */
+-GLOBAL_ENTRY(ia64_leave_kernel)
++GLOBAL_ENTRY(__ia64_leave_kernel)
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * work.need_resched etc. mustn't get changed by this CPU before it returns to
+@@ -1150,7 +1156,7 @@ skip_rbs_switch:
+ ld8 r10=[r3]
+ br.cond.sptk.many .work_processed_syscall // re-check
+
+-END(ia64_leave_kernel)
++END(__ia64_leave_kernel)
+
+ ENTRY(handle_syscall_error)
+ /*
+@@ -1190,7 +1196,7 @@ END(ia64_invoke_schedule_tail)
+ * be set up by the caller. We declare 8 input registers so the system call
+ * args get preserved, in case we need to restart a system call.
+ */
+-ENTRY(notify_resume_user)
++GLOBAL_ENTRY(notify_resume_user)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+ alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
+ mov r9=ar.unat
+@@ -1278,7 +1284,7 @@ ENTRY(sys_rt_sigreturn)
+ adds sp=16,sp
+ ;;
+ ld8 r9=[sp] // load new ar.unat
+- mov.sptk b7=r8,ia64_leave_kernel
++ mov.sptk b7=r8,__ia64_leave_kernel
+ ;;
+ mov ar.unat=r9
+ br.many b7
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/kernel/head.S
+--- a/arch/ia64/kernel/head.S Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/kernel/head.S Mon Mar 6 17:57:34 2006 +0000
+@@ -362,6 +362,12 @@ 1: // now we are in virtual mode
+ (isBP) movl r2=ia64_boot_param
+ ;;
+ (isBP) st8 [r2]=r28 // save the address of the boot param area passed by the bootloader
++
++#ifdef CONFIG_XEN
++ // Note: isBP is used by the subprogram.
++ br.call.sptk.many rp=early_xen_setup
++ ;;
++#endif
+
+ #ifdef CONFIG_SMP
+ (isAP) br.call.sptk.many rp=start_secondary
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/kernel/pal.S
+--- a/arch/ia64/kernel/pal.S Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/kernel/pal.S Mon Mar 6 17:57:34 2006 +0000
+@@ -16,6 +16,7 @@
+ #include <asm/processor.h>
+
+ .data
++ .globl pal_entry_point
+ pal_entry_point:
+ data8 ia64_pal_default_handler
+ .text
+@@ -53,7 +54,7 @@ END(ia64_pal_default_handler)
+ * in4 1 ==> clear psr.ic, 0 ==> don't clear psr.ic
+ *
+ */
+-GLOBAL_ENTRY(ia64_pal_call_static)
++GLOBAL_ENTRY(__ia64_pal_call_static)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
+ alloc loc1 = ar.pfs,5,5,0,0
+ movl loc2 = pal_entry_point
+@@ -90,7 +91,7 @@ 1: mov psr.l = loc3
+ ;;
+ srlz.d // seralize restoration of psr.l
+ br.ret.sptk.many b0
+-END(ia64_pal_call_static)
++END(__ia64_pal_call_static)
+
+ /*
+ * Make a PAL call using the stacked registers calling convention.
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/kernel/sal.c
+--- a/arch/ia64/kernel/sal.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/kernel/sal.c Mon Mar 6 17:57:34 2006 +0000
+@@ -336,6 +336,9 @@ ia64_sal_init (struct ia64_sal_systab *s
+ p += SAL_DESC_SIZE(*p);
+ }
+
++#ifdef CONFIG_XEN
++ if (!running_on_xen)
++#endif
+ check_sal_cache_flush();
+ }
+
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/kernel/setup.c
+--- a/arch/ia64/kernel/setup.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/ia64/kernel/setup.c Mon Mar 6 17:57:34 2006 +0000
+@@ -61,6 +61,9 @@
+ #include <asm/system.h>
+ #include <asm/unistd.h>
+ #include <asm/system.h>
++#ifdef CONFIG_XEN
++#include <asm/hypervisor.h>
++#endif
+
+ #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
+ # error "struct cpuinfo_ia64 too big!"
+@@ -243,6 +246,14 @@ reserve_memory (void)
+ rsvd_region[n].end = (unsigned long) ia64_imva(_end);
+ n++;
+
++#ifdef CONFIG_XEN
++ if (running_on_xen) {
++ rsvd_region[n].start = (unsigned long)__va((HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT));
++ rsvd_region[n].end = rsvd_region[n].start + PAGE_SIZE;
++ n++;
++ }
++#endif
++
+ #ifdef CONFIG_BLK_DEV_INITRD
+ if (ia64_boot_param->initrd_start) {
+ rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start);
+@@ -260,6 +271,7 @@ reserve_memory (void)
+ n++;
+
+ num_rsvd_regions = n;
++ BUG_ON(IA64_MAX_RSVD_REGIONS + 1 < n);
+
+ sort_regions(rsvd_region, num_rsvd_regions);
+ }
+@@ -333,6 +345,10 @@ early_console_setup (char *cmdline)
+ {
+ int earlycons = 0;
+
++#ifdef CONFIG_XEN
++ if (!early_xen_console_setup(cmdline))
++ earlycons++;
++#endif
+ #ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
+ {
+ extern int sn_serial_console_early_setup(void);
+diff -r c75ede70c907 -r f6bd46559b93 arch/x86_64/kernel/io_apic-xen.c
+--- a/arch/x86_64/kernel/io_apic-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/x86_64/kernel/io_apic-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -108,8 +108,8 @@ static inline unsigned int xen_io_apic_r
+ int ret;
+
+ op.cmd = PHYSDEVOP_APIC_READ;
+- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
+- op.u.apic_op.offset = reg;
++ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++ op.u.apic_op.reg = reg;
+ ret = HYPERVISOR_physdev_op(&op);
+ if (ret)
+ return ret;
+@@ -121,8 +121,8 @@ static inline void xen_io_apic_write(uns
+ physdev_op_t op;
+
+ op.cmd = PHYSDEVOP_APIC_WRITE;
+- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
+- op.u.apic_op.offset = reg;
++ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++ op.u.apic_op.reg = reg;
+ op.u.apic_op.value = value;
+ HYPERVISOR_physdev_op(&op);
+ }
+diff -r c75ede70c907 -r f6bd46559b93 arch/x86_64/kernel/process-xen.c
+--- a/arch/x86_64/kernel/process-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/x86_64/kernel/process-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -124,9 +124,9 @@ void xen_idle(void)
+ {
+ local_irq_disable();
+
+- if (need_resched()) {
++ if (need_resched())
+ local_irq_enable();
+- } else {
++ else {
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb__after_clear_bit();
+ stop_hz_timer();
+diff -r c75ede70c907 -r f6bd46559b93 arch/x86_64/kernel/setup-xen.c
+--- a/arch/x86_64/kernel/setup-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/x86_64/kernel/setup-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -661,13 +661,7 @@ void __init setup_arch(char **cmdline_p)
+ HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi);
+ #endif
+
+- clear_bit(X86_FEATURE_VME, boot_cpu_data.x86_capability);
+- clear_bit(X86_FEATURE_DE, boot_cpu_data.x86_capability);
+- clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+- clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+- clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
+- if (!(xen_start_info->flags & SIF_PRIVILEGED))
+- clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability);
++ modify_cpu_capabilities(&boot_cpu_data);
+ #endif
+
+ if (!MOUNT_ROOT_RDONLY)
+@@ -1393,6 +1387,8 @@ void __cpuinit identify_cpu(struct cpuin
+ 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
+diff -r c75ede70c907 -r f6bd46559b93 arch/x86_64/kernel/x8664_ksyms-xen.c
+--- a/arch/x86_64/kernel/x8664_ksyms-xen.c Mon Feb 27 15:43:34 2006 +0000
++++ b/arch/x86_64/kernel/x8664_ksyms-xen.c Mon Mar 6 17:57:34 2006 +0000
+@@ -32,8 +32,6 @@
+ #include <asm/tlbflush.h>
+ #include <asm/kdebug.h>
+
+-extern spinlock_t rtc_lock;
+-
+ #ifdef CONFIG_SMP
+ extern void __write_lock_failed(rwlock_t *rw);
+ extern void __read_lock_failed(rwlock_t *rw);
+@@ -42,9 +40,6 @@ extern void __read_lock_failed(rwlock_t
+ /* platform dependent support */
+ EXPORT_SYMBOL(boot_cpu_data);
+ //EXPORT_SYMBOL(dump_fpu);
+-EXPORT_SYMBOL(__ioremap);
+-EXPORT_SYMBOL(ioremap_nocache);
+-EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(kernel_thread);
+ EXPORT_SYMBOL(pm_idle);
+ EXPORT_SYMBOL(pm_power_off);
+@@ -101,8 +96,6 @@ EXPORT_SYMBOL(screen_info);
+ #endif
+
+ EXPORT_SYMBOL(get_wchan);
+-
+-EXPORT_SYMBOL(rtc_lock);
+
+ #ifdef CONFIG_X86_LOCAL_APIC
+ EXPORT_SYMBOL_GPL(set_nmi_callback);
+@@ -166,7 +159,5 @@ EXPORT_SYMBOL(flush_tlb_page);
+ EXPORT_SYMBOL(flush_tlb_page);
+ #endif
+
+-EXPORT_SYMBOL(cpu_khz);
+-
+ EXPORT_SYMBOL(load_gs_index);
+
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/Kconfig
+--- a/drivers/xen/Kconfig Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/Kconfig Mon Mar 6 17:57:34 2006 +0000
+@@ -68,7 +68,7 @@ config XEN_PCIDEV_BE_DEBUG
+ default n
+
+ config XEN_BLKDEV_BACKEND
+- bool "Block-device backend driver"
++ tristate "Block-device backend driver"
+ default y
+ help
+ The block-device backend driver allows the kernel to export its
+@@ -76,7 +76,7 @@ config XEN_BLKDEV_BACKEND
+ interface.
+
+ config XEN_BLKDEV_TAP_BE
+- bool "Block Tap support for backend driver (DANGEROUS)"
++ tristate "Block Tap support for backend driver (DANGEROUS)"
+ depends on XEN_BLKDEV_BACKEND
+ default n
+ help
+@@ -89,7 +89,7 @@ config XEN_BLKDEV_TAP_BE
+ modified to use grant tables.
+
+ config XEN_NETDEV_BACKEND
+- bool "Network-device backend driver"
++ tristate "Network-device backend driver"
+ default y
+ help
+ The network-device backend driver allows the kernel to export its
+@@ -109,8 +109,16 @@ config XEN_NETDEV_PIPELINED_TRANSMITTER
+ are unsure; or if you experience network hangs when this option is
+ enabled; then you must say N here.
+
++config XEN_NETDEV_LOOPBACK
++ tristate "Network-device loopback driver"
++ depends on XEN_NETDEV_BACKEND
++ default y
++ help
++ A two-interface loopback device to emulate a local netfront-netback
++ connection.
++
+ config XEN_TPMDEV_BACKEND
+- bool "TPM-device backend driver"
++ tristate "TPM-device backend driver"
+ default n
+ help
+ The TPM-device backend driver
+@@ -145,7 +153,7 @@ config XEN_NETDEV_FRONTEND
+ (domain 0), then you almost certainly want to say Y here.
+
+ config XEN_BLKDEV_TAP
+- bool "Block device tap driver"
++ tristate "Block device tap driver"
+ default n
+ help
+ This driver allows a VM to interact on block device channels
+@@ -154,7 +162,7 @@ config XEN_BLKDEV_TAP
+ space. Odds are that you want to say N here.
+
+ config XEN_TPMDEV_FRONTEND
+- bool "TPM-device frontend driver"
++ tristate "TPM-device frontend driver"
+ default n
+ select TCG_TPM
+ select TCG_XEN
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/blkback/Makefile
+--- a/drivers/xen/blkback/Makefile Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/blkback/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -1,2 +1,3 @@
++obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
+
+-obj-y := blkback.o xenbus.o interface.o vbd.o
++blkbk-y := blkback.o xenbus.o interface.o vbd.o
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/blkback/blkback.c
+--- a/drivers/xen/blkback/blkback.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/blkback/blkback.c Mon Mar 6 17:57:34 2006 +0000
+@@ -29,14 +29,10 @@
+ * 64 should be enough to keep us competitive with Linux.
+ */
+ static int blkif_reqs = 64;
++module_param_named(reqs, blkif_reqs, int, 0);
++MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate");
++
+ static int mmap_pages;
+-
+-static int __init set_blkif_reqs(char *str)
+-{
+- get_option(&str, &blkif_reqs);
+- return 1;
+-}
+-__setup("blkif_reqs=", set_blkif_reqs);
+
+ /* Run-time switchable: /sys/module/blkback/parameters/ */
+ static unsigned int log_stats = 0;
+@@ -574,10 +570,20 @@ static int __init blkif_init(void)
+ list_add_tail(&pending_reqs[i].free_list, &pending_free);
+
+ blkif_xenbus_init();
++ __unsafe(THIS_MODULE);
+ return 0;
+ }
+
+-__initcall(blkif_init);
++module_init(blkif_init);
++
++static void blkif_exit(void)
++{
++ BUG();
++}
++
++module_exit(blkif_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/blkfront/blkfront.c
+--- a/drivers/xen/blkfront/blkfront.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/blkfront/blkfront.c Mon Mar 6 17:57:34 2006 +0000
+@@ -182,9 +182,8 @@ again:
+ }
+
+ err = xenbus_switch_state(dev, xbt, XenbusStateInitialised);
+- if (err) {
++ if (err)
+ goto abort_transaction;
+- }
+
+ err = xenbus_transaction_end(xbt, 0);
+ if (err) {
+@@ -295,17 +294,17 @@ static void backend_changed(struct xenbu
+ /* ** Connection ** */
+
+
+-/*
+-** Invoked when the backend is finally 'ready' (and has told produced
+-** the details about the physical device - #sectors, size, etc).
+-*/
++/*
++ * Invoked when the backend is finally 'ready' (and has told produced
++ * the details about the physical device - #sectors, size, etc).
++ */
+ static void connect(struct blkfront_info *info)
+ {
+ unsigned long sectors, sector_size;
+ unsigned int binfo;
+ int err;
+
+- if( (info->connected == BLKIF_STATE_CONNECTED) ||
++ if ((info->connected == BLKIF_STATE_CONNECTED) ||
+ (info->connected == BLKIF_STATE_SUSPENDED) )
+ return;
+
+@@ -330,7 +329,7 @@ static void connect(struct blkfront_info
+ return;
+ }
+
+- (void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
++ (void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
+
+ /* Kick pending requests. */
+ spin_lock_irq(&blkif_io_lock);
+@@ -463,8 +462,7 @@ int blkif_ioctl(struct inode *inode, str
+ DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+ command, (long)argument, inode->i_rdev);
+
+- switch ( command )
+- {
++ switch (command) {
+ case HDIO_GETGEO:
+ /* return ENOSYS to use defaults */
+ return -ENOSYS;
+@@ -490,7 +488,7 @@ int blkif_ioctl(struct inode *inode, str
+ * blkif_queue_request
+ *
+ * request block io
+- *
++ *
+ * id: for guest use only.
+ * operation: BLKIF_OP_{READ,WRITE,PROBE}
+ * buffer: buffer to read/write into. this should be a
+@@ -557,7 +555,7 @@ static int blkif_queue_request(struct re
+ ring_req->seg[ring_req->nr_segments] =
+ (struct blkif_request_segment) {
+ .gref = ref,
+- .first_sect = fsect,
++ .first_sect = fsect,
+ .last_sect = lsect };
+
+ ring_req->nr_segments++;
+@@ -679,9 +677,8 @@ static irqreturn_t blkif_int(int irq, vo
+ RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
+ if (more_to_do)
+ goto again;
+- } else {
++ } else
+ info->ring.sring->rsp_event = i + 1;
+- }
+
+ kick_pending_request_queues(info);
+
+@@ -694,8 +691,8 @@ static void blkif_free(struct blkfront_i
+ {
+ /* Prevent new requests being issued until we fix things up. */
+ spin_lock_irq(&blkif_io_lock);
+- info->connected = suspend ?
+- BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
++ info->connected = suspend ?
++ BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
+ spin_unlock_irq(&blkif_io_lock);
+
+ /* Free resources associated with old device channel. */
+@@ -706,7 +703,7 @@ static void blkif_free(struct blkfront_i
+ info->ring.sring = NULL;
+ }
+ if (info->irq)
+- unbind_from_irqhandler(info->irq, info);
++ unbind_from_irqhandler(info->irq, info);
+ info->evtchn = info->irq = 0;
+
+ }
+@@ -767,11 +764,11 @@ static void blkif_recover(struct blkfron
+
+ kfree(copy);
+
+- (void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
+-
++ (void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
++
+ /* Now safe for us to use the shared ring */
+ spin_lock_irq(&blkif_io_lock);
+- info->connected = BLKIF_STATE_CONNECTED;
++ info->connected = BLKIF_STATE_CONNECTED;
+ spin_unlock_irq(&blkif_io_lock);
+
+ /* Send off requeued requests */
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/blkfront/block.h
+--- a/drivers/xen/blkfront/block.h Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/blkfront/block.h Mon Mar 6 17:57:34 2006 +0000
+@@ -55,24 +55,24 @@
+ #include <asm/atomic.h>
+ #include <asm/uaccess.h>
+
+-#if 1
++#if 1
+ #define IPRINTK(fmt, args...) \
+ printk(KERN_INFO "xen_blk: " fmt, ##args)
+ #else
+ #define IPRINTK(fmt, args...) ((void)0)
+ #endif
+
+-#if 1
++#if 1
+ #define WPRINTK(fmt, args...) \
+ printk(KERN_WARNING "xen_blk: " fmt, ##args)
+ #else
+ #define WPRINTK(fmt, args...) ((void)0)
+ #endif
+-
+-#define DPRINTK(_f, _a...) pr_debug ( _f , ## _a )
++
++#define DPRINTK(_f, _a...) pr_debug(_f, ## _a)
+
+ #if 0
+-#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a )
++#define DPRINTK_IOCTL(_f, _a...) printk(KERN_ALERT _f, ## _a)
+ #else
+ #define DPRINTK_IOCTL(_f, _a...) ((void)0)
+ #endif
+@@ -139,7 +139,7 @@ extern int blkif_ioctl(struct inode *ino
+ unsigned command, unsigned long argument);
+ extern int blkif_check(dev_t dev);
+ extern int blkif_revalidate(dev_t dev);
+-extern void do_blkif_request (request_queue_t *rq);
++extern void do_blkif_request (request_queue_t *rq);
+
+ /* Virtual block-device subsystem. */
+ /* Note that xlvbd_add doesn't call add_disk for you: you're expected
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/char/mem.c
+--- a/drivers/xen/char/mem.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/char/mem.c Mon Mar 6 17:57:34 2006 +0000
+@@ -43,49 +43,85 @@ static ssize_t read_mem(struct file * fi
+ static ssize_t read_mem(struct file * file, char __user * buf,
+ size_t count, loff_t *ppos)
+ {
+- unsigned long i, p = *ppos;
+- ssize_t read = -EFAULT;
++ unsigned long p = *ppos, ignored;
++ ssize_t read = 0, sz;
+ void __iomem *v;
+
+- if ((v = ioremap(p, count)) == NULL) {
++ while (count > 0) {
+ /*
+- * Some programs (e.g., dmidecode) groove off into weird RAM
+- * areas where no table scan possibly exist (because Xen will
+- * have stomped on them!). These programs get rather upset if
+- * we let them know that Xen failed their access, so we fake
+- * out a read of all zeroes. :-)
++ * Handle first page in case it's not aligned
+ */
+- for (i = 0; i < count; i++)
+- if (put_user(0, buf+i))
++ if (-p & (PAGE_SIZE - 1))
++ sz = -p & (PAGE_SIZE - 1);
++ else
++ sz = PAGE_SIZE;
++
++ sz = min_t(unsigned long, sz, count);
++
++ if ((v = ioremap(p, sz)) == NULL) {
++ /*
++ * Some programs (e.g., dmidecode) groove off into weird RAM
++ * areas where no tables can possibly exist (because Xen will
++ * have stomped on them!). These programs get rather upset if
++ * we let them know that Xen failed their access, so we fake
++ * out a read of all zeroes. :-)
++ */
++ if (clear_user(buf, count))
+ return -EFAULT;
+- return count;
++ read += count;
++ break;
++ }
++
++ ignored = copy_to_user(buf, v, sz);
++ iounmap(v);
++ if (ignored)
++ return -EFAULT;
++ buf += sz;
++ p += sz;
++ count -= sz;
++ read += sz;
+ }
+- if (copy_to_user(buf, v, count))
+- goto out;
+
+- read = count;
+ *ppos += read;
+-out:
+- iounmap(v);
+ return read;
+ }
+
+ static ssize_t write_mem(struct file * file, const char __user * buf,
+ size_t count, loff_t *ppos)
+ {
+- unsigned long p = *ppos;
+- ssize_t written = -EFAULT;
++ unsigned long p = *ppos, ignored;
++ ssize_t written = 0, sz;
+ void __iomem *v;
+
+- if ((v = ioremap(p, count)) == NULL)
+- return -EFAULT;
+- if (copy_from_user(v, buf, count))
+- goto out;
++ while (count > 0) {
++ /*
++ * Handle first page in case it's not aligned
++ */
++ if (-p & (PAGE_SIZE - 1))
++ sz = -p & (PAGE_SIZE - 1);
++ else
++ sz = PAGE_SIZE;
+
+- written = count;
++ sz = min_t(unsigned long, sz, count);
++
++ if ((v = ioremap(p, sz)) == NULL)
++ break;
++
++ ignored = copy_from_user(v, buf, sz);
++ iounmap(v);
++ if (ignored) {
++ written += sz - ignored;
++ if (written)
++ break;
++ return -EFAULT;
++ }
++ buf += sz;
++ p += sz;
++ count -= sz;
++ written += sz;
++ }
++
+ *ppos += written;
+-out:
+- iounmap(v);
+ return written;
+ }
+
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/console/console.c
+--- a/drivers/xen/console/console.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/console/console.c Mon Mar 6 17:57:34 2006 +0000
+@@ -85,8 +85,7 @@ static int __init xencons_setup(char *st
+ else if (!strncmp(str, "off", 3))
+ xc_mode = XC_OFF;
+
+- switch ( xc_mode )
+- {
++ switch (xc_mode) {
+ case XC_SERIAL:
+ n = simple_strtol(str+4, &q, 10);
+ if (q > (str + 4))
+@@ -227,7 +226,7 @@ asmlinkage int xprintk(const char *fmt,
+ va_list args;
+ int printk_len;
+ static char printk_buf[1024];
+-
++
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+ printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+@@ -485,7 +484,7 @@ static void xencons_flush_chars(struct t
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ __xencons_tx_flush();
+- spin_unlock_irqrestore(&xencons_lock, flags);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
+@@ -495,17 +494,15 @@ static void xencons_wait_until_sent(stru
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+- while (DRV(tty->driver)->chars_in_buffer(tty))
+- {
++ while (DRV(tty->driver)->chars_in_buffer(tty)) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ if (signal_pending(current))
+ break;
+- if ( (timeout != 0) &&
+- time_after(jiffies, orig_jiffies + timeout) )
++ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+-
++
+ set_current_state(TASK_RUNNING);
+ }
+
+@@ -521,7 +518,7 @@ static int xencons_open(struct tty_struc
+ if (xencons_tty == NULL)
+ xencons_tty = tty;
+ __xencons_tx_flush();
+- spin_unlock_irqrestore(&xencons_lock, flags);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
+ }
+@@ -543,7 +540,7 @@ static void xencons_close(struct tty_str
+ tty->closing = 0;
+ spin_lock_irqsave(&xencons_lock, flags);
+ xencons_tty = NULL;
+- spin_unlock_irqrestore(&xencons_lock, flags);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ }
+
+@@ -574,7 +571,7 @@ static int __init xencons_init(void)
+
+ xencons_ring_init();
+
+- xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
++ xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
+ 1 : MAX_NR_CONSOLES);
+ if (xencons_driver == NULL)
+ return -ENOMEM;
+@@ -584,15 +581,14 @@ static int __init xencons_init(void)
+ DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
+ DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
+ DRV(xencons_driver)->init_termios = tty_std_termios;
+- DRV(xencons_driver)->flags =
++ DRV(xencons_driver)->flags =
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_NO_DEVFS;
+ DRV(xencons_driver)->termios = xencons_termios;
+ DRV(xencons_driver)->termios_locked = xencons_termios_locked;
+
+- if (xc_mode == XC_SERIAL)
+- {
++ if (xc_mode == XC_SERIAL) {
+ DRV(xencons_driver)->name = "ttyS";
+ DRV(xencons_driver)->minor_start = 64 + xc_num;
+ DRV(xencons_driver)->name_base = 0 + xc_num;
+@@ -630,7 +626,7 @@ static int __init xencons_init(void)
+ printk("Xen virtual console successfully installed as %s%d\n",
+ DRV(xencons_driver)->name,
+ DRV(xencons_driver)->name_base );
+-
++
+ return 0;
+ }
+
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/console/xencons_ring.c
+--- a/drivers/xen/console/xencons_ring.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/console/xencons_ring.c Mon Mar 6 17:57:34 2006 +0000
+@@ -55,7 +55,7 @@ int xencons_ring_send(const char *data,
+ notify_daemon();
+
+ return sent;
+-}
++}
+
+ static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
+ {
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/core/evtchn.c
+--- a/drivers/xen/core/evtchn.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/core/evtchn.c Mon Mar 6 17:57:34 2006 +0000
+@@ -72,7 +72,7 @@ DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS
+
+ /* IRQ <-> IPI mapping. */
+ #ifndef NR_IPIS
+-#define NR_IPIS 1
++#define NR_IPIS 1
+ #endif
+ DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
+
+@@ -209,7 +209,7 @@ static int bind_evtchn_to_irq(unsigned i
+ irq_bindcount[irq]++;
+
+ spin_unlock(&irq_mapping_update_lock);
+-
++
+ return irq;
+ }
+
+@@ -238,7 +238,7 @@ static int bind_virq_to_irq(unsigned int
+ irq_bindcount[irq]++;
+
+ spin_unlock(&irq_mapping_update_lock);
+-
++
+ return irq;
+ }
+
+@@ -535,9 +535,9 @@ static unsigned int startup_pirq(unsigne
+ /* NB. We are happy to share unless we are probing. */
+ op.u.bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
+ if (HYPERVISOR_event_channel_op(&op) != 0) {
+- if ( !probing_irq(irq) )
+- printk(KERN_INFO "Failed to obtain physical "
+- "IRQ %d\n", irq);
++ if (!probing_irq(irq))
++ printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
++ irq);
+ return 0;
+ }
+ evtchn = op.u.bind_pirq.port;
+@@ -669,7 +669,7 @@ void unmask_evtchn(int port)
+ * like a real IO-APIC we 'lose the interrupt edge' if the channel is
+ * masked.
+ */
+- if (synch_test_bit(port, &s->evtchn_pending[0]) &&
++ if (synch_test_bit(port, &s->evtchn_pending[0]) &&
+ !synch_test_and_set_bit(port / BITS_PER_LONG,
+ &vcpu_info->evtchn_pending_sel)) {
+ vcpu_info->evtchn_upcall_pending = 1;
+@@ -722,7 +722,7 @@ void irq_resume(void)
+ op.u.bind_virq.vcpu = 0;
+ BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
+ evtchn = op.u.bind_virq.port;
+-
++
+ /* Record the new mapping. */
+ evtchn_to_irq[evtchn] = irq;
+ irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+@@ -744,7 +744,7 @@ void irq_resume(void)
+ op.u.bind_ipi.vcpu = 0;
+ BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
+ evtchn = op.u.bind_ipi.port;
+-
++
+ /* Record the new mapping. */
+ evtchn_to_irq[evtchn] = irq;
+ irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
+@@ -794,8 +794,7 @@ void __init init_IRQ(void)
+ }
+
+ /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
+- for (i = 0; i < NR_PIRQS; i++)
+- {
++ for (i = 0; i < NR_PIRQS; i++) {
+ irq_bindcount[pirq_to_irq(i)] = 1;
+
+ #ifdef RTC_IRQ
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/core/features.c
+--- a/drivers/xen/core/features.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/core/features.c Mon Mar 6 17:57:34 2006 +0000
+@@ -19,7 +19,7 @@ void setup_xen_features(void)
+ xen_feature_info_t fi;
+ int i, j;
+
+- for (i=0; i<XENFEAT_NR_SUBMAPS; i++) {
++ for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
+ fi.submap_idx = i;
+ if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
+ break;
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/core/gnttab.c
+--- a/drivers/xen/core/gnttab.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/core/gnttab.c Mon Mar 6 17:57:34 2006 +0000
+@@ -35,13 +35,12 @@
+ #include <xen/interface/xen.h>
+ #include <asm/fixmap.h>
+ #include <asm/uaccess.h>
+-#include <xen/public/privcmd.h>
+ #include <xen/gnttab.h>
+ #include <asm/synch_bitops.h>
+
+ #if 1
+ #define ASSERT(_p) \
+- if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
++ if (!(_p)) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
+ #_p , __LINE__, __FILE__); *(int*)0=0; }
+ #else
+ #define ASSERT(_p) ((void)0)
+@@ -153,7 +152,7 @@ gnttab_grant_foreign_access(domid_t domi
+ gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
+ {
+ int ref;
+-
++
+ if (unlikely((ref = get_free_entry()) == -1))
+ return -ENOSPC;
+
+@@ -193,13 +192,12 @@ gnttab_end_foreign_access_ref(grant_ref_
+
+ nflags = shared[ref].flags;
+ do {
+- if ( (flags = nflags) & (GTF_reading|GTF_writing) ) {
++ if ((flags = nflags) & (GTF_reading|GTF_writing)) {
+ printk(KERN_ALERT "WARNING: g.e. still in use!\n");
+ return 0;
+ }
+- }
+- while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
+- flags);
++ } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
++ flags);
+
+ return 1;
+ }
+@@ -212,8 +210,7 @@ gnttab_end_foreign_access(grant_ref_t re
+ if (page != 0) {
+ free_page(page);
+ }
+- }
+- else {
++ } else {
+ /* XXX This needs to be fixed so that the ref and page are
+ placed on a list to be freed up later. */
+ printk(KERN_WARNING
+@@ -254,7 +251,7 @@ gnttab_end_foreign_transfer_ref(grant_re
+ * reference and return failure (== 0).
+ */
+ while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
+- if ( synch_cmpxchg(&shared[ref].flags, flags, 0) == flags )
++ if (synch_cmpxchg(&shared[ref].flags, flags, 0) == flags)
+ return 0;
+ cpu_relax();
+ }
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/core/reboot.c
+--- a/drivers/xen/core/reboot.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/core/reboot.c Mon Mar 6 17:57:34 2006 +0000
+@@ -29,10 +29,11 @@ EXPORT_SYMBOL(pm_power_off);
+ #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!
+-// HALT is the same as POWEROFF, as far as we're concerned. The tools use
+-// the distinction when we return the reason code to them.
++/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
++ * report a crash, not be instructed to crash!
++ * HALT is the same as POWEROFF, as far as we're concerned. The tools use
++ * the distinction when we return the reason code to them.
++ */
+ #define SHUTDOWN_HALT 4
+
+ void machine_emergency_restart(void)
+@@ -84,13 +85,13 @@ static int __do_suspend(void *ignore)
+ {
+ int i, j, k, fpp;
+
+- extern int gnttab_suspend(void);
+- extern int gnttab_resume(void);
+-
+- extern void time_resume(void);
+ extern unsigned long max_pfn;
+ extern unsigned long *pfn_to_mfn_frame_list_list;
+ extern unsigned long *pfn_to_mfn_frame_list[];
++
++ extern int gnttab_suspend(void);
++ extern int gnttab_resume(void);
++ extern void time_resume(void);
+
+ #ifdef CONFIG_SMP
+ cpumask_t prev_online_cpus;
+@@ -167,26 +168,26 @@ static int __do_suspend(void *ignore)
+ */
+ HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+
+- shutting_down = SHUTDOWN_INVALID;
++ shutting_down = SHUTDOWN_INVALID;
+
+ 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, PAGE_SIZE);
+-
++
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ virt_to_mfn(pfn_to_mfn_frame_list_list);
+-
++
+ fpp = PAGE_SIZE/sizeof(unsigned long);
+ for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
+ if ((j % fpp) == 0) {
+ k++;
+- pfn_to_mfn_frame_list_list[k] =
++ pfn_to_mfn_frame_list_list[k] =
+ virt_to_mfn(pfn_to_mfn_frame_list[k]);
+ j = 0;
+ }
+- pfn_to_mfn_frame_list[k][j] =
++ pfn_to_mfn_frame_list[k][j] =
+ virt_to_mfn(&phys_to_machine_mapping[i]);
+ }
+ HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+@@ -207,7 +208,7 @@ static int __do_suspend(void *ignore)
+
+ #endif
+
+- /*
++ /*
+ * Only resume xenbus /after/ we've prepared our VCPUs; otherwise
+ * the VCPU hotplug callback can race with our vcpu_prepare
+ */
+@@ -231,7 +232,7 @@ static int __do_suspend(void *ignore)
+
+ static int shutdown_process(void *__unused)
+ {
+- static char *envp[] = { "HOME=/", "TERM=linux",
++ 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 };
+@@ -291,7 +292,7 @@ static void __shutdown_handler(void *unu
+ else
+ err = kthread_create_on_cpu(__do_suspend, NULL, "suspend", 0);
+
+- if ( err < 0 ) {
++ if (err < 0) {
+ printk(KERN_WARNING "Error creating shutdown process (%d): "
+ "retrying...\n", -err);
+ schedule_delayed_work(&shutdown_work, HZ/2);
+@@ -406,14 +407,12 @@ static int setup_shutdown_watcher(struct
+ err2 = register_xenbus_watch(&sysrq_watch);
+ #endif
+
+- if (err1) {
++ if (err1)
+ printk(KERN_ERR "Failed to set shutdown watcher\n");
+- }
+-
+-#ifdef CONFIG_MAGIC_SYSRQ
+- if (err2) {
++
++#ifdef CONFIG_MAGIC_SYSRQ
++ if (err2)
+ printk(KERN_ERR "Failed to set sysrq watcher\n");
+- }
+ #endif
+
+ return NOTIFY_DONE;
+@@ -421,11 +420,11 @@ static int setup_shutdown_watcher(struct
+
+ static int __init setup_shutdown_event(void)
+ {
+-
++
+ xenstore_notifier.notifier_call = setup_shutdown_watcher;
+
+ register_xenstore_notifier(&xenstore_notifier);
+-
++
+ return 0;
+ }
+
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/core/skbuff.c
+--- a/drivers/xen/core/skbuff.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/core/skbuff.c Mon Mar 6 17:57:34 2006 +0000
+@@ -16,6 +16,7 @@
+
+ /* Referenced in netback.c. */
+ /*static*/ kmem_cache_t *skbuff_cachep;
++EXPORT_SYMBOL(skbuff_cachep);
+
+ #define MAX_SKBUFF_ORDER 4
+ static kmem_cache_t *skbuff_order_cachep[MAX_SKBUFF_ORDER + 1];
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/net_driver_util.c
+--- a/drivers/xen/net_driver_util.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/net_driver_util.c Mon Mar 6 17:57:34 2006 +0000
+@@ -40,9 +40,8 @@ int xen_net_read_mac(struct xenbus_devic
+ int i;
+ char *e;
+ char *macstr = xenbus_read(XBT_NULL, dev->nodename, "mac", NULL);
+- if (IS_ERR(macstr)) {
++ if (IS_ERR(macstr))
+ return PTR_ERR(macstr);
+- }
+ s = macstr;
+ for (i = 0; i < ETH_ALEN; i++) {
+ mac[i] = simple_strtoul(s, &e, 16);
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/netback/Makefile
+--- a/drivers/xen/netback/Makefile Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/netback/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -1,2 +1,5 @@
++obj-$(CONFIG_XEN_NETDEV_BACKEND) := netbk.o
++obj-$(CONFIG_XEN_NETDEV_LOOPBACK) += netloop.o
+
+-obj-y := netback.o xenbus.o interface.o loopback.o
++netbk-y := netback.o xenbus.o interface.o
++netloop-y := loopback.o
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/netback/loopback.c
+--- a/drivers/xen/netback/loopback.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/netback/loopback.c Mon Mar 6 17:57:34 2006 +0000
+@@ -178,6 +178,23 @@ static int __init make_loopback(int i)
+ return err;
+ }
+
++static void __init clean_loopback(int i)
++{
++ struct net_device *dev1, *dev2;
++ char dev_name[IFNAMSIZ];
++
++ sprintf(dev_name, "vif0.%d", i);
++ dev1 = dev_get_by_name(dev_name);
++ sprintf(dev_name, "veth%d", i);
++ dev2 = dev_get_by_name(dev_name);
++ if (dev1 && dev2) {
++ unregister_netdev(dev2);
++ unregister_netdev(dev1);
++ free_netdev(dev2);
++ free_netdev(dev1);
++ }
++}
++
+ static int __init loopback_init(void)
+ {
+ int i, err = 0;
+@@ -190,6 +207,18 @@ static int __init loopback_init(void)
+ }
+
+ module_init(loopback_init);
++
++static void __exit loopback_exit(void)
++{
++ int i;
++
++ for (i = nloopbacks; i-- > 0; )
++ clean_loopback(i);
++}
++
++module_exit(loopback_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/netback/netback.c
+--- a/drivers/xen/netback/netback.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/netback/netback.c Mon Mar 6 17:57:34 2006 +0000
+@@ -505,14 +505,12 @@ static void net_tx_action(unsigned long
+ /* Still too big to send right now? Set a callback. */
+ if (txreq.size > netif->remaining_credit) {
+ netif->remaining_credit = 0;
+- netif->credit_timeout.expires =
+- next_credit;
+ netif->credit_timeout.data =
+ (unsigned long)netif;
+ netif->credit_timeout.function =
+ tx_credit_callback;
+- add_timer_on(&netif->credit_timeout,
+- smp_processor_id());
++ __mod_timer(&netif->credit_timeout,
++ next_credit);
+ break;
+ }
+ }
+@@ -811,6 +809,8 @@ static int __init netback_init(void)
+ &netif_be_dbg);
+ #endif
+
++ __unsafe(THIS_MODULE);
++
+ return 0;
+ }
+
+@@ -821,6 +821,8 @@ static void netback_cleanup(void)
+
+ module_init(netback_init);
+ module_exit(netback_cleanup);
++
++MODULE_LICENSE("Dual BSD/GPL");
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/netfront/netfront.c
+--- a/drivers/xen/netfront/netfront.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/netfront/netfront.c Mon Mar 6 17:57:34 2006 +0000
+@@ -91,7 +91,7 @@ struct netfront_info
+
+ struct net_device_stats stats;
+ unsigned int tx_full;
+-
++
+ netif_tx_front_ring_t tx;
+ netif_rx_front_ring_t rx;
+
+@@ -129,9 +129,9 @@ struct netfront_info
+ struct sk_buff *rx_skbs[NET_RX_RING_SIZE+1];
+
+ grant_ref_t gref_tx_head;
+- grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
++ grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
+ grant_ref_t gref_rx_head;
+- grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1];
++ grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1];
+
+ struct xenbus_device *xbdev;
+ int tx_ring_ref;
+@@ -433,7 +433,7 @@ static int send_fake_arp(struct net_devi
+
+ skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
+ dst_ip, dev, src_ip,
+- /*dst_hw*/ NULL, /*src_hw*/ NULL,
++ /*dst_hw*/ NULL, /*src_hw*/ NULL,
+ /*target_hw*/ dev->dev_addr);
+ if (skb == NULL)
+ return -ENOMEM;
+@@ -480,7 +480,7 @@ static void network_tx_buf_gc(struct net
+ printk(KERN_ALERT "network_tx_buf_gc: warning "
+ "-- grant still in use by backend "
+ "domain.\n");
+- goto out;
++ goto out;
+ }
+ gnttab_end_foreign_access_ref(
+ np->grant_tx_ref[id], GNTMAP_readonly);
+@@ -490,9 +490,9 @@ static void network_tx_buf_gc(struct net
+ ADD_ID_TO_FREELIST(np->tx_skbs, id);
+ dev_kfree_skb_irq(skb);
+ }
+-
++
+ np->tx.rsp_cons = prod;
+-
++
+ /*
+ * Set a new event, then check for race with update of tx_cons.
+ * Note that it is essential to schedule a callback, no matter
+@@ -506,7 +506,7 @@ static void network_tx_buf_gc(struct net
+ mb();
+ } while (prod != np->tx.sring->rsp_prod);
+
+- out:
++ out:
+ if (np->tx_full &&
+ ((np->tx.sring->req_prod - prod) < NET_TX_RING_SIZE)) {
+ np->tx_full = 0;
+@@ -582,7 +582,7 @@ static void network_alloc_rx_buffers(str
+ id = GET_ID_FROM_FREELIST(np->rx_skbs);
+
+ np->rx_skbs[id] = skb;
+-
++
+ RING_GET_REQUEST(&np->rx, req_prod + i)->id = id;
+ ref = gnttab_claim_grant_reference(&np->gref_rx_head);
+ BUG_ON((signed short)ref < 0);
+@@ -628,11 +628,10 @@ static void network_alloc_rx_buffers(str
+ /* Check return status of HYPERVISOR_memory_op(). */
+ if (unlikely(rx_mcl[i].result != i))
+ panic("Unable to reduce memory reservation\n");
+- } else {
++ } else
+ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+ &reservation) != i)
+ panic("Unable to reduce memory reservation\n");
+- }
+
+ /* Above is a suitable barrier to ensure backend will see requests. */
+ np->rx.req_prod_pvt = req_prod + i;
+@@ -668,7 +667,7 @@ static int network_start_xmit(struct sk_
+ dev_kfree_skb(skb);
+ skb = nskb;
+ }
+-
++
+ spin_lock_irq(&np->tx_lock);
+
+ if (np->backend_state != BEST_CONNECTED) {
+@@ -765,7 +764,7 @@ static int netif_poll(struct net_device
+ rp = np->rx.sring->rsp_prod;
+ rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+- for (i = np->rx.rsp_cons, work_done = 0;
++ for (i = np->rx.rsp_cons, work_done = 0;
+ (i != rp) && (work_done < budget);
+ i++, work_done++) {
+ rx = RING_GET_RESPONSE(&np->rx, i);
+@@ -807,7 +806,7 @@ static int netif_poll(struct net_device
+ skb->len = rx->status;
+ skb->tail = skb->data + skb->len;
+
+- if ( rx->flags & NETRXF_csum_valid )
++ if (rx->flags & NETRXF_csum_valid)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ np->stats.rx_packets++;
+@@ -862,7 +861,7 @@ static int netif_poll(struct net_device
+ * Enough room in skbuff for the data we were passed? Also,
+ * Linux expects at least 16 bytes headroom in each rx buffer.
+ */
+- if (unlikely(skb->tail > skb->end) ||
++ if (unlikely(skb->tail > skb->end) ||
+ unlikely((skb->data - skb->head) < 16)) {
+ if (net_ratelimit()) {
+ if (skb->tail > skb->end)
+@@ -894,7 +893,7 @@ static int netif_poll(struct net_device
+ if ((skb = nskb) == NULL)
+ continue;
+ }
+-
++
+ /* Set the shinfo area, which is hidden behind the data. */
+ init_skb_shinfo(skb);
+ /* Ethernet work: Delayed to here as it peeks the header. */
+@@ -995,9 +994,9 @@ static void network_connect(struct net_d
+
+ tx->id = i;
+ gnttab_grant_foreign_access_ref(
+- np->grant_tx_ref[i], np->xbdev->otherend_id,
++ np->grant_tx_ref[i], np->xbdev->otherend_id,
+ virt_to_mfn(np->tx_skbs[i]->data),
+- GNTMAP_readonly);
++ GNTMAP_readonly);
+ tx->gref = np->grant_tx_ref[i];
+ tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
+ tx->size = skb->len;
+@@ -1012,7 +1011,7 @@ static void network_connect(struct net_d
+ RING_PUSH_REQUESTS(&np->tx);
+
+ /* Rebuild the RX buffer freelist and the RX ring itself. */
+- for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) {
++ for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) {
+ if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET)
+ continue;
+ gnttab_grant_foreign_transfer_ref(
+@@ -1021,7 +1020,7 @@ static void network_connect(struct net_d
+ RING_GET_REQUEST(&np->rx, requeue_idx)->gref =
+ np->grant_rx_ref[i];
+ RING_GET_REQUEST(&np->rx, requeue_idx)->id = i;
+- requeue_idx++;
++ requeue_idx++;
+ }
+
+ np->rx.req_prod_pvt = requeue_idx;
+@@ -1055,9 +1054,8 @@ static void show_device(struct netfront_
+ np->evtchn,
+ np->tx,
+ np->rx);
+- } else {
++ } else
+ IPRINTK("<vif NULL>\n");
+- }
+ #endif
+ }
+
+@@ -1150,7 +1148,7 @@ static int create_netdev(int handle, str
+ SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &dev->dev);
+-
++
+ if ((err = register_netdev(netdev)) != 0) {
+ printk(KERN_WARNING "%s> register_netdev err=%d\n",
+ __FUNCTION__, err);
+@@ -1181,16 +1179,16 @@ static int create_netdev(int handle, str
+ * We use this notifier to send out a fake ARP reply to reset switches and
+ * router ARP caches when an IP interface is brought up on a VIF.
+ */
+-static int
++static int
+ inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr)
+ {
+- struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
++ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+ struct net_device *dev = ifa->ifa_dev->dev;
+
+ /* UP event and is it one of our devices? */
+ if (event == NETDEV_UP && dev->open == network_open)
+ (void)send_fake_arp(dev);
+-
++
+ return NOTIFY_DONE;
+ }
+
+@@ -1336,8 +1334,8 @@ module_exit(netif_exit);
+ module_exit(netif_exit);
+
+ MODULE_LICENSE("Dual BSD/GPL");
+-
+-
++
++
+ /* ** /proc **/
+
+
+@@ -1354,9 +1352,8 @@ static int xennet_proc_read(
+ (struct net_device *)((unsigned long)data & ~3UL);
+ struct netfront_info *np = netdev_priv(dev);
+ int len = 0, which_target = (long)data & 3;
+-
+- switch (which_target)
+- {
++
++ switch (which_target) {
+ case TARGET_MIN:
+ len = sprintf(page, "%d\n", np->rx_min_target);
+ break;
+@@ -1403,8 +1400,7 @@ static int xennet_proc_write(
+
+ spin_lock(&np->rx_lock);
+
+- switch (which_target)
+- {
++ switch (which_target) {
+ case TARGET_MIN:
+ if (target > np->rx_max_target)
+ np->rx_max_target = target;
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/tpmback/common.h
+--- a/drivers/xen/tpmback/common.h Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/tpmback/common.h Mon Mar 6 17:57:34 2006 +0000
+@@ -54,9 +54,11 @@ void tpmif_disconnect_complete(tpmif_t *
+ void tpmif_disconnect_complete(tpmif_t * tpmif);
+ tpmif_t *tpmif_find(domid_t domid, long int instance);
+ void tpmif_interface_init(void);
++void tpmif_interface_exit(void);
+ void tpmif_schedule_work(tpmif_t * tpmif);
+ void tpmif_deschedule_work(tpmif_t * tpmif);
+ void tpmif_xenbus_init(void);
++void tpmif_xenbus_exit(void);
+ int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+ irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+ int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance);
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/tpmback/interface.c
+--- a/drivers/xen/tpmback/interface.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/tpmback/interface.c Mon Mar 6 17:57:34 2006 +0000
+@@ -19,8 +19,7 @@ int num_frontends = 0;
+
+ LIST_HEAD(tpmif_list);
+
+-tpmif_t *
+-alloc_tpmif(domid_t domid, long int instance)
++static tpmif_t *alloc_tpmif(domid_t domid, long int instance)
+ {
+ struct page *page;
+ tpmif_t *tpmif;
+@@ -45,16 +44,14 @@ alloc_tpmif(domid_t domid, long int inst
+ return tpmif;
+ }
+
+-void
+-free_tpmif(tpmif_t * tpmif)
++static void free_tpmif(tpmif_t * tpmif)
+ {
+ num_frontends--;
+ list_del(&tpmif->tpmif_list);
+ kmem_cache_free(tpmif_cachep, tpmif);
+ }
+
+-tpmif_t *
+-tpmif_find(domid_t domid, long int instance)
++tpmif_t *tpmif_find(domid_t domid, long int instance)
+ {
+ tpmif_t *tpmif;
+
+@@ -72,8 +69,7 @@ tpmif_find(domid_t domid, long int insta
+ return alloc_tpmif(domid, instance);
+ }
+
+-static int
+-map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
++static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
+ {
+ int ret;
+ struct gnttab_map_grant_ref op = {
+@@ -99,8 +95,7 @@ map_frontend_page(tpmif_t *tpmif, unsign
+ return 0;
+ }
+
+-static void
+-unmap_frontend_page(tpmif_t *tpmif)
++static void unmap_frontend_page(tpmif_t *tpmif)
+ {
+ struct gnttab_unmap_grant_ref op;
+ int ret;
+@@ -115,14 +110,14 @@ unmap_frontend_page(tpmif_t *tpmif)
+ BUG_ON(ret);
+ }
+
+-int
+-tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
++int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
+ {
+ int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_interdomain,
+ .u.bind_interdomain.remote_dom = tpmif->domid,
+- .u.bind_interdomain.remote_port = evtchn };
++ .u.bind_interdomain.remote_port = evtchn,
++ };
+
+ if (tpmif->irq) {
+ return 0;
+@@ -156,8 +151,7 @@ tpmif_map(tpmif_t *tpmif, unsigned long
+ return 0;
+ }
+
+-static void
+-__tpmif_disconnect_complete(void *arg)
++static void __tpmif_disconnect_complete(void *arg)
+ {
+ tpmif_t *tpmif = (tpmif_t *) arg;
+
+@@ -172,18 +166,21 @@ __tpmif_disconnect_complete(void *arg)
+ free_tpmif(tpmif);
+ }
+
+-void
+-tpmif_disconnect_complete(tpmif_t * tpmif)
++void tpmif_disconnect_complete(tpmif_t * tpmif)
+ {
+ INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif);
+ schedule_work(&tpmif->work);
+ }
+
+-void __init
+-tpmif_interface_init(void)
++void __init tpmif_interface_init(void)
+ {
+ tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
+ 0, 0, NULL, NULL);
++}
++
++void __init tpmif_interface_exit(void)
++{
++ kmem_cache_destroy(tpmif_cachep);
+ }
+
+ /*
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/tpmback/tpmback.c
+--- a/drivers/xen/tpmback/tpmback.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/tpmback/tpmback.c Mon Mar 6 17:57:34 2006 +0000
+@@ -22,16 +22,22 @@
+ #include <xen/xenbus.h>
+ #include <xen/interface/grant_table.h>
+
+-
+ /* local data structures */
+ struct data_exchange {
+ struct list_head pending_pak;
+ struct list_head current_pak;
+ unsigned int copied_so_far;
+ u8 has_opener;
+- rwlock_t pak_lock; // protects all of the previous fields
++ rwlock_t pak_lock; // protects all of the previous fields
+ wait_queue_head_t wait_queue;
+ };
++
++struct vtpm_resp_hdr {
++ uint32_t instance_no;
++ uint16_t tag_no;
++ uint32_t len_no;
++ uint32_t ordinal_no;
++} __attribute__ ((packed));
+
+ struct packet {
+ struct list_head next;
+@@ -50,36 +56,30 @@ enum {
+ PACKET_FLAG_CHECK_RESPONSESTATUS = 2,
+ };
+
++/* local variables */
+ static struct data_exchange dataex;
+
+ /* local function prototypes */
++static int _packet_write(struct packet *pak,
++ const char *data, size_t size, int userbuffer);
++static void processing_timeout(unsigned long ptr);
++static int packet_read_shmem(struct packet *pak,
++ tpmif_t * tpmif,
++ u32 offset,
++ char *buffer, int isuserbuffer, u32 left);
+ static int vtpm_queue_packet(struct packet *pak);
+-static int _packet_write(struct packet *pak,
+- const char *data, size_t size,
+- int userbuffer);
+-static void processing_timeout(unsigned long ptr);
+-static int packet_read_shmem(struct packet *pak,
+- tpmif_t *tpmif,
+- u32 offset,
+- char *buffer,
+- int isuserbuffer,
+- u32 left);
+-
+
+ #define MIN(x,y) (x) < (y) ? (x) : (y)
+
+-
+ /***************************************************************
+- Buffer copying
++ Buffer copying fo user and kernel space buffes.
+ ***************************************************************/
+-static inline int
+-copy_from_buffer(void *to,
+- const void *from,
+- unsigned long size,
+- int userbuffer)
+-{
+- if (userbuffer) {
+- if (copy_from_user(to, from, size))
++static inline int copy_from_buffer(void *to,
++ const void *from, unsigned long size,
++ int isuserbuffer)
++{
++ if (isuserbuffer) {
++ if (copy_from_user(to, (void __user *)from, size))
+ return -EFAULT;
+ } else {
+ memcpy(to, from, size);
+@@ -87,21 +87,36 @@ copy_from_buffer(void *to,
+ return 0;
+ }
+
++static inline int copy_to_buffer(void *to,
++ const void *from, unsigned long size,
++ int isuserbuffer)
++{
++ if (isuserbuffer) {
++ if (copy_to_user((void __user *)to, from, size))
++ return -EFAULT;
++ } else {
++ memcpy(to, from, size);
++ }
++ return 0;
++}
++
+ /***************************************************************
+ Packet-related functions
+ ***************************************************************/
+
+-static struct packet *
+-packet_find_instance(struct list_head *head, u32 tpm_instance)
++static struct packet *packet_find_instance(struct list_head *head,
++ u32 tpm_instance)
+ {
+ struct packet *pak;
+ struct list_head *p;
++
+ /*
+ * traverse the list of packets and return the first
+ * one with the given instance number
+ */
+ list_for_each(p, head) {
+ pak = list_entry(p, struct packet, next);
++
+ if (pak->tpm_instance == tpm_instance) {
+ return pak;
+ }
+@@ -109,17 +124,18 @@ packet_find_instance(struct list_head *h
+ return NULL;
+ }
+
+-static struct packet *
+-packet_find_packet(struct list_head *head, void *packet)
++static struct packet *packet_find_packet(struct list_head *head, void *packet)
+ {
+ struct packet *pak;
+ struct list_head *p;
++
+ /*
+ * traverse the list of packets and return the first
+ * one with the given instance number
+ */
+ list_for_each(p, head) {
+ pak = list_entry(p, struct packet, next);
++
+ if (pak == packet) {
+ return pak;
+ }
+@@ -127,22 +143,20 @@ packet_find_packet(struct list_head *hea
+ return NULL;
+ }
+
+-static struct packet *
+-packet_alloc(tpmif_t *tpmif, u32 size, u8 req_tag, u8 flags)
++static struct packet *packet_alloc(tpmif_t * tpmif,
++ u32 size, u8 req_tag, u8 flags)
+ {
+ struct packet *pak = NULL;
+- pak = kmalloc(sizeof(struct packet),
+- GFP_KERNEL);
++ pak = kzalloc(sizeof (struct packet), GFP_KERNEL);
+ if (NULL != pak) {
+- memset(pak, 0x0, sizeof(*pak));
+ if (tpmif) {
+ pak->tpmif = tpmif;
+ pak->tpm_instance = tpmif->tpm_instance;
+ }
+- pak->data_len = size;
+- pak->req_tag = req_tag;
++ pak->data_len = size;
++ pak->req_tag = req_tag;
+ pak->last_read = 0;
+- pak->flags = flags;
++ pak->flags = flags;
+
+ /*
+ * cannot do tpmif_get(tpmif); bad things happen
+@@ -155,16 +169,16 @@ packet_alloc(tpmif_t *tpmif, u32 size, u
+ return pak;
+ }
+
+-static void inline
+-packet_reset(struct packet *pak)
++static void inline packet_reset(struct packet *pak)
+ {
+ pak->last_read = 0;
+ }
+
+-static void inline
+-packet_free(struct packet *pak)
+-{
+- del_singleshot_timer_sync(&pak->processing_timer);
++static void packet_free(struct packet *pak)
++{
++ if (timer_pending(&pak->processing_timer)) {
++ BUG();
++ }
+ kfree(pak->data_buffer);
+ /*
+ * cannot do tpmif_put(pak->tpmif); bad things happen
+@@ -173,13 +187,13 @@ packet_free(struct packet *pak)
+ kfree(pak);
+ }
+
+-static int
+-packet_set(struct packet *pak,
+- const unsigned char *buffer, u32 size)
++static int packet_set(struct packet *pak,
++ const unsigned char *buffer, u32 size)
+ {
+ int rc = 0;
+ unsigned char *buf = kmalloc(size, GFP_KERNEL);
+- if (NULL != buf) {
++
++ if (buf) {
+ pak->data_buffer = buf;
+ memcpy(buf, buffer, size);
+ pak->data_len = size;
+@@ -189,27 +203,21 @@ packet_set(struct packet *pak,
+ return rc;
+ }
+
+-
+ /*
+ * Write data to the shared memory and send it to the FE.
+ */
+-static int
+-packet_write(struct packet *pak,
+- const char *data, size_t size,
+- int userbuffer)
++static int packet_write(struct packet *pak,
++ const char *data, size_t size, int isuserbuffer)
+ {
+ int rc = 0;
+
+- DPRINTK("Supposed to send %d bytes to front-end!\n",
+- size);
+-
+- if (0 != (pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) {
++ if ((pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) {
+ #ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+ u32 res;
++
+ if (copy_from_buffer(&res,
+- &data[2+4],
+- sizeof(res),
+- userbuffer)) {
++ &data[2 + 4], sizeof (res),
++ isuserbuffer)) {
+ return -EFAULT;
+ }
+
+@@ -230,17 +238,14 @@ packet_write(struct packet *pak,
+ /* Don't send a respone to this packet. Just acknowledge it. */
+ rc = size;
+ } else {
+- rc = _packet_write(pak, data, size, userbuffer);
++ rc = _packet_write(pak, data, size, isuserbuffer);
+ }
+
+ return rc;
+ }
+
+-
+-static int
+-_packet_write(struct packet *pak,
+- const char *data, size_t size,
+- int userbuffer)
++int _packet_write(struct packet *pak,
++ const char *data, size_t size, int isuserbuffer)
+ {
+ /*
+ * Write into the shared memory pages directly
+@@ -254,7 +259,7 @@ _packet_write(struct packet *pak,
+
+ if (tpmif == NULL) {
+ return -EFAULT;
+- }
++ }
+
+ if (tpmif->status == DISCONNECTED) {
+ return size;
+@@ -273,16 +278,13 @@ _packet_write(struct packet *pak,
+ return 0;
+ }
+
+- map_op.host_addr = MMAP_VADDR(tpmif, i);
+- map_op.flags = GNTMAP_host_map;
+- map_op.ref = tx->ref;
+- map_op.dom = tpmif->domid;
+-
+- if(unlikely(
+- HYPERVISOR_grant_table_op(
+- GNTTABOP_map_grant_ref,
+- &map_op,
+- 1))) {
++ map_op.host_addr = MMAP_VADDR(tpmif, i);
++ map_op.flags = GNTMAP_host_map;
++ map_op.ref = tx->ref;
++ map_op.dom = tpmif->domid;
++
++ if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++ &map_op, 1))) {
+ BUG();
+ }
+
+@@ -292,28 +294,27 @@ _packet_write(struct packet *pak,
+ DPRINTK(" Grant table operation failure !\n");
+ return 0;
+ }
+- set_phys_to_machine(__pa(MMAP_VADDR(tpmif,i)) >> PAGE_SHIFT,
+- FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT));
++ set_phys_to_machine(__pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT,
++ FOREIGN_FRAME(map_op.
++ dev_bus_addr >> PAGE_SHIFT));
+
+ tocopy = MIN(size - offset, PAGE_SIZE);
+
+- if (copy_from_buffer((void *)(MMAP_VADDR(tpmif,i)|
+- (tx->addr & ~PAGE_MASK)),
+- &data[offset],
+- tocopy,
+- userbuffer)) {
++ if (copy_from_buffer((void *)(MMAP_VADDR(tpmif, i) |
++ (tx->addr & ~PAGE_MASK)),
++ &data[offset], tocopy, isuserbuffer)) {
+ tpmif_put(tpmif);
+ return -EFAULT;
+ }
+ tx->size = tocopy;
+
+- unmap_op.host_addr = MMAP_VADDR(tpmif, i);
+- unmap_op.handle = handle;
++ unmap_op.host_addr = MMAP_VADDR(tpmif, i);
++ unmap_op.handle = handle;
+ unmap_op.dev_bus_addr = 0;
+
+- if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+- &unmap_op,
+- 1))) {
++ if (unlikely
++ (HYPERVISOR_grant_table_op
++ (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) {
+ BUG();
+ }
+
+@@ -322,8 +323,7 @@ _packet_write(struct packet *pak,
+ }
+
+ rc = offset;
+- DPRINTK("Notifying frontend via irq %d\n",
+- tpmif->irq);
++ DPRINTK("Notifying frontend via irq %d\n", tpmif->irq);
+ notify_remote_via_irq(tpmif->irq);
+
+ return rc;
+@@ -334,26 +334,19 @@ _packet_write(struct packet *pak,
+ * provided buffer. Advance the read_last indicator which tells
+ * how many bytes have already been read.
+ */
+-static int
+-packet_read(struct packet *pak, size_t numbytes,
+- char *buffer, size_t buffersize,
+- int userbuffer)
++static int packet_read(struct packet *pak, size_t numbytes,
++ char *buffer, size_t buffersize, int isuserbuffer)
+ {
+ tpmif_t *tpmif = pak->tpmif;
+- /*
+- * I am supposed to read 'numbytes' of data from the
+- * buffer.
+- * The first 4 bytes that are read are the instance number in
+- * network byte order, after that comes the data from the
+- * shared memory buffer.
++
++ /*
++ * Read 'numbytes' of data from the buffer. The first 4
++ * bytes are the instance number in network byte order,
++ * after that come the data from the shared memory buffer.
+ */
+ u32 to_copy;
+ u32 offset = 0;
+ u32 room_left = buffersize;
+- /*
+- * Ensure that we see the request when we copy it.
+- */
+- mb();
+
+ if (pak->last_read < 4) {
+ /*
+@@ -361,18 +354,13 @@ packet_read(struct packet *pak, size_t n
+ */
+ u32 instance_no = htonl(pak->tpm_instance);
+ u32 last_read = pak->last_read;
++
+ to_copy = MIN(4 - last_read, numbytes);
+
+- if (userbuffer) {
+- if (copy_to_user(&buffer[0],
+- &(((u8 *)&instance_no)[last_read]),
+- to_copy)) {
+- return -EFAULT;
+- }
+- } else {
+- memcpy(&buffer[0],
+- &(((u8 *)&instance_no)[last_read]),
+- to_copy);
++ if (copy_to_buffer(&buffer[0],
++ &(((u8 *) & instance_no)[last_read]),
++ to_copy, isuserbuffer)) {
++ return -EFAULT;
+ }
+
+ pak->last_read += to_copy;
+@@ -388,39 +376,30 @@ packet_read(struct packet *pak, size_t n
+ if (pak->data_buffer) {
+ u32 to_copy = MIN(pak->data_len - offset, room_left);
+ u32 last_read = pak->last_read - 4;
+- if (userbuffer) {
+- if (copy_to_user(&buffer[offset],
+- &pak->data_buffer[last_read],
+- to_copy)) {
+- return -EFAULT;
+- }
+- } else {
+- memcpy(&buffer[offset],
+- &pak->data_buffer[last_read],
+- to_copy);
++
++ if (copy_to_buffer(&buffer[offset],
++ &pak->data_buffer[last_read],
++ to_copy, isuserbuffer)) {
++ return -EFAULT;
+ }
+ pak->last_read += to_copy;
+ offset += to_copy;
+ } else {
+ offset = packet_read_shmem(pak,
+- tpmif,
+- offset,
+- buffer,
+- userbuffer,
+- room_left);
++ tpmif,
++ offset,
++ buffer,
++ isuserbuffer, room_left);
+ }
+ }
+ return offset;
+ }
+
+-
+-static int
+-packet_read_shmem(struct packet *pak,
+- tpmif_t *tpmif,
+- u32 offset,
+- char *buffer,
+- int isuserbuffer,
+- u32 room_left) {
++static int packet_read_shmem(struct packet *pak,
++ tpmif_t * tpmif,
++ u32 offset, char *buffer, int isuserbuffer,
++ u32 room_left)
++{
+ u32 last_read = pak->last_read - 4;
+ u32 i = (last_read / PAGE_SIZE);
+ u32 pg_offset = last_read & (PAGE_SIZE - 1);
+@@ -428,6 +407,7 @@ packet_read_shmem(struct packet *pak,
+ grant_handle_t handle;
+
+ tpmif_tx_request_t *tx;
++
+ tx = &tpmif->tx->ring[0].req;
+ /*
+ * Start copying data at the page with index 'index'
+@@ -443,13 +423,12 @@ packet_read_shmem(struct packet *pak,
+ tx = &tpmif->tx->ring[i].req;
+
+ map_op.host_addr = MMAP_VADDR(tpmif, i);
+- map_op.flags = GNTMAP_host_map;
+- map_op.ref = tx->ref;
+- map_op.dom = tpmif->domid;
+-
+- if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+- &map_op,
+- 1))) {
++ map_op.flags = GNTMAP_host_map;
++ map_op.ref = tx->ref;
++ map_op.dom = tpmif->domid;
++
++ if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++ &map_op, 1))) {
+ BUG();
+ }
+
+@@ -462,41 +441,33 @@ packet_read_shmem(struct packet *pak,
+
+ if (to_copy > tx->size) {
+ /*
+- * This is the case when the user wants to read more
+- * than what we have. So we just give him what we
+- * have.
++ * User requests more than what's available
+ */
+ to_copy = MIN(tx->size, to_copy);
+ }
+
+ DPRINTK("Copying from mapped memory at %08lx\n",
+- (unsigned long)(MMAP_VADDR(tpmif,i) |
+- (tx->addr & ~PAGE_MASK)));
+-
+- src = (void *)(MMAP_VADDR(tpmif,i) | ((tx->addr & ~PAGE_MASK) + pg_offset));
+- if (isuserbuffer) {
+- if (copy_to_user(&buffer[offset],
+- src,
+- to_copy)) {
+- return -EFAULT;
+- }
+- } else {
+- memcpy(&buffer[offset],
+- src,
+- to_copy);
+- }
+-
++ (unsigned long)(MMAP_VADDR(tpmif, i) |
++ (tx->addr & ~PAGE_MASK)));
++
++ src = (void *)(MMAP_VADDR(tpmif, i) |
++ ((tx->addr & ~PAGE_MASK) + pg_offset));
++ if (copy_to_buffer(&buffer[offset],
++ src, to_copy, isuserbuffer)) {
++ return -EFAULT;
++ }
+
+ DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n",
+- tpmif->domid, buffer[offset], buffer[offset+1],buffer[offset+2],buffer[offset+3]);
+-
+- unmap_op.host_addr = MMAP_VADDR(tpmif, i);
+- unmap_op.handle = handle;
++ tpmif->domid, buffer[offset], buffer[offset + 1],
++ buffer[offset + 2], buffer[offset + 3]);
++
++ unmap_op.host_addr = MMAP_VADDR(tpmif, i);
++ unmap_op.handle = handle;
+ unmap_op.dev_bus_addr = 0;
+
+- if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+- &unmap_op,
+- 1))) {
++ if (unlikely
++ (HYPERVISOR_grant_table_op
++ (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) {
+ BUG();
+ }
+
+@@ -507,21 +478,19 @@ packet_read_shmem(struct packet *pak,
+
+ to_copy = MIN(PAGE_SIZE, room_left);
+ i++;
+- } /* while (to_copy > 0) */
++ } /* while (to_copy > 0) */
+ /*
+ * Adjust the last_read pointer
+ */
+ pak->last_read = last_read + 4;
+ return offset;
+ }
+-
+
+ /* ============================================================
+ * The file layer for reading data from this device
+ * ============================================================
+ */
+-static int
+-vtpm_op_open(struct inode *inode, struct file *f)
++static int vtpm_op_open(struct inode *inode, struct file *f)
+ {
+ int rc = 0;
+ unsigned long flags;
+@@ -536,9 +505,8 @@ vtpm_op_open(struct inode *inode, struct
+ return rc;
+ }
+
+-static ssize_t
+-vtpm_op_read(struct file *file,
+- char __user * data, size_t size, loff_t * offset)
++static ssize_t vtpm_op_read(struct file *file,
++ char __user * data, size_t size, loff_t * offset)
+ {
+ int ret_size = -ENODATA;
+ struct packet *pak = NULL;
+@@ -549,7 +517,7 @@ vtpm_op_read(struct file *file,
+ if (list_empty(&dataex.pending_pak)) {
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ wait_event_interruptible(dataex.wait_queue,
+- !list_empty(&dataex.pending_pak));
++ !list_empty(&dataex.pending_pak));
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ }
+
+@@ -561,7 +529,7 @@ vtpm_op_read(struct file *file,
+
+ DPRINTK("size given by app: %d, available: %d\n", size, left);
+
+- ret_size = MIN(size,left);
++ ret_size = MIN(size, left);
+
+ ret_size = packet_read(pak, ret_size, data, size, 1);
+ if (ret_size < 0) {
+@@ -574,7 +542,8 @@ vtpm_op_read(struct file *file,
+ DPRINTK("All data from this packet given to app.\n");
+ /* All data given to app */
+
+- del_singleshot_timer_sync(&pak->processing_timer);
++ del_singleshot_timer_sync(&pak->
++ processing_timer);
+ list_del(&pak->next);
+ list_add_tail(&pak->next, &dataex.current_pak);
+ /*
+@@ -582,7 +551,7 @@ vtpm_op_read(struct file *file,
+ * the more time we give the TPM to process the request.
+ */
+ mod_timer(&pak->processing_timer,
+- jiffies + (num_frontends * 60 * HZ));
++ jiffies + (num_frontends * 60 * HZ));
+ dataex.copied_so_far = 0;
+ }
+ }
+@@ -597,16 +566,15 @@ vtpm_op_read(struct file *file,
+ /*
+ * Write operation - only works after a previous read operation!
+ */
+-static ssize_t
+-vtpm_op_write(struct file *file, const char __user * data, size_t size,
+- loff_t * offset)
++static ssize_t vtpm_op_write(struct file *file,
++ const char __user * data, size_t size,
++ loff_t * offset)
+ {
+ struct packet *pak;
+ int rc = 0;
+ unsigned int off = 4;
+ unsigned long flags;
+- u32 instance_no = 0;
+- u32 len_no = 0;
++ struct vtpm_resp_hdr vrh;
+
+ /*
+ * Minimum required packet size is:
+@@ -616,45 +584,38 @@ vtpm_op_write(struct file *file, const c
+ * 4 bytes for the ordinal
+ * sum: 14 bytes
+ */
+- if ( size < off + 10 ) {
++ if (size < sizeof (vrh))
+ return -EFAULT;
+- }
+-
+- if (copy_from_user(&instance_no,
+- (void __user *)&data[0],
+- 4)) {
++
++ if (copy_from_user(&vrh, data, sizeof (vrh)))
+ return -EFAULT;
+- }
+-
+- if (copy_from_user(&len_no,
+- (void __user *)&data[off+2],
+- 4) ||
+- (off + ntohl(len_no) != size)) {
++
++ /* malformed packet? */
++ if ((off + ntohl(vrh.len_no)) != size)
+ return -EFAULT;
+- }
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+- pak = packet_find_instance(&dataex.current_pak, ntohl(instance_no));
++ pak = packet_find_instance(&dataex.current_pak,
++ ntohl(vrh.instance_no));
+
+ if (pak == NULL) {
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+- printk(KERN_ALERT "No associated packet!\n");
++ printk(KERN_ALERT "No associated packet! (inst=%d)\n",
++ ntohl(vrh.instance_no));
+ return -EFAULT;
+- } else {
+- del_singleshot_timer_sync(&pak->processing_timer);
+- list_del(&pak->next);
+- }
++ }
++
++ del_singleshot_timer_sync(&pak->processing_timer);
++ list_del(&pak->next);
+
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+ /*
+- * The first 'offset' bytes must be the instance number.
+- * I will just pull that from the packet.
++ * The first 'offset' bytes must be the instance number - skip them.
+ */
+ size -= off;
+- data = &data[off];
+-
+- rc = packet_write(pak, data, size, 1);
++
++ rc = packet_write(pak, &data[off], size, 1);
+
+ if (rc > 0) {
+ /* I neglected the first 4 bytes */
+@@ -664,10 +625,10 @@ vtpm_op_write(struct file *file, const c
+ return rc;
+ }
+
+-static int
+-vtpm_op_release(struct inode *inode, struct file *file)
++static int vtpm_op_release(struct inode *inode, struct file *file)
+ {
+ unsigned long flags;
++
+ vtpm_release_packets(NULL, 1);
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ dataex.has_opener = 0;
+@@ -675,10 +636,11 @@ vtpm_op_release(struct inode *inode, str
+ return 0;
+ }
+
+-static unsigned int
+-vtpm_op_poll(struct file *file, struct poll_table_struct *pts)
++static unsigned int vtpm_op_poll(struct file *file,
++ struct poll_table_struct *pts)
+ {
+ unsigned int flags = POLLOUT | POLLWRNORM;
++
+ poll_wait(file, &dataex.wait_queue, pts);
+ if (!list_empty(&dataex.pending_pak)) {
+ flags |= POLLIN | POLLRDNORM;
+@@ -696,54 +658,47 @@ static struct file_operations vtpm_ops =
+ .poll = vtpm_op_poll,
+ };
+
+-static struct miscdevice ibmvtpms_miscdevice = {
++static struct miscdevice vtpms_miscdevice = {
+ .minor = 225,
+ .name = "vtpm",
+ .fops = &vtpm_ops,
+ };
+
+-
+ /***************************************************************
+ Virtual TPM functions and data stuctures
+ ***************************************************************/
+
+ static u8 create_cmd[] = {
+- 1,193, /* 0: TPM_TAG_RQU_COMMAMD */
+- 0,0,0,19, /* 2: length */
+- 0,0,0,0x1, /* 6: VTPM_ORD_OPEN */
+- 0, /* 10: VTPM type */
+- 0,0,0,0, /* 11: domain id */
+- 0,0,0,0 /* 15: instance id */
++ 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */
++ 0, 0, 0, 19, /* 2: length */
++ 0, 0, 0, 0x1, /* 6: VTPM_ORD_OPEN */
++ 0, /* 10: VTPM type */
++ 0, 0, 0, 0, /* 11: domain id */
++ 0, 0, 0, 0 /* 15: instance id */
+ };
+
+-static u8 destroy_cmd[] = {
+- 1,193, /* 0: TPM_TAG_RQU_COMMAMD */
+- 0,0,0,14, /* 2: length */
+- 0,0,0,0x2, /* 6: VTPM_ORD_CLOSE */
+- 0,0,0,0 /* 10: instance id */
+-};
+-
+-int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domid, u32 instance)
++int tpmif_vtpm_open(tpmif_t * tpmif, domid_t domid, u32 instance)
+ {
+ int rc = 0;
+ struct packet *pak;
+
+ pak = packet_alloc(tpmif,
+- sizeof(create_cmd),
+- create_cmd[0],
+- PACKET_FLAG_DISCARD_RESPONSE|
+- PACKET_FLAG_CHECK_RESPONSESTATUS);
++ sizeof (create_cmd),
++ create_cmd[1],
++ PACKET_FLAG_DISCARD_RESPONSE |
++ PACKET_FLAG_CHECK_RESPONSESTATUS);
+ if (pak) {
+- u8 buf[sizeof(create_cmd)];
+- u32 domid_no = htonl((u32)domid);
++ u8 buf[sizeof (create_cmd)];
++ u32 domid_no = htonl((u32) domid);
+ u32 instance_no = htonl(instance);
+- memcpy(buf, create_cmd, sizeof(create_cmd));
+-
+- memcpy(&buf[11], &domid_no, sizeof(u32));
+- memcpy(&buf[15], &instance_no, sizeof(u32));
++
++ memcpy(buf, create_cmd, sizeof (create_cmd));
++
++ memcpy(&buf[11], &domid_no, sizeof (u32));
++ memcpy(&buf[15], &instance_no, sizeof (u32));
+
+ /* copy the buffer into the packet */
+- rc = packet_set(pak, buf, sizeof(buf));
++ rc = packet_set(pak, buf, sizeof (buf));
+
+ if (rc == 0) {
+ pak->tpm_instance = 0;
+@@ -759,23 +714,30 @@ int tpmif_vtpm_open(tpmif_t *tpmif, domi
+ return rc;
+ }
+
++static u8 destroy_cmd[] = {
++ 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */
++ 0, 0, 0, 14, /* 2: length */
++ 0, 0, 0, 0x2, /* 6: VTPM_ORD_CLOSE */
++ 0, 0, 0, 0 /* 10: instance id */
++};
++
+ int tpmif_vtpm_close(u32 instid)
+ {
+ int rc = 0;
+ struct packet *pak;
+
+ pak = packet_alloc(NULL,
+- sizeof(create_cmd),
+- create_cmd[0],
+- PACKET_FLAG_DISCARD_RESPONSE);
++ sizeof (destroy_cmd),
++ destroy_cmd[1], PACKET_FLAG_DISCARD_RESPONSE);
+ if (pak) {
+- u8 buf[sizeof(destroy_cmd)];
++ u8 buf[sizeof (destroy_cmd)];
+ u32 instid_no = htonl(instid);
+- memcpy(buf, destroy_cmd, sizeof(destroy_cmd));
+- memcpy(&buf[10], &instid_no, sizeof(u32));
++
++ memcpy(buf, destroy_cmd, sizeof (destroy_cmd));
++ memcpy(&buf[10], &instid_no, sizeof (u32));
+
+ /* copy the buffer into the packet */
+- rc = packet_set(pak, buf, sizeof(buf));
++ rc = packet_set(pak, buf, sizeof (buf));
+
+ if (rc == 0) {
+ pak->tpm_instance = 0;
+@@ -791,23 +753,22 @@ int tpmif_vtpm_close(u32 instid)
+ return rc;
+ }
+
+-
+ /***************************************************************
+ Utility functions
+ ***************************************************************/
+
+-static int
+-tpm_send_fail_message(struct packet *pak, u8 req_tag)
++static int tpm_send_fail_message(struct packet *pak, u8 req_tag)
+ {
+ int rc;
+ static const unsigned char tpm_error_message_fail[] = {
+ 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a,
+- 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */
++ 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */
+ };
+- unsigned char buffer[sizeof(tpm_error_message_fail)];
+-
+- memcpy(buffer, tpm_error_message_fail, sizeof(tpm_error_message_fail));
++ unsigned char buffer[sizeof (tpm_error_message_fail)];
++
++ memcpy(buffer, tpm_error_message_fail,
++ sizeof (tpm_error_message_fail));
+ /*
+ * Insert the right response tag depending on the given tag
+ * All response tags are '+3' to the request tag.
+@@ -817,23 +778,24 @@ tpm_send_fail_message(struct packet *pak
+ /*
+ * Write the data to shared memory and notify the front-end
+ */
+- rc = packet_write(pak, buffer, sizeof(buffer), 0);
++ rc = packet_write(pak, buffer, sizeof (buffer), 0);
+
+ return rc;
+ }
+
+-
+-static void
+-_vtpm_release_packets(struct list_head *head, tpmif_t *tpmif,
+- int send_msgs)
++static void _vtpm_release_packets(struct list_head *head,
++ tpmif_t * tpmif, int send_msgs)
+ {
+ struct packet *pak;
+- struct list_head *pos, *tmp;
++ struct list_head *pos,
++ *tmp;
+
+ list_for_each_safe(pos, tmp, head) {
+ pak = list_entry(pos, struct packet, next);
++
+ if (tpmif == NULL || pak->tpmif == tpmif) {
+ int can_send = 0;
++
+ del_singleshot_timer_sync(&pak->processing_timer);
+ list_del(&pak->next);
+
+@@ -849,9 +811,7 @@ _vtpm_release_packets(struct list_head *
+ }
+ }
+
+-
+-int
+-vtpm_release_packets(tpmif_t *tpmif, int send_msgs)
++int vtpm_release_packets(tpmif_t * tpmif, int send_msgs)
+ {
+ unsigned long flags;
+
+@@ -860,23 +820,22 @@ vtpm_release_packets(tpmif_t *tpmif, int
+ _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs);
+ _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs);
+
+- write_unlock_irqrestore(&dataex.pak_lock,
+- flags);
++ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ return 0;
+ }
+
+-
+ static int vtpm_queue_packet(struct packet *pak)
+ {
+ int rc = 0;
++
+ if (dataex.has_opener) {
+ unsigned long flags;
++
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ list_add_tail(&pak->next, &dataex.pending_pak);
+ /* give the TPM some time to pick up the request */
+ mod_timer(&pak->processing_timer, jiffies + (30 * HZ));
+- write_unlock_irqrestore(&dataex.pak_lock,
+- flags);
++ write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+ wake_up_interruptible(&dataex.wait_queue);
+ } else {
+@@ -885,24 +844,22 @@ static int vtpm_queue_packet(struct pack
+ return rc;
+ }
+
+-
+-static int vtpm_receive(tpmif_t *tpmif, u32 size)
++static int vtpm_receive(tpmif_t * tpmif, u32 size)
+ {
+ int rc = 0;
+ unsigned char buffer[10];
+ __be32 *native_size;
+-
+- struct packet *pak = packet_alloc(tpmif, size, buffer[4], 0);
+- if (NULL == pak) {
++ struct packet *pak = packet_alloc(tpmif, size, 0, 0);
++
++ if (!pak)
+ return -ENOMEM;
+- }
+ /*
+ * Read 10 bytes from the received buffer to test its
+ * content for validity.
+ */
+- if (sizeof(buffer) != packet_read(pak,
+- sizeof(buffer), buffer,
+- sizeof(buffer), 0)) {
++ if (sizeof (buffer) != packet_read(pak,
++ sizeof (buffer), buffer,
++ sizeof (buffer), 0)) {
+ goto failexit;
+ }
+ /*
+@@ -911,7 +868,7 @@ static int vtpm_receive(tpmif_t *tpmif,
+ */
+ packet_reset(pak);
+
+- native_size = (__force __be32 *)(&buffer[4+2]);
++ native_size = (__force __be32 *) (&buffer[4 + 2]);
+ /*
+ * Verify that the size of the packet is correct
+ * as indicated and that there's actually someone reading packets.
+@@ -920,25 +877,23 @@ static int vtpm_receive(tpmif_t *tpmif,
+ */
+ if (size < 10 ||
+ be32_to_cpu(*native_size) != size ||
+- 0 == dataex.has_opener ||
+- tpmif->status != CONNECTED) {
+- rc = -EINVAL;
+- goto failexit;
++ 0 == dataex.has_opener || tpmif->status != CONNECTED) {
++ rc = -EINVAL;
++ goto failexit;
+ } else {
+- if ((rc = vtpm_queue_packet(pak)) < 0) {
++ rc = vtpm_queue_packet(pak);
++ if (rc < 0)
+ goto failexit;
+- }
+ }
+ return 0;
+
+-failexit:
++ failexit:
+ if (pak) {
+- tpm_send_fail_message(pak, buffer[4+1]);
++ tpm_send_fail_message(pak, buffer[4 + 1]);
+ packet_free(pak);
+ }
+ return rc;
+ }
+-
+
+ /*
+ * Timeout function that gets invoked when a packet has not been processed
+@@ -951,22 +906,23 @@ static void processing_timeout(unsigned
+ {
+ struct packet *pak = (struct packet *)ptr;
+ unsigned long flags;
++
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ /*
+ * The packet needs to be searched whether it
+ * is still on the list.
+ */
+ if (pak == packet_find_packet(&dataex.pending_pak, pak) ||
+- pak == packet_find_packet(&dataex.current_pak, pak) ) {
++ pak == packet_find_packet(&dataex.current_pak, pak)) {
+ list_del(&pak->next);
+- tpm_send_fail_message(pak, pak->req_tag);
++ if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) {
++ tpm_send_fail_message(pak, pak->req_tag);
++ }
+ packet_free(pak);
+ }
+
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ }
+-
+-
+
+ static void tpm_tx_action(unsigned long unused);
+ static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0);
+@@ -974,21 +930,18 @@ static struct list_head tpm_schedule_lis
+ static struct list_head tpm_schedule_list;
+ static spinlock_t tpm_schedule_list_lock;
+
+-static inline void
+-maybe_schedule_tx_action(void)
++static inline void maybe_schedule_tx_action(void)
+ {
+ smp_mb();
+ tasklet_schedule(&tpm_tx_tasklet);
+ }
+
+-static inline int
+-__on_tpm_schedule_list(tpmif_t * tpmif)
++static inline int __on_tpm_schedule_list(tpmif_t * tpmif)
+ {
+ return tpmif->list.next != NULL;
+ }
+
+-static void
+-remove_from_tpm_schedule_list(tpmif_t * tpmif)
++static void remove_from_tpm_schedule_list(tpmif_t * tpmif)
+ {
+ spin_lock_irq(&tpm_schedule_list_lock);
+ if (likely(__on_tpm_schedule_list(tpmif))) {
+@@ -999,8 +952,7 @@ remove_from_tpm_schedule_list(tpmif_t *
+ spin_unlock_irq(&tpm_schedule_list_lock);
+ }
+
+-static void
+-add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
++static void add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
+ {
+ if (__on_tpm_schedule_list(tpmif))
+ return;
+@@ -1013,22 +965,18 @@ add_to_tpm_schedule_list_tail(tpmif_t *
+ spin_unlock_irq(&tpm_schedule_list_lock);
+ }
+
+-void
+-tpmif_schedule_work(tpmif_t * tpmif)
++void tpmif_schedule_work(tpmif_t * tpmif)
+ {
+ add_to_tpm_schedule_list_tail(tpmif);
+ maybe_schedule_tx_action();
+ }
+
+-void
+-tpmif_deschedule_work(tpmif_t * tpmif)
++void tpmif_deschedule_work(tpmif_t * tpmif)
+ {
+ remove_from_tpm_schedule_list(tpmif);
+ }
+
+-
+-static void
+-tpm_tx_action(unsigned long unused)
++static void tpm_tx_action(unsigned long unused)
+ {
+ struct list_head *ent;
+ tpmif_t *tpmif;
+@@ -1042,10 +990,6 @@ tpm_tx_action(unsigned long unused)
+ tpmif = list_entry(ent, tpmif_t, list);
+ tpmif_get(tpmif);
+ remove_from_tpm_schedule_list(tpmif);
+- /*
+- * Ensure that we see the request when we read from it.
+- */
+- mb();
+
+ tx = &tpmif->tx->ring[0].req;
+
+@@ -1056,22 +1000,22 @@ tpm_tx_action(unsigned long unused)
+ }
+ }
+
+-irqreturn_t
+-tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+-{
+- tpmif_t *tpmif = dev_id;
++irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++ tpmif_t *tpmif = (tpmif_t *) dev_id;
++
+ add_to_tpm_schedule_list_tail(tpmif);
+ maybe_schedule_tx_action();
+ return IRQ_HANDLED;
+ }
+
+-static int __init
+-tpmback_init(void)
++static int __init tpmback_init(void)
+ {
+ int rc;
+
+- if ((rc = misc_register(&ibmvtpms_miscdevice)) != 0) {
+- printk(KERN_ALERT "Could not register misc device for TPM BE.\n");
++ if ((rc = misc_register(&vtpms_miscdevice)) != 0) {
++ printk(KERN_ALERT
++ "Could not register misc device for TPM BE.\n");
+ return rc;
+ }
+
+@@ -1092,7 +1036,18 @@ tpmback_init(void)
+ return 0;
+ }
+
+-__initcall(tpmback_init);
++module_init(tpmback_init);
++
++static void __exit tpmback_exit(void)
++{
++ tpmif_xenbus_exit();
++ tpmif_interface_exit();
++ misc_deregister(&vtpms_miscdevice);
++}
++
++module_exit(tpmback_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/tpmback/xenbus.c
+--- a/drivers/xen/tpmback/xenbus.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/tpmback/xenbus.c Mon Mar 6 17:57:34 2006 +0000
+@@ -317,6 +317,11 @@ void tpmif_xenbus_init(void)
+ xenbus_register_backend(&tpmback);
+ }
+
++void tpmif_xenbus_exit(void)
++{
++ xenbus_unregister_driver(&tpmback);
++}
++
+ /*
+ * Local variables:
+ * c-file-style: "linux"
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/tpmfront/tpmfront.c
+--- a/drivers/xen/tpmfront/tpmfront.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/tpmfront/tpmfront.c Mon Mar 6 17:57:34 2006 +0000
+@@ -480,6 +480,11 @@ static void __init init_tpm_xenbus(void)
+ xenbus_register_frontend(&tpmfront);
+ }
+
++static void __exit exit_tpm_xenbus(void)
++{
++ xenbus_unregister_driver(&tpmfront);
++}
++
+
+ static int
+ tpm_allocate_buffers(struct tpm_private *tp)
+@@ -597,7 +602,6 @@ tpm_xmit(struct tpm_private *tp,
+
+ tx = &tp->tx->ring[i].req;
+
+- tx->id = i;
+ tx->addr = virt_to_machine(txb->data);
+ tx->size = txb->len;
+
+@@ -700,7 +704,18 @@ tpmif_init(void)
+ return 0;
+ }
+
+-__initcall(tpmif_init);
++module_init(tpmif_init);
++
++static void __exit
++tpmif_exit(void)
++{
++ exit_tpm_xenbus();
++ gnttab_free_grant_references(gref_head);
++}
++
++module_exit(tpmif_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/xenbus/Makefile
+--- a/drivers/xen/xenbus/Makefile Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/xenbus/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -1,8 +1,8 @@ obj-y += xenbus.o
+ obj-y += xenbus.o
+
+ xenbus-objs =
+-xenbus-objs += xenbus_client.o
++xenbus-objs += xenbus_client.o
+ xenbus-objs += xenbus_comms.o
+ xenbus-objs += xenbus_xs.o
+-xenbus-objs += xenbus_probe.o
+-xenbus-objs += xenbus_dev.o
++xenbus-objs += xenbus_probe.o
++xenbus-objs += xenbus_dev.o
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/xenbus/xenbus_client.c
+--- a/drivers/xen/xenbus/xenbus_client.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/xenbus/xenbus_client.c Mon Mar 6 17:57:34 2006 +0000
+@@ -39,7 +39,7 @@ extern char *kasprintf(const char *fmt,
+ pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
+
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+- struct xenbus_watch *watch,
++ struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *,
+ const char **, unsigned int))
+ {
+@@ -62,7 +62,7 @@ EXPORT_SYMBOL(xenbus_watch_path);
+
+
+ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
+- const char *path2, struct xenbus_watch *watch,
++ const char *path2, struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *,
+ const char **, unsigned int))
+ {
+@@ -74,9 +74,8 @@ int xenbus_watch_path2(struct xenbus_dev
+ }
+ err = xenbus_watch_path(dev, state, watch, callback);
+
+- if (err) {
++ if (err)
+ kfree(state);
+- }
+ return err;
+ }
+ EXPORT_SYMBOL(xenbus_watch_path2);
+@@ -95,18 +94,25 @@ int xenbus_switch_state(struct xenbus_de
+ */
+
+ int current_state;
+-
+- int err = xenbus_scanf(xbt, dev->nodename, "state", "%d",
++ int err;
++
++ if (state == dev->state)
++ return 0;
++
++ err = xenbus_scanf(xbt, dev->nodename, "state", "%d",
+ ¤t_state);
+- if ((err == 1 && (XenbusState)current_state == state) ||
+- err == -ENOENT)
++ if (err != 1)
+ return 0;
+
+ err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
+ if (err) {
+- xenbus_dev_fatal(dev, err, "writing new state");
++ if (state != XenbusStateClosing) /* Avoid looping */
++ xenbus_dev_fatal(dev, err, "writing new state");
+ return err;
+ }
++
++ dev->state = state;
++
+ return 0;
+ }
+ EXPORT_SYMBOL(xenbus_switch_state);
+@@ -138,7 +144,6 @@ void _dev_error(struct xenbus_device *de
+ ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
+
+ BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
+- dev->has_error = 1;
+
+ dev_err(&dev->dev, "%s\n", printf_buffer);
+
+@@ -184,7 +189,7 @@ void xenbus_dev_fatal(struct xenbus_devi
+ va_start(ap, fmt);
+ _dev_error(dev, err, fmt, ap);
+ va_end(ap);
+-
++
+ xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
+ }
+ EXPORT_SYMBOL(xenbus_dev_fatal);
+@@ -207,7 +212,6 @@ int xenbus_alloc_evtchn(struct xenbus_de
+ .u.alloc_unbound.dom = DOMID_SELF,
+ .u.alloc_unbound.remote_dom = dev->otherend_id
+ };
+-
+ int err = HYPERVISOR_event_channel_op(&op);
+ if (err)
+ xenbus_dev_fatal(dev, err, "allocating event channel");
+@@ -225,7 +229,6 @@ int xenbus_bind_evtchn(struct xenbus_dev
+ .u.bind_interdomain.remote_dom = dev->otherend_id,
+ .u.bind_interdomain.remote_port = remote_port,
+ };
+-
+ int err = HYPERVISOR_event_channel_op(&op);
+ if (err)
+ xenbus_dev_fatal(dev, err,
+@@ -382,7 +385,6 @@ XenbusState xenbus_read_driver_state(con
+ XenbusState xenbus_read_driver_state(const char *path)
+ {
+ XenbusState result;
+-
+ int err = xenbus_gather(XBT_NULL, path, "state", "%d", &result, NULL);
+ if (err)
+ result = XenbusStateClosed;
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/xenbus/xenbus_comms.c
+--- a/drivers/xen/xenbus/xenbus_comms.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/xenbus/xenbus_comms.c Mon Mar 6 17:57:34 2006 +0000
+@@ -38,8 +38,8 @@
+
+ static int xenbus_irq;
+
+-extern void xenbus_probe(void *);
+-extern int xenstored_ready;
++extern void xenbus_probe(void *);
++extern int xenstored_ready;
+ static DECLARE_WORK(probe_work, xenbus_probe, NULL);
+
+ DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+@@ -52,9 +52,9 @@ static irqreturn_t wake_waiting(int irq,
+ static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
+ {
+ if (unlikely(xenstored_ready == 0)) {
+- xenstored_ready = 1;
+- schedule_work(&probe_work);
+- }
++ xenstored_ready = 1;
++ schedule_work(&probe_work);
++ }
+
+ wake_up(&xb_waitq);
+ return IRQ_HANDLED;
+@@ -89,14 +89,18 @@ int xb_write(const void *data, unsigned
+ {
+ struct xenstore_domain_interface *intf = xenstore_domain_interface();
+ XENSTORE_RING_IDX cons, prod;
++ int rc;
+
+ while (len != 0) {
+ void *dst;
+ unsigned int avail;
+
+- wait_event_interruptible(xb_waitq,
+- (intf->req_prod - intf->req_cons) !=
+- XENSTORE_RING_SIZE);
++ rc = wait_event_interruptible(
++ xb_waitq,
++ (intf->req_prod - intf->req_cons) !=
++ XENSTORE_RING_SIZE);
++ if (rc < 0)
++ return rc;
+
+ /* Read indexes, then verify. */
+ cons = intf->req_cons;
+@@ -130,13 +134,17 @@ int xb_read(void *data, unsigned len)
+ {
+ struct xenstore_domain_interface *intf = xenstore_domain_interface();
+ XENSTORE_RING_IDX cons, prod;
++ int rc;
+
+ while (len != 0) {
+ unsigned int avail;
+ const char *src;
+
+- wait_event_interruptible(xb_waitq,
+- intf->rsp_cons != intf->rsp_prod);
++ rc = wait_event_interruptible(
++ xb_waitq,
++ intf->rsp_cons != intf->rsp_prod);
++ if (rc < 0)
++ return rc;
+
+ /* Read indexes, then verify. */
+ cons = intf->rsp_cons;
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/xenbus/xenbus_probe.c
+--- a/drivers/xen/xenbus/xenbus_probe.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/xenbus/xenbus_probe.c Mon Mar 6 17:57:34 2006 +0000
+@@ -45,9 +45,7 @@
+ #include <asm/hypervisor.h>
+ #include <xen/xenbus.h>
+ #include <xen/xen_proc.h>
+-#include <xen/balloon.h>
+ #include <xen/evtchn.h>
+-#include <xen/public/evtchn.h>
+
+ #include "xenbus_comms.h"
+
+@@ -368,7 +366,6 @@ fail:
+ xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
+ xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
+ return -ENODEV;
+-
+ }
+
+ static int xenbus_dev_remove(struct device *_dev)
+@@ -497,9 +494,8 @@ static void xenbus_dev_free(struct xenbu
+
+ static void xenbus_dev_release(struct device *dev)
+ {
+- if (dev) {
++ if (dev)
+ xenbus_dev_free(to_xenbus_device(dev));
+- }
+ }
+
+ /* Simplified asprintf. */
+@@ -602,7 +598,7 @@ static int xenbus_probe_frontend(const c
+ nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
+ if (!nodename)
+ return -ENOMEM;
+-
++
+ DPRINTK("%s", nodename);
+
+ err = xenbus_probe_node(&xenbus_frontend, type, nodename);
+@@ -886,9 +882,33 @@ EXPORT_SYMBOL(unregister_xenstore_notifi
+ EXPORT_SYMBOL(unregister_xenstore_notifier);
+
+
++static int all_devices_ready_(struct device *dev, void *data)
++{
++ struct xenbus_device *xendev = to_xenbus_device(dev);
++ int *result = data;
++
++ if (xendev->state != XenbusStateConnected) {
++ result = 0;
++ return 1;
++ }
++
++ return 0;
++}
++
++
++static int all_devices_ready(void)
++{
++ int ready = 1;
++ bus_for_each_dev(&xenbus_frontend.bus, NULL, &ready,
++ all_devices_ready_);
++ return ready;
++}
++
+
+ void xenbus_probe(void *unused)
+ {
++ int i;
++
+ BUG_ON((xenstored_ready <= 0));
+
+ /* Enumerate devices in xenstore. */
+@@ -901,17 +921,56 @@ void xenbus_probe(void *unused)
+
+ /* Notify others that xenstore is up */
+ notifier_call_chain(&xenstore_chain, 0, NULL);
+-}
+-
+-
++
++ /* On a 10 second timeout, waiting for all devices currently
++ configured. We need to do this to guarantee that the filesystems
++ and / or network devices needed for boot are available, before we
++ can allow the boot to proceed.
++
++ A possible improvement here would be to have the tools add a
++ per-device flag to the store entry, indicating whether it is needed
++ at boot time. This would allow people who knew what they were
++ doing to accelerate their boot slightly, but of course needs tools
++ or manual intervention to set up those flags correctly.
++ */
++ for (i = 0; i < 10 * HZ; i++) {
++ if (all_devices_ready())
++ return;
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(1);
++ }
++
++ printk(KERN_WARNING
++ "XENBUS: Timeout connecting to devices!\n");
++}
++
++
++static struct file_operations xsd_kva_fops;
+ static struct proc_dir_entry *xsd_kva_intf;
+ static struct proc_dir_entry *xsd_port_intf;
+
++static int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ size_t size = vma->vm_end - vma->vm_start;
++
++ 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,
++ size, vma->vm_page_prot))
++ return -EAGAIN;
++
++ return 0;
++}
+
+ static int xsd_kva_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+ int len;
++
+ len = sprintf(page, "0x%p", mfn_to_virt(xen_start_info->store_mfn));
+ *eof = 1;
+ return len;
+@@ -946,8 +1005,8 @@ static int __init xenbus_probe_init(void
+ device_register(&xenbus_backend.dev);
+
+ /*
+- ** Domain0 doesn't have a store_evtchn or store_mfn yet.
+- */
++ * Domain0 doesn't have a store_evtchn or store_mfn yet.
++ */
+ dom0 = (xen_start_info->store_evtchn == 0);
+
+ if (dom0) {
+@@ -969,7 +1028,7 @@ static int __init xenbus_probe_init(void
+ xen_start_info->store_mfn =
+ pfn_to_mfn(virt_to_phys((void *)page) >>
+ PAGE_SHIFT);
+-
++
+ /* Next allocate a local port which xenstored can bind to */
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+@@ -980,9 +1039,16 @@ static int __init xenbus_probe_init(void
+ xen_start_info->store_evtchn = op.u.alloc_unbound.port;
+
+ /* And finally publish the above info in /proc/xen */
+- if((xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0400)))
++ xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0400);
++ if (xsd_kva_intf) {
++ memcpy(&xsd_kva_fops, xsd_kva_intf->proc_fops,
++ sizeof(xsd_kva_fops));
++ xsd_kva_fops.mmap = xsd_kva_mmap;
++ xsd_kva_intf->proc_fops = &xsd_kva_fops;
+ xsd_kva_intf->read_proc = xsd_kva_read;
+- if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
++ }
++ xsd_port_intf = create_xen_proc_entry("xsd_port", 0400);
++ if (xsd_port_intf)
+ xsd_port_intf->read_proc = xsd_port_read;
+ }
+
+diff -r c75ede70c907 -r f6bd46559b93 drivers/xen/xenbus/xenbus_xs.c
+--- a/drivers/xen/xenbus/xenbus_xs.c Mon Feb 27 15:43:34 2006 +0000
++++ b/drivers/xen/xenbus/xenbus_xs.c Mon Mar 6 17:57:34 2006 +0000
+@@ -123,8 +123,9 @@ static void *read_reply(enum xsd_sockmsg
+
+ while (list_empty(&xs_state.reply_list)) {
+ spin_unlock(&xs_state.reply_lock);
+- wait_event_interruptible(xs_state.reply_waitq,
+- !list_empty(&xs_state.reply_list));
++ /* XXX FIXME: Avoid synchronous wait for response here. */
++ wait_event(xs_state.reply_waitq,
++ !list_empty(&xs_state.reply_list));
+ spin_lock(&xs_state.reply_lock);
+ }
+
+@@ -175,9 +176,8 @@ void *xenbus_dev_request_and_reply(struc
+ if (err) {
+ msg->type = XS_ERROR;
+ ret = ERR_PTR(err);
+- } else {
++ } else
+ ret = read_reply(&msg->type, &msg->len);
+- }
+
+ up(&xs_state.request_mutex);
+
+@@ -274,7 +274,7 @@ static unsigned int count_strings(const
+ return num;
+ }
+
+-/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */
++/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */
+ static char *join(const char *dir, const char *name)
+ {
+ char *buffer;
+@@ -685,6 +685,9 @@ static int xenwatch_thread(void *unused)
+ wait_event_interruptible(watch_events_waitq,
+ !list_empty(&watch_events));
+
++ if (kthread_should_stop())
++ break;
++
+ down(&xenwatch_mutex);
+
+ spin_lock(&watch_events_lock);
+@@ -705,6 +708,8 @@ static int xenwatch_thread(void *unused)
+
+ up(&xenwatch_mutex);
+ }
++
++ return 0;
+ }
+
+ static int process_msg(void)
+@@ -778,7 +783,11 @@ static int xenbus_thread(void *unused)
+ if (err)
+ printk(KERN_WARNING "XENBUS error %d while reading "
+ "message\n", err);
+- }
++ if (kthread_should_stop())
++ break;
++ }
++
++ return 0;
+ }
+
+ int xs_init(void)
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-i386/mach-xen/mach_page.h
+--- a/include/asm-i386/mach-xen/mach_page.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-i386/mach-xen/mach_page.h Mon Mar 6 17:57:34 2006 +0000
+@@ -41,7 +41,8 @@ static inline unsigned long pfn_to_mfn(u
+ {
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return pfn;
+- return phys_to_machine_mapping[(unsigned int)(pfn)] & ~FOREIGN_FRAME_BIT;
++ return phys_to_machine_mapping[(unsigned int)(pfn)] &
++ ~FOREIGN_FRAME_BIT;
+ }
+
+ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-i386/mach-xen/mach_pgtable.h
+--- a/include/asm-i386/mach-xen/mach_pgtable.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-i386/mach-xen/mach_pgtable.h Mon Mar 6 17:57:34 2006 +0000
+@@ -27,8 +27,8 @@ extern pgd_t *swapper_pg_dir;
+ #define pfn_pte_ma(pfn, prot) __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+ #else
+ #define PTRS_PER_PGD_NO_HV PTRS_PER_PGD
+-#define pte_mfn(_pte) ( ((_pte).pte_low >> PAGE_SHIFT) |\
+- (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)) )
++#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) |\
++ (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)))
+ static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+ {
+ pte_t pte;
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-i386/mach-xen/mach_system.h
+--- a/include/asm-i386/mach-xen/mach_system.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-i386/mach-xen/mach_system.h Mon Mar 6 17:57:34 2006 +0000
+@@ -93,7 +93,7 @@ do { \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \
+ _vcpu->evtchn_upcall_mask = 0; \
+ barrier(); /* unmask then check (avoid races) */ \
+- if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
++ if (unlikely(_vcpu->evtchn_upcall_pending)) \
+ force_evtchn_callback(); \
+ preempt_enable(); \
+ } while (0)
+@@ -115,7 +115,7 @@ do { \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \
+ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \
+ barrier(); /* unmask then check (avoid races) */ \
+- if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
++ if (unlikely(_vcpu->evtchn_upcall_pending)) \
+ force_evtchn_callback(); \
+ preempt_enable(); \
+ } else \
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-i386/mach-xen/setup_arch_post.h
+--- a/include/asm-i386/mach-xen/setup_arch_post.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-i386/mach-xen/setup_arch_post.h Mon Mar 6 17:57:34 2006 +0000
+@@ -16,7 +16,7 @@ static char * __init machine_specific_me
+ return "Xen";
+ }
+
+-void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c)
++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);
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/gcc_intrin.h
+--- a/include/asm-ia64/gcc_intrin.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-ia64/gcc_intrin.h Mon Mar 6 17:57:34 2006 +0000
+@@ -26,7 +26,7 @@ extern void ia64_bad_param_for_getreg (v
+
+ register unsigned long ia64_r13 asm ("r13") __attribute_used__;
+
+-#define ia64_setreg(regnum, val) \
++#define __ia64_setreg(regnum, val) \
+ ({ \
+ switch (regnum) { \
+ case _IA64_REG_PSR_L: \
+@@ -55,7 +55,7 @@ register unsigned long ia64_r13 asm ("r1
+ } \
+ })
+
+-#define ia64_getreg(regnum) \
++#define __ia64_getreg(regnum) \
+ ({ \
+ __u64 ia64_intri_res; \
+ \
+@@ -92,7 +92,7 @@ register unsigned long ia64_r13 asm ("r1
+
+ #define ia64_hint_pause 0
+
+-#define ia64_hint(mode) \
++#define __ia64_hint(mode) \
+ ({ \
+ switch (mode) { \
+ case ia64_hint_pause: \
+@@ -374,7 +374,7 @@ register unsigned long ia64_r13 asm ("r1
+
+ #define ia64_invala() asm volatile ("invala" ::: "memory")
+
+-#define ia64_thash(addr) \
++#define __ia64_thash(addr) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \
+@@ -394,18 +394,18 @@ register unsigned long ia64_r13 asm ("r1
+
+ #define ia64_nop(x) asm volatile ("nop %0"::"i"(x));
+
+-#define ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
+-
+-#define ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
+-
+-
+-#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \
++#define __ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
++
++#define __ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
++
++
++#define __ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \
+ :: "r"(trnum), "r"(addr) : "memory")
+
+-#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \
++#define __ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \
+ :: "r"(trnum), "r"(addr) : "memory")
+
+-#define ia64_tpa(addr) \
++#define __ia64_tpa(addr) \
+ ({ \
+ __u64 ia64_pa; \
+ asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory"); \
+@@ -415,22 +415,22 @@ register unsigned long ia64_r13 asm ("r1
+ #define __ia64_set_dbr(index, val) \
+ asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+-#define ia64_set_ibr(index, val) \
++#define __ia64_set_ibr(index, val) \
+ asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+-#define ia64_set_pkr(index, val) \
++#define __ia64_set_pkr(index, val) \
+ asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+-#define ia64_set_pmc(index, val) \
++#define __ia64_set_pmc(index, val) \
+ asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+-#define ia64_set_pmd(index, val) \
++#define __ia64_set_pmd(index, val) \
+ asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
+
+-#define ia64_set_rr(index, val) \
++#define __ia64_set_rr(index, val) \
+ asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
+
+-#define ia64_get_cpuid(index) \
++#define __ia64_get_cpuid(index) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index)); \
+@@ -444,21 +444,21 @@ register unsigned long ia64_r13 asm ("r1
+ ia64_intri_res; \
+ })
+
+-#define ia64_get_ibr(index) \
++#define __ia64_get_ibr(index) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
+ ia64_intri_res; \
+ })
+
+-#define ia64_get_pkr(index) \
++#define __ia64_get_pkr(index) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
+ ia64_intri_res; \
+ })
+
+-#define ia64_get_pmc(index) \
++#define __ia64_get_pmc(index) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
+@@ -466,48 +466,48 @@ register unsigned long ia64_r13 asm ("r1
+ })
+
+
+-#define ia64_get_pmd(index) \
++#define __ia64_get_pmd(index) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
+ ia64_intri_res; \
+ })
+
+-#define ia64_get_rr(index) \
++#define __ia64_get_rr(index) \
+ ({ \
+ __u64 ia64_intri_res; \
+ asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index)); \
+ ia64_intri_res; \
+ })
+
+-#define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
++#define __ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
+
+
+ #define ia64_sync_i() asm volatile (";; sync.i" ::: "memory")
+
+-#define ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
+-#define ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
++#define __ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
++#define __ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
+ #define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory")
+ #define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory")
+
+-#define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr))
+-
+-#define ia64_ptcga(addr, size) \
++#define __ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr))
++
++#define __ia64_ptcga(addr, size) \
+ do { \
+ asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \
+ ia64_dv_serialize_data(); \
+ } while (0)
+
+-#define ia64_ptcl(addr, size) \
++#define __ia64_ptcl(addr, size) \
+ do { \
+ asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory"); \
+ ia64_dv_serialize_data(); \
+ } while (0)
+
+-#define ia64_ptri(addr, size) \
++#define __ia64_ptri(addr, size) \
+ asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
+
+-#define ia64_ptrd(addr, size) \
++#define __ia64_ptrd(addr, size) \
+ asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
+
+ /* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
+@@ -589,7 +589,7 @@ do { \
+ } \
+ })
+
+-#define ia64_intrin_local_irq_restore(x) \
++#define __ia64_intrin_local_irq_restore(x) \
+ do { \
+ asm volatile (";; cmp.ne p6,p7=%0,r0;;" \
+ "(p6) ssm psr.i;" \
+@@ -598,4 +598,6 @@ do { \
+ :: "r"((x)) : "p6", "p7", "memory"); \
+ } while (0)
+
++#define __ia64_get_psr_i() (__ia64_getreg(_IA64_REG_PSR) & 0x4000UL)
++
+ #endif /* _ASM_IA64_GCC_INTRIN_H */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/intel_intrin.h
+--- a/include/asm-ia64/intel_intrin.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-ia64/intel_intrin.h Mon Mar 6 17:57:34 2006 +0000
+@@ -119,10 +119,10 @@ __s64 _m64_popcnt(__s64 a);
+ * intrinsic
+ */
+
+-#define ia64_getreg __getReg
+-#define ia64_setreg __setReg
+-
+-#define ia64_hint(x)
++#define __ia64_getreg __getReg
++#define __ia64_setreg __setReg
++
++#define __ia64_hint(x)
+
+ #define ia64_mux1_brcst 0
+ #define ia64_mux1_mix 8
+@@ -135,16 +135,16 @@ __s64 _m64_popcnt(__s64 a);
+ #define ia64_getf_exp __getf_exp
+ #define ia64_shrp _m64_shrp
+
+-#define ia64_tpa __tpa
++#define __ia64_tpa __tpa
+ #define ia64_invala __invala
+ #define ia64_invala_gr __invala_gr
+ #define ia64_invala_fr __invala_fr
+ #define ia64_nop __nop
+ #define ia64_sum __sum
+-#define ia64_ssm __ssm
++#define __ia64_ssm __ssm
+ #define ia64_rum __rum
+-#define ia64_rsm __rsm
+-#define ia64_fc __fc
++#define __ia64_rsm __rsm
++#define __ia64_fc __fc
+
+ #define ia64_ldfs __ldfs
+ #define ia64_ldfd __ldfd
+@@ -182,24 +182,24 @@ __s64 _m64_popcnt(__s64 a);
+
+ #define __ia64_set_dbr(index, val) \
+ __setIndReg(_IA64_REG_INDR_DBR, index, val)
+-#define ia64_set_ibr(index, val) \
++#define __ia64_set_ibr(index, val) \
+ __setIndReg(_IA64_REG_INDR_IBR, index, val)
+-#define ia64_set_pkr(index, val) \
++#define __ia64_set_pkr(index, val) \
+ __setIndReg(_IA64_REG_INDR_PKR, index, val)
+-#define ia64_set_pmc(index, val) \
++#define __ia64_set_pmc(index, val) \
+ __setIndReg(_IA64_REG_INDR_PMC, index, val)
+-#define ia64_set_pmd(index, val) \
++#define __ia64_set_pmd(index, val) \
+ __setIndReg(_IA64_REG_INDR_PMD, index, val)
+-#define ia64_set_rr(index, val) \
++#define __ia64_set_rr(index, val) \
+ __setIndReg(_IA64_REG_INDR_RR, index, val)
+
+-#define ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index)
++#define __ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index)
+ #define __ia64_get_dbr(index) __getIndReg(_IA64_REG_INDR_DBR, index)
+-#define ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index)
+-#define ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index)
+-#define ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index)
+-#define ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index)
+-#define ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index)
++#define __ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index)
++#define __ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index)
++#define __ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index)
++#define __ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index)
++#define __ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index)
+
+ #define ia64_srlz_d __dsrlz
+ #define ia64_srlz_i __isrlz
+@@ -218,18 +218,18 @@ __s64 _m64_popcnt(__s64 a);
+ #define ia64_ld8_acq __ld8_acq
+
+ #define ia64_sync_i __synci
+-#define ia64_thash __thash
+-#define ia64_ttag __ttag
+-#define ia64_itcd __itcd
+-#define ia64_itci __itci
+-#define ia64_itrd __itrd
+-#define ia64_itri __itri
+-#define ia64_ptce __ptce
+-#define ia64_ptcl __ptcl
+-#define ia64_ptcg __ptcg
+-#define ia64_ptcga __ptcga
+-#define ia64_ptri __ptri
+-#define ia64_ptrd __ptrd
++#define __ia64_thash __thash
++#define __ia64_ttag __ttag
++#define __ia64_itcd __itcd
++#define __ia64_itci __itci
++#define __ia64_itrd __itrd
++#define __ia64_itri __itri
++#define __ia64_ptce __ptce
++#define __ia64_ptcl __ptcl
++#define __ia64_ptcg __ptcg
++#define __ia64_ptcga __ptcga
++#define __ia64_ptri __ptri
++#define __ia64_ptrd __ptrd
+ #define ia64_dep_mi _m64_dep_mi
+
+ /* Values for lfhint in __lfetch and __lfetch_fault */
+@@ -244,14 +244,16 @@ __s64 _m64_popcnt(__s64 a);
+ #define ia64_lfetch_fault __lfetch_fault
+ #define ia64_lfetch_fault_excl __lfetch_fault_excl
+
+-#define ia64_intrin_local_irq_restore(x) \
++#define __ia64_intrin_local_irq_restore(x) \
+ do { \
+ if ((x) != 0) { \
+- ia64_ssm(IA64_PSR_I); \
++ __ia64_ssm(IA64_PSR_I); \
+ ia64_srlz_d(); \
+ } else { \
+- ia64_rsm(IA64_PSR_I); \
++ __ia64_rsm(IA64_PSR_I); \
+ } \
+ } while (0)
+
++#define __ia64_get_psr_i() (__ia64_getreg(_IA64_REG_PSR) & 0x4000UL)
++
+ #endif /* _ASM_IA64_INTEL_INTRIN_H */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/meminit.h
+--- a/include/asm-ia64/meminit.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-ia64/meminit.h Mon Mar 6 17:57:34 2006 +0000
+@@ -17,10 +17,15 @@
+ * - command line string
+ * - kernel code & data
+ * - Kernel memory map built from EFI memory map
++ * - xen start info
+ *
+ * More could be added if necessary
+ */
++#ifndef CONFIG_XEN
+ #define IA64_MAX_RSVD_REGIONS 6
++#else
++#define IA64_MAX_RSVD_REGIONS 7
++#endif
+
+ struct rsvd_region {
+ unsigned long start; /* virtual address of beginning of element */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/pal.h
+--- a/include/asm-ia64/pal.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-ia64/pal.h Mon Mar 6 17:57:34 2006 +0000
+@@ -81,6 +81,7 @@
+ #ifndef __ASSEMBLY__
+
+ #include <linux/types.h>
++#include <asm/processor.h>
+ #include <asm/fpu.h>
+
+ /*
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/processor.h
+--- a/include/asm-ia64/processor.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-ia64/processor.h Mon Mar 6 17:57:34 2006 +0000
+@@ -19,6 +19,7 @@
+ #include <asm/kregs.h>
+ #include <asm/ptrace.h>
+ #include <asm/ustack.h>
++#include <asm/privop.h>
+
+ #define IA64_NUM_DBG_REGS 8
+ /*
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/system.h
+--- a/include/asm-ia64/system.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-ia64/system.h Mon Mar 6 17:57:34 2006 +0000
+@@ -125,7 +125,7 @@ extern struct ia64_boot_param {
+ #define __local_irq_save(x) \
+ do { \
+ ia64_stop(); \
+- (x) = ia64_getreg(_IA64_REG_PSR); \
++ (x) = ia64_get_psr_i(); \
+ ia64_stop(); \
+ ia64_rsm(IA64_PSR_I); \
+ } while (0)
+@@ -173,7 +173,7 @@ do { \
+ #endif /* !CONFIG_IA64_DEBUG_IRQ */
+
+ #define local_irq_enable() ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
+-#define local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); })
++#define local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_get_psr_i(); })
+
+ #define irqs_disabled() \
+ ({ \
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-x86_64/page.h
+--- a/include/asm-x86_64/page.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-x86_64/page.h Mon Mar 6 17:57:34 2006 +0000
+@@ -94,7 +94,8 @@ static inline unsigned long pfn_to_mfn(u
+ {
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return pfn;
+- return phys_to_machine_mapping[(unsigned int)(pfn)] & ~FOREIGN_FRAME_BIT;
++ return phys_to_machine_mapping[(unsigned int)(pfn)] &
++ ~FOREIGN_FRAME_BIT;
+ }
+
+ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-x86_64/processor.h
+--- a/include/asm-x86_64/processor.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/asm-x86_64/processor.h Mon Mar 6 17:57:34 2006 +0000
+@@ -520,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 -r c75ede70c907 -r f6bd46559b93 include/linux/mm.h
+--- a/include/linux/mm.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/linux/mm.h Mon Mar 6 17:57:34 2006 +0000
+@@ -1020,9 +1020,9 @@ struct page *follow_page(struct vm_area_
+ #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,
++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,
++extern int generic_page_range(struct mm_struct *mm, unsigned long address,
+ unsigned long size, pte_fn_t fn, void *data);
+ #endif
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/acm.h
+--- a/include/xen/interface/acm.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/acm.h Mon Mar 6 17:57:34 2006 +0000
+@@ -152,7 +152,7 @@ struct acm_ste_stats_buffer {
+ uint32_t ec_eval_count;
+ uint32_t gt_eval_count;
+ uint32_t ec_denied_count;
+- uint32_t gt_denied_count;
++ uint32_t gt_denied_count;
+ uint32_t ec_cachehit_count;
+ uint32_t gt_cachehit_count;
+ };
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/arch-ia64.h
+--- a/include/xen/interface/arch-ia64.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/arch-ia64.h Mon Mar 6 17:57:34 2006 +0000
+@@ -6,6 +6,28 @@
+
+ #ifndef __HYPERVISOR_IF_IA64_H__
+ #define __HYPERVISOR_IF_IA64_H__
++
++#ifdef __XEN__
++#define __DEFINE_GUEST_HANDLE(name, type) \
++ typedef struct { type *p; } __guest_handle_ ## name
++#else
++#define __DEFINE_GUEST_HANDLE(name, type) \
++ typedef type * __guest_handle_ ## name
++#endif
++
++#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
++#define GUEST_HANDLE(name) __guest_handle_ ## name
++
++#ifndef __ASSEMBLY__
++/* Guest handles for primitive C types. */
++__DEFINE_GUEST_HANDLE(uchar, unsigned char);
++__DEFINE_GUEST_HANDLE(uint, unsigned int);
++__DEFINE_GUEST_HANDLE(ulong, unsigned long);
++DEFINE_GUEST_HANDLE(char);
++DEFINE_GUEST_HANDLE(int);
++DEFINE_GUEST_HANDLE(long);
++DEFINE_GUEST_HANDLE(void);
++#endif
+
+ /* Maximum number of virtual CPUs in multi-processor guests. */
+ /* WARNING: before changing this, check that shared_info fits on a page */
+@@ -263,6 +285,7 @@ typedef struct vcpu_guest_context {
+ arch_vcpu_info_t vcpu;
+ arch_shared_info_t shared;
+ } vcpu_guest_context_t;
++DEFINE_GUEST_HANDLE(vcpu_guest_context_t);
+
+ #endif /* !__ASSEMBLY__ */
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/arch-x86_32.h
+--- a/include/xen/interface/arch-x86_32.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/arch-x86_32.h Mon Mar 6 17:57:34 2006 +0000
+@@ -8,6 +8,28 @@
+
+ #ifndef __XEN_PUBLIC_ARCH_X86_32_H__
+ #define __XEN_PUBLIC_ARCH_X86_32_H__
++
++#ifdef __XEN__
++#define __DEFINE_GUEST_HANDLE(name, type) \
++ typedef struct { type *p; } __guest_handle_ ## name
++#else
++#define __DEFINE_GUEST_HANDLE(name, type) \
++ typedef type * __guest_handle_ ## name
++#endif
++
++#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
++#define GUEST_HANDLE(name) __guest_handle_ ## name
++
++#ifndef __ASSEMBLY__
++/* Guest handles for primitive C types. */
++__DEFINE_GUEST_HANDLE(uchar, unsigned char);
++__DEFINE_GUEST_HANDLE(uint, unsigned int);
++__DEFINE_GUEST_HANDLE(ulong, unsigned long);
++DEFINE_GUEST_HANDLE(char);
++DEFINE_GUEST_HANDLE(int);
++DEFINE_GUEST_HANDLE(long);
++DEFINE_GUEST_HANDLE(void);
++#endif
+
+ /*
+ * SEGMENT DESCRIPTOR TABLES
+@@ -130,11 +152,12 @@ typedef struct vcpu_guest_context {
+ unsigned long failsafe_callback_eip;
+ unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
+ } vcpu_guest_context_t;
++DEFINE_GUEST_HANDLE(vcpu_guest_context_t);
+
+ typedef struct arch_shared_info {
+ unsigned long max_pfn; /* max pfn that appears in table */
+ /* Frame containing list of mfns containing list of mfns containing p2m. */
+- unsigned long pfn_to_mfn_frame_list_list;
++ unsigned long pfn_to_mfn_frame_list_list;
+ unsigned long nmi_reason;
+ } arch_shared_info_t;
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/arch-x86_64.h
+--- a/include/xen/interface/arch-x86_64.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/arch-x86_64.h Mon Mar 6 17:57:34 2006 +0000
+@@ -8,6 +8,28 @@
+
+ #ifndef __XEN_PUBLIC_ARCH_X86_64_H__
+ #define __XEN_PUBLIC_ARCH_X86_64_H__
++
++#ifdef __XEN__
++#define __DEFINE_GUEST_HANDLE(name, type) \
++ typedef struct { type *p; } __guest_handle_ ## name
++#else
++#define __DEFINE_GUEST_HANDLE(name, type) \
++ typedef type * __guest_handle_ ## name
++#endif
++
++#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
++#define GUEST_HANDLE(name) __guest_handle_ ## name
++
++#ifndef __ASSEMBLY__
++/* Guest handles for primitive C types. */
++__DEFINE_GUEST_HANDLE(uchar, unsigned char);
++__DEFINE_GUEST_HANDLE(uint, unsigned int);
++__DEFINE_GUEST_HANDLE(ulong, unsigned long);
++DEFINE_GUEST_HANDLE(char);
++DEFINE_GUEST_HANDLE(int);
++DEFINE_GUEST_HANDLE(long);
++DEFINE_GUEST_HANDLE(void);
++#endif
+
+ /*
+ * SEGMENT DESCRIPTOR TABLES
+@@ -215,11 +237,12 @@ typedef struct vcpu_guest_context {
+ uint64_t gs_base_kernel;
+ uint64_t gs_base_user;
+ } vcpu_guest_context_t;
++DEFINE_GUEST_HANDLE(vcpu_guest_context_t);
+
+ typedef struct arch_shared_info {
+ unsigned long max_pfn; /* max pfn that appears in table */
+ /* Frame containing list of mfns containing list of mfns containing p2m. */
+- unsigned long pfn_to_mfn_frame_list_list;
++ unsigned long pfn_to_mfn_frame_list_list;
+ unsigned long nmi_reason;
+ } arch_shared_info_t;
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/dom0_ops.h
+--- a/include/xen/interface/dom0_ops.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/dom0_ops.h Mon Mar 6 17:57:34 2006 +0000
+@@ -28,18 +28,21 @@ typedef struct dom0_getmemlist {
+ /* IN variables. */
+ domid_t domain;
+ unsigned long max_pfns;
+- void *buffer;
++ GUEST_HANDLE(ulong) buffer;
+ /* OUT variables. */
+ unsigned long num_pfns;
+ } dom0_getmemlist_t;
++DEFINE_GUEST_HANDLE(dom0_getmemlist_t);
+
+ #define DOM0_SCHEDCTL 6
+ /* struct sched_ctl_cmd is from sched-ctl.h */
+ typedef struct sched_ctl_cmd dom0_schedctl_t;
++DEFINE_GUEST_HANDLE(dom0_schedctl_t);
+
+ #define DOM0_ADJUSTDOM 7
+ /* struct sched_adjdom_cmd is from sched-ctl.h */
+ typedef struct sched_adjdom_cmd dom0_adjustdom_t;
++DEFINE_GUEST_HANDLE(dom0_adjustdom_t);
+
+ #define DOM0_CREATEDOMAIN 8
+ typedef struct dom0_createdomain {
+@@ -50,24 +53,28 @@ typedef struct dom0_createdomain {
+ /* Identifier for new domain (auto-allocate if zero is specified). */
+ domid_t domain;
+ } dom0_createdomain_t;
++DEFINE_GUEST_HANDLE(dom0_createdomain_t);
+
+ #define DOM0_DESTROYDOMAIN 9
+ typedef struct dom0_destroydomain {
+ /* IN variables. */
+ domid_t domain;
+ } dom0_destroydomain_t;
++DEFINE_GUEST_HANDLE(dom0_destroydomain_t);
+
+ #define DOM0_PAUSEDOMAIN 10
+ typedef struct dom0_pausedomain {
+ /* IN parameters. */
+ domid_t domain;
+ } dom0_pausedomain_t;
++DEFINE_GUEST_HANDLE(dom0_pausedomain_t);
+
+ #define DOM0_UNPAUSEDOMAIN 11
+ typedef struct dom0_unpausedomain {
+ /* IN parameters. */
+ domid_t domain;
+ } dom0_unpausedomain_t;
++DEFINE_GUEST_HANDLE(dom0_unpausedomain_t);
+
+ #define DOM0_GETDOMAININFO 12
+ typedef struct dom0_getdomaininfo {
+@@ -93,6 +100,7 @@ typedef struct dom0_getdomaininfo {
+ uint32_t ssidref;
+ xen_domain_handle_t handle;
+ } dom0_getdomaininfo_t;
++DEFINE_GUEST_HANDLE(dom0_getdomaininfo_t);
+
+ #define DOM0_SETVCPUCONTEXT 13
+ typedef struct dom0_setvcpucontext {
+@@ -100,8 +108,9 @@ typedef struct dom0_setvcpucontext {
+ domid_t domain;
+ uint32_t vcpu;
+ /* IN/OUT parameters */
+- vcpu_guest_context_t *ctxt;
++ GUEST_HANDLE(vcpu_guest_context_t) ctxt;
+ } dom0_setvcpucontext_t;
++DEFINE_GUEST_HANDLE(dom0_setvcpucontext_t);
+
+ #define DOM0_MSR 15
+ typedef struct dom0_msr {
+@@ -115,6 +124,7 @@ typedef struct dom0_msr {
+ uint32_t out1;
+ uint32_t out2;
+ } dom0_msr_t;
++DEFINE_GUEST_HANDLE(dom0_msr_t);
+
+ /*
+ * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
+@@ -127,6 +137,7 @@ typedef struct dom0_settime {
+ uint32_t nsecs;
+ uint64_t system_time;
+ } dom0_settime_t;
++DEFINE_GUEST_HANDLE(dom0_settime_t);
+
+ #define DOM0_GETPAGEFRAMEINFO 18
+ #define NOTAB 0 /* normal page */
+@@ -147,6 +158,7 @@ typedef struct dom0_getpageframeinfo {
+ /* Is the page PINNED to a type? */
+ uint32_t type; /* see above type defs */
+ } dom0_getpageframeinfo_t;
++DEFINE_GUEST_HANDLE(dom0_getpageframeinfo_t);
+
+ /*
+ * Read console content from Xen buffer ring.
+@@ -154,13 +166,14 @@ typedef struct dom0_getpageframeinfo {
+ #define DOM0_READCONSOLE 19
+ typedef struct dom0_readconsole {
+ /* IN variables. */
+- uint32_t clear; /* Non-zero -> clear after reading. */
++ uint32_t clear; /* Non-zero -> clear after reading. */
+ /* IN/OUT variables. */
+- char *buffer; /* In: Buffer start; Out: Used buffer start */
+- uint32_t count; /* In: Buffer size; Out: Used buffer size */
++ GUEST_HANDLE(char) buffer; /* In: Buffer start; Out: Used buffer start */
++ uint32_t count; /* In: Buffer size; Out: Used buffer size */
+ } dom0_readconsole_t;
+-
+-/*
++DEFINE_GUEST_HANDLE(dom0_readconsole_t);
++
++/*
+ * Set which physical cpus a vcpu can execute on.
+ */
+ #define DOM0_SETVCPUAFFINITY 20
+@@ -170,6 +183,7 @@ typedef struct dom0_setvcpuaffinity {
+ uint32_t vcpu;
+ cpumap_t cpumap;
+ } dom0_setvcpuaffinity_t;
++DEFINE_GUEST_HANDLE(dom0_setvcpuaffinity_t);
+
+ /* Get trace buffers machine base address */
+ #define DOM0_TBUFCONTROL 21
+@@ -189,6 +203,7 @@ typedef struct dom0_tbufcontrol {
+ unsigned long buffer_mfn;
+ uint32_t size;
+ } dom0_tbufcontrol_t;
++DEFINE_GUEST_HANDLE(dom0_tbufcontrol_t);
+
+ /*
+ * Get physical information about the host machine
+@@ -204,6 +219,7 @@ typedef struct dom0_physinfo {
+ unsigned long free_pages;
+ uint32_t hw_cap[8];
+ } dom0_physinfo_t;
++DEFINE_GUEST_HANDLE(dom0_physinfo_t);
+
+ /*
+ * Get the ID of the current scheduler.
+@@ -213,8 +229,9 @@ typedef struct dom0_sched_id {
+ /* OUT variable */
+ uint32_t sched_id;
+ } dom0_sched_id_t;
+-
+-/*
++DEFINE_GUEST_HANDLE(dom0_sched_id_t);
++
++/*
+ * Control shadow pagetables operation
+ */
+ #define DOM0_SHADOW_CONTROL 25
+@@ -231,20 +248,22 @@ typedef struct dom0_shadow_control_stats
+ typedef struct dom0_shadow_control_stats {
+ uint32_t fault_count;
+ uint32_t dirty_count;
+- uint32_t dirty_net_count;
+- uint32_t dirty_block_count;
++ uint32_t dirty_net_count;
++ uint32_t dirty_block_count;
+ } dom0_shadow_control_stats_t;
++DEFINE_GUEST_HANDLE(dom0_shadow_control_stats_t);
+
+ typedef struct dom0_shadow_control {
+ /* IN variables. */
+ domid_t domain;
+ uint32_t op;
+- unsigned long *dirty_bitmap; /* pointer to locked buffer */
++ GUEST_HANDLE(ulong) dirty_bitmap;
+ /* IN/OUT variables. */
+ unsigned long pages; /* size of buffer, updated with actual size */
+ /* OUT variables. */
+ dom0_shadow_control_stats_t stats;
+ } dom0_shadow_control_t;
++DEFINE_GUEST_HANDLE(dom0_shadow_control_t);
+
+ #define DOM0_SETDOMAINMAXMEM 28
+ typedef struct dom0_setdomainmaxmem {
+@@ -252,6 +271,7 @@ typedef struct dom0_setdomainmaxmem {
+ domid_t domain;
+ unsigned long max_memkb;
+ } dom0_setdomainmaxmem_t;
++DEFINE_GUEST_HANDLE(dom0_setdomainmaxmem_t);
+
+ #define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */
+ typedef struct dom0_getpageframeinfo2 {
+@@ -259,8 +279,9 @@ typedef struct dom0_getpageframeinfo2 {
+ domid_t domain;
+ unsigned long num;
+ /* IN/OUT variables. */
+- unsigned long *array;
++ GUEST_HANDLE(ulong) array;
+ } dom0_getpageframeinfo2_t;
++DEFINE_GUEST_HANDLE(dom0_getpageframeinfo2_t);
+
+ /*
+ * Request memory range (@mfn, @mfn+ at nr_mfns-1) to have type @type.
+@@ -279,6 +300,7 @@ typedef struct dom0_add_memtype {
+ uint32_t handle;
+ uint32_t reg;
+ } dom0_add_memtype_t;
++DEFINE_GUEST_HANDLE(dom0_add_memtype_t);
+
+ /*
+ * Tear down an existing memory-range type. If @handle is remembered then it
+@@ -293,6 +315,7 @@ typedef struct dom0_del_memtype {
+ uint32_t handle;
+ uint32_t reg;
+ } dom0_del_memtype_t;
++DEFINE_GUEST_HANDLE(dom0_del_memtype_t);
+
+ /* Read current type of an MTRR (x86-specific). */
+ #define DOM0_READ_MEMTYPE 33
+@@ -304,6 +327,7 @@ typedef struct dom0_read_memtype {
+ unsigned long nr_mfns;
+ uint32_t type;
+ } dom0_read_memtype_t;
++DEFINE_GUEST_HANDLE(dom0_read_memtype_t);
+
+ /* Interface for controlling Xen software performance counters. */
+ #define DOM0_PERFCCONTROL 34
+@@ -315,20 +339,23 @@ typedef struct dom0_perfc_desc {
+ uint32_t nr_vals; /* number of values for this counter */
+ uint32_t vals[64]; /* array of values */
+ } dom0_perfc_desc_t;
++DEFINE_GUEST_HANDLE(dom0_perfc_desc_t);
+ typedef struct dom0_perfccontrol {
+ /* IN variables. */
+ uint32_t op; /* DOM0_PERFCCONTROL_OP_??? */
+ /* OUT variables. */
+ uint32_t nr_counters; /* number of counters */
+- dom0_perfc_desc_t *desc; /* counter information (or NULL) */
++ GUEST_HANDLE(dom0_perfc_desc_t) desc; /* counter information (or NULL) */
+ } dom0_perfccontrol_t;
++DEFINE_GUEST_HANDLE(dom0_perfccontrol_t);
+
+ #define DOM0_MICROCODE 35
+ typedef struct dom0_microcode {
+ /* IN variables. */
+- void *data; /* Pointer to microcode data */
++ GUEST_HANDLE(void) data; /* Pointer to microcode data */
+ uint32_t length; /* Length of microcode data. */
+ } dom0_microcode_t;
++DEFINE_GUEST_HANDLE(dom0_microcode_t);
+
+ #define DOM0_IOPORT_PERMISSION 36
+ typedef struct dom0_ioport_permission {
+@@ -337,6 +364,7 @@ typedef struct dom0_ioport_permission {
+ uint32_t nr_ports; /* size of port range */
+ uint8_t allow_access; /* allow or deny access to range? */
+ } dom0_ioport_permission_t;
++DEFINE_GUEST_HANDLE(dom0_ioport_permission_t);
+
+ #define DOM0_GETVCPUCONTEXT 37
+ typedef struct dom0_getvcpucontext {
+@@ -344,8 +372,9 @@ typedef struct dom0_getvcpucontext {
+ domid_t domain; /* domain to be affected */
+ uint32_t vcpu; /* vcpu # */
+ /* OUT variables. */
+- vcpu_guest_context_t *ctxt;
++ GUEST_HANDLE(vcpu_guest_context_t) ctxt;
+ } dom0_getvcpucontext_t;
++DEFINE_GUEST_HANDLE(dom0_getvcpucontext_t);
+
+ #define DOM0_GETVCPUINFO 43
+ typedef struct dom0_getvcpuinfo {
+@@ -360,54 +389,63 @@ typedef struct dom0_getvcpuinfo {
+ uint32_t cpu; /* current mapping */
+ cpumap_t cpumap; /* allowable mapping */
+ } dom0_getvcpuinfo_t;
++DEFINE_GUEST_HANDLE(dom0_getvcpuinfo_t);
+
+ #define DOM0_GETDOMAININFOLIST 38
+ typedef struct dom0_getdomaininfolist {
+ /* IN variables. */
+ domid_t first_domain;
+ uint32_t max_domains;
+- dom0_getdomaininfo_t *buffer;
++ GUEST_HANDLE(dom0_getdomaininfo_t) buffer;
+ /* OUT variables. */
+ uint32_t num_domains;
+ } dom0_getdomaininfolist_t;
+-
+-#define DOM0_PLATFORM_QUIRK 39
++DEFINE_GUEST_HANDLE(dom0_getdomaininfolist_t);
++
++#define DOM0_PLATFORM_QUIRK 39
+ #define QUIRK_NOIRQBALANCING 1
+ typedef struct dom0_platform_quirk {
+ /* IN variables. */
+ uint32_t quirk_id;
+ } dom0_platform_quirk_t;
++DEFINE_GUEST_HANDLE(dom0_platform_quirk_t);
+
+ #define DOM0_PHYSICAL_MEMORY_MAP 40
++typedef struct dom0_memory_map_entry {
++ uint64_t start, end;
++ uint32_t flags; /* reserved */
++ uint8_t is_ram;
++} dom0_memory_map_entry_t;
++DEFINE_GUEST_HANDLE(dom0_memory_map_entry_t);
+ typedef struct dom0_physical_memory_map {
+ /* IN variables. */
+ uint32_t max_map_entries;
+ /* OUT variables. */
+ uint32_t nr_map_entries;
+- struct dom0_memory_map_entry {
+- uint64_t start, end;
+- uint32_t flags; /* reserved */
+- uint8_t is_ram;
+- } *memory_map;
++ GUEST_HANDLE(dom0_memory_map_entry_t) memory_map;
+ } dom0_physical_memory_map_t;
++DEFINE_GUEST_HANDLE(dom0_physical_memory_map_t);
+
+ #define DOM0_MAX_VCPUS 41
+ typedef struct dom0_max_vcpus {
+ domid_t domain; /* domain to be affected */
+ uint32_t max; /* maximum number of vcpus */
+ } dom0_max_vcpus_t;
++DEFINE_GUEST_HANDLE(dom0_max_vcpus_t);
+
+ #define DOM0_SETDOMAINHANDLE 44
+ typedef struct dom0_setdomainhandle {
+ domid_t domain;
+ xen_domain_handle_t handle;
+ } dom0_setdomainhandle_t;
++DEFINE_GUEST_HANDLE(dom0_setdomainhandle_t);
+
+ #define DOM0_SETDEBUGGING 45
+ typedef struct dom0_setdebugging {
+ domid_t domain;
+ uint8_t enable;
+ } dom0_setdebugging_t;
++DEFINE_GUEST_HANDLE(dom0_setdebugging_t);
+
+ #define DOM0_IRQ_PERMISSION 46
+ typedef struct dom0_irq_permission {
+@@ -415,6 +453,7 @@ typedef struct dom0_irq_permission {
+ uint8_t pirq;
+ uint8_t allow_access; /* flag to specify enable/disable of IRQ access */
+ } dom0_irq_permission_t;
++DEFINE_GUEST_HANDLE(dom0_irq_permission_t);
+
+ #define DOM0_IOMEM_PERMISSION 47
+ typedef struct dom0_iomem_permission {
+@@ -423,12 +462,14 @@ typedef struct dom0_iomem_permission {
+ unsigned long nr_mfns; /* number of pages in range (>0) */
+ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */
+ } dom0_iomem_permission_t;
++DEFINE_GUEST_HANDLE(dom0_iomem_permission_t);
+
+ #define DOM0_HYPERCALL_INIT 48
+ typedef struct dom0_hypercall_init {
+ domid_t domain; /* domain to be affected */
+ unsigned long mfn; /* machine frame to be initialised */
+ } dom0_hypercall_init_t;
++DEFINE_GUEST_HANDLE(dom0_hypercall_init_t);
+
+ typedef struct dom0_op {
+ uint32_t cmd;
+@@ -466,14 +507,15 @@ typedef struct dom0_op {
+ struct dom0_platform_quirk platform_quirk;
+ struct dom0_physical_memory_map physical_memory_map;
+ struct dom0_max_vcpus max_vcpus;
+- struct dom0_setdomainhandle setdomainhandle;
++ struct dom0_setdomainhandle setdomainhandle;
+ struct dom0_setdebugging setdebugging;
+ struct dom0_irq_permission irq_permission;
+ struct dom0_iomem_permission iomem_permission;
+ struct dom0_hypercall_init hypercall_init;
+- uint8_t pad[128];
++ uint8_t pad[128];
+ } u;
+ } dom0_op_t;
++DEFINE_GUEST_HANDLE(dom0_op_t);
+
+ #endif /* __XEN_PUBLIC_DOM0_OPS_H__ */
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/grant_table.h
+--- a/include/xen/interface/grant_table.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/grant_table.h Mon Mar 6 17:57:34 2006 +0000
+@@ -262,7 +262,7 @@ typedef struct gnttab_transfer {
+ * GNTMAP_contains_pte subflag:
+ * 0 => This map request contains a host virtual address.
+ * 1 => This map request contains the machine addess of the PTE to update.
+- */
++ */
+ #define _GNTMAP_contains_pte (4)
+ #define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/hvm/ioreq.h
+--- a/include/xen/interface/hvm/ioreq.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/hvm/ioreq.h Mon Mar 6 17:57:34 2006 +0000
+@@ -71,8 +71,8 @@ typedef struct {
+ typedef struct {
+ ioreq_t vp_ioreq;
+ /* Event channel port */
+- unsigned long vp_eport; /* VMX vcpu uses this to notify DM */
+- unsigned long dm_eport; /* DM uses this to notify VMX vcpu */
++ unsigned int vp_eport; /* VMX vcpu uses this to notify DM */
++ unsigned int dm_eport; /* DM uses this to notify VMX vcpu */
+ } vcpu_iodata_t;
+
+ typedef struct {
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/hvm/vmx_assist.h
+--- a/include/xen/interface/hvm/vmx_assist.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/hvm/vmx_assist.h Mon Mar 6 17:57:34 2006 +0000
+@@ -22,13 +22,13 @@ union vmcs_arbytes {
+ unsigned int seg_type : 4,
+ s : 1,
+ dpl : 2,
+- p : 1,
++ p : 1,
+ reserved0 : 4,
+ avl : 1,
+- reserved1 : 1,
++ reserved1 : 1,
+ default_ops_size: 1,
+ g : 1,
+- null_bit : 1,
++ null_bit : 1,
+ reserved2 : 15;
+ } fields;
+ unsigned int bytes;
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/io/ring.h
+--- a/include/xen/interface/io/ring.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/io/ring.h Mon Mar 6 17:57:34 2006 +0000
+@@ -39,7 +39,7 @@ typedef unsigned int RING_IDX;
+ *
+ * These expand out to give you a set of types, as you can see below.
+ * The most important of these are:
+- *
++ *
+ * mytag_sring_t - The shared ring.
+ * mytag_front_ring_t - The 'front' half of the ring.
+ * mytag_back_ring_t - The 'back' half of the ring.
+@@ -58,7 +58,7 @@ typedef unsigned int RING_IDX;
+ * mytag_back_ring_t back_ring;
+ * BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ */
+-
++
+ #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
+ \
+ /* Shared ring entry */ \
+@@ -97,7 +97,7 @@ typedef struct __name##_back_ring __name
+ typedef struct __name##_back_ring __name##_back_ring_t
+
+ /*
+- * Macros for manipulating rings.
++ * Macros for manipulating rings.
+ *
+ * FRONT_RING_whatever works on the "front end" of a ring: here
+ * requests are pushed on to the ring and responses taken off it.
+@@ -105,7 +105,7 @@ typedef struct __name##_back_ring __name
+ * BACK_RING_whatever works on the "back end" of a ring: here
+ * requests are taken off the ring and responses put on.
+ *
+- * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
++ * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
+ * This is OK in 1-for-1 request-response situations where the
+ * requestor (front end) never has more than RING_SIZE()-1
+ * outstanding requests.
+@@ -151,7 +151,7 @@ typedef struct __name##_back_ring __name
+ #define RING_SIZE(_r) \
+ ((_r)->nr_ents)
+
+-/* Test if there is an empty slot available on the front ring.
++/* Test if there is an empty slot available on the front ring.
+ * (This is only meaningful from the front. )
+ */
+ #define RING_FULL(_r) \
+@@ -159,24 +159,19 @@ typedef struct __name##_back_ring __name
+
+ /* Test if there are outstanding messages to be processed on a ring. */
+ #define RING_HAS_UNCONSUMED_RESPONSES(_r) \
+- ( (_r)->rsp_cons != (_r)->sring->rsp_prod )
+-
++ ((_r)->rsp_cons != (_r)->sring->rsp_prod)
++
+ #define RING_HAS_UNCONSUMED_REQUESTS(_r) \
+- ( ((_r)->req_cons != (_r)->sring->req_prod ) && \
+- (((_r)->req_cons - (_r)->rsp_prod_pvt) != \
+- RING_SIZE(_r)) )
+-
++ (((_r)->req_cons != (_r)->sring->req_prod) && \
++ (((_r)->req_cons - (_r)->rsp_prod_pvt) != RING_SIZE(_r)))
++
+ /* Direct access to individual ring elements, by index. */
+ #define RING_GET_REQUEST(_r, _idx) \
+- (&((_r)->sring->ring[ \
+- ((_idx) & (RING_SIZE(_r) - 1)) \
+- ].req))
++ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+
+ #define RING_GET_RESPONSE(_r, _idx) \
+- (&((_r)->sring->ring[ \
+- ((_idx) & (RING_SIZE(_r) - 1)) \
+- ].rsp))
+-
++ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
++
+ /* Loop termination condition: Would the specified index overflow the ring? */
+ #define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
+ (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+@@ -212,7 +207,7 @@ typedef struct __name##_back_ring __name
+ * The second argument is a boolean return value. True indicates that there
+ * are pending messages on the ring (i.e., the connection should not be put
+ * to sleep).
+- *
++ *
+ * These macros will set the req_event/rsp_event field to trigger a
+ * notification on the very next message that is enqueued. If you want to
+ * create batches of work (i.e., only receive a notification after several
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/io/tpmif.h
+--- a/include/xen/interface/io/tpmif.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/io/tpmif.h Mon Mar 6 17:57:34 2006 +0000
+@@ -21,7 +21,7 @@ typedef struct {
+ typedef struct {
+ unsigned long addr; /* Machine address of packet. */
+ grant_ref_t ref; /* grant table access reference */
+- uint16_t id; /* Echoed in response message. */
++ uint16_t unused;
+ uint16_t size; /* Packet size in bytes. */
+ } tpmif_tx_request_t;
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/io/xenbus.h
+--- a/include/xen/interface/io/xenbus.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/io/xenbus.h Mon Mar 6 17:57:34 2006 +0000
+@@ -6,9 +6,8 @@
+ * Copyright (C) 2005 XenSource Ltd.
+ */
+
+-#ifndef _XEN_XENBUS_H
+-#define _XEN_XENBUS_H
+-
++#ifndef _XEN_PUBLIC_IO_XENBUS_H
++#define _XEN_PUBLIC_IO_XENBUS_H
+
+ /* The state of either end of the Xenbus, i.e. the current communication
+ status of initialisation across the bus. States here imply nothing about
+@@ -30,8 +29,7 @@ typedef enum
+
+ } XenbusState;
+
+-
+-#endif /* _XEN_XENBUS_H */
++#endif /* _XEN_PUBLIC_IO_XENBUS_H */
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/memory.h
+--- a/include/xen/interface/memory.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/memory.h Mon Mar 6 17:57:34 2006 +0000
+@@ -29,7 +29,7 @@ typedef struct xen_memory_reservation {
+ * OUT: GMFN bases of extents that were allocated
+ * (NB. This command also updates the mach_to_phys translation table)
+ */
+- unsigned long *extent_start;
++ GUEST_HANDLE(ulong) extent_start;
+
+ /* Number of extents, and size/alignment of each (2^extent_order pages). */
+ unsigned long nr_extents;
+@@ -50,6 +50,7 @@ typedef struct xen_memory_reservation {
+ domid_t domid;
+
+ } xen_memory_reservation_t;
++DEFINE_GUEST_HANDLE(xen_memory_reservation_t);
+
+ /*
+ * Returns the maximum machine frame number of mapped RAM in this system.
+@@ -79,13 +80,13 @@ typedef struct xen_machphys_mfn_list {
+ * machphys table is smaller than max_extents * 2MB.
+ */
+ unsigned int max_extents;
+-
++
+ /*
+ * Pointer to buffer to fill with list of extent starts. If there are
+ * any large discontiguities in the machine address space, 2MB gaps in
+ * the machphys table will be represented by an MFN base of zero.
+ */
+- unsigned long *extent_start;
++ GUEST_HANDLE(ulong) extent_start;
+
+ /*
+ * Number of extents written to the above array. This will be smaller
+@@ -93,6 +94,7 @@ typedef struct xen_machphys_mfn_list {
+ */
+ unsigned int nr_extents;
+ } xen_machphys_mfn_list_t;
++DEFINE_GUEST_HANDLE(xen_machphys_mfn_list_t);
+
+ /*
+ * Returns the base and size of the specified reserved 'RAM hole' in the
+@@ -113,6 +115,7 @@ typedef struct xen_reserved_phys_area {
+ /* 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);
+
+ /*
+ * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
+@@ -127,14 +130,15 @@ typedef struct xen_translate_gpfn_list {
+ unsigned long nr_gpfns;
+
+ /* List of GPFNs to translate. */
+- unsigned long *gpfn_list;
++ GUEST_HANDLE(ulong) gpfn_list;
+
+ /*
+ * Output list to contain MFN translations. May be the same as the input
+ * list (in which case each input GPFN is overwritten with the output MFN).
+ */
+- unsigned long *mfn_list;
++ GUEST_HANDLE(ulong) mfn_list;
+ } xen_translate_gpfn_list_t;
++DEFINE_GUEST_HANDLE(xen_translate_gpfn_list_t);
+
+ #endif /* __XEN_PUBLIC_MEMORY_H__ */
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/physdev.h
+--- a/include/xen/interface/physdev.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/physdev.h Mon Mar 6 17:57:34 2006 +0000
+@@ -33,18 +33,18 @@ typedef struct physdevop_set_iobitmap {
+
+ typedef struct physdevop_apic {
+ /* IN */
+- uint32_t apic;
+- uint32_t offset;
++ unsigned long apic_physbase;
++ uint32_t reg;
+ /* IN or OUT */
+ uint32_t value;
+-} physdevop_apic_t;
++} physdevop_apic_t;
+
+ typedef struct physdevop_irq {
+ /* IN */
+ uint32_t irq;
+ /* OUT */
+ uint32_t vector;
+-} physdevop_irq_t;
++} physdevop_irq_t;
+
+ typedef struct physdev_op {
+ uint32_t cmd;
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/sched_ctl.h
+--- a/include/xen/interface/sched_ctl.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/sched_ctl.h Mon Mar 6 17:57:34 2006 +0000
+@@ -34,24 +34,20 @@ struct sched_adjdom_cmd {
+ uint32_t direction;
+ domid_t domain;
+ union {
+- struct bvt_adjdom
+- {
++ struct bvt_adjdom {
+ uint32_t mcu_adv; /* mcu advance: inverse of weight */
+ uint32_t warpback; /* warp? */
+ int32_t warpvalue; /* warp value */
+ int64_t warpl; /* warp limit */
+ int64_t warpu; /* unwarp time requirement */
+ } bvt;
+-
+- struct sedf_adjdom
+- {
++ struct sedf_adjdom {
+ uint64_t period;
+ uint64_t slice;
+ uint64_t latency;
+ uint32_t extratime;
+ uint32_t weight;
+ } sedf;
+-
+ } u;
+ };
+
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/interface/xen.h
+--- a/include/xen/interface/xen.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/interface/xen.h Mon Mar 6 17:57:34 2006 +0000
+@@ -380,8 +380,8 @@ typedef struct shared_info {
+ * a. relocated kernel image
+ * b. initial ram disk [mod_start, mod_len]
+ * c. list of allocated page frames [mfn_list, nr_pages]
+- * d. bootstrap page tables [pt_base, CR3 (x86)]
+- * e. start_info_t structure [register ESI (x86)]
++ * d. start_info_t structure [register ESI (x86)]
++ * e. bootstrap page tables [pt_base, CR3 (x86)]
+ * f. bootstrap stack [register ESP (x86)]
+ * 5. Bootstrap elements are packed together, but each is 4kB-aligned.
+ * 6. The initial ram disk may be omitted.
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/xenbus.h
+--- a/include/xen/xenbus.h Mon Feb 27 15:43:34 2006 +0000
++++ b/include/xen/xenbus.h Mon Mar 6 17:57:34 2006 +0000
+@@ -28,8 +28,8 @@
+ * IN THE SOFTWARE.
+ */
+
+-#ifndef _ASM_XEN_XENBUS_H
+-#define _ASM_XEN_XENBUS_H
++#ifndef _XEN_XENBUS_H
++#define _XEN_XENBUS_H
+
+ #include <linux/device.h>
+ #include <linux/notifier.h>
+@@ -63,7 +63,7 @@ struct xenbus_device {
+ int otherend_id;
+ struct xenbus_watch otherend_watch;
+ struct device dev;
+- int has_error;
++ XenbusState state;
+ void *data;
+ };
+
+@@ -170,7 +170,7 @@ void xenbus_resume(void);
+ * be saved in the store.
+ */
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+- struct xenbus_watch *watch,
++ struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *,
+ const char **, unsigned int));
+
+@@ -185,7 +185,7 @@ int xenbus_watch_path(struct xenbus_devi
+ * saved in the store.
+ */
+ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
+- const char *path2, struct xenbus_watch *watch,
++ const char *path2, struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *,
+ const char **, unsigned int));
+
+@@ -216,8 +216,8 @@ int xenbus_grant_ring(struct xenbus_devi
+ * page to that address, and sets *vaddr to that address.
+ * xenbus_map_ring does not allocate the virtual address space (you must do
+ * this yourself!). It only maps in the page to the specified address.
+- * Returns 0 on success, and GNTST_* (see xen/include/public/grant_table.h) or
+- * -ENOMEM on error. If an error is returned, device will switch to
++ * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
++ * or -ENOMEM on error. If an error is returned, device will switch to
+ * XenbusStateClosing and the error message will be saved in XenStore.
+ */
+ int xenbus_map_ring_valloc(struct xenbus_device *dev,
+@@ -231,7 +231,7 @@ int xenbus_map_ring(struct xenbus_device
+ * Use xenbus_unmap_ring_vfree if you mapped in your memory with
+ * xenbus_map_ring_valloc (it will free the virtual address space).
+ * Returns 0 on success and returns GNTST_* on error
+- * (see xen/include/public/grant_table.h).
++ * (see xen/include/interface/grant_table.h).
+ */
+ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
+ int xenbus_unmap_ring(struct xenbus_device *dev,
+@@ -285,7 +285,7 @@ void xenbus_dev_fatal(struct xenbus_devi
+ ...);
+
+
+-#endif /* _ASM_XEN_XENBUS_H */
++#endif /* _XEN_XENBUS_H */
+
+ /*
+ * Local variables:
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/Makefile
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,5 @@
++#
++# Makefile for Xen components
++#
++
++obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o xenconsole.o xen_ksyms.o
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/Makefile
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/Makefile Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,20 @@
++
++obj-y += util.o
++
++obj-y += core/
++obj-y += console/
++obj-y += evtchn/
++#obj-y += balloon/
++obj-y += privcmd/
++obj-y += blkback/
++#obj-y += netback/
++obj-y += blkfront/
++obj-y += xenbus/
++#obj-y += netfront/
++#obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += privcmd/
++#obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
++#obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
++#obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
++#obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/
++#obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
++
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/README
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/README Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,2 @@
++This is a temporary location for source/Makefiles that need to be
++patched/reworked in drivers/xen to work with xenlinux/ia64.
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/coreMakefile
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/coreMakefile Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,24 @@
++#
++# Makefile for the linux kernel.
++#
++
++XENARCH := $(subst ",,$(CONFIG_XENARCH))
++
++CPPFLAGS_vmlinux.lds += -U$(XENARCH)
++
++$(obj)/vmlinux.lds.S:
++ @ln -fsn $(srctree)/arch/$(XENARCH)/kernel/vmlinux.lds.S $@
++
++
++obj-y := gnttab.o
++obj-$(CONFIG_PROC_FS) += xen_proc.o
++
++ifeq ($(ARCH),ia64)
++obj-y += evtchn_ia64.o
++obj-y += xenia64_init.o
++else
++extra-y += vmlinux.lds
++obj-y += reboot.o evtchn.o fixup.o
++obj-$(CONFIG_SMP) += smp.o # setup_profiling_timer def'd in ia64
++obj-$(CONFIG_NET) += skbuff.o # until networking is up on ia64
++endif
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/evtchn_ia64.c
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/evtchn_ia64.c Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,273 @@
++/* NOTE: This file split off from evtchn.c because there was
++ some discussion that the mechanism is sufficiently different.
++ It may be possible to merge it back in the future... djm */
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <asm/hw_irq.h>
++#include <xen/evtchn.h>
++
++#define MAX_EVTCHN 1024
++
++/* Xen will never allocate port zero for any purpose. */
++#define VALID_EVTCHN(_chn) (((_chn) != 0) && ((_chn) < MAX_EVTCHN))
++
++/* Binding types. Hey, only IRQT_VIRQ and IRQT_EVTCHN are supported now
++ * for XEN/IA64 - ktian1
++ */
++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))
++/* 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))
++
++/* Packed IRQ information: binding type, sub-type index, and event channel. */
++static u32 irq_info[NR_IRQS];
++
++/* One note for XEN/IA64 is that we have all event channels bound to one
++ * physical irq vector. So we always mean evtchn vector identical to 'irq'
++ * vector in this context. - ktian1
++ */
++static struct {
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ void *dev_id;
++ char opened; /* Whether allocated */
++} evtchns[MAX_EVTCHN];
++
++/*
++ * This lock protects updates to the following mapping and reference-count
++ * arrays. The lock does not need to be acquired to read the mapping tables.
++ */
++static spinlock_t irq_mapping_update_lock;
++
++void mask_evtchn(int port)
++{
++ shared_info_t *s = HYPERVISOR_shared_info;
++ synch_set_bit(port, &s->evtchn_mask[0]);
++}
++EXPORT_SYMBOL(mask_evtchn);
++
++void unmask_evtchn(int port)
++{
++ shared_info_t *s = HYPERVISOR_shared_info;
++ unsigned int cpu = smp_processor_id();
++ vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
++
++#if 0 // FIXME: diverged from x86 evtchn.c
++ /* Slow path (hypercall) if this is a non-local port. */
++ if (unlikely(cpu != cpu_from_evtchn(port))) {
++ evtchn_op_t op = { .cmd = EVTCHNOP_unmask,
++ .u.unmask.port = port };
++ (void)HYPERVISOR_event_channel_op(&op);
++ return;
++ }
++#endif
++
++ synch_clear_bit(port, &s->evtchn_mask[0]);
++
++ /*
++ * The following is basically the equivalent of 'hw_resend_irq'. Just
++ * like a real IO-APIC we 'lose the interrupt edge' if the channel is
++ * masked.
++ */
++ if (synch_test_bit(port, &s->evtchn_pending[0]) &&
++ !synch_test_and_set_bit(port / BITS_PER_LONG,
++ &vcpu_info->evtchn_pending_sel)) {
++ vcpu_info->evtchn_upcall_pending = 1;
++ if (!vcpu_info->evtchn_upcall_mask)
++ force_evtchn_callback();
++ }
++}
++EXPORT_SYMBOL(unmask_evtchn);
++
++
++#define unbound_irq(e) (VALID_EVTCHN(e) && (!evtchns[(e)].opened))
++int bind_virq_to_irqhandler(
++ unsigned int virq,
++ unsigned int cpu,
++ irqreturn_t (*handler)(int, void *, struct pt_regs *),
++ unsigned long irqflags,
++ const char *devname,
++ void *dev_id)
++{
++ evtchn_op_t op;
++ int evtchn;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ op.cmd = EVTCHNOP_bind_virq;
++ op.u.bind_virq.virq = virq;
++ op.u.bind_virq.vcpu = cpu;
++ BUG_ON(HYPERVISOR_event_channel_op(&op) != 0 );
++ evtchn = op.u.bind_virq.port;
++
++ if (!unbound_irq(evtchn)) {
++ evtchn = -EINVAL;
++ goto out;
++ }
++
++ evtchns[evtchn].handler = handler;
++ evtchns[evtchn].dev_id = dev_id;
++ evtchns[evtchn].opened = 1;
++ irq_info[evtchn] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++
++ unmask_evtchn(evtchn);
++out:
++ spin_unlock(&irq_mapping_update_lock);
++ return evtchn;
++}
++
++int bind_evtchn_to_irqhandler(unsigned int evtchn,
++ irqreturn_t (*handler)(int, void *, struct pt_regs *),
++ unsigned long irqflags, const char * devname, void *dev_id)
++{
++ spin_lock(&irq_mapping_update_lock);
++
++ if (!unbound_irq(evtchn)) {
++ evtchn = -EINVAL;
++ goto out;
++ }
++
++ evtchns[evtchn].handler = handler;
++ evtchns[evtchn].dev_id = dev_id;
++ evtchns[evtchn].opened = 1;
++ irq_info[evtchn] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
++
++ unmask_evtchn(evtchn);
++out:
++ spin_unlock(&irq_mapping_update_lock);
++ return evtchn;
++}
++
++int bind_ipi_to_irqhandler(
++ unsigned int ipi,
++ unsigned int cpu,
++ irqreturn_t (*handler)(int, void *, struct pt_regs *),
++ unsigned long irqflags,
++ const char *devname,
++ void *dev_id)
++{
++ printk("%s is called which has not been supported now...?\n", __FUNCTION__);
++ while(1);
++}
++
++void unbind_from_irqhandler(unsigned int irq, void *dev_id)
++{
++ evtchn_op_t op;
++ int evtchn = evtchn_from_irq(irq);
++
++ spin_lock(&irq_mapping_update_lock);
++
++ if (unbound_irq(irq))
++ goto out;
++
++ op.cmd = EVTCHNOP_close;
++ op.u.close.port = evtchn;
++ BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
++
++ switch (type_from_irq(irq)) {
++ case IRQT_VIRQ:
++ /* Add smp stuff later... */
++ break;
++ case IRQT_IPI:
++ /* Add smp stuff later... */
++ break;
++ default:
++ break;
++ }
++
++ mask_evtchn(evtchn);
++ evtchns[evtchn].handler = NULL;
++ evtchns[evtchn].opened = 0;
++
++out:
++ spin_unlock(&irq_mapping_update_lock);
++}
++
++void notify_remote_via_irq(int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (!unbound_irq(evtchn))
++ notify_remote_via_evtchn(evtchn);
++}
++
++irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned long l1, l2;
++ unsigned int l1i, l2i, port;
++ irqreturn_t (*handler)(int, void *, struct pt_regs *);
++ shared_info_t *s = HYPERVISOR_shared_info;
++ vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
++
++ vcpu_info->evtchn_upcall_mask = 1;
++ vcpu_info->evtchn_upcall_pending = 0;
++
++ /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
++ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
++ while ( l1 != 0 )
++ {
++ l1i = __ffs(l1);
++ l1 &= ~(1UL << l1i);
++
++ while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
++ {
++ l2i = __ffs(l2);
++ l2 &= ~(1UL << l2i);
++
++ port = (l1i * BITS_PER_LONG) + l2i;
++ if ( (handler = evtchns[port].handler) != NULL )
++ {
++ clear_evtchn(port);
++ handler(port, evtchns[port].dev_id, regs);
++ }
++ else
++ {
++ evtchn_device_upcall(port);
++ }
++ }
++ }
++ vcpu_info->evtchn_upcall_mask = 0;
++ return IRQ_HANDLED;
++}
++
++void force_evtchn_callback(void)
++{
++ //(void)HYPERVISOR_xen_version(0, NULL);
++}
++
++static struct irqaction evtchn_irqaction = {
++ .handler = evtchn_interrupt,
++ .flags = SA_INTERRUPT,
++ .name = "xen-event-channel"
++};
++
++int evtchn_irq = 0xe9;
++void __init evtchn_init(void)
++{
++ shared_info_t *s = HYPERVISOR_shared_info;
++ vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
++
++#if 0
++ int ret;
++ irq = assign_irq_vector(AUTO_ASSIGN);
++ ret = request_irq(irq, evtchn_interrupt, 0, "xen-event-channel", NULL);
++ if (ret < 0)
++ {
++ printk("xen-event-channel unable to get irq %d (%d)\n", irq, ret);
++ return;
++ }
++#endif
++ register_percpu_irq(evtchn_irq, &evtchn_irqaction);
++
++ vcpu_info->arch.evtchn_vector = evtchn_irq;
++ printk("xen-event-channel using irq %d\n", evtchn_irq);
++
++ spin_lock_init(&irq_mapping_update_lock);
++ memset(evtchns, 0, sizeof(evtchns));
++}
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/patches/blkback.c.patch
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/patches/blkback.c.patch Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,57 @@
++diff -Naur xen/blkback/blkback.c xen.patched/blkback/blkback.c
++--- xen/blkback/blkback.c 2005-09-23 10:54:50.000000000 -0600
+++++ xen.patched/blkback/blkback.c 2005-09-23 10:57:51.000000000 -0600
++@@ -30,10 +30,16 @@
++ static unsigned long mmap_vstart;
++ #define MMAP_PAGES \
++ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+++#ifdef __ia64__
+++static void *pending_vaddrs[MMAP_PAGES];
+++#define MMAP_VADDR(_idx, _i) \
+++ (unsigned long)(pending_vaddrs[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
+++#else
++ #define MMAP_VADDR(_req,_seg) \
++ (mmap_vstart + \
++ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
++ ((_seg) * PAGE_SIZE))
+++#endif
++
++ /*
++ * Each outstanding request that we've passed to the lower device layers has a
++@@ -377,9 +383,13 @@
++ goto bad_descriptor;
++ }
++
+++#ifdef __ia64__
+++ MMAP_VADDR(pending_idx,i) = gnttab_map_vaddr(map[i]);
+++#else
++ phys_to_machine_mapping[__pa(MMAP_VADDR(
++ pending_idx, i)) >> PAGE_SHIFT] =
++ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+++#endif
++
++ pending_handle(pending_idx, i) = map[i].handle;
++ }
++@@ -500,9 +510,22 @@
++
++ blkif_interface_init();
++
+++#ifdef __ia64__
+++ {
+++ extern unsigned long alloc_empty_foreign_map_page_range(unsigned long pages);
+++ int i;
+++
+++ mmap_vstart = alloc_empty_foreign_map_page_range(MMAP_PAGES);
+++ printk("Allocated mmap_vstart: 0x%lx\n", mmap_vstart);
+++ for(i = 0; i < MMAP_PAGES; i++)
+++ pending_vaddrs[i] = mmap_vstart + (i << PAGE_SHIFT);
+++ BUG_ON(mmap_vstart == NULL);
+++ }
+++#else
++ page = balloon_alloc_empty_page_range(MMAP_PAGES);
++ BUG_ON(page == NULL);
++ mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+++#endif
++
++ pending_cons = 0;
++ pending_prod = MAX_PENDING_REQS;
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/patches/console.c.patch
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/patches/console.c.patch Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,18 @@
++--- xen/console/console.c 2005-11-02 14:13:07.000000000 +0100
+++++ xen.patched/console/console.c 2005-11-02 14:21:20.000000000 +0100
++@@ -768,9 +771,15 @@
++ #endif
++
++ if (xen_start_info->flags & SIF_INITDOMAIN) {
+++#ifdef __ia64__
+++ xencons_priv_irq = bind_virq_to_evtchn(VIRQ_CONSOLE);
+++ bind_evtchn_to_irqhandler(xencons_priv_irq,
+++ xencons_priv_interrupt, 0, "console", NULL);
+++#else
++ xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
++ (void)request_irq(xencons_priv_irq,
++ xencons_priv_interrupt, 0, "console", NULL);
+++#endif
++ } else {
++ xencons_ring_register_receiver(xencons_rx);
++ }
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/patches/devmem.c.patch
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/patches/devmem.c.patch Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,3 @@
++diff -Naur xen/core/devmem.c xen.patched/core/devmem.c
++--- xen/core/devmem.c 2005-09-23 10:54:50.000000000 -0600
+++++ xen.patched/core/devmem.c 2005-09-23 10:57:51.000000000 -0600
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/patches/gnttab.c.patch
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/patches/gnttab.c.patch Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,46 @@
++diff -Naur xen/core/gnttab.c xen.patched/core/gnttab.c
++--- xen/core/gnttab.c 2005-09-23 10:54:50.000000000 -0600
+++++ xen.patched/core/gnttab.c 2005-09-23 10:57:51.000000000 -0600
++@@ -346,6 +350,10 @@
++ if ( hypercall.op != __HYPERVISOR_grant_table_op )
++ return -ENOSYS;
++
+++
+++#ifdef __ia64__
+++ ret = HYPERVISOR_grant_table_op(hypercall.arg[0], (void *)hypercall.arg[1], hypercall.arg[2]);
+++#else
++ /* hypercall-invoking asm taken from privcmd.c */
++ __asm__ __volatile__ (
++ "pushl %%ebx; pushl %%ecx; pushl %%edx; "
++@@ -359,6 +367,7 @@
++ TRAP_INSTR "; "
++ "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
++ : "=a" (ret) : "0" (&hypercall) : "memory" );
+++#endif
++
++ return ret;
++ }
++@@ -423,8 +432,13 @@
++ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1));
++ BUG_ON(setup.status != 0);
++
+++#ifdef __ia64__
+++ 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;
++ }
++@@ -450,7 +466,9 @@
++
++ 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;
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/patches/privcmd.c.patch
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/patches/privcmd.c.patch Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,43 @@
++diff -Naur xen/privcmd/privcmd.c xen.patched/privcmd/privcmd.c
++--- xen/privcmd/privcmd.c 2005-09-23 10:54:50.000000000 -0600
+++++ xen.patched/privcmd/privcmd.c 2005-09-23 10:57:51.000000000 -0600
++@@ -180,6 +183,15 @@
++ for (i = 0; i < m.num; i++, addr += PAGE_SIZE, p++) {
++ if (get_user(mfn, p))
++ return -EFAULT;
+++#ifdef __ia64__
+++ ret = remap_pfn_range(vma,
+++ addr&PAGE_MASK,
+++ mfn,
+++ 1<<PAGE_SHIFT,
+++ vma->vm_page_prot);
+++ if (ret < 0)
+++ goto batch_err;
+++#else
++
++ ret = create_lookup_pte_addr(vma->vm_mm, addr, &ptep);
++ if (ret)
++@@ -190,6 +202,7 @@
++
++ if (HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0)
++ put_user(0xF0000000 | mfn, p);
+++#endif
++ }
++
++ ret = 0;
++@@ -205,6 +218,7 @@
++ break;
++ #endif
++
+++#ifndef __ia64__
++ case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN: {
++ unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
++ pgd_t *pgd = pgd_offset_k(m2pv);
++@@ -216,6 +230,7 @@
++ -EFAULT: 0;
++ }
++ break;
+++#endif
++
++ default:
++ ret = -EINVAL;
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/drivers/xenia64_init.c
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/drivers/xenia64_init.c Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,55 @@
++#ifdef __ia64__
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/efi.h>
++#include <asm/sal.h>
++#include <asm/hypervisor.h>
++/* #include <asm-xen/evtchn.h> */
++#include <linux/vmalloc.h>
++
++shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)0xf100000000000000;
++EXPORT_SYMBOL(HYPERVISOR_shared_info);
++
++static int initialized;
++start_info_t *xen_start_info;
++
++int xen_init(void)
++{
++ shared_info_t *s = HYPERVISOR_shared_info;
++
++ if (initialized)
++ return running_on_xen ? 0 : -1;
++
++ if (!running_on_xen)
++ return -1;
++
++ xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
++ xen_start_info->flags = s->arch.flags;
++ printk("Running on Xen! start_info_pfn=0x%lx nr_pages=%d flags=0x%x\n",
++ s->arch.start_info_pfn, xen_start_info->nr_pages,
++ xen_start_info->flags);
++
++ evtchn_init();
++ initialized = 1;
++ return 0;
++}
++
++/* We just need a range of legal va here, though finally identity
++ * mapped one is instead used for gnttab mapping.
++ */
++unsigned long alloc_empty_foreign_map_page_range(unsigned long pages)
++{
++ struct vm_struct *vma;
++
++ if ( (vma = get_vm_area(PAGE_SIZE * pages, VM_ALLOC)) == NULL )
++ return NULL;
++
++ return (unsigned long)vma->addr;
++}
++
++#if 0
++/* These should be define'd but some drivers use them without
++ * a convenient arch include */
++unsigned long mfn_to_pfn(unsigned long mfn) { return mfn; }
++#endif
++#endif
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/hypercall.S
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/hypercall.S Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,323 @@
++/*
++ * Support routines for Xen hypercalls
++ *
++ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer at hp.com>
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/asmmacro.h>
++
++GLOBAL_ENTRY(xen_get_ivr)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov r8=cr.ivr;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_GET_IVR
++ ;;
++ st8 [r9]=r10
++ br.ret.sptk.many rp
++ ;;
++END(xen_get_ivr)
++
++GLOBAL_ENTRY(xen_get_tpr)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov r8=cr.tpr;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_GET_TPR
++ ;;
++ st8 [r9]=r10
++ br.ret.sptk.many rp
++ ;;
++END(xen_get_tpr)
++
++GLOBAL_ENTRY(xen_set_tpr)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov cr.tpr=r32;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_SET_TPR
++ ;;
++ st8 [r9]=r10
++ br.ret.sptk.many rp
++ ;;
++END(xen_set_tpr)
++
++GLOBAL_ENTRY(xen_eoi)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov cr.eoi=r0;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_EOI
++ ;;
++ st8 [r9]=r10
++ br.ret.sptk.many rp
++ ;;
++END(xen_eoi)
++
++GLOBAL_ENTRY(xen_thash)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) thash r8=r32;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_THASH
++ ;;
++ st8 [r9]=r10
++ ;;
++ br.ret.sptk.many rp
++ ;;
++END(xen_thash)
++
++GLOBAL_ENTRY(xen_set_itm)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov cr.itm=r32;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_SET_ITM
++ ;;
++ st8 [r9]=r10
++ ;;
++ br.ret.sptk.many rp
++ ;;
++END(xen_set_itm)
++
++GLOBAL_ENTRY(xen_ptcga)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) ptc.ga r32,r33;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r11=XSI_PSR_IC
++ mov r8=r32
++ mov r9=r33
++ ;;
++ ld8 r10=[r11]
++ ;;
++ st8 [r11]=r0
++ ;;
++ XEN_HYPER_PTC_GA
++ ;;
++ st8 [r11]=r10
++ ;;
++ br.ret.sptk.many rp
++ ;;
++END(xen_ptcga)
++
++GLOBAL_ENTRY(xen_get_rr)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov r8=rr[r32];;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r9=XSI_PSR_IC
++ mov r8=r32
++ ;;
++ ld8 r10=[r9]
++ ;;
++ st8 [r9]=r0
++ ;;
++ XEN_HYPER_GET_RR
++ ;;
++ st8 [r9]=r10
++ ;;
++ br.ret.sptk.many rp
++ ;;
++END(xen_get_rr)
++
++GLOBAL_ENTRY(xen_set_rr)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov rr[r32]=r33;;
++(p7) br.ret.sptk.many rp
++ ;;
++ movl r11=XSI_PSR_IC
++ mov r8=r32
++ mov r9=r33
++ ;;
++ ld8 r10=[r11]
++ ;;
++ st8 [r11]=r0
++ ;;
++ XEN_HYPER_SET_RR
++ ;;
++ st8 [r11]=r10
++ ;;
++ br.ret.sptk.many rp
++ ;;
++END(xen_set_rr)
++
++GLOBAL_ENTRY(xen_set_kr)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.ne p7,p0=r8,r0;;
++(p7) br.cond.spnt.few 1f;
++ ;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar0=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar1=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar2=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar3=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar4=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar5=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar6=r9
++(p7) br.ret.sptk.many rp;;
++ cmp.eq p7,p0=r8,r0
++ adds r8=-1,r8;;
++(p7) mov ar7=r9
++(p7) br.ret.sptk.many rp;;
++
++1: movl r11=XSI_PSR_IC
++ mov r8=r32
++ mov r9=r33
++ ;;
++ ld8 r10=[r11]
++ ;;
++ st8 [r11]=r0
++ ;;
++ XEN_HYPER_SET_KR
++ ;;
++ st8 [r11]=r10
++ ;;
++ br.ret.sptk.many rp
++ ;;
++END(xen_set_rr)
++
++GLOBAL_ENTRY(xen_fc)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) fc r32;;
++(p7) br.ret.sptk.many rp
++ ;;
++ ptc.e r96 // this is a "privified" fc r32
++ ;;
++ br.ret.sptk.many rp
++END(xen_fc)
++
++GLOBAL_ENTRY(xen_get_cpuid)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov r8=cpuid[r32];;
++(p7) br.ret.sptk.many rp
++ ;;
++ mov r72=rr[r32] // this is a "privified" mov r8=cpuid[r32]
++ ;;
++ br.ret.sptk.many rp
++END(xen_get_cpuid)
++
++GLOBAL_ENTRY(xen_get_pmd)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov r8=pmd[r32];;
++(p7) br.ret.sptk.many rp
++ ;;
++ mov r72=pmc[r32] // this is a "privified" mov r8=pmd[r32]
++ ;;
++ br.ret.sptk.many rp
++END(xen_get_pmd)
++
++#ifdef CONFIG_IA32_SUPPORT
++GLOBAL_ENTRY(xen_get_eflag)
++ movl r8=running_on_xen;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(p7) mov r8=ar24;;
++(p7) br.ret.sptk.many rp
++ ;;
++ mov ar24=r72 // this is a "privified" mov r8=ar.eflg
++ ;;
++ 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;;
++ ld4 r8=[r8];;
++ cmp.eq p7,p0=r8,r0;;
++(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
++ ;;
++ br.ret.sptk.many rp
++END(xen_get_eflag)
++#endif
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xen_ksyms.c
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xen_ksyms.c Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,12 @@
++/*
++ * Architecture-specific kernel symbols
++ *
++ * Don't put any exports here unless it's defined in an assembler file.
++ * All other exports should be put directly after the definition.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++extern int is_running_on_xen(void);
++EXPORT_SYMBOL(is_running_on_xen);
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xenconsole.c
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xenconsole.c Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,19 @@
++#include <linux/config.h>
++#include <linux/console.h>
++
++int
++early_xen_console_setup (char *cmdline)
++{
++#ifdef CONFIG_XEN
++#ifndef CONFIG_IA64_HP_SIM
++ extern int running_on_xen;
++ if (running_on_xen) {
++ extern struct console hpsim_cons;
++ hpsim_cons.flags |= CON_BOOT;
++ register_console(&hpsim_cons);
++ return 0;
++ }
++#endif
++#endif
++ return -1;
++}
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xenentry.S
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xenentry.S Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,850 @@
++/*
++ * ia64/xen/entry.S
++ *
++ * Alternate kernel routines for Xen. Heavily leveraged from
++ * ia64/kernel/entry.S
++ *
++ * Copyright (C) 2005 Hewlett-Packard Co
++ * Dan Magenheimer <dan.magenheimer at .hp.com>
++ */
++
++#include <linux/config.h>
++
++#include <asm/asmmacro.h>
++#include <asm/cache.h>
++#include <asm/errno.h>
++#include <asm/kregs.h>
++#include <asm/asm-offsets.h>
++#include <asm/pgtable.h>
++#include <asm/percpu.h>
++#include <asm/processor.h>
++#include <asm/thread_info.h>
++#include <asm/unistd.h>
++
++#ifdef CONFIG_XEN
++#include "xenminstate.h"
++#else
++#include "minstate.h"
++#endif
++
++/*
++ * prev_task <- ia64_switch_to(struct task_struct *next)
++ * With Ingo's new scheduler, interrupts are disabled when this routine gets
++ * called. The code starting at .map relies on this. The rest of the code
++ * doesn't care about the interrupt masking status.
++ */
++#ifdef CONFIG_XEN
++GLOBAL_ENTRY(xen_switch_to)
++ .prologue
++ alloc r16=ar.pfs,1,0,0,0
++ movl r22=running_on_xen;;
++ ld4 r22=[r22];;
++ cmp.eq p7,p0=r22,r0
++(p7) br.cond.sptk.many __ia64_switch_to;;
++#else
++GLOBAL_ENTRY(ia64_switch_to)
++ .prologue
++ alloc r16=ar.pfs,1,0,0,0
++#endif
++ DO_SAVE_SWITCH_STACK
++ .body
++
++ adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
++ movl r25=init_task
++ mov r27=IA64_KR(CURRENT_STACK)
++ adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
++ dep r20=0,in0,61,3 // physical address of "next"
++ ;;
++ st8 [r22]=sp // save kernel stack pointer of old task
++ shr.u r26=r20,IA64_GRANULE_SHIFT
++ cmp.eq p7,p6=r25,in0
++ ;;
++#ifdef CONFIG_XEN
++ movl r8=XSI_PSR_IC
++ ;;
++ st4 [r8]=r0 // force psr.ic off for hyperprivop(s)
++ ;;
++#endif
++ /*
++ * If we've already mapped this task's page, we can skip doing it again.
++ */
++(p6) cmp.eq p7,p6=r26,r27
++(p6) br.cond.dpnt .map
++ ;;
++.done:
++#ifdef CONFIG_XEN
++ // psr.ic already off
++ // update "current" application register
++ mov r8=IA64_KR_CURRENT
++ mov r9=in0;;
++ XEN_HYPER_SET_KR
++ ld8 sp=[r21] // load kernel stack pointer of new task
++ movl r27=XSI_PSR_IC
++ mov r8=1
++ ;;
++ st4 [r27]=r8 // psr.ic back on
++ ;;
++#else
++(p6) ssm psr.ic // if we had to map, reenable the psr.ic bit FIRST!!!
++ ;;
++(p6) srlz.d
++ ld8 sp=[r21] // load kernel stack pointer of new task
++ mov IA64_KR(CURRENT)=in0 // update "current" application register
++#endif
++ mov r8=r13 // return pointer to previously running task
++ mov r13=in0 // set "current" pointer
++ ;;
++ DO_LOAD_SWITCH_STACK
++
++#ifdef CONFIG_SMP
++ sync.i // ensure "fc"s done by this CPU are visible on other CPUs
++#endif
++ br.ret.sptk.many rp // boogie on out in new context
++
++.map:
++#ifdef CONFIG_XEN
++ // psr.ic already off
++#else
++ rsm psr.ic // interrupts (psr.i) are already disabled here
++#endif
++ movl r25=PAGE_KERNEL
++ ;;
++ srlz.d
++ or r23=r25,r20 // construct PA | page properties
++ mov r25=IA64_GRANULE_SHIFT<<2
++ ;;
++#ifdef CONFIG_XEN
++ movl r8=XSI_ITIR
++ ;;
++ st8 [r8]=r25
++ ;;
++ movl r8=XSI_IFA
++ ;;
++ st8 [r8]=in0 // VA of next task...
++ ;;
++ mov r25=IA64_TR_CURRENT_STACK
++ // remember last page we mapped...
++ mov r8=IA64_KR_CURRENT_STACK
++ mov r9=r26;;
++ XEN_HYPER_SET_KR;;
++#else
++ mov cr.itir=r25
++ mov cr.ifa=in0 // VA of next task...
++ ;;
++ mov r25=IA64_TR_CURRENT_STACK
++ mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped...
++#endif
++ ;;
++ itr.d dtr[r25]=r23 // wire in new mapping...
++ br.cond.sptk .done
++#ifdef CONFIG_XEN
++END(xen_switch_to)
++#else
++END(ia64_switch_to)
++#endif
++
++ /*
++ * Invoke a system call, but do some tracing before and after the call.
++ * We MUST preserve the current register frame throughout this routine
++ * because some system calls (such as ia64_execve) directly
++ * manipulate ar.pfs.
++ */
++#ifdef CONFIG_XEN
++GLOBAL_ENTRY(xen_trace_syscall)
++ PT_REGS_UNWIND_INFO(0)
++ movl r16=running_on_xen;;
++ ld4 r16=[r16];;
++ cmp.eq p7,p0=r16,r0
++(p7) br.cond.sptk.many __ia64_trace_syscall;;
++#else
++GLOBAL_ENTRY(ia64_trace_syscall)
++ PT_REGS_UNWIND_INFO(0)
++#endif
++ /*
++ * We need to preserve the scratch registers f6-f11 in case the system
++ * call is sigreturn.
++ */
++ adds r16=PT(F6)+16,sp
++ adds r17=PT(F7)+16,sp
++ ;;
++ stf.spill [r16]=f6,32
++ stf.spill [r17]=f7,32
++ ;;
++ stf.spill [r16]=f8,32
++ stf.spill [r17]=f9,32
++ ;;
++ stf.spill [r16]=f10
++ stf.spill [r17]=f11
++ br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args
++ adds r16=PT(F6)+16,sp
++ adds r17=PT(F7)+16,sp
++ ;;
++ ldf.fill f6=[r16],32
++ ldf.fill f7=[r17],32
++ ;;
++ ldf.fill f8=[r16],32
++ ldf.fill f9=[r17],32
++ ;;
++ ldf.fill f10=[r16]
++ ldf.fill f11=[r17]
++ // the syscall number may have changed, so re-load it and re-calculate the
++ // syscall entry-point:
++ adds r15=PT(R15)+16,sp // r15 = &pt_regs.r15 (syscall #)
++ ;;
++ ld8 r15=[r15]
++ mov r3=NR_syscalls - 1
++ ;;
++ adds r15=-1024,r15
++ movl r16=sys_call_table
++ ;;
++ shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024)
++ cmp.leu p6,p7=r15,r3
++ ;;
++(p6) ld8 r20=[r20] // load address of syscall entry point
++(p7) movl r20=sys_ni_syscall
++ ;;
++ mov b6=r20
++ br.call.sptk.many rp=b6 // do the syscall
++.strace_check_retval:
++ cmp.lt p6,p0=r8,r0 // syscall failed?
++ adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
++ adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
++ mov r10=0
++(p6) br.cond.sptk strace_error // syscall failed ->
++ ;; // avoid RAW on r10
++.strace_save_retval:
++.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8
++.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10
++ br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value
++.ret3: br.cond.sptk .work_pending_syscall_end
++
++strace_error:
++ ld8 r3=[r2] // load pt_regs.r8
++ sub r9=0,r8 // negate return value to get errno value
++ ;;
++ cmp.ne p6,p0=r3,r0 // is pt_regs.r8!=0?
++ adds r3=16,r2 // r3=&pt_regs.r10
++ ;;
++(p6) mov r10=-1
++(p6) mov r8=r9
++ br.cond.sptk .strace_save_retval
++#ifdef CONFIG_XEN
++END(xen_trace_syscall)
++#else
++END(ia64_trace_syscall)
++#endif
++
++/*
++ * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
++ * need to switch to bank 0 and doesn't restore the scratch registers.
++ * To avoid leaking kernel bits, the scratch registers are set to
++ * the following known-to-be-safe values:
++ *
++ * r1: restored (global pointer)
++ * r2: cleared
++ * r3: 1 (when returning to user-level)
++ * r8-r11: restored (syscall return value(s))
++ * r12: restored (user-level stack pointer)
++ * r13: restored (user-level thread pointer)
++ * r14: cleared
++ * r15: restored (syscall #)
++ * r16-r17: cleared
++ * r18: user-level b6
++ * r19: cleared
++ * r20: user-level ar.fpsr
++ * r21: user-level b0
++ * r22: cleared
++ * r23: user-level ar.bspstore
++ * r24: user-level ar.rnat
++ * r25: user-level ar.unat
++ * r26: user-level ar.pfs
++ * r27: user-level ar.rsc
++ * r28: user-level ip
++ * r29: user-level psr
++ * r30: user-level cfm
++ * r31: user-level pr
++ * f6-f11: cleared
++ * pr: restored (user-level pr)
++ * b0: restored (user-level rp)
++ * b6: restored
++ * b7: cleared
++ * ar.unat: restored (user-level ar.unat)
++ * ar.pfs: restored (user-level ar.pfs)
++ * ar.rsc: restored (user-level ar.rsc)
++ * ar.rnat: restored (user-level ar.rnat)
++ * ar.bspstore: restored (user-level ar.bspstore)
++ * ar.fpsr: restored (user-level ar.fpsr)
++ * ar.ccv: cleared
++ * ar.csd: cleared
++ * ar.ssd: cleared
++ */
++#ifdef CONFIG_XEN
++GLOBAL_ENTRY(xen_leave_syscall)
++ PT_REGS_UNWIND_INFO(0)
++ movl r22=running_on_xen;;
++ ld4 r22=[r22];;
++ cmp.eq p7,p0=r22,r0
++(p7) br.cond.sptk.many __ia64_leave_syscall;;
++#else
++ENTRY(ia64_leave_syscall)
++ PT_REGS_UNWIND_INFO(0)
++#endif
++ /*
++ * work.need_resched etc. mustn't get changed by this CPU before it returns to
++ * user- or fsys-mode, hence we disable interrupts early on.
++ *
++ * p6 controls whether current_thread_info()->flags needs to be check for
++ * extra work. We always check for extra work when returning to user-level.
++ * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
++ * is 0. After extra work processing has been completed, execution
++ * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
++ * needs to be redone.
++ */
++#ifdef CONFIG_PREEMPT
++ rsm psr.i // disable interrupts
++ cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
++(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
++ ;;
++ .pred.rel.mutex pUStk,pKStk
++(pKStk) ld4 r21=[r20] // r21 <- preempt_count
++(pUStk) mov r21=0 // r21 <- 0
++ ;;
++ cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
++#else /* !CONFIG_PREEMPT */
++#ifdef CONFIG_XEN
++ movl r2=XSI_PSR_I
++ ;;
++(pUStk) st4 [r2]=r0
++#else
++(pUStk) rsm psr.i
++#endif
++ cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
++(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
++#endif
++.work_processed_syscall:
++ adds r2=PT(LOADRS)+16,r12
++ adds r3=PT(AR_BSPSTORE)+16,r12
++ adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
++ ;;
++(p6) ld4 r31=[r18] // load current_thread_info()->flags
++ ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
++ mov b7=r0 // clear b7
++ ;;
++ ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage)
++ ld8 r18=[r2],PT(R9)-PT(B6) // load b6
++(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
++ ;;
++ mov r16=ar.bsp // M2 get existing backing store pointer
++(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending?
++(p6) br.cond.spnt .work_pending_syscall
++ ;;
++ // start restoring the state saved on the kernel stack (struct pt_regs):
++ ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
++ ld8 r11=[r3],PT(CR_IIP)-PT(R11)
++ mov f6=f0 // clear f6
++ ;;
++ invala // M0|1 invalidate ALAT
++#ifdef CONFIG_XEN
++ movl r29=XSI_PSR_IC
++ ;;
++ st8 [r29]=r0 // note: clears both vpsr.i and vpsr.ic!
++ ;;
++#else
++ rsm psr.i | psr.ic // M2 initiate turning off of interrupt and interruption collection
++#endif
++ mov f9=f0 // clear f9
++
++ ld8 r29=[r2],16 // load cr.ipsr
++ ld8 r28=[r3],16 // load cr.iip
++ mov f8=f0 // clear f8
++ ;;
++ ld8 r30=[r2],16 // M0|1 load cr.ifs
++ mov.m ar.ssd=r0 // M2 clear ar.ssd
++ cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
++ ;;
++ ld8 r25=[r3],16 // M0|1 load ar.unat
++ mov.m ar.csd=r0 // M2 clear ar.csd
++ mov r22=r0 // clear r22
++ ;;
++ ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
++(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
++ mov f10=f0 // clear f10
++ ;;
++ ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // load b0
++ ld8 r27=[r3],PT(PR)-PT(AR_RSC) // load ar.rsc
++ mov f11=f0 // clear f11
++ ;;
++ ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT) // load ar.rnat (may be garbage)
++ ld8 r31=[r3],PT(R1)-PT(PR) // load predicates
++(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
++ ;;
++ ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // load ar.fpsr
++ ld8.fill r1=[r3],16 // load r1
++(pUStk) mov r17=1
++ ;;
++ srlz.d // M0 ensure interruption collection is off
++ ld8.fill r13=[r3],16
++ mov f7=f0 // clear f7
++ ;;
++ ld8.fill r12=[r2] // restore r12 (sp)
++ ld8.fill r15=[r3] // restore r15
++ addl r3=THIS_CPU(ia64_phys_stacked_size_p8),r0
++ ;;
++(pUStk) ld4 r3=[r3] // r3 = cpu_data->phys_stacked_size_p8
++(pUStk) st1 [r14]=r17
++ mov b6=r18 // I0 restore b6
++ ;;
++ mov r14=r0 // clear r14
++ shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
++(pKStk) br.cond.dpnt.many skip_rbs_switch
++
++ mov.m ar.ccv=r0 // clear ar.ccv
++(pNonSys) br.cond.dpnt.many dont_preserve_current_frame
++ br.cond.sptk.many rbs_switch
++#ifdef CONFIG_XEN
++END(xen_leave_syscall)
++#else
++END(ia64_leave_syscall)
++#endif
++
++#ifdef CONFIG_XEN
++GLOBAL_ENTRY(xen_leave_kernel)
++ PT_REGS_UNWIND_INFO(0)
++ movl r22=running_on_xen;;
++ ld4 r22=[r22];;
++ cmp.eq p7,p0=r22,r0
++(p7) br.cond.sptk.many __ia64_leave_kernel;;
++#else
++GLOBAL_ENTRY(ia64_leave_kernel)
++ PT_REGS_UNWIND_INFO(0)
++#endif
++ /*
++ * work.need_resched etc. mustn't get changed by this CPU before it returns to
++ * user- or fsys-mode, hence we disable interrupts early on.
++ *
++ * p6 controls whether current_thread_info()->flags needs to be check for
++ * extra work. We always check for extra work when returning to user-level.
++ * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
++ * is 0. After extra work processing has been completed, execution
++ * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
++ * needs to be redone.
++ */
++#ifdef CONFIG_PREEMPT
++ rsm psr.i // disable interrupts
++ cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
++(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
++ ;;
++ .pred.rel.mutex pUStk,pKStk
++(pKStk) ld4 r21=[r20] // r21 <- preempt_count
++(pUStk) mov r21=0 // r21 <- 0
++ ;;
++ cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
++#else
++#ifdef CONFIG_XEN
++(pUStk) movl r17=XSI_PSR_I
++ ;;
++(pUStk) st4 [r17]=r0
++ ;;
++#else
++(pUStk) rsm psr.i
++#endif
++ cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
++(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
++#endif
++.work_processed_kernel:
++ adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
++ ;;
++(p6) ld4 r31=[r17] // load current_thread_info()->flags
++ adds r21=PT(PR)+16,r12
++ ;;
++
++ lfetch [r21],PT(CR_IPSR)-PT(PR)
++ adds r2=PT(B6)+16,r12
++ adds r3=PT(R16)+16,r12
++ ;;
++ lfetch [r21]
++ ld8 r28=[r2],8 // load b6
++ adds r29=PT(R24)+16,r12
++
++ ld8.fill r16=[r3],PT(AR_CSD)-PT(R16)
++ adds r30=PT(AR_CCV)+16,r12
++(p6) and r19=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
++ ;;
++ ld8.fill r24=[r29]
++ ld8 r15=[r30] // load ar.ccv
++(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending?
++ ;;
++ ld8 r29=[r2],16 // load b7
++ ld8 r30=[r3],16 // load ar.csd
++(p6) br.cond.spnt .work_pending
++ ;;
++ ld8 r31=[r2],16 // load ar.ssd
++ ld8.fill r8=[r3],16
++ ;;
++ ld8.fill r9=[r2],16
++ ld8.fill r10=[r3],PT(R17)-PT(R10)
++ ;;
++ ld8.fill r11=[r2],PT(R18)-PT(R11)
++ ld8.fill r17=[r3],16
++ ;;
++ ld8.fill r18=[r2],16
++ ld8.fill r19=[r3],16
++ ;;
++ ld8.fill r20=[r2],16
++ ld8.fill r21=[r3],16
++ mov ar.csd=r30
++ mov ar.ssd=r31
++ ;;
++#ifdef CONFIG_XEN
++ movl r22=XSI_PSR_IC
++ ;;
++ st8 [r22]=r0 // note: clears both vpsr.i and vpsr.ic!
++ ;;
++#else
++ rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection
++#endif
++ invala // invalidate ALAT
++ ;;
++ ld8.fill r22=[r2],24
++ ld8.fill r23=[r3],24
++ mov b6=r28
++ ;;
++ ld8.fill r25=[r2],16
++ ld8.fill r26=[r3],16
++ mov b7=r29
++ ;;
++ ld8.fill r27=[r2],16
++ ld8.fill r28=[r3],16
++ ;;
++ ld8.fill r29=[r2],16
++ ld8.fill r30=[r3],24
++ ;;
++ ld8.fill r31=[r2],PT(F9)-PT(R31)
++ adds r3=PT(F10)-PT(F6),r3
++ ;;
++ ldf.fill f9=[r2],PT(F6)-PT(F9)
++ ldf.fill f10=[r3],PT(F8)-PT(F10)
++ ;;
++ ldf.fill f6=[r2],PT(F7)-PT(F6)
++ ;;
++ ldf.fill f7=[r2],PT(F11)-PT(F7)
++ ldf.fill f8=[r3],32
++ ;;
++ srlz.i // ensure interruption collection is off
++ mov ar.ccv=r15
++ ;;
++ ldf.fill f11=[r2]
++#ifdef CONFIG_XEN
++ ;;
++ // r16-r31 all now hold bank1 values
++ movl r2=XSI_BANK1_R16
++ movl r3=XSI_BANK1_R16+8
++ ;;
++ st8.spill [r2]=r16,16
++ st8.spill [r3]=r17,16
++ ;;
++ st8.spill [r2]=r18,16
++ st8.spill [r3]=r19,16
++ ;;
++ st8.spill [r2]=r20,16
++ st8.spill [r3]=r21,16
++ ;;
++ st8.spill [r2]=r22,16
++ st8.spill [r3]=r23,16
++ ;;
++ st8.spill [r2]=r24,16
++ st8.spill [r3]=r25,16
++ ;;
++ st8.spill [r2]=r26,16
++ st8.spill [r3]=r27,16
++ ;;
++ st8.spill [r2]=r28,16
++ st8.spill [r3]=r29,16
++ ;;
++ st8.spill [r2]=r30,16
++ st8.spill [r3]=r31,16
++ ;;
++ movl r2=XSI_BANKNUM;;
++ st4 [r2]=r0;
++#else
++ bsw.0 // switch back to bank 0 (no stop bit required beforehand...)
++#endif
++ ;;
++(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
++ adds r16=PT(CR_IPSR)+16,r12
++ adds r17=PT(CR_IIP)+16,r12
++
++(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
++ nop.i 0
++ nop.i 0
++ ;;
++ ld8 r29=[r16],16 // load cr.ipsr
++ ld8 r28=[r17],16 // load cr.iip
++ ;;
++ ld8 r30=[r16],16 // load cr.ifs
++ ld8 r25=[r17],16 // load ar.unat
++ ;;
++ ld8 r26=[r16],16 // load ar.pfs
++ ld8 r27=[r17],16 // load ar.rsc
++ cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
++ ;;
++ ld8 r24=[r16],16 // load ar.rnat (may be garbage)
++ ld8 r23=[r17],16 // load ar.bspstore (may be garbage)
++ ;;
++ ld8 r31=[r16],16 // load predicates
++ ld8 r21=[r17],16 // load b0
++ ;;
++ ld8 r19=[r16],16 // load ar.rsc value for "loadrs"
++ ld8.fill r1=[r17],16 // load r1
++ ;;
++ ld8.fill r12=[r16],16
++ ld8.fill r13=[r17],16
++(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
++ ;;
++ ld8 r20=[r16],16 // ar.fpsr
++ ld8.fill r15=[r17],16
++ ;;
++ ld8.fill r14=[r16],16
++ ld8.fill r2=[r17]
++(pUStk) mov r17=1
++ ;;
++ ld8.fill r3=[r16]
++(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
++ shr.u r18=r19,16 // get byte size of existing "dirty" partition
++ ;;
++ mov r16=ar.bsp // get existing backing store pointer
++ addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
++ ;;
++ ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8
++(pKStk) br.cond.dpnt skip_rbs_switch
++
++ /*
++ * Restore user backing store.
++ *
++ * NOTE: alloc, loadrs, and cover can't be predicated.
++ */
++(pNonSys) br.cond.dpnt dont_preserve_current_frame
++
++rbs_switch:
++#ifdef CONFIG_XEN
++ XEN_HYPER_COVER;
++#else
++ cover // add current frame into dirty partition and set cr.ifs
++#endif
++ ;;
++ mov r19=ar.bsp // get new backing store pointer
++ sub r16=r16,r18 // krbs = old bsp - size of dirty partition
++ cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs
++ ;;
++ sub r19=r19,r16 // calculate total byte size of dirty partition
++ add r18=64,r18 // don't force in0-in7 into memory...
++ ;;
++ shl r19=r19,16 // shift size of dirty partition into loadrs position
++ ;;
++dont_preserve_current_frame:
++ /*
++ * To prevent leaking bits between the kernel and user-space,
++ * we must clear the stacked registers in the "invalid" partition here.
++ * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium,
++ * 5 registers/cycle on McKinley).
++ */
++# define pRecurse p6
++# define pReturn p7
++#ifdef CONFIG_ITANIUM
++# define Nregs 10
++#else
++# define Nregs 14
++#endif
++ alloc loc0=ar.pfs,2,Nregs-2,2,0
++ shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
++ sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize
++ ;;
++ mov ar.rsc=r19 // load ar.rsc to be used for "loadrs"
++ shladd in0=loc1,3,r17
++ mov in1=0
++ ;;
++ TEXT_ALIGN(32)
++rse_clear_invalid:
++#ifdef CONFIG_ITANIUM
++ // cycle 0
++ { .mii
++ alloc loc0=ar.pfs,2,Nregs-2,2,0
++ cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
++ add out0=-Nregs*8,in0
++}{ .mfb
++ add out1=1,in1 // increment recursion count
++ nop.f 0
++ nop.b 0 // can't do br.call here because of alloc (WAW on CFM)
++ ;;
++}{ .mfi // cycle 1
++ mov loc1=0
++ nop.f 0
++ mov loc2=0
++}{ .mib
++ mov loc3=0
++ mov loc4=0
++(pRecurse) br.call.sptk.many b0=rse_clear_invalid
++
++}{ .mfi // cycle 2
++ mov loc5=0
++ nop.f 0
++ cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
++}{ .mib
++ mov loc6=0
++ mov loc7=0
++(pReturn) br.ret.sptk.many b0
++}
++#else /* !CONFIG_ITANIUM */
++ alloc loc0=ar.pfs,2,Nregs-2,2,0
++ cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
++ add out0=-Nregs*8,in0
++ add out1=1,in1 // increment recursion count
++ mov loc1=0
++ mov loc2=0
++ ;;
++ mov loc3=0
++ mov loc4=0
++ mov loc5=0
++ mov loc6=0
++ mov loc7=0
++(pRecurse) br.call.sptk.few b0=rse_clear_invalid
++ ;;
++ mov loc8=0
++ mov loc9=0
++ cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
++ mov loc10=0
++ mov loc11=0
++(pReturn) br.ret.sptk.many b0
++#endif /* !CONFIG_ITANIUM */
++# undef pRecurse
++# undef pReturn
++ ;;
++ alloc r17=ar.pfs,0,0,0,0 // drop current register frame
++ ;;
++ loadrs
++ ;;
++skip_rbs_switch:
++ mov ar.unat=r25 // M2
++(pKStk) extr.u r22=r22,21,1 // I0 extract current value of psr.pp from r22
++(pLvSys)mov r19=r0 // A clear r19 for leave_syscall, no-op otherwise
++ ;;
++(pUStk) mov ar.bspstore=r23 // M2
++(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp
++(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise
++ ;;
++#ifdef CONFIG_XEN
++ movl r25=XSI_IPSR
++ ;;
++ st8[r25]=r29,XSI_IFS-XSI_IPSR
++ ;;
++#else
++ mov cr.ipsr=r29 // M2
++#endif
++ mov ar.pfs=r26 // I0
++(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise
++
++#ifdef CONFIG_XEN
++(p9) st8 [r25]=r30
++ ;;
++ adds r25=XSI_IIP-XSI_IFS,r25
++ ;;
++#else
++(p9) mov cr.ifs=r30 // M2
++#endif
++ mov b0=r21 // I0
++(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise
++
++ mov ar.fpsr=r20 // M2
++#ifdef CONFIG_XEN
++ st8 [r25]=r28
++#else
++ mov cr.iip=r28 // M2
++#endif
++ nop 0
++ ;;
++(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode
++ nop 0
++(pLvSys)mov r2=r0
++
++ mov ar.rsc=r27 // M2
++ mov pr=r31,-1 // I0
++#ifdef CONFIG_XEN
++ ;;
++ XEN_HYPER_RFI;
++#else
++ rfi // B
++#endif
++
++ /*
++ * On entry:
++ * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPT)
++ * r31 = current->thread_info->flags
++ * On exit:
++ * p6 = TRUE if work-pending-check needs to be redone
++ */
++.work_pending_syscall:
++ add r2=-8,r2
++ add r3=-8,r3
++ ;;
++ st8 [r2]=r8
++ st8 [r3]=r10
++.work_pending:
++ tbit.nz p6,p0=r31,TIF_SIGDELAYED // signal delayed from MCA/INIT/NMI/PMI context?
++(p6) br.cond.sptk.few .sigdelayed
++ ;;
++ tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0?
++(p6) br.cond.sptk.few .notify
++#ifdef CONFIG_PREEMPT
++(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
++ ;;
++(pKStk) st4 [r20]=r21
++ ssm psr.i // enable interrupts
++#endif
++ br.call.spnt.many rp=schedule
++.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1
++#ifdef CONFIG_XEN
++ movl r2=XSI_PSR_I
++ ;;
++ st4 [r2]=r0
++#else
++ rsm psr.i // disable interrupts
++#endif
++ ;;
++#ifdef CONFIG_PREEMPT
++(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
++ ;;
++(pKStk) st4 [r20]=r0 // preempt_count() <- 0
++#endif
++(pLvSys)br.cond.sptk.few .work_pending_syscall_end
++ br.cond.sptk.many .work_processed_kernel // re-check
++
++.notify:
++(pUStk) br.call.spnt.many rp=notify_resume_user
++.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0
++(pLvSys)br.cond.sptk.few .work_pending_syscall_end
++ br.cond.sptk.many .work_processed_kernel // don't re-check
++
++// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where
++// it could not be delivered. Deliver it now. The signal might be for us and
++// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed
++// signal.
++
++.sigdelayed:
++ br.call.sptk.many rp=do_sigdelayed
++ cmp.eq p6,p0=r0,r0 // p6 <- 1, always re-check
++(pLvSys)br.cond.sptk.few .work_pending_syscall_end
++ br.cond.sptk.many .work_processed_kernel // re-check
++
++.work_pending_syscall_end:
++ adds r2=PT(R8)+16,r12
++ adds r3=PT(R10)+16,r12
++ ;;
++ ld8 r8=[r2]
++ ld8 r10=[r3]
++ br.cond.sptk.many .work_processed_syscall // re-check
++
++#ifdef CONFIG_XEN
++END(xen_leave_kernel)
++#else
++END(ia64_leave_kernel)
++#endif
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xenhpski.c
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xenhpski.c Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,19 @@
++
++extern unsigned long xen_get_cpuid(int);
++
++int
++running_on_sim(void)
++{
++ int i;
++ long cpuid[6];
++
++ for (i = 0; i < 5; ++i)
++ cpuid[i] = xen_get_cpuid(i);
++ if ((cpuid[0] & 0xff) != 'H') return 0;
++ if ((cpuid[3] & 0xff) != 0x4) return 0;
++ if (((cpuid[3] >> 8) & 0xff) != 0x0) return 0;
++ if (((cpuid[3] >> 16) & 0xff) != 0x0) return 0;
++ if (((cpuid[3] >> 24) & 0x7) != 0x7) return 0;
++ return 1;
++}
++
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xenivt.S
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xenivt.S Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,2044 @@
++/*
++ * arch/ia64/xen/ivt.S
++ *
++ * Copyright (C) 2005 Hewlett-Packard Co
++ * Dan Magenheimer <dan.magenheimer at hp.com>
++ */
++/*
++ * This file defines the interruption vector table used by the CPU.
++ * It does not include one entry per possible cause of interruption.
++ *
++ * The first 20 entries of the table contain 64 bundles each while the
++ * remaining 48 entries contain only 16 bundles each.
++ *
++ * The 64 bundles are used to allow inlining the whole handler for critical
++ * interruptions like TLB misses.
++ *
++ * For each entry, the comment is as follows:
++ *
++ * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
++ * entry offset ----/ / / / /
++ * entry number ---------/ / / /
++ * size of the entry -------------/ / /
++ * vector name -------------------------------------/ /
++ * interruptions triggering this vector ----------------------/
++ *
++ * The table is 32KB in size and must be aligned on 32KB boundary.
++ * (The CPU ignores the 15 lower bits of the address)
++ *
++ * Table is based upon EAS2.6 (Oct 1999)
++ */
++
++#include <linux/config.h>
++
++#include <asm/asmmacro.h>
++#include <asm/break.h>
++#include <asm/ia32.h>
++#include <asm/kregs.h>
++#include <asm/asm-offsets.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include <asm/thread_info.h>
++#include <asm/unistd.h>
++#include <asm/errno.h>
++
++#ifdef CONFIG_XEN
++#define ia64_ivt xen_ivt
++#endif
++
++#if 1
++# define PSR_DEFAULT_BITS psr.ac
++#else
++# define PSR_DEFAULT_BITS 0
++#endif
++
++#if 0
++ /*
++ * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
++ * needed for something else before enabling this...
++ */
++# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
++#else
++# define DBG_FAULT(i)
++#endif
++
++#define MINSTATE_VIRT /* needed by minstate.h */
++#include "xenminstate.h"
++
++#define FAULT(n) \
++ mov r31=pr; \
++ mov r19=n;; /* prepare to save predicates */ \
++ br.sptk.many dispatch_to_fault_handler
++
++ .section .text.ivt,"ax"
++
++ .align 32768 // align on 32KB boundary
++ .global ia64_ivt
++ia64_ivt:
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
++ENTRY(vhpt_miss)
++ DBG_FAULT(0)
++ /*
++ * The VHPT vector is invoked when the TLB entry for the virtual page table
++ * is missing. This happens only as a result of a previous
++ * (the "original") TLB miss, which may either be caused by an instruction
++ * fetch or a data access (or non-access).
++ *
++ * What we do here is normal TLB miss handing for the _original_ miss, followed
++ * by inserting the TLB entry for the virtual page table page that the VHPT
++ * walker was attempting to access. The latter gets inserted as long
++ * as both L1 and L2 have valid mappings for the faulting address.
++ * The TLB entry for the original miss gets inserted only if
++ * the L3 entry indicates that the page is present.
++ *
++ * do_page_fault gets invoked in the following cases:
++ * - the faulting virtual address uses unimplemented address bits
++ * - the faulting virtual address has no L1, L2, or L3 mapping
++ */
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++#ifdef CONFIG_HUGETLB_PAGE
++ movl r18=PAGE_SHIFT
++ movl r25=XSI_ITIR
++ ;;
++ ld8 r25=[r25]
++#endif
++ ;;
++#else
++ mov r16=cr.ifa // get address that caused the TLB miss
++#ifdef CONFIG_HUGETLB_PAGE
++ movl r18=PAGE_SHIFT
++ mov r25=cr.itir
++#endif
++#endif
++ ;;
++#ifdef CONFIG_XEN
++ XEN_HYPER_RSM_PSR_DT;
++#else
++ rsm psr.dt // use physical addressing for data
++#endif
++ mov r31=pr // save the predicate registers
++ mov r19=IA64_KR(PT_BASE) // get page table base address
++ shl r21=r16,3 // shift bit 60 into sign bit
++ shr.u r17=r16,61 // get the region number into r17
++ ;;
++ shr r22=r21,3
++#ifdef CONFIG_HUGETLB_PAGE
++ extr.u r26=r25,2,6
++ ;;
++ cmp.ne p8,p0=r18,r26
++ sub r27=r26,r18
++ ;;
++(p8) dep r25=r18,r25,2,6
++(p8) shr r22=r22,r27
++#endif
++ ;;
++ cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
++ shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address
++ ;;
++(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
++
++ srlz.d
++ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
++
++ .pred.rel "mutex", p6, p7
++(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
++(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
++ ;;
++(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8
++(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
++ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
++ shr.u r18=r22,PMD_SHIFT // shift L2 index into position
++ ;;
++ ld8 r17=[r17] // fetch the L1 entry (may be 0)
++ ;;
++(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL?
++ dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
++ ;;
++(p7) ld8 r20=[r17] // fetch the L2 entry (may be 0)
++ shr.u r19=r22,PAGE_SHIFT // shift L3 index into position
++ ;;
++(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L2 entry NULL?
++ dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
++ ;;
++#ifdef CONFIG_XEN
++(p7) ld8 r18=[r21] // read the L3 PTE
++ movl r19=XSI_ISR
++ ;;
++ ld8 r19=[r19]
++ ;;
++(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
++ movl r22=XSI_IHA
++ ;;
++ ld8 r22=[r22]
++ ;;
++#else
++(p7) ld8 r18=[r21] // read the L3 PTE
++ mov r19=cr.isr // cr.isr bit 0 tells us if this is an insn miss
++ ;;
++(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
++ mov r22=cr.iha // get the VHPT address that caused the TLB miss
++ ;; // avoid RAW on p7
++#endif
++(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
++ dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
++ ;;
++#ifdef CONFIG_XEN
++ mov r24=r8
++ mov r8=r18
++ ;;
++(p10) XEN_HYPER_ITC_D
++ ;;
++(p11) XEN_HYPER_ITC_I
++ ;;
++ mov r8=r24
++ ;;
++(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
++ ;;
++ movl r24=XSI_IFA
++ ;;
++ st8 [r24]=r22
++ ;;
++#else
++(p10) itc.i r18 // insert the instruction TLB entry
++(p11) itc.d r18 // insert the data TLB entry
++(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
++ mov cr.ifa=r22
++#endif
++
++#ifdef CONFIG_HUGETLB_PAGE
++(p8) mov cr.itir=r25 // change to default page-size for VHPT
++#endif
++
++ /*
++ * Now compute and insert the TLB entry for the virtual page table. We never
++ * execute in a page table page so there is no need to set the exception deferral
++ * bit.
++ */
++ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
++ ;;
++#ifdef CONFIG_XEN
++(p7) mov r25=r8
++(p7) mov r8=r24
++ ;;
++(p7) XEN_HYPER_ITC_D
++ ;;
++(p7) mov r8=r25
++ ;;
++#else
++(p7) itc.d r24
++#endif
++ ;;
++#ifdef CONFIG_SMP
++ /*
++ * Tell the assemblers dependency-violation checker that the above "itc" instructions
++ * cannot possibly affect the following loads:
++ */
++ dv_serialize_data
++
++ /*
++ * Re-check L2 and L3 pagetable. If they changed, we may have received a ptc.g
++ * between reading the pagetable and the "itc". If so, flush the entry we
++ * inserted and retry.
++ */
++ ld8 r25=[r21] // read L3 PTE again
++ ld8 r26=[r17] // read L2 entry again
++ ;;
++ cmp.ne p6,p7=r26,r20 // did L2 entry change
++ mov r27=PAGE_SHIFT<<2
++ ;;
++(p6) ptc.l r22,r27 // purge PTE page translation
++(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did L3 PTE change
++ ;;
++(p6) ptc.l r16,r27 // purge translation
++#endif
++
++ mov pr=r31,-1 // restore predicate registers
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(vhpt_miss)
++
++ .org ia64_ivt+0x400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
++ENTRY(itlb_miss)
++ DBG_FAULT(1)
++ /*
++ * The ITLB handler accesses the L3 PTE via the virtually mapped linear
++ * page table. If a nested TLB miss occurs, we switch into physical
++ * mode, walk the page table, and then re-execute the L3 PTE read
++ * and go on normally after that.
++ */
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++#else
++ mov r16=cr.ifa // get virtual address
++#endif
++ mov r29=b0 // save b0
++ mov r31=pr // save predicates
++.itlb_fault:
++#ifdef CONFIG_XEN
++ movl r17=XSI_IHA
++ ;;
++ ld8 r17=[r17] // get virtual address of L3 PTE
++#else
++ mov r17=cr.iha // get virtual address of L3 PTE
++#endif
++ movl r30=1f // load nested fault continuation point
++ ;;
++1: ld8 r18=[r17] // read L3 PTE
++ ;;
++ mov b0=r29
++ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
++(p6) br.cond.spnt page_fault
++ ;;
++#ifdef CONFIG_XEN
++ mov r19=r8
++ mov r8=r18
++ ;;
++ XEN_HYPER_ITC_I
++ ;;
++ mov r8=r19
++#else
++ itc.i r18
++#endif
++ ;;
++#ifdef CONFIG_SMP
++ /*
++ * Tell the assemblers dependency-violation checker that the above "itc" instructions
++ * cannot possibly affect the following loads:
++ */
++ dv_serialize_data
++
++ ld8 r19=[r17] // read L3 PTE again and see if same
++ mov r20=PAGE_SHIFT<<2 // setup page size for purge
++ ;;
++ cmp.ne p7,p0=r18,r19
++ ;;
++(p7) ptc.l r16,r20
++#endif
++ mov pr=r31,-1
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(itlb_miss)
++
++ .org ia64_ivt+0x0800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
++ENTRY(dtlb_miss)
++ DBG_FAULT(2)
++ /*
++ * The DTLB handler accesses the L3 PTE via the virtually mapped linear
++ * page table. If a nested TLB miss occurs, we switch into physical
++ * mode, walk the page table, and then re-execute the L3 PTE read
++ * and go on normally after that.
++ */
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++#else
++ mov r16=cr.ifa // get virtual address
++#endif
++ mov r29=b0 // save b0
++ mov r31=pr // save predicates
++dtlb_fault:
++#ifdef CONFIG_XEN
++ movl r17=XSI_IHA
++ ;;
++ ld8 r17=[r17] // get virtual address of L3 PTE
++#else
++ mov r17=cr.iha // get virtual address of L3 PTE
++#endif
++ movl r30=1f // load nested fault continuation point
++ ;;
++1: ld8 r18=[r17] // read L3 PTE
++ ;;
++ mov b0=r29
++ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
++(p6) br.cond.spnt page_fault
++ ;;
++#ifdef CONFIG_XEN
++ mov r19=r8
++ mov r8=r18
++ ;;
++ XEN_HYPER_ITC_D
++ ;;
++ mov r8=r19
++ ;;
++#else
++ itc.d r18
++#endif
++ ;;
++#ifdef CONFIG_SMP
++ /*
++ * Tell the assemblers dependency-violation checker that the above "itc" instructions
++ * cannot possibly affect the following loads:
++ */
++ dv_serialize_data
++
++ ld8 r19=[r17] // read L3 PTE again and see if same
++ mov r20=PAGE_SHIFT<<2 // setup page size for purge
++ ;;
++ cmp.ne p7,p0=r18,r19
++ ;;
++(p7) ptc.l r16,r20
++#endif
++ mov pr=r31,-1
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(dtlb_miss)
++
++ .org ia64_ivt+0x0c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
++ENTRY(alt_itlb_miss)
++ DBG_FAULT(3)
++#ifdef CONFIG_XEN
++ movl r31=XSI_IPSR
++ ;;
++ ld8 r21=[r31],XSI_IFA-XSI_IPSR // get ipsr, point to ifa
++ movl r17=PAGE_KERNEL
++ ;;
++ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
++ ;;
++ ld8 r16=[r31] // get ifa
++ mov r31=pr
++ ;;
++#else
++ mov r16=cr.ifa // get address that caused the TLB miss
++ movl r17=PAGE_KERNEL
++ mov r21=cr.ipsr
++ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
++ mov r31=pr
++ ;;
++#endif
++#ifdef CONFIG_DISABLE_VHPT
++ shr.u r22=r16,61 // get the region number into r21
++ ;;
++ cmp.gt p8,p0=6,r22 // user mode
++ ;;
++#ifndef CONFIG_XEN
++(p8) thash r17=r16
++ ;;
++(p8) mov cr.iha=r17
++#endif
++(p8) mov r29=b0 // save b0
++(p8) br.cond.dptk .itlb_fault
++#endif
++ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
++ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
++ shr.u r18=r16,57 // move address bit 61 to bit 4
++ ;;
++ andcm r18=0x10,r18 // bit 4=~address-bit(61)
++ cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
++ or r19=r17,r19 // insert PTE control bits into r19
++ ;;
++ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
++(p8) br.cond.spnt page_fault
++ ;;
++#ifdef CONFIG_XEN
++ mov r18=r8
++ mov r8=r19
++ ;;
++ XEN_HYPER_ITC_I
++ ;;
++ mov r8=r18
++ ;;
++ mov pr=r31,-1
++ ;;
++ XEN_HYPER_RFI;
++#else
++ itc.i r19 // insert the TLB entry
++ mov pr=r31,-1
++ rfi
++#endif
++END(alt_itlb_miss)
++
++ .org ia64_ivt+0x1000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
++ENTRY(alt_dtlb_miss)
++ DBG_FAULT(4)
++#ifdef CONFIG_XEN
++ movl r31=XSI_IPSR
++ ;;
++ ld8 r21=[r31],XSI_ISR-XSI_IPSR // get ipsr, point to isr
++ movl r17=PAGE_KERNEL
++ ;;
++ ld8 r20=[r31],XSI_IFA-XSI_ISR // get isr, point to ifa
++ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
++ ;;
++ ld8 r16=[r31] // get ifa
++ mov r31=pr
++ ;;
++#else
++ mov r16=cr.ifa // get address that caused the TLB miss
++ movl r17=PAGE_KERNEL
++ mov r20=cr.isr
++ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
++ mov r21=cr.ipsr
++ mov r31=pr
++ ;;
++#endif
++#ifdef CONFIG_DISABLE_VHPT
++ shr.u r22=r16,61 // get the region number into r21
++ ;;
++ cmp.gt p8,p0=6,r22 // access to region 0-5
++ ;;
++#ifndef CONFIG_XEN
++(p8) thash r17=r16
++ ;;
++(p8) mov cr.iha=r17
++#endif
++(p8) mov r29=b0 // save b0
++(p8) br.cond.dptk dtlb_fault
++#endif
++ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
++ and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
++ tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
++ shr.u r18=r16,57 // move address bit 61 to bit 4
++ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
++ tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
++ ;;
++ andcm r18=0x10,r18 // bit 4=~address-bit(61)
++ cmp.ne p8,p0=r0,r23
++(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
++(p8) br.cond.spnt page_fault
++
++ dep r21=-1,r21,IA64_PSR_ED_BIT,1
++ or r19=r19,r17 // insert PTE control bits into r19
++ ;;
++ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
++(p6) mov cr.ipsr=r21
++ ;;
++#ifdef CONFIG_XEN
++(p7) mov r18=r8
++(p7) mov r8=r19
++ ;;
++(p7) XEN_HYPER_ITC_D
++ ;;
++(p7) mov r8=r18
++ ;;
++ mov pr=r31,-1
++ ;;
++ XEN_HYPER_RFI;
++#else
++(p7) itc.d r19 // insert the TLB entry
++ mov pr=r31,-1
++ rfi
++#endif
++END(alt_dtlb_miss)
++
++ .org ia64_ivt+0x1400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
++ENTRY(nested_dtlb_miss)
++ /*
++ * In the absence of kernel bugs, we get here when the virtually mapped linear
++ * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
++ * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
++ * table is missing, a nested TLB miss fault is triggered and control is
++ * transferred to this point. When this happens, we lookup the pte for the
++ * faulting address by walking the page table in physical mode and return to the
++ * continuation point passed in register r30 (or call page_fault if the address is
++ * not mapped).
++ *
++ * Input: r16: faulting address
++ * r29: saved b0
++ * r30: continuation address
++ * r31: saved pr
++ *
++ * Output: r17: physical address of L3 PTE of faulting address
++ * r29: saved b0
++ * r30: continuation address
++ * r31: saved pr
++ *
++ * Clobbered: b0, r18, r19, r21, psr.dt (cleared)
++ */
++#ifdef CONFIG_XEN
++ XEN_HYPER_RSM_PSR_DT;
++#else
++ rsm psr.dt // switch to using physical data addressing
++#endif
++ mov r19=IA64_KR(PT_BASE) // get the page table base address
++ shl r21=r16,3 // shift bit 60 into sign bit
++ ;;
++ shr.u r17=r16,61 // get the region number into r17
++ ;;
++ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
++ shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address
++ ;;
++(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
++
++ srlz.d
++ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
++
++ .pred.rel "mutex", p6, p7
++(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
++(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
++ ;;
++(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8
++(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
++ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
++ shr.u r18=r16,PMD_SHIFT // shift L2 index into position
++ ;;
++ ld8 r17=[r17] // fetch the L1 entry (may be 0)
++ ;;
++(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL?
++ dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
++ ;;
++(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0)
++ shr.u r19=r16,PAGE_SHIFT // shift L3 index into position
++ ;;
++(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL?
++ dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
++(p6) br.cond.spnt page_fault
++ mov b0=r30
++ br.sptk.many b0 // return to continuation point
++END(nested_dtlb_miss)
++
++ .org ia64_ivt+0x1800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
++ENTRY(ikey_miss)
++ DBG_FAULT(6)
++ FAULT(6)
++END(ikey_miss)
++
++ //-----------------------------------------------------------------------------------
++ // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
++ENTRY(page_fault)
++#ifdef CONFIG_XEN
++ XEN_HYPER_SSM_PSR_DT;
++#else
++ ssm psr.dt
++ ;;
++ srlz.i
++#endif
++ ;;
++ SAVE_MIN_WITH_COVER
++ alloc r15=ar.pfs,0,0,3,0
++#ifdef CONFIG_XEN
++ movl r3=XSI_ISR
++ ;;
++ ld8 out1=[r3],XSI_IFA-XSI_ISR // get vcr.isr, point to ifa
++ ;;
++ ld8 out0=[r3] // get vcr.ifa
++ mov r14=1
++ ;;
++ add r3=XSI_PSR_IC-XSI_IFA, r3 // point to vpsr.ic
++ ;;
++ st4 [r3]=r14 // vpsr.ic = 1
++ adds r3=8,r2 // set up second base pointer
++ ;;
++#else
++ mov out0=cr.ifa
++ mov out1=cr.isr
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collectin is on
++ ;;
++#endif
++#ifdef CONFIG_XEN
++ br.cond.sptk.many xen_page_fault
++ ;;
++done_xen_page_fault:
++#endif
++(p15) ssm psr.i // restore psr.i
++ movl r14=ia64_leave_kernel
++ ;;
++ SAVE_REST
++ mov rp=r14
++ ;;
++ adds out2=16,r12 // out2 = pointer to pt_regs
++ br.call.sptk.many b6=ia64_do_page_fault // ignore return address
++END(page_fault)
++
++ .org ia64_ivt+0x1c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
++ENTRY(dkey_miss)
++ DBG_FAULT(7)
++ FAULT(7)
++#ifdef CONFIG_XEN
++ // Leaving this code inline above results in an IVT section overflow
++ // There is no particular reason for this code to be here...
++xen_page_fault:
++(p15) movl r3=XSI_PSR_I
++ ;;
++(p15) st4 [r3]=r14,XSI_PEND-XSI_PSR_I // if (p15) vpsr.i = 1
++ mov r14=r0
++ ;;
++(p15) ld4 r14=[r3] // if (pending_interrupts)
++ adds r3=8,r2 // re-set up second base pointer
++ ;;
++(p15) cmp.ne p15,p0=r14,r0
++ ;;
++ br.cond.sptk.many done_xen_page_fault
++ ;;
++#endif
++END(dkey_miss)
++
++ .org ia64_ivt+0x2000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
++ENTRY(dirty_bit)
++ DBG_FAULT(8)
++ /*
++ * What we do here is to simply turn on the dirty bit in the PTE. We need to
++ * update both the page-table and the TLB entry. To efficiently access the PTE,
++ * we address it through the virtual page table. Most likely, the TLB entry for
++ * the relevant virtual page table page is still present in the TLB so we can
++ * normally do this without additional TLB misses. In case the necessary virtual
++ * page table TLB entry isn't present, we take a nested TLB miss hit where we look
++ * up the physical address of the L3 PTE and then continue at label 1 below.
++ */
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++ ;;
++#else
++ mov r16=cr.ifa // get the address that caused the fault
++#endif
++ 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
++ mov r31=pr // save pr
++#ifdef CONFIG_SMP
++ mov r28=ar.ccv // save ar.ccv
++ ;;
++1: ld8 r18=[r17]
++ ;; // avoid RAW on r18
++ mov ar.ccv=r18 // set compare value for cmpxchg
++ or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
++ ;;
++ cmpxchg8.acq r26=[r17],r25,ar.ccv
++ mov r24=PAGE_SHIFT<<2
++ ;;
++ cmp.eq p6,p7=r26,r18
++ ;;
++(p6) itc.d r25 // install updated PTE
++ ;;
++ /*
++ * Tell the assemblers dependency-violation checker that the above "itc" instructions
++ * cannot possibly affect the following loads:
++ */
++ dv_serialize_data
++
++ ld8 r18=[r17] // read PTE again
++ ;;
++ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
++ ;;
++(p7) ptc.l r16,r24
++ mov b0=r29 // restore b0
++ mov ar.ccv=r28
++#else
++ ;;
++1: ld8 r18=[r17]
++ ;; // avoid RAW on r18
++ or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
++ mov b0=r29 // restore b0
++ ;;
++ st8 [r17]=r18 // store back updated PTE
++ itc.d r18 // install updated PTE
++#endif
++ mov pr=r31,-1 // restore pr
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(dirty_bit)
++
++ .org ia64_ivt+0x2400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
++ENTRY(iaccess_bit)
++ DBG_FAULT(9)
++ // Like Entry 8, except for instruction access
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++ ;;
++#else
++ mov r16=cr.ifa // get the address that caused the fault
++#endif
++ movl r30=1f // load continuation point in case of nested fault
++ mov r31=pr // save predicates
++#ifdef CONFIG_ITANIUM
++ /*
++ * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
++ */
++ mov r17=cr.ipsr
++ ;;
++ mov r18=cr.iip
++ tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
++ ;;
++(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
++#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)
++#ifdef CONFIG_SMP
++ mov r28=ar.ccv // save ar.ccv
++ ;;
++1: ld8 r18=[r17]
++ ;;
++ mov ar.ccv=r18 // set compare value for cmpxchg
++ or r25=_PAGE_A,r18 // set the accessed bit
++ ;;
++ cmpxchg8.acq r26=[r17],r25,ar.ccv
++ mov r24=PAGE_SHIFT<<2
++ ;;
++ cmp.eq p6,p7=r26,r18
++ ;;
++#ifdef CONFIG_XEN
++ mov r26=r8
++ mov r8=r25
++ ;;
++(p6) XEN_HYPER_ITC_I
++ ;;
++ mov r8=r26
++ ;;
++#else
++(p6) itc.i r25 // install updated PTE
++#endif
++ ;;
++ /*
++ * Tell the assemblers dependency-violation checker that the above "itc" instructions
++ * cannot possibly affect the following loads:
++ */
++ dv_serialize_data
++
++ ld8 r18=[r17] // read PTE again
++ ;;
++ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
++ ;;
++(p7) ptc.l r16,r24
++ mov b0=r29 // restore b0
++ mov ar.ccv=r28
++#else /* !CONFIG_SMP */
++ ;;
++1: ld8 r18=[r17]
++ ;;
++ or r18=_PAGE_A,r18 // set the accessed bit
++ mov b0=r29 // restore b0
++ ;;
++ st8 [r17]=r18 // store back updated PTE
++ itc.i r18 // install updated PTE
++#endif /* !CONFIG_SMP */
++ mov pr=r31,-1
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(iaccess_bit)
++
++ .org ia64_ivt+0x2800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
++ENTRY(daccess_bit)
++ DBG_FAULT(10)
++ // Like Entry 8, except for data access
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++ ;;
++#else
++ mov r16=cr.ifa // get the address that caused the fault
++#endif
++ 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
++ mov r29=b0 // save b0 in case of nested fault)
++#ifdef CONFIG_SMP
++ mov r28=ar.ccv // save ar.ccv
++ ;;
++1: ld8 r18=[r17]
++ ;; // avoid RAW on r18
++ mov ar.ccv=r18 // set compare value for cmpxchg
++ or r25=_PAGE_A,r18 // set the dirty bit
++ ;;
++ cmpxchg8.acq r26=[r17],r25,ar.ccv
++ mov r24=PAGE_SHIFT<<2
++ ;;
++ cmp.eq p6,p7=r26,r18
++ ;;
++#ifdef CONFIG_XEN
++ mov r26=r8
++ mov r8=r25
++ ;;
++(p6) XEN_HYPER_ITC_D
++ ;;
++ mov r8=r26
++ ;;
++#else
++(p6) itc.d r25 // install updated PTE
++#endif
++ /*
++ * Tell the assemblers dependency-violation checker that the above "itc" instructions
++ * cannot possibly affect the following loads:
++ */
++ dv_serialize_data
++ ;;
++ ld8 r18=[r17] // read PTE again
++ ;;
++ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
++ ;;
++(p7) ptc.l r16,r24
++ mov ar.ccv=r28
++#else
++ ;;
++1: ld8 r18=[r17]
++ ;; // avoid RAW on r18
++ or r18=_PAGE_A,r18 // set the accessed bit
++ ;;
++ st8 [r17]=r18 // store back updated PTE
++ itc.d r18 // install updated PTE
++#endif
++ mov b0=r29 // restore b0
++ mov pr=r31,-1
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(daccess_bit)
++
++ .org ia64_ivt+0x2c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
++ENTRY(break_fault)
++ /*
++ * The streamlined system call entry/exit paths only save/restore the initial part
++ * of pt_regs. This implies that the callers of system-calls must adhere to the
++ * normal procedure calling conventions.
++ *
++ * Registers to be saved & restored:
++ * CR registers: cr.ipsr, cr.iip, cr.ifs
++ * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
++ * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
++ * Registers to be restored only:
++ * r8-r11: output value from the system call.
++ *
++ * During system call exit, scratch registers (including r15) are modified/cleared
++ * to prevent leaking bits from kernel to user level.
++ */
++ DBG_FAULT(11)
++ mov r16=IA64_KR(CURRENT) // r16 = current task; 12 cycle read lat.
++#ifdef CONFIG_XEN
++ movl r31=XSI_IPSR
++ ;;
++ ld8 r29=[r31],XSI_IIP-XSI_IPSR // get ipsr, point to iip
++ mov r18=__IA64_BREAK_SYSCALL
++ mov r21=ar.fpsr
++ ;;
++ ld8 r28=[r31],XSI_IIM-XSI_IIP // get iip, point to iim
++ mov r19=b6
++ mov r25=ar.unat
++ ;;
++ ld8 r17=[r31] // get iim
++ mov r27=ar.rsc
++ mov r26=ar.pfs
++ ;;
++#else
++ mov r17=cr.iim
++ mov r18=__IA64_BREAK_SYSCALL
++ mov r21=ar.fpsr
++ mov r29=cr.ipsr
++ mov r19=b6
++ mov r25=ar.unat
++ mov r27=ar.rsc
++ mov r26=ar.pfs
++ mov r28=cr.iip
++#endif
++ mov r31=pr // prepare to save predicates
++ mov r20=r1
++ ;;
++ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
++ cmp.eq p0,p7=r18,r17 // is this a system call? (p7 <- false, if so)
++(p7) br.cond.spnt non_syscall
++ ;;
++ ld1 r17=[r16] // load current->thread.on_ustack flag
++ st1 [r16]=r0 // clear current->thread.on_ustack flag
++ add r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 // set r1 for MINSTATE_START_SAVE_MIN_VIRT
++ ;;
++ invala
++
++ /* adjust return address so we skip over the break instruction: */
++
++ extr.u r8=r29,41,2 // extract ei field from cr.ipsr
++ ;;
++ cmp.eq p6,p7=2,r8 // isr.ei==2?
++ mov r2=r1 // setup r2 for ia64_syscall_setup
++ ;;
++(p6) mov r8=0 // clear ei to 0
++(p6) adds r28=16,r28 // switch cr.iip to next bundle cr.ipsr.ei wrapped
++(p7) adds r8=1,r8 // increment ei to next slot
++ ;;
++ cmp.eq pKStk,pUStk=r0,r17 // are we in kernel mode already?
++ dep r29=r8,r29,41,2 // insert new ei into cr.ipsr
++ ;;
++
++ // switch from user to kernel RBS:
++ MINSTATE_START_SAVE_MIN_VIRT
++ br.call.sptk.many b7=ia64_syscall_setup
++ ;;
++#ifdef CONFIG_XEN
++ mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2;;
++#else
++ MINSTATE_END_SAVE_MIN_VIRT // switch to bank 1
++#endif
++#ifdef CONFIG_XEN
++ movl r3=XSI_PSR_IC
++ mov r16=1
++ ;;
++#if 1
++ st4 [r3]=r16,XSI_PSR_I-XSI_PSR_IC // vpsr.ic = 1
++ ;;
++(p15) st4 [r3]=r16,XSI_PEND-XSI_PSR_I // if (p15) vpsr.i = 1
++ mov r16=r0
++ ;;
++(p15) ld4 r16=[r3] // if (pending_interrupts)
++ ;;
++ cmp.ne p6,p0=r16,r0
++ ;;
++(p6) ssm psr.i // do a real ssm psr.i
++ ;;
++#else
++// st4 [r3]=r16,XSI_PSR_I-XSI_PSR_IC // vpsr.ic = 1
++ adds r3=XSI_PSR_I-XSI_PSR_IC,r3 // SKIP vpsr.ic = 1
++ ;;
++(p15) st4 [r3]=r16,XSI_PEND-XSI_PSR_I // if (p15) vpsr.i = 1
++ mov r16=r0
++ ;;
++(p15) ld4 r16=[r3] // if (pending_interrupts)
++ ;;
++ cmp.ne p6,p0=r16,r0
++ ;;
++//(p6) ssm psr.i // do a real ssm psr.i
++//(p6) XEN_HYPER_SSM_I;
++(p6) break 0x7;
++ ;;
++#endif
++ mov r3=NR_syscalls - 1
++ ;;
++#else
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ mov r3=NR_syscalls - 1
++ ;;
++(p15) ssm psr.i // restore psr.i
++#endif
++ // p10==true means out registers are more than 8 or r15's Nat is true
++(p10) br.cond.spnt.many ia64_ret_from_syscall
++ ;;
++ movl r16=sys_call_table
++
++ adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024
++ movl r2=ia64_ret_from_syscall
++ ;;
++ shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024)
++ cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + NR_syscalls) ?
++ mov rp=r2 // set the real return addr
++ ;;
++(p6) ld8 r20=[r20] // load address of syscall entry point
++(p7) movl r20=sys_ni_syscall
++
++ add r2=TI_FLAGS+IA64_TASK_SIZE,r13
++ ;;
++ ld4 r2=[r2] // r2 = current_thread_info()->flags
++ ;;
++ and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
++ ;;
++ cmp.eq p8,p0=r2,r0
++ mov b6=r20
++ ;;
++(p8) br.call.sptk.many b6=b6 // ignore this return addr
++ br.cond.sptk ia64_trace_syscall
++ // NOT REACHED
++END(break_fault)
++
++ .org ia64_ivt+0x3000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
++ENTRY(interrupt)
++ DBG_FAULT(12)
++ mov r31=pr // prepare to save predicates
++ ;;
++ SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
++#ifdef CONFIG_XEN
++ movl r3=XSI_PSR_IC
++ mov r14=1
++ ;;
++ st4 [r3]=r14
++#else
++ ssm psr.ic | PSR_DEFAULT_BITS
++#endif
++ ;;
++ adds r3=8,r2 // set up second base pointer for SAVE_REST
++ srlz.i // ensure everybody knows psr.ic is back on
++ ;;
++ SAVE_REST
++ ;;
++ alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
++#ifdef CONFIG_XEN
++ ;;
++ br.call.sptk.many rp=xen_get_ivr
++ ;;
++ mov out0=r8 // pass cr.ivr as first arg
++#else
++ mov out0=cr.ivr // pass cr.ivr as first arg
++#endif
++ add out1=16,sp // pass pointer to pt_regs as second arg
++ ;;
++ srlz.d // make sure we see the effect of cr.ivr
++ movl r14=ia64_leave_kernel
++ ;;
++ mov rp=r14
++ br.call.sptk.many b6=ia64_handle_irq
++END(interrupt)
++
++ .org ia64_ivt+0x3400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x3400 Entry 13 (size 64 bundles) Reserved
++ DBG_FAULT(13)
++ FAULT(13)
++
++ .org ia64_ivt+0x3800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x3800 Entry 14 (size 64 bundles) Reserved
++ DBG_FAULT(14)
++ FAULT(14)
++
++ /*
++ * There is no particular reason for this code to be here, other than that
++ * there happens to be space here that would go unused otherwise. If this
++ * fault ever gets "unreserved", simply moved the following code to a more
++ * suitable spot...
++ *
++ * ia64_syscall_setup() is a separate subroutine so that it can
++ * allocate stacked registers so it can safely demine any
++ * potential NaT values from the input registers.
++ *
++ * On entry:
++ * - executing on bank 0 or bank 1 register set (doesn't matter)
++ * - r1: stack pointer
++ * - r2: current task pointer
++ * - r3: preserved
++ * - r11: original contents (saved ar.pfs to be saved)
++ * - r12: original contents (sp to be saved)
++ * - r13: original contents (tp to be saved)
++ * - r15: original contents (syscall # to be saved)
++ * - r18: saved bsp (after switching to kernel stack)
++ * - r19: saved b6
++ * - r20: saved r1 (gp)
++ * - r21: saved ar.fpsr
++ * - r22: kernel's register backing store base (krbs_base)
++ * - r23: saved ar.bspstore
++ * - r24: saved ar.rnat
++ * - r25: saved ar.unat
++ * - r26: saved ar.pfs
++ * - r27: saved ar.rsc
++ * - r28: saved cr.iip
++ * - r29: saved cr.ipsr
++ * - r31: saved pr
++ * - b0: original contents (to be saved)
++ * On exit:
++ * - executing on bank 1 registers
++ * - psr.ic enabled, interrupts restored
++ * - p10: TRUE if syscall is invoked with more than 8 out
++ * registers or r15's Nat is true
++ * - r1: kernel's gp
++ * - r3: preserved (same as on entry)
++ * - r8: -EINVAL if p10 is true
++ * - r12: points to kernel stack
++ * - r13: points to current task
++ * - p15: TRUE if interrupts need to be re-enabled
++ * - ar.fpsr: set to kernel settings
++ */
++#ifndef CONFIG_XEN
++GLOBAL_ENTRY(ia64_syscall_setup)
++#if PT(B6) != 0
++# error This code assumes that b6 is the first field in pt_regs.
++#endif
++ st8 [r1]=r19 // save b6
++ add r16=PT(CR_IPSR),r1 // initialize first base pointer
++ add r17=PT(R11),r1 // initialize second base pointer
++ ;;
++ alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
++ st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
++ tnat.nz p8,p0=in0
++
++ st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
++ tnat.nz p9,p0=in1
++(pKStk) mov r18=r0 // make sure r18 isn't NaT
++ ;;
++
++ st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
++ st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
++ mov r28=b0 // save b0 (2 cyc)
++ ;;
++
++ st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
++ dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
++(p8) mov in0=-1
++ ;;
++
++ st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
++ extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
++ and r8=0x7f,r19 // A // get sof of ar.pfs
++
++ st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
++ tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
++(p9) mov in1=-1
++ ;;
++
++(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
++ tnat.nz p10,p0=in2
++ add r11=8,r11
++ ;;
++(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
++(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
++ tnat.nz p11,p0=in3
++ ;;
++(p10) mov in2=-1
++ tnat.nz p12,p0=in4 // [I0]
++(p11) mov in3=-1
++ ;;
++(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
++(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
++ shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
++ ;;
++ st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
++ st8 [r17]=r28,PT(R1)-PT(B0) // save b0
++ tnat.nz p13,p0=in5 // [I0]
++ ;;
++ st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
++ st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
++(p12) mov in4=-1
++ ;;
++
++.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
++.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
++(p13) mov in5=-1
++ ;;
++ st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
++ tnat.nz p14,p0=in6
++ cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
++ ;;
++ stf8 [r16]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
++(p9) tnat.nz p10,p0=r15
++ adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
++
++ st8.spill [r17]=r15 // save r15
++ tnat.nz p8,p0=in7
++ nop.i 0
++
++ mov r13=r2 // establish `current'
++ movl r1=__gp // establish kernel global pointer
++ ;;
++(p14) mov in6=-1
++(p8) mov in7=-1
++ nop.i 0
++
++ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
++ movl r17=FPSR_DEFAULT
++ ;;
++ mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
++(p10) mov r8=-EINVAL
++ br.ret.sptk.many b7
++END(ia64_syscall_setup)
++#endif
++
++ .org ia64_ivt+0x3c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x3c00 Entry 15 (size 64 bundles) Reserved
++ DBG_FAULT(15)
++ FAULT(15)
++
++ /*
++ * Squatting in this space ...
++ *
++ * This special case dispatcher for illegal operation faults allows preserved
++ * registers to be modified through a callback function (asm only) that is handed
++ * back from the fault handler in r8. Up to three arguments can be passed to the
++ * callback function by returning an aggregate with the callback as its first
++ * element, followed by the arguments.
++ */
++ENTRY(dispatch_illegal_op_fault)
++ SAVE_MIN_WITH_COVER
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++(p15) ssm psr.i // restore psr.i
++ adds r3=8,r2 // set up second base pointer for SAVE_REST
++ ;;
++ alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
++ mov out0=ar.ec
++ ;;
++ SAVE_REST
++ ;;
++ br.call.sptk.many rp=ia64_illegal_op_fault
++.ret0: ;;
++ alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
++ mov out0=r9
++ mov out1=r10
++ mov out2=r11
++ movl r15=ia64_leave_kernel
++ ;;
++ mov rp=r15
++ mov b6=r8
++ ;;
++ cmp.ne p6,p0=0,r8
++(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
++ br.sptk.many ia64_leave_kernel
++END(dispatch_illegal_op_fault)
++
++ .org ia64_ivt+0x4000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x4000 Entry 16 (size 64 bundles) Reserved
++ DBG_FAULT(16)
++ FAULT(16)
++
++ .org ia64_ivt+0x4400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x4400 Entry 17 (size 64 bundles) Reserved
++ DBG_FAULT(17)
++ FAULT(17)
++
++ENTRY(non_syscall)
++ SAVE_MIN_WITH_COVER
++
++ // There is no particular reason for this code to be here, other than that
++ // there happens to be space here that would go unused otherwise. If this
++ // fault ever gets "unreserved", simply moved the following code to a more
++ // suitable spot...
++
++ alloc r14=ar.pfs,0,0,2,0
++ mov out0=cr.iim
++ add out1=16,sp
++ adds r3=8,r2 // set up second base pointer for SAVE_REST
++
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++(p15) ssm psr.i // restore psr.i
++ movl r15=ia64_leave_kernel
++ ;;
++ SAVE_REST
++ mov rp=r15
++ ;;
++ br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
++END(non_syscall)
++
++ .org ia64_ivt+0x4800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x4800 Entry 18 (size 64 bundles) Reserved
++ DBG_FAULT(18)
++ FAULT(18)
++
++ /*
++ * There is no particular reason for this code to be here, other than that
++ * there happens to be space here that would go unused otherwise. If this
++ * fault ever gets "unreserved", simply moved the following code to a more
++ * suitable spot...
++ */
++
++ENTRY(dispatch_unaligned_handler)
++ SAVE_MIN_WITH_COVER
++ ;;
++ alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
++ mov out0=cr.ifa
++ adds out1=16,sp
++
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++(p15) ssm psr.i // restore psr.i
++ adds r3=8,r2 // set up second base pointer
++ ;;
++ SAVE_REST
++ movl r14=ia64_leave_kernel
++ ;;
++ mov rp=r14
++ br.sptk.many ia64_prepare_handle_unaligned
++END(dispatch_unaligned_handler)
++
++ .org ia64_ivt+0x4c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x4c00 Entry 19 (size 64 bundles) Reserved
++ DBG_FAULT(19)
++ FAULT(19)
++
++ /*
++ * There is no particular reason for this code to be here, other than that
++ * there happens to be space here that would go unused otherwise. If this
++ * fault ever gets "unreserved", simply moved the following code to a more
++ * suitable spot...
++ */
++
++ENTRY(dispatch_to_fault_handler)
++ /*
++ * Input:
++ * psr.ic: off
++ * r19: fault vector number (e.g., 24 for General Exception)
++ * r31: contains saved predicates (pr)
++ */
++ SAVE_MIN_WITH_COVER_R19
++ alloc r14=ar.pfs,0,0,5,0
++ mov out0=r15
++#ifdef CONFIG_XEN
++ movl out1=XSI_ISR
++ ;;
++ adds out2=XSI_IFA-XSI_ISR,out1
++ adds out3=XSI_IIM-XSI_ISR,out1
++ adds out4=XSI_ITIR-XSI_ISR,out1
++ ;;
++ ld8 out1=[out1]
++ ld8 out2=[out2]
++ ld8 out3=[out4]
++ ld8 out4=[out4]
++ ;;
++#else
++ mov out1=cr.isr
++ mov out2=cr.ifa
++ mov out3=cr.iim
++ mov out4=cr.itir
++ ;;
++#endif
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++(p15) ssm psr.i // restore psr.i
++ adds r3=8,r2 // set up second base pointer for SAVE_REST
++ ;;
++ SAVE_REST
++ movl r14=ia64_leave_kernel
++ ;;
++ mov rp=r14
++ br.call.sptk.many b6=ia64_fault
++END(dispatch_to_fault_handler)
++
++//
++// --- End of long entries, Beginning of short entries
++//
++
++ .org ia64_ivt+0x5000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
++ENTRY(page_not_present)
++ DBG_FAULT(20)
++ mov r16=cr.ifa
++ rsm psr.dt
++ /*
++ * The Linux page fault handler doesn't expect non-present pages to be in
++ * the TLB. Flush the existing entry now, so we meet that expectation.
++ */
++ mov r17=PAGE_SHIFT<<2
++ ;;
++ ptc.l r16,r17
++ ;;
++ mov r31=pr
++ srlz.d
++ br.sptk.many page_fault
++END(page_not_present)
++
++ .org ia64_ivt+0x5100
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
++ENTRY(key_permission)
++ DBG_FAULT(21)
++ mov r16=cr.ifa
++ rsm psr.dt
++ mov r31=pr
++ ;;
++ srlz.d
++ br.sptk.many page_fault
++END(key_permission)
++
++ .org ia64_ivt+0x5200
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
++ENTRY(iaccess_rights)
++ DBG_FAULT(22)
++ mov r16=cr.ifa
++ rsm psr.dt
++ mov r31=pr
++ ;;
++ srlz.d
++ br.sptk.many page_fault
++END(iaccess_rights)
++
++ .org ia64_ivt+0x5300
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
++ENTRY(daccess_rights)
++ DBG_FAULT(23)
++#ifdef CONFIG_XEN
++ movl r16=XSI_IFA
++ ;;
++ ld8 r16=[r16]
++ ;;
++ XEN_HYPER_RSM_PSR_DT;
++#else
++ mov r16=cr.ifa
++ rsm psr.dt
++#endif
++ mov r31=pr
++ ;;
++ srlz.d
++ br.sptk.many page_fault
++END(daccess_rights)
++
++ .org ia64_ivt+0x5400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
++ENTRY(general_exception)
++ DBG_FAULT(24)
++ mov r16=cr.isr
++ mov r31=pr
++ ;;
++ cmp4.eq p6,p0=0,r16
++(p6) br.sptk.many dispatch_illegal_op_fault
++ ;;
++ mov r19=24 // fault number
++ br.sptk.many dispatch_to_fault_handler
++END(general_exception)
++
++ .org ia64_ivt+0x5500
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
++ENTRY(disabled_fp_reg)
++ DBG_FAULT(25)
++ rsm psr.dfh // ensure we can access fph
++ ;;
++ srlz.d
++ mov r31=pr
++ mov r19=25
++ br.sptk.many dispatch_to_fault_handler
++END(disabled_fp_reg)
++
++ .org ia64_ivt+0x5600
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
++ENTRY(nat_consumption)
++ DBG_FAULT(26)
++ FAULT(26)
++END(nat_consumption)
++
++ .org ia64_ivt+0x5700
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
++ENTRY(speculation_vector)
++ DBG_FAULT(27)
++ /*
++ * A [f]chk.[as] instruction needs to take the branch to the recovery code but
++ * this part of the architecture is not implemented in hardware on some CPUs, such
++ * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
++ * the relative target (not yet sign extended). So after sign extending it we
++ * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
++ * i.e., the slot to restart into.
++ *
++ * cr.imm contains zero_ext(imm21)
++ */
++ mov r18=cr.iim
++ ;;
++ mov r17=cr.iip
++ shl r18=r18,43 // put sign bit in position (43=64-21)
++ ;;
++
++ mov r16=cr.ipsr
++ shr r18=r18,39 // sign extend (39=43-4)
++ ;;
++
++ add r17=r17,r18 // now add the offset
++ ;;
++ mov cr.iip=r17
++ dep r16=0,r16,41,2 // clear EI
++ ;;
++
++ mov cr.ipsr=r16
++ ;;
++
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++END(speculation_vector)
++
++ .org ia64_ivt+0x5800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5800 Entry 28 (size 16 bundles) Reserved
++ DBG_FAULT(28)
++ FAULT(28)
++
++ .org ia64_ivt+0x5900
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
++ENTRY(debug_vector)
++ DBG_FAULT(29)
++ FAULT(29)
++END(debug_vector)
++
++ .org ia64_ivt+0x5a00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
++ENTRY(unaligned_access)
++ DBG_FAULT(30)
++ mov r16=cr.ipsr
++ mov r31=pr // prepare to save predicates
++ ;;
++ br.sptk.many dispatch_unaligned_handler
++END(unaligned_access)
++
++ .org ia64_ivt+0x5b00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
++ENTRY(unsupported_data_reference)
++ DBG_FAULT(31)
++ FAULT(31)
++END(unsupported_data_reference)
++
++ .org ia64_ivt+0x5c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
++ENTRY(floating_point_fault)
++ DBG_FAULT(32)
++ FAULT(32)
++END(floating_point_fault)
++
++ .org ia64_ivt+0x5d00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
++ENTRY(floating_point_trap)
++ DBG_FAULT(33)
++ FAULT(33)
++END(floating_point_trap)
++
++ .org ia64_ivt+0x5e00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
++ENTRY(lower_privilege_trap)
++ DBG_FAULT(34)
++ FAULT(34)
++END(lower_privilege_trap)
++
++ .org ia64_ivt+0x5f00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
++ENTRY(taken_branch_trap)
++ DBG_FAULT(35)
++ FAULT(35)
++END(taken_branch_trap)
++
++ .org ia64_ivt+0x6000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
++ENTRY(single_step_trap)
++ DBG_FAULT(36)
++ FAULT(36)
++END(single_step_trap)
++
++ .org ia64_ivt+0x6100
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6100 Entry 37 (size 16 bundles) Reserved
++ DBG_FAULT(37)
++ FAULT(37)
++
++ .org ia64_ivt+0x6200
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6200 Entry 38 (size 16 bundles) Reserved
++ DBG_FAULT(38)
++ FAULT(38)
++
++ .org ia64_ivt+0x6300
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6300 Entry 39 (size 16 bundles) Reserved
++ DBG_FAULT(39)
++ FAULT(39)
++
++ .org ia64_ivt+0x6400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6400 Entry 40 (size 16 bundles) Reserved
++ DBG_FAULT(40)
++ FAULT(40)
++
++ .org ia64_ivt+0x6500
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6500 Entry 41 (size 16 bundles) Reserved
++ DBG_FAULT(41)
++ FAULT(41)
++
++ .org ia64_ivt+0x6600
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6600 Entry 42 (size 16 bundles) Reserved
++ DBG_FAULT(42)
++ FAULT(42)
++
++ .org ia64_ivt+0x6700
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6700 Entry 43 (size 16 bundles) Reserved
++ DBG_FAULT(43)
++ FAULT(43)
++
++ .org ia64_ivt+0x6800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6800 Entry 44 (size 16 bundles) Reserved
++ DBG_FAULT(44)
++ FAULT(44)
++
++ .org ia64_ivt+0x6900
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
++ENTRY(ia32_exception)
++ DBG_FAULT(45)
++ FAULT(45)
++END(ia32_exception)
++
++ .org ia64_ivt+0x6a00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
++ENTRY(ia32_intercept)
++ DBG_FAULT(46)
++#ifdef CONFIG_IA32_SUPPORT
++ mov r31=pr
++ mov r16=cr.isr
++ ;;
++ extr.u r17=r16,16,8 // get ISR.code
++ mov r18=ar.eflag
++ mov r19=cr.iim // old eflag value
++ ;;
++ cmp.ne p6,p0=2,r17
++(p6) br.cond.spnt 1f // not a system flag fault
++ xor r16=r18,r19
++ ;;
++ extr.u r17=r16,18,1 // get the eflags.ac bit
++ ;;
++ cmp.eq p6,p0=0,r17
++(p6) br.cond.spnt 1f // eflags.ac bit didn't change
++ ;;
++ mov pr=r31,-1 // restore predicate registers
++#ifdef CONFIG_XEN
++ XEN_HYPER_RFI;
++#else
++ rfi
++#endif
++
++1:
++#endif // CONFIG_IA32_SUPPORT
++ FAULT(46)
++END(ia32_intercept)
++
++ .org ia64_ivt+0x6b00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
++ENTRY(ia32_interrupt)
++ DBG_FAULT(47)
++#ifdef CONFIG_IA32_SUPPORT
++ mov r31=pr
++ br.sptk.many dispatch_to_ia32_handler
++#else
++ FAULT(47)
++#endif
++END(ia32_interrupt)
++
++ .org ia64_ivt+0x6c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6c00 Entry 48 (size 16 bundles) Reserved
++ DBG_FAULT(48)
++ FAULT(48)
++
++ .org ia64_ivt+0x6d00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6d00 Entry 49 (size 16 bundles) Reserved
++ DBG_FAULT(49)
++ FAULT(49)
++
++ .org ia64_ivt+0x6e00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6e00 Entry 50 (size 16 bundles) Reserved
++ DBG_FAULT(50)
++ FAULT(50)
++
++ .org ia64_ivt+0x6f00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x6f00 Entry 51 (size 16 bundles) Reserved
++ DBG_FAULT(51)
++ FAULT(51)
++
++ .org ia64_ivt+0x7000
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7000 Entry 52 (size 16 bundles) Reserved
++ DBG_FAULT(52)
++ FAULT(52)
++
++ .org ia64_ivt+0x7100
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7100 Entry 53 (size 16 bundles) Reserved
++ DBG_FAULT(53)
++ FAULT(53)
++
++ .org ia64_ivt+0x7200
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7200 Entry 54 (size 16 bundles) Reserved
++ DBG_FAULT(54)
++ FAULT(54)
++
++ .org ia64_ivt+0x7300
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7300 Entry 55 (size 16 bundles) Reserved
++ DBG_FAULT(55)
++ FAULT(55)
++
++ .org ia64_ivt+0x7400
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7400 Entry 56 (size 16 bundles) Reserved
++ DBG_FAULT(56)
++ FAULT(56)
++
++ .org ia64_ivt+0x7500
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7500 Entry 57 (size 16 bundles) Reserved
++ DBG_FAULT(57)
++ FAULT(57)
++
++ .org ia64_ivt+0x7600
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7600 Entry 58 (size 16 bundles) Reserved
++ DBG_FAULT(58)
++ FAULT(58)
++
++ .org ia64_ivt+0x7700
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7700 Entry 59 (size 16 bundles) Reserved
++ DBG_FAULT(59)
++ FAULT(59)
++
++ .org ia64_ivt+0x7800
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7800 Entry 60 (size 16 bundles) Reserved
++ DBG_FAULT(60)
++ FAULT(60)
++
++ .org ia64_ivt+0x7900
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7900 Entry 61 (size 16 bundles) Reserved
++ DBG_FAULT(61)
++ FAULT(61)
++
++ .org ia64_ivt+0x7a00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7a00 Entry 62 (size 16 bundles) Reserved
++ DBG_FAULT(62)
++ FAULT(62)
++
++ .org ia64_ivt+0x7b00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7b00 Entry 63 (size 16 bundles) Reserved
++ DBG_FAULT(63)
++ FAULT(63)
++
++ .org ia64_ivt+0x7c00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7c00 Entry 64 (size 16 bundles) Reserved
++ DBG_FAULT(64)
++ FAULT(64)
++
++ .org ia64_ivt+0x7d00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7d00 Entry 65 (size 16 bundles) Reserved
++ DBG_FAULT(65)
++ FAULT(65)
++
++ .org ia64_ivt+0x7e00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7e00 Entry 66 (size 16 bundles) Reserved
++ DBG_FAULT(66)
++ FAULT(66)
++
++#ifdef CONFIG_XEN
++ /*
++ * There is no particular reason for this code to be here, other than that
++ * there happens to be space here that would go unused otherwise. If this
++ * fault ever gets "unreserved", simply moved the following code to a more
++ * suitable spot...
++ */
++
++GLOBAL_ENTRY(xen_bsw1)
++ /* FIXME: THIS CODE IS NOT NaT SAFE! */
++ movl r30=XSI_BANKNUM;
++ mov r31=1;;
++ st4 [r30]=r31;
++ movl r30=XSI_BANK1_R16;
++ movl r31=XSI_BANK1_R16+8;;
++ ld8 r16=[r30],16; ld8 r17=[r31],16;;
++ ld8 r18=[r30],16; ld8 r19=[r31],16;;
++ ld8 r20=[r30],16; ld8 r21=[r31],16;;
++ ld8 r22=[r30],16; ld8 r23=[r31],16;;
++ ld8 r24=[r30],16; ld8 r25=[r31],16;;
++ ld8 r26=[r30],16; ld8 r27=[r31],16;;
++ ld8 r28=[r30],16; ld8 r29=[r31],16;;
++ ld8 r30=[r30]; ld8 r31=[r31];;
++ br.ret.sptk.many b0
++#endif
++
++ .org ia64_ivt+0x7f00
++/////////////////////////////////////////////////////////////////////////////////////////
++// 0x7f00 Entry 67 (size 16 bundles) Reserved
++ DBG_FAULT(67)
++ FAULT(67)
++
++#ifdef CONFIG_IA32_SUPPORT
++
++ /*
++ * There is no particular reason for this code to be here, other than that
++ * there happens to be space here that would go unused otherwise. If this
++ * fault ever gets "unreserved", simply moved the following code to a more
++ * suitable spot...
++ */
++
++ // IA32 interrupt entry point
++
++ENTRY(dispatch_to_ia32_handler)
++ SAVE_MIN
++ ;;
++ mov r14=cr.isr
++ ssm psr.ic | PSR_DEFAULT_BITS
++ ;;
++ srlz.i // guarantee that interruption collection is on
++ ;;
++(p15) ssm psr.i
++ adds r3=8,r2 // Base pointer for SAVE_REST
++ ;;
++ SAVE_REST
++ ;;
++ mov r15=0x80
++ shr r14=r14,16 // Get interrupt number
++ ;;
++ cmp.ne p6,p0=r14,r15
++(p6) br.call.dpnt.many b6=non_ia32_syscall
++
++ adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
++ adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
++ ;;
++ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
++ ld8 r8=[r14] // get r8
++ ;;
++ st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
++ ;;
++ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
++ ;;
++ ld4 r8=[r14],8 // r8 == eax (syscall number)
++ mov r15=IA32_NR_syscalls
++ ;;
++ cmp.ltu.unc p6,p7=r8,r15
++ ld4 out1=[r14],8 // r9 == ecx
++ ;;
++ ld4 out2=[r14],8 // r10 == edx
++ ;;
++ ld4 out0=[r14] // r11 == ebx
++ adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
++ ;;
++ ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp
++ ;;
++ ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi
++ adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
++ ;;
++ ld4 out4=[r14] // r15 == edi
++ movl r16=ia32_syscall_table
++ ;;
++(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
++ ld4 r2=[r2] // r2 = current_thread_info()->flags
++ ;;
++ ld8 r16=[r16]
++ and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
++ ;;
++ mov b6=r16
++ movl r15=ia32_ret_from_syscall
++ cmp.eq p8,p0=r2,r0
++ ;;
++ mov rp=r15
++(p8) br.call.sptk.many b6=b6
++ br.cond.sptk ia32_trace_syscall
++
++non_ia32_syscall:
++ alloc r15=ar.pfs,0,0,2,0
++ mov out0=r14 // interrupt #
++ add out1=16,sp // pointer to pt_regs
++ ;; // avoid WAW on CFM
++ br.call.sptk.many rp=ia32_bad_interrupt
++.ret1: movl r15=ia64_leave_kernel
++ ;;
++ mov rp=r15
++ br.ret.sptk.many rp
++END(dispatch_to_ia32_handler)
++
++#endif /* CONFIG_IA32_SUPPORT */
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xenminstate.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xenminstate.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,367 @@
++#include <linux/config.h>
++
++#include <asm/cache.h>
++
++#ifdef CONFIG_XEN
++#include "../kernel/entry.h"
++#else
++#include "entry.h"
++#endif
++
++/*
++ * For ivt.s we want to access the stack virtually so we don't have to disable translation
++ * on interrupts.
++ *
++ * On entry:
++ * r1: pointer to current task (ar.k6)
++ */
++#define MINSTATE_START_SAVE_MIN_VIRT \
++(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
++ ;; \
++(pUStk) mov.m r24=ar.rnat; \
++(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \
++(pKStk) mov r1=sp; /* get sp */ \
++ ;; \
++(pUStk) lfetch.fault.excl.nt1 [r22]; \
++(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
++(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
++ ;; \
++(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
++(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
++ ;; \
++(pUStk) mov r18=ar.bsp; \
++(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
++
++#define MINSTATE_END_SAVE_MIN_VIRT \
++ bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
++ ;;
++
++/*
++ * For mca_asm.S we want to access the stack physically since the state is saved before we
++ * go virtual and don't want to destroy the iip or ipsr.
++ */
++#define MINSTATE_START_SAVE_MIN_PHYS \
++(pKStk) mov r3=IA64_KR(PER_CPU_DATA);; \
++(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \
++(pKStk) ld8 r3 = [r3];; \
++(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \
++(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
++(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
++(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \
++ ;; \
++(pUStk) mov r24=ar.rnat; \
++(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
++(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
++(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \
++ ;; \
++(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
++(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
++ ;; \
++(pUStk) mov r18=ar.bsp; \
++(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
++
++#define MINSTATE_END_SAVE_MIN_PHYS \
++ dep r12=-1,r12,61,3; /* make sp a kernel virtual address */ \
++ ;;
++
++#ifdef MINSTATE_VIRT
++# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT)
++# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_VIRT
++# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_VIRT
++#endif
++
++#ifdef MINSTATE_PHYS
++# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT);; tpa reg=reg
++# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS
++# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS
++#endif
++
++/*
++ * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
++ * the minimum state necessary that allows us to turn psr.ic back
++ * on.
++ *
++ * Assumed state upon entry:
++ * psr.ic: off
++ * r31: contains saved predicates (pr)
++ *
++ * Upon exit, the state is as follows:
++ * psr.ic: off
++ * r2 = points to &pt_regs.r16
++ * r8 = contents of ar.ccv
++ * r9 = contents of ar.csd
++ * r10 = contents of ar.ssd
++ * r11 = FPSR_DEFAULT
++ * r12 = kernel sp (kernel virtual address)
++ * r13 = points to current task_struct (kernel virtual address)
++ * p15 = TRUE if psr.i is set in cr.ipsr
++ * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
++ * preserved
++ * CONFIG_XEN note: p6/p7 are not preserved
++ *
++ * Note that psr.ic is NOT turned on by this macro. This is so that
++ * we can pass interruption state as arguments to a handler.
++ */
++#ifdef CONFIG_XEN
++#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \
++ MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \
++ mov r27=ar.rsc; /* M */ \
++ mov r20=r1; /* A */ \
++ mov r25=ar.unat; /* M */ \
++ /* mov r29=cr.ipsr; /* M */ \
++ movl r29=XSI_IPSR;; \
++ ld8 r29=[r29];; \
++ mov r26=ar.pfs; /* I */ \
++ /* mov r28=cr.iip; /* M */ \
++ movl r28=XSI_IIP;; \
++ ld8 r28=[r28];; \
++ mov r21=ar.fpsr; /* M */ \
++ COVER; /* B;; (or nothing) */ \
++ ;; \
++ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \
++ ;; \
++ ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \
++ st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \
++ adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \
++ /* switch from user to kernel RBS: */ \
++ ;; \
++ invala; /* M */ \
++ /* SAVE_IFS; /* see xen special handling below */ \
++ cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \
++ ;; \
++ MINSTATE_START_SAVE_MIN \
++ adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \
++ adds r16=PT(CR_IPSR),r1; \
++ ;; \
++ lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \
++ st8 [r16]=r29; /* save cr.ipsr */ \
++ ;; \
++ lfetch.fault.excl.nt1 [r17]; \
++ tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \
++ mov r29=b0 \
++ ;; \
++ adds r16=PT(R8),r1; /* initialize first base pointer */ \
++ adds r17=PT(R9),r1; /* initialize second base pointer */ \
++(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r8,16; \
++.mem.offset 8,0; st8.spill [r17]=r9,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r10,24; \
++.mem.offset 8,0; st8.spill [r17]=r11,24; \
++ ;; \
++ /* xen special handling for possibly lazy cover */ \
++ movl r8=XSI_INCOMPL_REGFR; \
++ ;; \
++ ld4 r30=[r8]; \
++ ;; \
++ cmp.eq p6,p7=r30,r0; \
++ ;; /* not sure if this stop bit is necessary */ \
++(p6) adds r8=XSI_PRECOVER_IFS-XSI_INCOMPL_REGFR,r8; \
++(p7) adds r8=XSI_IFS-XSI_INCOMPL_REGFR,r8; \
++ ;; \
++ ld8 r30=[r8]; \
++ ;; \
++ st8 [r16]=r28,16; /* save cr.iip */ \
++ st8 [r17]=r30,16; /* save cr.ifs */ \
++(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \
++ mov r8=ar.ccv; \
++ mov r9=ar.csd; \
++ mov r10=ar.ssd; \
++ movl r11=FPSR_DEFAULT; /* L-unit */ \
++ ;; \
++ st8 [r16]=r25,16; /* save ar.unat */ \
++ st8 [r17]=r26,16; /* save ar.pfs */ \
++ shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \
++ ;; \
++ st8 [r16]=r27,16; /* save ar.rsc */ \
++(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \
++(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \
++ ;; /* avoid RAW on r16 & r17 */ \
++(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \
++ st8 [r17]=r31,16; /* save predicates */ \
++(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \
++ ;; \
++ st8 [r16]=r29,16; /* save b0 */ \
++ st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \
++ cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \
++.mem.offset 8,0; st8.spill [r17]=r12,16; \
++ adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r13,16; \
++.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \
++ mov r13=IA64_KR(CURRENT); /* establish `current' */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r15,16; \
++.mem.offset 8,0; st8.spill [r17]=r14,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r2,16; \
++.mem.offset 8,0; st8.spill [r17]=r3,16; \
++ ;; \
++ EXTRA; \
++ mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2; \
++ adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
++ ;; \
++ movl r1=__gp; /* establish kernel global pointer */ \
++ ;; \
++ /* MINSTATE_END_SAVE_MIN */
++#else
++#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \
++ MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \
++ mov r27=ar.rsc; /* M */ \
++ mov r20=r1; /* A */ \
++ mov r25=ar.unat; /* M */ \
++ mov r29=cr.ipsr; /* M */ \
++ mov r26=ar.pfs; /* I */ \
++ mov r28=cr.iip; /* M */ \
++ mov r21=ar.fpsr; /* M */ \
++ COVER; /* B;; (or nothing) */ \
++ ;; \
++ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \
++ ;; \
++ ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \
++ st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \
++ adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \
++ /* switch from user to kernel RBS: */ \
++ ;; \
++ invala; /* M */ \
++ SAVE_IFS; \
++ cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \
++ ;; \
++ MINSTATE_START_SAVE_MIN \
++ adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \
++ adds r16=PT(CR_IPSR),r1; \
++ ;; \
++ lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \
++ st8 [r16]=r29; /* save cr.ipsr */ \
++ ;; \
++ lfetch.fault.excl.nt1 [r17]; \
++ tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \
++ mov r29=b0 \
++ ;; \
++ adds r16=PT(R8),r1; /* initialize first base pointer */ \
++ adds r17=PT(R9),r1; /* initialize second base pointer */ \
++(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r8,16; \
++.mem.offset 8,0; st8.spill [r17]=r9,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r10,24; \
++.mem.offset 8,0; st8.spill [r17]=r11,24; \
++ ;; \
++ st8 [r16]=r28,16; /* save cr.iip */ \
++ st8 [r17]=r30,16; /* save cr.ifs */ \
++(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \
++ mov r8=ar.ccv; \
++ mov r9=ar.csd; \
++ mov r10=ar.ssd; \
++ movl r11=FPSR_DEFAULT; /* L-unit */ \
++ ;; \
++ st8 [r16]=r25,16; /* save ar.unat */ \
++ st8 [r17]=r26,16; /* save ar.pfs */ \
++ shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \
++ ;; \
++ st8 [r16]=r27,16; /* save ar.rsc */ \
++(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \
++(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \
++ ;; /* avoid RAW on r16 & r17 */ \
++(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \
++ st8 [r17]=r31,16; /* save predicates */ \
++(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \
++ ;; \
++ st8 [r16]=r29,16; /* save b0 */ \
++ st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \
++ cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \
++.mem.offset 8,0; st8.spill [r17]=r12,16; \
++ adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r13,16; \
++.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \
++ mov r13=IA64_KR(CURRENT); /* establish `current' */ \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r15,16; \
++.mem.offset 8,0; st8.spill [r17]=r14,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r16]=r2,16; \
++.mem.offset 8,0; st8.spill [r17]=r3,16; \
++ adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
++ ;; \
++ EXTRA; \
++ movl r1=__gp; /* establish kernel global pointer */ \
++ ;; \
++ MINSTATE_END_SAVE_MIN
++#endif
++
++/*
++ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
++ *
++ * Assumed state upon entry:
++ * psr.ic: on
++ * r2: points to &pt_regs.r16
++ * r3: points to &pt_regs.r17
++ * r8: contents of ar.ccv
++ * r9: contents of ar.csd
++ * r10: contents of ar.ssd
++ * r11: FPSR_DEFAULT
++ *
++ * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
++ */
++#define SAVE_REST \
++.mem.offset 0,0; st8.spill [r2]=r16,16; \
++.mem.offset 8,0; st8.spill [r3]=r17,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r18,16; \
++.mem.offset 8,0; st8.spill [r3]=r19,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r20,16; \
++.mem.offset 8,0; st8.spill [r3]=r21,16; \
++ mov r18=b6; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r22,16; \
++.mem.offset 8,0; st8.spill [r3]=r23,16; \
++ mov r19=b7; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r24,16; \
++.mem.offset 8,0; st8.spill [r3]=r25,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r26,16; \
++.mem.offset 8,0; st8.spill [r3]=r27,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r28,16; \
++.mem.offset 8,0; st8.spill [r3]=r29,16; \
++ ;; \
++.mem.offset 0,0; st8.spill [r2]=r30,16; \
++.mem.offset 8,0; st8.spill [r3]=r31,32; \
++ ;; \
++ mov ar.fpsr=r11; /* M-unit */ \
++ st8 [r2]=r8,8; /* ar.ccv */ \
++ adds r24=PT(B6)-PT(F7),r3; \
++ ;; \
++ stf.spill [r2]=f6,32; \
++ stf.spill [r3]=f7,32; \
++ ;; \
++ stf.spill [r2]=f8,32; \
++ stf.spill [r3]=f9,32; \
++ ;; \
++ stf.spill [r2]=f10; \
++ stf.spill [r3]=f11; \
++ adds r25=PT(B7)-PT(F11),r3; \
++ ;; \
++ st8 [r24]=r18,16; /* b6 */ \
++ st8 [r25]=r19,16; /* b7 */ \
++ ;; \
++ st8 [r24]=r9; /* ar.csd */ \
++ st8 [r25]=r10; /* ar.ssd */ \
++ ;;
++
++#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs,)
++#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19)
++#ifdef CONFIG_XEN
++#define SAVE_MIN break 0;; /* FIXME: non-cover version only for ia32 support? */
++#else
++#define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, )
++#endif
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xenpal.S
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xenpal.S Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,73 @@
++/*
++ * ia64/xen/xenpal.S
++ *
++ * Alternate PAL routines for Xen. Heavily leveraged from
++ * ia64/kernel/pal.S
++ *
++ * Copyright (C) 2005 Hewlett-Packard Co
++ * Dan Magenheimer <dan.magenheimer at .hp.com>
++ */
++
++#include <asm/asmmacro.h>
++#include <asm/processor.h>
++
++GLOBAL_ENTRY(xen_pal_call_static)
++ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
++ alloc loc1 = ar.pfs,5,5,0,0
++#ifdef CONFIG_XEN
++ movl r22=running_on_xen;;
++ ld4 r22=[r22];;
++ cmp.eq p7,p0=r22,r0
++(p7) br.cond.spnt.many __ia64_pal_call_static;;
++#endif
++ movl loc2 = pal_entry_point
++1: {
++ mov r28 = in0
++ mov r29 = in1
++ mov r8 = ip
++ }
++ ;;
++ ld8 loc2 = [loc2] // loc2 <- entry point
++ tbit.nz p6,p7 = in4, 0
++ adds r8 = 1f-1b,r8
++ mov loc4=ar.rsc // save RSE configuration
++ ;;
++ mov ar.rsc=0 // put RSE in enforced lazy, LE mode
++ mov loc3 = psr
++ mov loc0 = rp
++ .body
++ mov r30 = in2
++
++#ifdef CONFIG_XEN
++ // this is low priority for paravirtualization, but is called
++ // from the idle loop so confuses privop counting
++ movl r31=XSI_PSR_IC
++ ;;
++(p6) st8 [r31]=r0
++ ;;
++(p7) adds r31=XSI_PSR_I-XSI_PSR_IC,r31
++ ;;
++(p7) st4 [r31]=r0
++ ;;
++ mov r31 = in3
++ mov b7 = loc2
++ ;;
++#else
++(p6) rsm psr.i | psr.ic
++ mov r31 = in3
++ mov b7 = loc2
++
++(p7) rsm psr.i
++ ;;
++(p6) srlz.i
++#endif
++ mov rp = r8
++ br.cond.sptk.many b7
++1: mov psr.l = loc3
++ mov ar.rsc = loc4 // restore RSE configuration
++ mov ar.pfs = loc1
++ mov rp = loc0
++ ;;
++ srlz.d // seralize restoration of psr.l
++ br.ret.sptk.many b0
++END(xen_pal_call_static)
+diff -r c75ede70c907 -r f6bd46559b93 arch/ia64/xen/xensetup.S
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/arch/ia64/xen/xensetup.S Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,35 @@
++/*
++ * Support routines for Xen
++ *
++ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer at hp.com>
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/asmmacro.h>
++
++ .data
++ .align 8
++ .globl running_on_xen
++running_on_xen:
++ data4 0
++
++#define isBP p3 // are we the Bootstrap Processor?
++
++ .text
++GLOBAL_ENTRY(early_xen_setup)
++ mov r8=cr.dcr
++(isBP) movl r9=running_on_xen;;
++ extr.u r8=r8,63,1;;
++ cmp.ne p7,p0=r8,r0;;
++(isBP) st4 [r9]=r8
++(p7) movl r10=xen_ivt;;
++(p7) mov cr.iva=r10
++ br.ret.sptk.many rp;;
++END(early_xen_setup)
++
++GLOBAL_ENTRY(is_running_on_xen)
++ movl r9=running_on_xen;;
++ ld4 r8=[r9]
++ br.ret.sptk.many rp;;
++END(is_running_on_xen)
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/fixmap.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/include/asm-ia64/fixmap.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,2 @@
++#define clear_fixmap(x) do {} while (0)
++#define set_fixmap(x,y) do {} while (0)
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/hypercall.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/include/asm-ia64/hypercall.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,253 @@
++/******************************************************************************
++ * hypercall.h
++ *
++ * Linux-specific hypervisor handling.
++ *
++ * 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:
++ *
++ * 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 __HYPERCALL_H__
++#define __HYPERCALL_H__
++
++#include <xen/interface/xen.h>
++#include <xen/interface/sched.h>
++
++/* FIXME: temp place to hold these page related macros */
++#include <asm/page.h>
++#define virt_to_machine(v) __pa(v)
++#define machine_to_virt(m) __va(m)
++#define virt_to_mfn(v) ((__pa(v)) >> PAGE_SHIFT)
++#define mfn_to_virt(m) (__va((m) << PAGE_SHIFT))
++
++/*
++ * Assembler stubs for hyper-calls.
++ */
++
++#define _hypercall0(type, name) \
++({ \
++ long __res; \
++ __asm__ __volatile__ (";;\n" \
++ "mov r2=%1\n" \
++ "break 0x1000 ;;\n" \
++ "mov %0=r8 ;;\n" \
++ : "=r" (__res) \
++ : "i" (__HYPERVISOR_##name) \
++ : "r2","r8", \
++ "memory" ); \
++ (type)__res; \
++})
++
++#define _hypercall1(type, name, a1) \
++({ \
++ long __res; \
++ __asm__ __volatile__ (";;\n" \
++ "mov r14=%2\n" \
++ "mov r2=%1\n" \
++ "break 0x1000 ;;\n" \
++ "mov %0=r8 ;;\n" \
++ : "=r" (__res) \
++ : "i" (__HYPERVISOR_##name), \
++ "r" ((unsigned long)(a1)) \
++ : "r14","r2","r8", \
++ "memory" ); \
++ (type)__res; \
++})
++
++#define _hypercall2(type, name, a1, a2) \
++({ \
++ long __res; \
++ __asm__ __volatile__ (";;\n" \
++ "mov r14=%2\n" \
++ "mov r15=%3\n" \
++ "mov r2=%1\n" \
++ "break 0x1000 ;;\n" \
++ "mov %0=r8 ;;\n" \
++ : "=r" (__res) \
++ : "i" (__HYPERVISOR_##name), \
++ "r" ((unsigned long)(a1)), \
++ "r" ((unsigned long)(a2)) \
++ : "r14","r15","r2","r8", \
++ "memory" ); \
++ (type)__res; \
++})
++
++#define _hypercall3(type, name, a1, a2, a3) \
++({ \
++ long __res; \
++ __asm__ __volatile__ (";;\n" \
++ "mov r14=%2\n" \
++ "mov r15=%3\n" \
++ "mov r16=%4\n" \
++ "mov r2=%1\n" \
++ "break 0x1000 ;;\n" \
++ "mov %0=r8 ;;\n" \
++ : "=r" (__res) \
++ : "i" (__HYPERVISOR_##name), \
++ "r" ((unsigned long)(a1)), \
++ "r" ((unsigned long)(a2)), \
++ "r" ((unsigned long)(a3)) \
++ : "r14","r15","r16","r2","r8", \
++ "memory" ); \
++ (type)__res; \
++})
++
++#define _hypercall4(type, name, a1, a2, a3, a4) \
++({ \
++ long __res; \
++ __asm__ __volatile__ (";;\n" \
++ "mov r14=%2\n" \
++ "mov r15=%3\n" \
++ "mov r16=%4\n" \
++ "mov r17=%5\n" \
++ "mov r2=%1\n" \
++ "break 0x1000 ;;\n" \
++ "mov %0=r8 ;;\n" \
++ : "=r" (__res) \
++ : "i" (__HYPERVISOR_##name), \
++ "r" ((unsigned long)(a1)), \
++ "r" ((unsigned long)(a2)), \
++ "r" ((unsigned long)(a3)), \
++ "r" ((unsigned long)(a4)) \
++ : "r14","r15","r16","r2","r8", \
++ "r17","memory" ); \
++ (type)__res; \
++})
++
++#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
++({ \
++ long __res; \
++ __asm__ __volatile__ (";;\n" \
++ "mov r14=%2\n" \
++ "mov r15=%3\n" \
++ "mov r16=%4\n" \
++ "mov r17=%5\n" \
++ "mov r18=%6\n" \
++ "mov r2=%1\n" \
++ "break 0x1000 ;;\n" \
++ "mov %0=r8 ;;\n" \
++ : "=r" (__res) \
++ : "i" (__HYPERVISOR_##name), \
++ "r" ((unsigned long)(a1)), \
++ "r" ((unsigned long)(a2)), \
++ "r" ((unsigned long)(a3)), \
++ "r" ((unsigned long)(a4)), \
++ "r" ((unsigned long)(a5)) \
++ : "r14","r15","r16","r2","r8", \
++ "r17","r18","memory" ); \
++ (type)__res; \
++})
++
++static inline int
++HYPERVISOR_sched_op(
++ int cmd, unsigned long arg)
++{
++ return _hypercall2(int, sched_op, cmd, arg);
++}
++
++static inline long
++HYPERVISOR_set_timer_op(
++ u64 timeout)
++{
++ unsigned long timeout_hi = (unsigned long)(timeout>>32);
++ unsigned long timeout_lo = (unsigned long)timeout;
++ return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
++}
++
++static inline int
++HYPERVISOR_dom0_op(
++ dom0_op_t *dom0_op)
++{
++ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
++ return _hypercall1(int, dom0_op, dom0_op);
++}
++
++static inline int
++HYPERVISOR_multicall(
++ void *call_list, int nr_calls)
++{
++ return _hypercall2(int, multicall, call_list, nr_calls);
++}
++
++static inline int
++HYPERVISOR_memory_op(
++ unsigned int cmd, void *arg)
++{
++ return _hypercall2(int, memory_op, cmd, arg);
++}
++
++static inline int
++HYPERVISOR_event_channel_op(
++ void *op)
++{
++ return _hypercall1(int, event_channel_op, op);
++}
++
++static inline int
++HYPERVISOR_xen_version(
++ int cmd, void *arg)
++{
++ return _hypercall2(int, xen_version, cmd, arg);
++}
++
++static inline int
++HYPERVISOR_console_io(
++ int cmd, int count, char *str)
++{
++ return _hypercall3(int, console_io, cmd, count, str);
++}
++
++static inline int
++HYPERVISOR_physdev_op(
++ void *physdev_op)
++{
++ return _hypercall1(int, physdev_op, physdev_op);
++}
++
++static inline int
++HYPERVISOR_grant_table_op(
++ unsigned int cmd, void *uop, unsigned int count)
++{
++ return _hypercall3(int, grant_table_op, cmd, uop, count);
++}
++
++static inline int
++HYPERVISOR_vcpu_op(
++ int cmd, int vcpuid, void *extra_args)
++{
++ return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
++}
++
++static inline int
++HYPERVISOR_suspend(
++ unsigned long srec)
++{
++ return _hypercall3(int, sched_op, SCHEDOP_shutdown,
++ SHUTDOWN_suspend, srec);
++}
++
++extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
++static inline void exit_idle(void) {}
++#define do_IRQ(irq, regs) __do_IRQ((irq), (regs))
++
++#endif /* __HYPERCALL_H__ */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/hypervisor.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/include/asm-ia64/hypervisor.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,70 @@
++/******************************************************************************
++ * hypervisor.h
++ *
++ * Linux-specific hypervisor handling.
++ *
++ * 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:
++ *
++ * 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 __HYPERVISOR_H__
++#define __HYPERVISOR_H__
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/dom0_ops.h>
++#include <asm/ptrace.h>
++#include <asm/page.h>
++
++extern shared_info_t *HYPERVISOR_shared_info;
++extern start_info_t *xen_start_info;
++
++void force_evtchn_callback(void);
++
++#include <asm/hypercall.h>
++
++// for drivers/xen/privcmd/privcmd.c
++#define direct_remap_pfn_range(a,b,c,d,e,f) remap_pfn_range(a,b,c,d,e)
++#define pfn_to_mfn(x) (x)
++#define mfn_to_pfn(x) (x)
++#define machine_to_phys_mapping 0
++
++// for drivers/xen/balloon/balloon.c
++#ifdef CONFIG_XEN_SCRUB_PAGES
++#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
++#else
++#define scrub_pages(_p,_n) ((void)0)
++#endif
++#define pte_mfn(_x) pte_pfn(_x)
++#define INVALID_P2M_ENTRY (~0UL)
++#define __pte_ma(_x) ((pte_t) {(_x)})
++#define phys_to_machine_mapping_valid(_x) (1)
++#define kmap_flush_unused() do {} while (0)
++#define set_phys_to_machine(_x,_y) do {} while (0)
++#define xen_machphys_update(_x,_y) do {} while (0)
++#define pfn_pte_ma(_x,_y) __pte_ma(0)
++
++#endif /* __HYPERVISOR_H__ */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/privop.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/include/asm-ia64/privop.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,59 @@
++#ifndef _ASM_IA64_PRIVOP_H
++#define _ASM_IA64_PRIVOP_H
++
++/*
++ * Copyright (C) 2005 Hewlett-Packard Co
++ * Dan Magenheimer <dan.magenheimer at hp.com>
++ *
++ */
++
++#include <linux/config.h>
++#ifdef CONFIG_XEN
++#include <asm/xen/privop.h>
++#endif
++
++#ifndef __ASSEMBLY
++
++#ifndef IA64_PARAVIRTUALIZED
++
++#define ia64_getreg __ia64_getreg
++#define ia64_setreg __ia64_setreg
++#define ia64_hint __ia64_hint
++#define ia64_thash __ia64_thash
++#define ia64_itci __ia64_itci
++#define ia64_itcd __ia64_itcd
++#define ia64_itri __ia64_itri
++#define ia64_itrd __ia64_itrd
++#define ia64_tpa __ia64_tpa
++#define ia64_set_ibr __ia64_set_ibr
++#define ia64_set_pkr __ia64_set_pkr
++#define ia64_set_pmc __ia64_set_pmc
++#define ia64_set_pmd __ia64_set_pmd
++#define ia64_set_rr __ia64_set_rr
++#define ia64_get_cpuid __ia64_get_cpuid
++#define ia64_get_ibr __ia64_get_ibr
++#define ia64_get_pkr __ia64_get_pkr
++#define ia64_get_pmc __ia64_get_pmc
++#define ia64_get_pmd __ia64_get_pmd
++#define ia64_get_rr __ia64_get_rr
++#define ia64_fc __ia64_fc
++#define ia64_ssm __ia64_ssm
++#define ia64_rsm __ia64_rsm
++#define ia64_ptce __ia64_ptce
++#define ia64_ptcga __ia64_ptcga
++#define ia64_ptcl __ia64_ptcl
++#define ia64_ptri __ia64_ptri
++#define ia64_ptrd __ia64_ptrd
++#define ia64_get_psr_i __ia64_get_psr_i
++#define ia64_intrin_local_irq_restore __ia64_intrin_local_irq_restore
++#define ia64_pal_halt_light __ia64_pal_halt_light
++#define ia64_leave_kernel __ia64_leave_kernel
++#define ia64_leave_syscall __ia64_leave_syscall
++#define ia64_switch_to __ia64_switch_to
++#define ia64_pal_call_static __ia64_pal_call_static
++
++#endif /* !IA64_PARAVIRTUALIZED */
++
++#endif /* !__ASSEMBLY */
++
++#endif /* _ASM_IA64_PRIVOP_H */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/synch_bitops.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/include/asm-ia64/synch_bitops.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,61 @@
++#ifndef __XEN_SYNCH_BITOPS_H__
++#define __XEN_SYNCH_BITOPS_H__
++
++/*
++ * Copyright 1992, Linus Torvalds.
++ * Heavily modified to provide guaranteed strong synchronisation
++ * when communicating with Xen or other guest OSes running on other CPUs.
++ */
++
++#include <linux/config.h>
++
++#define ADDR (*(volatile long *) addr)
++
++static __inline__ void synch_set_bit(int nr, volatile void * addr)
++{
++ set_bit(nr, addr);
++}
++
++static __inline__ void synch_clear_bit(int nr, volatile void * addr)
++{
++ clear_bit(nr, addr);
++}
++
++static __inline__ void synch_change_bit(int nr, volatile void * addr)
++{
++ change_bit(nr, addr);
++}
++
++static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
++{
++ return test_and_set_bit(nr, addr);
++}
++
++static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
++{
++ return test_and_clear_bit(nr, addr);
++}
++
++static __inline__ int synch_test_and_change_bit(int nr, volatile void * addr)
++{
++ return test_and_change_bit(nr, addr);
++}
++
++static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
++{
++ return test_bit(nr, addr);
++}
++
++static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
++{
++ return test_bit(nr, addr);
++}
++
++#define synch_cmpxchg ia64_cmpxchg4_acq
++
++#define synch_test_bit(nr,addr) \
++(__builtin_constant_p(nr) ? \
++ synch_const_test_bit((nr),(addr)) : \
++ synch_var_test_bit((nr),(addr)))
++
++#endif /* __XEN_SYNCH_BITOPS_H__ */
+diff -r c75ede70c907 -r f6bd46559b93 include/asm-ia64/xen/privop.h
+--- /dev/null Thu Jan 1 00:00:00 1970 +0000
++++ b/include/asm-ia64/xen/privop.h Mon Mar 6 17:57:34 2006 +0000
+@@ -0,0 +1,272 @@
++#ifndef _ASM_IA64_XEN_PRIVOP_H
++#define _ASM_IA64_XEN_PRIVOP_H
++
++/*
++ * Copyright (C) 2005 Hewlett-Packard Co
++ * Dan Magenheimer <dan.magenheimer at hp.com>
++ *
++ * Paravirtualizations of privileged operations for Xen/ia64
++ *
++ */
++
++
++#include <asm/xen/asm-xsi-offsets.h>
++
++#define IA64_PARAVIRTUALIZED
++
++#ifdef __ASSEMBLY__
++#define XEN_HYPER_RFI break 0x1
++#define XEN_HYPER_RSM_PSR_DT break 0x2
++#define XEN_HYPER_SSM_PSR_DT break 0x3
++#define XEN_HYPER_COVER break 0x4
++#define XEN_HYPER_ITC_D break 0x5
++#define XEN_HYPER_ITC_I break 0x6
++#define XEN_HYPER_SSM_I break 0x7
++#define XEN_HYPER_GET_IVR break 0x8
++#define XEN_HYPER_GET_TPR break 0x9
++#define XEN_HYPER_SET_TPR break 0xa
++#define XEN_HYPER_EOI break 0xb
++#define XEN_HYPER_SET_ITM break 0xc
++#define XEN_HYPER_THASH break 0xd
++#define XEN_HYPER_PTC_GA break 0xe
++#define XEN_HYPER_ITR_D break 0xf
++#define XEN_HYPER_GET_RR break 0x10
++#define XEN_HYPER_SET_RR break 0x11
++#define XEN_HYPER_SET_KR break 0x12
++#endif
++
++#ifndef __ASSEMBLY__
++#ifdef MODULE
++extern int is_running_on_xen(void);
++#define running_on_xen (is_running_on_xen())
++#else
++extern int running_on_xen;
++#endif
++
++#define XEN_HYPER_SSM_I asm("break 0x7");
++#define XEN_HYPER_GET_IVR asm("break 0x8");
++
++/************************************************/
++/* Instructions paravirtualized for correctness */
++/************************************************/
++
++/* "fc" and "thash" are privilege-sensitive instructions, meaning they
++ * may have different semantics depending on whether they are executed
++ * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't
++ * be allowed to execute directly, lest incorrect semantics result. */
++extern unsigned long xen_fc(unsigned long addr);
++#define ia64_fc(addr) xen_fc((unsigned long)(addr))
++extern unsigned long xen_thash(unsigned long addr);
++#define ia64_thash(addr) xen_thash((unsigned long)(addr))
++/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
++ * is not currently used (though it may be in a long-format VHPT system!)
++ * and the semantics of cover only change if psr.ic is off which is very
++ * rare (and currently non-existent outside of assembly code */
++
++/* There are also privilege-sensitive registers. These registers are
++ * readable at any privilege level but only writable at PL0. */
++extern unsigned long xen_get_cpuid(int index);
++#define ia64_get_cpuid(i) xen_get_cpuid(i)
++extern unsigned long xen_get_pmd(int index);
++#define ia64_get_pmd(i) xen_get_pmd(i)
++extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */
++extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */
++
++/************************************************/
++/* Instructions paravirtualized for performance */
++/************************************************/
++
++/* Xen uses memory-mapped virtual privileged registers for access to many
++ * performance-sensitive privileged registers. Some, like the processor
++ * status register (psr), are broken up into multiple memory locations.
++ * Others, like "pend", are abstractions based on privileged registers.
++ * "Pend" is guaranteed to be set if reading cr.ivr would return a
++ * (non-spurious) interrupt. */
++#define xen_get_virtual_psr_i() (*(int *)(XSI_PSR_I))
++#define xen_set_virtual_psr_i(_val) ({ *(int *)(XSI_PSR_I) = _val ? 1:0; })
++#define xen_set_virtual_psr_ic(_val) ({ *(int *)(XSI_PSR_IC) = _val ? 1:0; })
++#define xen_get_virtual_pend() (*(int *)(XSI_PEND))
++
++/* Hyperprivops are "break" instructions with a well-defined API.
++ * In particular, the virtual psr.ic bit must be off; in this way
++ * it is guaranteed to never conflict with a linux break instruction.
++ * Normally, this is done in a xen stub but this one is frequent enough
++ * that we inline it */
++#define xen_hyper_ssm_i() \
++({ \
++ xen_set_virtual_psr_i(0); \
++ xen_set_virtual_psr_ic(0); \
++ XEN_HYPER_SSM_I; \
++})
++
++/* turning off interrupts can be paravirtualized simply by writing
++ * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */
++#define xen_rsm_i() xen_set_virtual_psr_i(0)
++
++/* turning on interrupts is a bit more complicated.. write to the
++ * memory-mapped virtual psr.i bit first (to avoid race condition),
++ * then if any interrupts were pending, we have to execute a hyperprivop
++ * to ensure the pending interrupt gets delivered; else we're done! */
++#define xen_ssm_i() \
++({ \
++ int old = xen_get_virtual_psr_i(); \
++ xen_set_virtual_psr_i(1); \
++ if (!old && xen_get_virtual_pend()) xen_hyper_ssm_i(); \
++})
++
++#define xen_ia64_intrin_local_irq_restore(x) \
++{ \
++ if (running_on_xen) { \
++ if ((x) & IA64_PSR_I) { xen_ssm_i(); } \
++ else { xen_rsm_i(); } \
++ } \
++ else __ia64_intrin_local_irq_restore((x)); \
++}
++
++#define xen_get_psr_i() \
++( \
++ (running_on_xen) ? \
++ (xen_get_virtual_psr_i() ? IA64_PSR_I : 0) \
++ : __ia64_get_psr_i() \
++)
++
++#define xen_ia64_ssm(mask) \
++{ \
++ if ((mask)==IA64_PSR_I) { \
++ if (running_on_xen) { xen_ssm_i(); } \
++ else { __ia64_ssm(mask); } \
++ } \
++ else { __ia64_ssm(mask); } \
++}
++
++#define xen_ia64_rsm(mask) \
++{ \
++ if ((mask)==IA64_PSR_I) { \
++ if (running_on_xen) { xen_rsm_i(); } \
++ else { __ia64_rsm(mask); } \
++ } \
++ else { __ia64_rsm(mask); } \
++}
++
++
++/* Although all privileged operations can be left to trap and will
++ * be properly handled by Xen, some are frequent enough that we use
++ * hyperprivops for performance. */
++
++extern unsigned long xen_get_ivr(void);
++extern unsigned long xen_get_tpr(void);
++extern void xen_set_itm(unsigned long);
++extern void xen_set_tpr(unsigned long);
++extern void xen_eoi(void);
++extern void xen_set_rr(unsigned long index, unsigned long val);
++extern unsigned long xen_get_rr(unsigned long index);
++extern void xen_set_kr(unsigned long index, unsigned long val);
++
++/* Note: It may look wrong to test for running_on_xen in each case.
++ * However regnum is always a constant so, as written, the compiler
++ * eliminates the switch statement, whereas running_on_xen must be
++ * tested dynamically. */
++#define xen_ia64_getreg(regnum) \
++({ \
++ __u64 ia64_intri_res; \
++ \
++ switch(regnum) { \
++ case _IA64_REG_CR_IVR: \
++ ia64_intri_res = (running_on_xen) ? \
++ xen_get_ivr() : \
++ __ia64_getreg(regnum); \
++ break; \
++ case _IA64_REG_CR_TPR: \
++ ia64_intri_res = (running_on_xen) ? \
++ xen_get_tpr() : \
++ __ia64_getreg(regnum); \
++ break; \
++ case _IA64_REG_AR_EFLAG: \
++ ia64_intri_res = (running_on_xen) ? \
++ xen_get_eflag() : \
++ __ia64_getreg(regnum); \
++ break; \
++ default: \
++ ia64_intri_res = __ia64_getreg(regnum); \
++ break; \
++ } \
++ ia64_intri_res; \
++})
++
++#define xen_ia64_setreg(regnum,val) \
++({ \
++ switch(regnum) { \
++ case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: \
++ (running_on_xen) ? \
++ xen_set_kr((regnum-_IA64_REG_AR_KR0), val) : \
++ __ia64_setreg(regnum,val); \
++ break; \
++ case _IA64_REG_CR_ITM: \
++ (running_on_xen) ? \
++ xen_set_itm(val) : \
++ __ia64_setreg(regnum,val); \
++ break; \
++ case _IA64_REG_CR_TPR: \
++ (running_on_xen) ? \
++ xen_set_tpr(val) : \
++ __ia64_setreg(regnum,val); \
++ break; \
++ case _IA64_REG_CR_EOI: \
++ (running_on_xen) ? \
++ xen_eoi() : \
++ __ia64_setreg(regnum,val); \
++ break; \
++ case _IA64_REG_AR_EFLAG: \
++ (running_on_xen) ? \
++ xen_set_eflag(val) : \
++ __ia64_setreg(regnum,val); \
++ break; \
++ default: \
++ __ia64_setreg(regnum,val); \
++ break; \
++ } \
++})
++
++#define ia64_ssm xen_ia64_ssm
++#define ia64_rsm xen_ia64_rsm
++#define ia64_intrin_local_irq_restore xen_ia64_intrin_local_irq_restore
++#define ia64_ptcga xen_ptcga
++#define ia64_set_rr(index,val) xen_set_rr(index,val)
++#define ia64_get_rr(index) xen_get_rr(index)
++#define ia64_getreg xen_ia64_getreg
++#define ia64_setreg xen_ia64_setreg
++#define ia64_get_psr_i xen_get_psr_i
++
++/* the remainder of these are not performance-sensitive so its
++ * OK to not paravirtualize and just take a privop trap and emulate */
++#define ia64_hint __ia64_hint
++#define ia64_set_pmd __ia64_set_pmd
++#define ia64_itci __ia64_itci
++#define ia64_itcd __ia64_itcd
++#define ia64_itri __ia64_itri
++#define ia64_itrd __ia64_itrd
++#define ia64_tpa __ia64_tpa
++#define ia64_set_ibr __ia64_set_ibr
++#define ia64_set_pkr __ia64_set_pkr
++#define ia64_set_pmc __ia64_set_pmc
++#define ia64_get_ibr __ia64_get_ibr
++#define ia64_get_pkr __ia64_get_pkr
++#define ia64_get_pmc __ia64_get_pmc
++#define ia64_ptce __ia64_ptce
++#define ia64_ptcl __ia64_ptcl
++#define ia64_ptri __ia64_ptri
++#define ia64_ptrd __ia64_ptrd
++
++#endif /* !__ASSEMBLY__ */
++
++/* these routines utilize privilege-sensitive or performance-sensitive
++ * privileged instructions so the code must be replaced with
++ * paravirtualized versions */
++#define ia64_pal_halt_light xen_pal_halt_light
++#define ia64_leave_kernel xen_leave_kernel
++#define ia64_leave_syscall xen_leave_syscall
++#define ia64_trace_syscall xen_trace_syscall
++#define ia64_switch_to xen_switch_to
++#define ia64_pal_call_static xen_pal_call_static
++
++#endif /* _ASM_IA64_XEN_PRIVOP_H */
+diff -r c75ede70c907 -r f6bd46559b93 include/xen/public/xenstored.h
+--- a/include/xen/public/xenstored.h Mon Feb 27 15:43:34 2006 +0000
++++ /dev/null Thu Jan 1 00:00:00 1970 +0000
+@@ -1,89 +0,0 @@
+-/*
+- * Simple prototyle Xen Store Daemon providing simple tree-like database.
+- * 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:
+- *
+- * 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 _XENSTORED_H
+-#define _XENSTORED_H
+-
+-enum xsd_sockmsg_type
+-{
+- XS_DEBUG,
+- XS_SHUTDOWN,
+- XS_DIRECTORY,
+- XS_READ,
+- XS_GET_PERMS,
+- XS_WATCH,
+- XS_WATCH_ACK,
+- XS_UNWATCH,
+- XS_TRANSACTION_START,
+- XS_TRANSACTION_END,
+- XS_OP_READ_ONLY = XS_TRANSACTION_END,
+- XS_INTRODUCE,
+- XS_RELEASE,
+- XS_GET_DOMAIN_PATH,
+- XS_WRITE,
+- XS_MKDIR,
+- XS_RM,
+- XS_SET_PERMS,
+- XS_WATCH_EVENT,
+- XS_ERROR,
+-};
+-
+-#define XS_WRITE_NONE "NONE"
+-#define XS_WRITE_CREATE "CREATE"
+-#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
+-
+-/* We hand errors as strings, for portability. */
+-struct xsd_errors
+-{
+- int errnum;
+- const char *errstring;
+-};
+-#define XSD_ERROR(x) { x, #x }
+-static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
+- XSD_ERROR(EINVAL),
+- XSD_ERROR(EACCES),
+- XSD_ERROR(EEXIST),
+- XSD_ERROR(EISDIR),
+- XSD_ERROR(ENOENT),
+- XSD_ERROR(ENOMEM),
+- XSD_ERROR(ENOSPC),
+- XSD_ERROR(EIO),
+- XSD_ERROR(ENOTEMPTY),
+- XSD_ERROR(ENOSYS),
+- XSD_ERROR(EROFS),
+- XSD_ERROR(EBUSY),
+- XSD_ERROR(EAGAIN),
+- XSD_ERROR(EISCONN),
+-};
+-struct xsd_sockmsg
+-{
+- u32 type;
+- u32 len; /* Length of data following this. */
+-
+- /* Generally followed by nul-terminated string(s). */
+-};
+-
+-#endif /* _XENSTORED_H */
More information about the Kernel-svn-changes
mailing list