ia64/xen-unstable

changeset 13528:3c8bb086025e

[merge] with xen-unstable

Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Fri Jan 19 14:48:57 2007 +0000 (2007-01-19)
parents 8475a4e0425e 3157835b1d45
children 9a0b157a0ab0
files buildconfigs/linux-defconfig_xen0_x86_32 buildconfigs/linux-defconfig_xen0_x86_64 buildconfigs/linux-defconfig_xenU_x86_32 buildconfigs/linux-defconfig_xenU_x86_64 buildconfigs/linux-defconfig_xen_x86_32 buildconfigs/linux-defconfig_xen_x86_64 buildconfigs/mk.linux-2.6-xen linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c linux-2.6-xen-sparse/arch/ia64/Kconfig linux-2.6-xen-sparse/arch/ia64/kernel/asm-offsets.c linux-2.6-xen-sparse/arch/ia64/kernel/gate.S linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S linux-2.6-xen-sparse/arch/ia64/kernel/patch.c linux-2.6-xen-sparse/arch/ia64/kernel/setup.c linux-2.6-xen-sparse/drivers/xen/Kconfig linux-2.6-xen-sparse/drivers/xen/netback/netback.c linux-2.6-xen-sparse/include/asm-ia64/page.h linux-2.6-xen-sparse/include/linux/skbuff.h linux-2.6-xen-sparse/net/core/skbuff.c tools/python/xen/xend/XendRoot.py xen/arch/ia64/linux/cmdline.c xen/include/asm-ia64/linux-null/linux/ioport.h xen/include/asm-ia64/linux-xen/asm/sn/sn_sal.h xen/include/asm-ia64/linux/asm/machvec.h xen/include/asm-ia64/linux/asm/pci.h
line diff
     1.1 --- a/Config.mk	Thu Jan 18 15:18:07 2007 +0000
     1.2 +++ b/Config.mk	Fri Jan 19 14:48:57 2007 +0000
     1.3 @@ -6,9 +6,12 @@ debug ?= n
     1.4  XEN_COMPILE_ARCH    ?= $(shell uname -m | sed -e s/i.86/x86_32/ \
     1.5                           -e s/ppc/powerpc/ -e s/i86pc/x86_32/)
     1.6  XEN_TARGET_ARCH     ?= $(XEN_COMPILE_ARCH)
     1.7 -XEN_TARGET_X86_PAE  ?= n
     1.8  XEN_OS              ?= $(shell uname -s)
     1.9  
    1.10 +ifeq ($(XEN_TARGET_ARCH),x86_32)
    1.11 +XEN_TARGET_X86_PAE  ?= y
    1.12 +endif
    1.13 +
    1.14  CONFIG_$(XEN_OS) := y
    1.15  
    1.16  SHELL     ?= /bin/sh
     2.1 --- a/buildconfigs/linux-defconfig_xen0_ia64	Thu Jan 18 15:18:07 2007 +0000
     2.2 +++ b/buildconfigs/linux-defconfig_xen0_ia64	Fri Jan 19 14:48:57 2007 +0000
     2.3 @@ -1512,10 +1512,7 @@ CONFIG_CRYPTO_DES=y
     2.4  # Hardware crypto devices
     2.5  #
     2.6  # CONFIG_XEN_UTIL is not set
     2.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
     2.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
     2.9  CONFIG_XEN_BALLOON=y
    2.10 -CONFIG_XEN_SKBUFF=y
    2.11  # CONFIG_XEN_DEVMEM is not set
    2.12  CONFIG_XEN_REBOOT=y
    2.13  # CONFIG_XEN_SMPBOOT is not set
     3.1 --- a/buildconfigs/linux-defconfig_xen0_x86_32	Thu Jan 18 15:18:07 2007 +0000
     3.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_32	Fri Jan 19 14:48:57 2007 +0000
     3.3 @@ -569,7 +569,7 @@ CONFIG_MEGARAID_NEWGEN=y
     3.4  # CONFIG_MEGARAID_LEGACY is not set
     3.5  # CONFIG_MEGARAID_SAS is not set
     3.6  CONFIG_SCSI_SATA=y
     3.7 -# CONFIG_SCSI_SATA_AHCI is not set
     3.8 +CONFIG_SCSI_SATA_AHCI=y
     3.9  # CONFIG_SCSI_SATA_SVW is not set
    3.10  CONFIG_SCSI_ATA_PIIX=y
    3.11  # CONFIG_SCSI_SATA_MV is not set
    3.12 @@ -734,7 +734,7 @@ CONFIG_E1000=y
    3.13  CONFIG_SK98LIN=y
    3.14  # CONFIG_VIA_VELOCITY is not set
    3.15  CONFIG_TIGON3=y
    3.16 -# CONFIG_BNX2 is not set
    3.17 +CONFIG_BNX2=y
    3.18  
    3.19  #
    3.20  # Ethernet (10000 Mbit)
    3.21 @@ -1413,8 +1413,6 @@ CONFIG_XEN_SYSFS=y
    3.22  CONFIG_XEN_COMPAT_030002_AND_LATER=y
    3.23  # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
    3.24  CONFIG_XEN_COMPAT_030002=y
    3.25 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
    3.26 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
    3.27  CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
    3.28  CONFIG_NO_IDLE_HZ=y
    3.29  CONFIG_XEN_UTIL=y
     4.1 --- a/buildconfigs/linux-defconfig_xen0_x86_64	Thu Jan 18 15:18:07 2007 +0000
     4.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_64	Fri Jan 19 14:48:57 2007 +0000
     4.3 @@ -517,7 +517,7 @@ CONFIG_MEGARAID_NEWGEN=y
     4.4  # CONFIG_MEGARAID_LEGACY is not set
     4.5  # CONFIG_MEGARAID_SAS is not set
     4.6  CONFIG_SCSI_SATA=y
     4.7 -# CONFIG_SCSI_SATA_AHCI is not set
     4.8 +CONFIG_SCSI_SATA_AHCI=y
     4.9  # CONFIG_SCSI_SATA_SVW is not set
    4.10  CONFIG_SCSI_ATA_PIIX=y
    4.11  # CONFIG_SCSI_SATA_MV is not set
    4.12 @@ -683,7 +683,7 @@ CONFIG_E1000=y
    4.13  CONFIG_SK98LIN=y
    4.14  # CONFIG_VIA_VELOCITY is not set
    4.15  CONFIG_TIGON3=y
    4.16 -# CONFIG_BNX2 is not set
    4.17 +CONFIG_BNX2=y
    4.18  
    4.19  #
    4.20  # Ethernet (10000 Mbit)
    4.21 @@ -1363,8 +1363,6 @@ CONFIG_XEN_SYSFS=y
    4.22  CONFIG_XEN_COMPAT_030002_AND_LATER=y
    4.23  # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
    4.24  CONFIG_XEN_COMPAT_030002=y
    4.25 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
    4.26 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
    4.27  CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
    4.28  CONFIG_NO_IDLE_HZ=y
    4.29  CONFIG_XEN_UTIL=y
     5.1 --- a/buildconfigs/linux-defconfig_xenU_ia64	Thu Jan 18 15:18:07 2007 +0000
     5.2 +++ b/buildconfigs/linux-defconfig_xenU_ia64	Fri Jan 19 14:48:57 2007 +0000
     5.3 @@ -1386,10 +1386,7 @@ CONFIG_CRYPTO_DES=y
     5.4  # Hardware crypto devices
     5.5  #
     5.6  # CONFIG_XEN_UTIL is not set
     5.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
     5.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
     5.9  CONFIG_XEN_BALLOON=y
    5.10 -CONFIG_XEN_SKBUFF=y
    5.11  # CONFIG_XEN_DEVMEM is not set
    5.12  CONFIG_XEN_REBOOT=y
    5.13  # CONFIG_XEN_SMPBOOT is not set
     6.1 --- a/buildconfigs/linux-defconfig_xenU_x86_32	Thu Jan 18 15:18:07 2007 +0000
     6.2 +++ b/buildconfigs/linux-defconfig_xenU_x86_32	Fri Jan 19 14:48:57 2007 +0000
     6.3 @@ -922,8 +922,6 @@ CONFIG_XEN_SYSFS=y
     6.4  CONFIG_XEN_COMPAT_030002_AND_LATER=y
     6.5  # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
     6.6  CONFIG_XEN_COMPAT_030002=y
     6.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
     6.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
     6.9  CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
    6.10  CONFIG_NO_IDLE_HZ=y
    6.11  CONFIG_XEN_UTIL=y
     7.1 --- a/buildconfigs/linux-defconfig_xenU_x86_64	Thu Jan 18 15:18:07 2007 +0000
     7.2 +++ b/buildconfigs/linux-defconfig_xenU_x86_64	Fri Jan 19 14:48:57 2007 +0000
     7.3 @@ -1218,8 +1218,6 @@ CONFIG_XEN_SYSFS=y
     7.4  CONFIG_XEN_COMPAT_030002_AND_LATER=y
     7.5  # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
     7.6  CONFIG_XEN_COMPAT_030002=y
     7.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
     7.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
     7.9  CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
    7.10  CONFIG_NO_IDLE_HZ=y
    7.11  CONFIG_XEN_UTIL=y
     8.1 --- a/buildconfigs/linux-defconfig_xen_ia64	Thu Jan 18 15:18:07 2007 +0000
     8.2 +++ b/buildconfigs/linux-defconfig_xen_ia64	Fri Jan 19 14:48:57 2007 +0000
     8.3 @@ -1518,10 +1518,7 @@ CONFIG_CRYPTO_DES=y
     8.4  # Hardware crypto devices
     8.5  #
     8.6  # CONFIG_XEN_UTIL is not set
     8.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
     8.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
     8.9  CONFIG_XEN_BALLOON=y
    8.10 -CONFIG_XEN_SKBUFF=y
    8.11  # CONFIG_XEN_DEVMEM is not set
    8.12  CONFIG_XEN_REBOOT=y
    8.13  # CONFIG_XEN_SMPBOOT is not set
     9.1 --- a/buildconfigs/linux-defconfig_xen_x86_32	Thu Jan 18 15:18:07 2007 +0000
     9.2 +++ b/buildconfigs/linux-defconfig_xen_x86_32	Fri Jan 19 14:48:57 2007 +0000
     9.3 @@ -3272,8 +3272,6 @@ CONFIG_XEN_SYSFS=y
     9.4  CONFIG_XEN_COMPAT_030002_AND_LATER=y
     9.5  # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
     9.6  CONFIG_XEN_COMPAT_030002=y
     9.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
     9.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
     9.9  CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
    9.10  CONFIG_NO_IDLE_HZ=y
    9.11  CONFIG_XEN_UTIL=y
    10.1 --- a/buildconfigs/linux-defconfig_xen_x86_64	Thu Jan 18 15:18:07 2007 +0000
    10.2 +++ b/buildconfigs/linux-defconfig_xen_x86_64	Fri Jan 19 14:48:57 2007 +0000
    10.3 @@ -3103,8 +3103,6 @@ CONFIG_XEN_SYSFS=y
    10.4  CONFIG_XEN_COMPAT_030002_AND_LATER=y
    10.5  # CONFIG_XEN_COMPAT_LATEST_ONLY is not set
    10.6  CONFIG_XEN_COMPAT_030002=y
    10.7 -CONFIG_HAVE_ARCH_ALLOC_SKB=y
    10.8 -CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
    10.9  CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
   10.10  CONFIG_NO_IDLE_HZ=y
   10.11  CONFIG_XEN_UTIL=y
    11.1 --- a/buildconfigs/mk.linux-2.6-xen	Thu Jan 18 15:18:07 2007 +0000
    11.2 +++ b/buildconfigs/mk.linux-2.6-xen	Fri Jan 19 14:48:57 2007 +0000
    11.3 @@ -9,6 +9,10 @@ LINUX_DIR    = build-linux-$(LINUX_VER)-
    11.4  IMAGE_TARGET ?= vmlinuz
    11.5  INSTALL_BOOT_PATH ?= $(DESTDIR)
    11.6  
    11.7 +ifeq ($(XEN_TARGET_ARCH),ia64)
    11.8 +INSTALL_BOOT_PATH := $(DESTDIR)/boot
    11.9 +endif
   11.10 +
   11.11  LINUX_VER3  := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
   11.12  
   11.13  include buildconfigs/Rules.mk
    12.1 --- a/extras/mini-os/Makefile	Thu Jan 18 15:18:07 2007 +0000
    12.2 +++ b/extras/mini-os/Makefile	Fri Jan 19 14:48:57 2007 +0000
    12.3 @@ -9,7 +9,7 @@ pae ?= n
    12.4  XEN_ROOT = ../..
    12.5  include $(XEN_ROOT)/Config.mk
    12.6  
    12.7 -XEN_INTERFACE_VERSION := 0x00030204
    12.8 +XEN_INTERFACE_VERSION := 0x00030205
    12.9  export XEN_INTERFACE_VERSION
   12.10  
   12.11  # Set TARGET_ARCH
    13.1 --- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h	Thu Jan 18 15:18:07 2007 +0000
    13.2 +++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h	Fri Jan 19 14:48:57 2007 +0000
    13.3 @@ -305,6 +305,20 @@ HYPERVISOR_nmi_op(
    13.4  	return _hypercall2(int, nmi_op, op, arg);
    13.5  }
    13.6  
    13.7 +static inline int
    13.8 +HYPERVISOR_sysctl(
    13.9 +	unsigned long op)
   13.10 +{
   13.11 +	return _hypercall1(int, sysctl, op);
   13.12 +}
   13.13 +
   13.14 +static inline int
   13.15 +HYPERVISOR_domctl(
   13.16 +	unsigned long op)
   13.17 +{
   13.18 +	return _hypercall1(int, domctl, op);
   13.19 +}
   13.20 +
   13.21  #endif /* __HYPERCALL_X86_32_H__ */
   13.22  
   13.23  /*
    14.1 --- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h	Thu Jan 18 15:18:07 2007 +0000
    14.2 +++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h	Fri Jan 19 14:48:57 2007 +0000
    14.3 @@ -305,6 +305,20 @@ HYPERVISOR_nmi_op(
    14.4  	return _hypercall2(int, nmi_op, op, arg);
    14.5  }
    14.6  
    14.7 +static inline int
    14.8 +HYPERVISOR_sysctl(
    14.9 +	unsigned long op)
   14.10 +{
   14.11 +	return _hypercall1(int, sysctl, op);
   14.12 +}
   14.13 +
   14.14 +static inline int
   14.15 +HYPERVISOR_domctl(
   14.16 +	unsigned long op)
   14.17 +{
   14.18 +	return _hypercall1(int, domctl, op);
   14.19 +}
   14.20 +
   14.21  #endif /* __HYPERCALL_X86_64_H__ */
   14.22  
   14.23  /*
    15.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c	Thu Jan 18 15:18:07 2007 +0000
    15.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c	Fri Jan 19 14:48:57 2007 +0000
    15.3 @@ -76,7 +76,9 @@ static void *syscall_page;
    15.4  
    15.5  int __init sysenter_setup(void)
    15.6  {
    15.7 -	syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
    15.8 +	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
    15.9 +
   15.10 +	syscall_page = page;
   15.11  
   15.12  #ifdef CONFIG_XEN
   15.13  	if (boot_cpu_has(X86_FEATURE_SEP)) {
    16.1 --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig	Thu Jan 18 15:18:07 2007 +0000
    16.2 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig	Fri Jan 19 14:48:57 2007 +0000
    16.3 @@ -579,12 +579,6 @@ if XEN
    16.4  config XEN_UTIL
    16.5  	default n
    16.6  
    16.7 -config HAVE_ARCH_ALLOC_SKB
    16.8 -	default y
    16.9 -
   16.10 -config HAVE_ARCH_DEV_ALLOC_SKB
   16.11 -	default y
   16.12 -
   16.13  config XEN_BALLOON
   16.14  	default y
   16.15  
    17.1 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/asm-offsets.c	Thu Jan 18 15:18:07 2007 +0000
    17.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/asm-offsets.c	Fri Jan 19 14:48:57 2007 +0000
    17.3 @@ -287,7 +287,6 @@ void foo(void)
    17.4  	DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha);
    17.5  	DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir);
    17.6  	DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled);
    17.7 -	DEFINE_MAPPED_REG_OFS(XSI_INCOMPL_REGFR_OFS, incomplete_regframe);
    17.8  	DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum);
    17.9  	DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]);
   17.10  	DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]);
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/fsys.S	Fri Jan 19 14:48:57 2007 +0000
    18.3 @@ -0,0 +1,925 @@
    18.4 +/*
    18.5 + * This file contains the light-weight system call handlers (fsyscall-handlers).
    18.6 + *
    18.7 + * Copyright (C) 2003 Hewlett-Packard Co
    18.8 + * 	David Mosberger-Tang <davidm@hpl.hp.com>
    18.9 + *
   18.10 + * 25-Sep-03 davidm	Implement fsys_rt_sigprocmask().
   18.11 + * 18-Feb-03 louisk	Implement fsys_gettimeofday().
   18.12 + * 28-Feb-03 davidm	Fixed several bugs in fsys_gettimeofday().  Tuned it some more,
   18.13 + *			probably broke it along the way... ;-)
   18.14 + * 13-Jul-04 clameter   Implement fsys_clock_gettime and revise fsys_gettimeofday to make
   18.15 + *                      it capable of using memory based clocks without falling back to C code.
   18.16 + */
   18.17 +
   18.18 +#include <asm/asmmacro.h>
   18.19 +#include <asm/errno.h>
   18.20 +#include <asm/asm-offsets.h>
   18.21 +#include <asm/percpu.h>
   18.22 +#include <asm/thread_info.h>
   18.23 +#include <asm/sal.h>
   18.24 +#include <asm/signal.h>
   18.25 +#include <asm/system.h>
   18.26 +#include <asm/unistd.h>
   18.27 +
   18.28 +#include "entry.h"
   18.29 +
   18.30 +/*
   18.31 + * See Documentation/ia64/fsys.txt for details on fsyscalls.
   18.32 + *
   18.33 + * On entry to an fsyscall handler:
   18.34 + *   r10	= 0 (i.e., defaults to "successful syscall return")
   18.35 + *   r11	= saved ar.pfs (a user-level value)
   18.36 + *   r15	= system call number
   18.37 + *   r16	= "current" task pointer (in normal kernel-mode, this is in r13)
   18.38 + *   r32-r39	= system call arguments
   18.39 + *   b6		= return address (a user-level value)
   18.40 + *   ar.pfs	= previous frame-state (a user-level value)
   18.41 + *   PSR.be	= cleared to zero (i.e., little-endian byte order is in effect)
   18.42 + *   all other registers may contain values passed in from user-mode
   18.43 + *
   18.44 + * On return from an fsyscall handler:
   18.45 + *   r11	= saved ar.pfs (as passed into the fsyscall handler)
   18.46 + *   r15	= system call number (as passed into the fsyscall handler)
   18.47 + *   r32-r39	= system call arguments (as passed into the fsyscall handler)
   18.48 + *   b6		= return address (as passed into the fsyscall handler)
   18.49 + *   ar.pfs	= previous frame-state (as passed into the fsyscall handler)
   18.50 + */
   18.51 +
   18.52 +ENTRY(fsys_ni_syscall)
   18.53 +	.prologue
   18.54 +	.altrp b6
   18.55 +	.body
   18.56 +	mov r8=ENOSYS
   18.57 +	mov r10=-1
   18.58 +	FSYS_RETURN
   18.59 +END(fsys_ni_syscall)
   18.60 +
   18.61 +ENTRY(fsys_getpid)
   18.62 +	.prologue
   18.63 +	.altrp b6
   18.64 +	.body
   18.65 +	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
   18.66 +	;;
   18.67 +	ld4 r9=[r9]
   18.68 +	add r8=IA64_TASK_TGID_OFFSET,r16
   18.69 +	;;
   18.70 +	and r9=TIF_ALLWORK_MASK,r9
   18.71 +	ld4 r8=[r8]				// r8 = current->tgid
   18.72 +	;;
   18.73 +	cmp.ne p8,p0=0,r9
   18.74 +(p8)	br.spnt.many fsys_fallback_syscall
   18.75 +	FSYS_RETURN
   18.76 +END(fsys_getpid)
   18.77 +
   18.78 +ENTRY(fsys_getppid)
   18.79 +	.prologue
   18.80 +	.altrp b6
   18.81 +	.body
   18.82 +	add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
   18.83 +	;;
   18.84 +	ld8 r17=[r17]				// r17 = current->group_leader
   18.85 +	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
   18.86 +	;;
   18.87 +
   18.88 +	ld4 r9=[r9]
   18.89 +	add r17=IA64_TASK_REAL_PARENT_OFFSET,r17 // r17 = &current->group_leader->real_parent
   18.90 +	;;
   18.91 +	and r9=TIF_ALLWORK_MASK,r9
   18.92 +
   18.93 +1:	ld8 r18=[r17]				// r18 = current->group_leader->real_parent
   18.94 +	;;
   18.95 +	cmp.ne p8,p0=0,r9
   18.96 +	add r8=IA64_TASK_TGID_OFFSET,r18	// r8 = &current->group_leader->real_parent->tgid
   18.97 +	;;
   18.98 +
   18.99 +	/*
  18.100 +	 * The .acq is needed to ensure that the read of tgid has returned its data before
  18.101 +	 * we re-check "real_parent".
  18.102 +	 */
  18.103 +	ld4.acq r8=[r8]				// r8 = current->group_leader->real_parent->tgid
  18.104 +#ifdef CONFIG_SMP
  18.105 +	/*
  18.106 +	 * Re-read current->group_leader->real_parent.
  18.107 +	 */
  18.108 +	ld8 r19=[r17]				// r19 = current->group_leader->real_parent
  18.109 +(p8)	br.spnt.many fsys_fallback_syscall
  18.110 +	;;
  18.111 +	cmp.ne p6,p0=r18,r19			// did real_parent change?
  18.112 +	mov r19=0			// i must not leak kernel bits...
  18.113 +(p6)	br.cond.spnt.few 1b			// yes -> redo the read of tgid and the check
  18.114 +	;;
  18.115 +	mov r17=0			// i must not leak kernel bits...
  18.116 +	mov r18=0			// i must not leak kernel bits...
  18.117 +#else
  18.118 +	mov r17=0			// i must not leak kernel bits...
  18.119 +	mov r18=0			// i must not leak kernel bits...
  18.120 +	mov r19=0			// i must not leak kernel bits...
  18.121 +#endif
  18.122 +	FSYS_RETURN
  18.123 +END(fsys_getppid)
  18.124 +
  18.125 +ENTRY(fsys_set_tid_address)
  18.126 +	.prologue
  18.127 +	.altrp b6
  18.128 +	.body
  18.129 +	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
  18.130 +	;;
  18.131 +	ld4 r9=[r9]
  18.132 +	tnat.z p6,p7=r32		// check argument register for being NaT
  18.133 +	;;
  18.134 +	and r9=TIF_ALLWORK_MASK,r9
  18.135 +	add r8=IA64_TASK_PID_OFFSET,r16
  18.136 +	add r18=IA64_TASK_CLEAR_CHILD_TID_OFFSET,r16
  18.137 +	;;
  18.138 +	ld4 r8=[r8]
  18.139 +	cmp.ne p8,p0=0,r9
  18.140 +	mov r17=-1
  18.141 +	;;
  18.142 +(p6)	st8 [r18]=r32
  18.143 +(p7)	st8 [r18]=r17
  18.144 +(p8)	br.spnt.many fsys_fallback_syscall
  18.145 +	;;
  18.146 +	mov r17=0			// i must not leak kernel bits...
  18.147 +	mov r18=0			// i must not leak kernel bits...
  18.148 +	FSYS_RETURN
  18.149 +END(fsys_set_tid_address)
  18.150 +
  18.151 +/*
  18.152 + * Ensure that the time interpolator structure is compatible with the asm code
  18.153 + */
  18.154 +#if IA64_TIME_INTERPOLATOR_SOURCE_OFFSET !=0 || IA64_TIME_INTERPOLATOR_SHIFT_OFFSET != 2 \
  18.155 +	|| IA64_TIME_INTERPOLATOR_JITTER_OFFSET != 3 || IA64_TIME_INTERPOLATOR_NSEC_OFFSET != 4
  18.156 +#error fsys_gettimeofday incompatible with changes to struct time_interpolator
  18.157 +#endif
  18.158 +#define CLOCK_REALTIME 0
  18.159 +#define CLOCK_MONOTONIC 1
  18.160 +#define CLOCK_DIVIDE_BY_1000 0x4000
  18.161 +#define CLOCK_ADD_MONOTONIC 0x8000
  18.162 +
  18.163 +ENTRY(fsys_gettimeofday)
  18.164 +	.prologue
  18.165 +	.altrp b6
  18.166 +	.body
  18.167 +	mov r31 = r32
  18.168 +	tnat.nz p6,p0 = r33		// guard against NaT argument
  18.169 +(p6)    br.cond.spnt.few .fail_einval
  18.170 +	mov r30 = CLOCK_DIVIDE_BY_1000
  18.171 +	;;
  18.172 +.gettime:
  18.173 +	// Register map
  18.174 +	// Incoming r31 = pointer to address where to place result
  18.175 +	//          r30 = flags determining how time is processed
  18.176 +	// r2,r3 = temp r4-r7 preserved
  18.177 +	// r8 = result nanoseconds
  18.178 +	// r9 = result seconds
  18.179 +	// r10 = temporary storage for clock difference
  18.180 +	// r11 = preserved: saved ar.pfs
  18.181 +	// r12 = preserved: memory stack
  18.182 +	// r13 = preserved: thread pointer
  18.183 +	// r14 = address of mask / mask
  18.184 +	// r15 = preserved: system call number
  18.185 +	// r16 = preserved: current task pointer
  18.186 +	// r17 = wall to monotonic use
  18.187 +	// r18 = time_interpolator->offset
  18.188 +	// r19 = address of wall_to_monotonic
  18.189 +	// r20 = pointer to struct time_interpolator / pointer to time_interpolator->address
  18.190 +	// r21 = shift factor
  18.191 +	// r22 = address of time interpolator->last_counter
  18.192 +	// r23 = address of time_interpolator->last_cycle
  18.193 +	// r24 = adress of time_interpolator->offset
  18.194 +	// r25 = last_cycle value
  18.195 +	// r26 = last_counter value
  18.196 +	// r27 = pointer to xtime
  18.197 +	// r28 = sequence number at the beginning of critcal section
  18.198 +	// r29 = address of seqlock
  18.199 +	// r30 = time processing flags / memory address
  18.200 +	// r31 = pointer to result
  18.201 +	// Predicates
  18.202 +	// p6,p7 short term use
  18.203 +	// p8 = timesource ar.itc
  18.204 +	// p9 = timesource mmio64
  18.205 +	// p10 = timesource mmio32
  18.206 +	// p11 = timesource not to be handled by asm code
  18.207 +	// p12 = memory time source ( = p9 | p10)
  18.208 +	// p13 = do cmpxchg with time_interpolator_last_cycle
  18.209 +	// p14 = Divide by 1000
  18.210 +	// p15 = Add monotonic
  18.211 +	//
  18.212 +	// Note that instructions are optimized for McKinley. McKinley can process two
  18.213 +	// bundles simultaneously and therefore we continuously try to feed the CPU
  18.214 +	// two bundles and then a stop.
  18.215 +	tnat.nz p6,p0 = r31	// branch deferred since it does not fit into bundle structure
  18.216 +	mov pr = r30,0xc000	// Set predicates according to function
  18.217 +	add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
  18.218 +	movl r20 = time_interpolator
  18.219 +	;;
  18.220 +	ld8 r20 = [r20]		// get pointer to time_interpolator structure
  18.221 +	movl r29 = xtime_lock
  18.222 +	ld4 r2 = [r2]		// process work pending flags
  18.223 +	movl r27 = xtime
  18.224 +	;;	// only one bundle here
  18.225 +	ld8 r21 = [r20]		// first quad with control information
  18.226 +	and r2 = TIF_ALLWORK_MASK,r2
  18.227 +(p6)    br.cond.spnt.few .fail_einval	// deferred branch
  18.228 +	;;
  18.229 +	add r10 = IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET,r20
  18.230 +	extr r3 = r21,32,32	// time_interpolator->nsec_per_cyc
  18.231 +	extr r8 = r21,0,16	// time_interpolator->source
  18.232 +	cmp.ne p6, p0 = 0, r2	// Fallback if work is scheduled
  18.233 +(p6)    br.cond.spnt.many fsys_fallback_syscall
  18.234 +	;;
  18.235 +	cmp.eq p8,p12 = 0,r8	// Check for cpu timer
  18.236 +	cmp.eq p9,p0 = 1,r8	// MMIO64 ?
  18.237 +	extr r2 = r21,24,8	// time_interpolator->jitter
  18.238 +	cmp.eq p10,p0 = 2,r8	// MMIO32 ?
  18.239 +	cmp.ltu p11,p0 = 2,r8	// function or other clock
  18.240 +(p11)	br.cond.spnt.many fsys_fallback_syscall
  18.241 +	;;
  18.242 +	setf.sig f7 = r3	// Setup for scaling of counter
  18.243 +(p15)	movl r19 = wall_to_monotonic
  18.244 +(p12)	ld8 r30 = [r10]
  18.245 +	cmp.ne p13,p0 = r2,r0	// need jitter compensation?
  18.246 +	extr r21 = r21,16,8	// shift factor
  18.247 +	;;
  18.248 +.time_redo:
  18.249 +	.pred.rel.mutex p8,p9,p10
  18.250 +	ld4.acq r28 = [r29]	// xtime_lock.sequence. Must come first for locking purposes
  18.251 +(p8)	mov r2 = ar.itc		// CPU_TIMER. 36 clocks latency!!!
  18.252 +	add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20
  18.253 +(p9)	ld8 r2 = [r30]		// readq(ti->address). Could also have latency issues..
  18.254 +(p10)	ld4 r2 = [r30]		// readw(ti->address)
  18.255 +(p13)	add r23 = IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET,r20
  18.256 +	;;			// could be removed by moving the last add upward
  18.257 +	ld8 r26 = [r22]		// time_interpolator->last_counter
  18.258 +(p13)	ld8 r25 = [r23]		// time interpolator->last_cycle
  18.259 +	add r24 = IA64_TIME_INTERPOLATOR_OFFSET_OFFSET,r20
  18.260 +(p15)	ld8 r17 = [r19],IA64_TIMESPEC_TV_NSEC_OFFSET
  18.261 + 	ld8 r9 = [r27],IA64_TIMESPEC_TV_NSEC_OFFSET
  18.262 +	add r14 = IA64_TIME_INTERPOLATOR_MASK_OFFSET, r20
  18.263 +	;;
  18.264 +	ld8 r18 = [r24]		// time_interpolator->offset
  18.265 +	ld8 r8 = [r27],-IA64_TIMESPEC_TV_NSEC_OFFSET	// xtime.tv_nsec
  18.266 +(p13)	sub r3 = r25,r2	// Diff needed before comparison (thanks davidm)
  18.267 +	;;
  18.268 +	ld8 r14 = [r14]		// time_interpolator->mask
  18.269 +(p13)	cmp.gt.unc p6,p7 = r3,r0	// check if it is less than last. p6,p7 cleared
  18.270 +	sub r10 = r2,r26	// current_counter - last_counter
  18.271 +	;;
  18.272 +(p6)	sub r10 = r25,r26	// time we got was less than last_cycle
  18.273 +(p7)	mov ar.ccv = r25	// more than last_cycle. Prep for cmpxchg
  18.274 +	;;
  18.275 +	and r10 = r10,r14	// Apply mask
  18.276 +	;;
  18.277 +	setf.sig f8 = r10
  18.278 +	nop.i 123
  18.279 +	;;
  18.280 +(p7)	cmpxchg8.rel r3 = [r23],r2,ar.ccv
  18.281 +EX(.fail_efault, probe.w.fault r31, 3)	// This takes 5 cycles and we have spare time
  18.282 +	xmpy.l f8 = f8,f7	// nsec_per_cyc*(counter-last_counter)
  18.283 +(p15)	add r9 = r9,r17		// Add wall to monotonic.secs to result secs
  18.284 +	;;
  18.285 +(p15)	ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET
  18.286 +(p7)	cmp.ne p7,p0 = r25,r3	// if cmpxchg not successful redo
  18.287 +	// simulate tbit.nz.or p7,p0 = r28,0
  18.288 +	and r28 = ~1,r28	// Make sequence even to force retry if odd
  18.289 +	getf.sig r2 = f8
  18.290 +	mf
  18.291 +	add r8 = r8,r18		// Add time interpolator offset
  18.292 +	;;
  18.293 +	ld4 r10 = [r29]		// xtime_lock.sequence
  18.294 +(p15)	add r8 = r8, r17	// Add monotonic.nsecs to nsecs
  18.295 +	shr.u r2 = r2,r21
  18.296 +	;;		// overloaded 3 bundles!
  18.297 +	// End critical section.
  18.298 +	add r8 = r8,r2		// Add xtime.nsecs
  18.299 +	cmp4.ne.or p7,p0 = r28,r10
  18.300 +(p7)	br.cond.dpnt.few .time_redo	// sequence number changed ?
  18.301 +	// Now r8=tv->tv_nsec and r9=tv->tv_sec
  18.302 +	mov r10 = r0
  18.303 +	movl r2 = 1000000000
  18.304 +	add r23 = IA64_TIMESPEC_TV_NSEC_OFFSET, r31
  18.305 +(p14)	movl r3 = 2361183241434822607	// Prep for / 1000 hack
  18.306 +	;;
  18.307 +.time_normalize:
  18.308 +	mov r21 = r8
  18.309 +	cmp.ge p6,p0 = r8,r2
  18.310 +(p14)	shr.u r20 = r8, 3		// We can repeat this if necessary just wasting some time
  18.311 +	;;
  18.312 +(p14)	setf.sig f8 = r20
  18.313 +(p6)	sub r8 = r8,r2
  18.314 +(p6)	add r9 = 1,r9			// two nops before the branch.
  18.315 +(p14)	setf.sig f7 = r3		// Chances for repeats are 1 in 10000 for gettod
  18.316 +(p6)	br.cond.dpnt.few .time_normalize
  18.317 +	;;
  18.318 +	// Divided by 8 though shift. Now divide by 125
  18.319 +	// The compiler was able to do that with a multiply
  18.320 +	// and a shift and we do the same
  18.321 +EX(.fail_efault, probe.w.fault r23, 3)		// This also costs 5 cycles
  18.322 +(p14)	xmpy.hu f8 = f8, f7			// xmpy has 5 cycles latency so use it...
  18.323 +	;;
  18.324 +	mov r8 = r0
  18.325 +(p14)	getf.sig r2 = f8
  18.326 +	;;
  18.327 +(p14)	shr.u r21 = r2, 4
  18.328 +	;;
  18.329 +EX(.fail_efault, st8 [r31] = r9)
  18.330 +EX(.fail_efault, st8 [r23] = r21)
  18.331 +	FSYS_RETURN
  18.332 +.fail_einval:
  18.333 +	mov r8 = EINVAL
  18.334 +	mov r10 = -1
  18.335 +	FSYS_RETURN
  18.336 +.fail_efault:
  18.337 +	mov r8 = EFAULT
  18.338 +	mov r10 = -1
  18.339 +	FSYS_RETURN
  18.340 +END(fsys_gettimeofday)
  18.341 +
  18.342 +ENTRY(fsys_clock_gettime)
  18.343 +	.prologue
  18.344 +	.altrp b6
  18.345 +	.body
  18.346 +	cmp4.ltu p6, p0 = CLOCK_MONOTONIC, r32
  18.347 +	// Fallback if this is not CLOCK_REALTIME or CLOCK_MONOTONIC
  18.348 +(p6)	br.spnt.few fsys_fallback_syscall
  18.349 +	mov r31 = r33
  18.350 +	shl r30 = r32,15
  18.351 +	br.many .gettime
  18.352 +END(fsys_clock_gettime)
  18.353 +
  18.354 +/*
  18.355 + * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize).
  18.356 + */
  18.357 +#if _NSIG_WORDS != 1
  18.358 +# error Sorry, fsys_rt_sigprocmask() needs to be updated for _NSIG_WORDS != 1.
  18.359 +#endif
  18.360 +ENTRY(fsys_rt_sigprocmask)
  18.361 +	.prologue
  18.362 +	.altrp b6
  18.363 +	.body
  18.364 +
  18.365 +	add r2=IA64_TASK_BLOCKED_OFFSET,r16
  18.366 +	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
  18.367 +	cmp4.ltu p6,p0=SIG_SETMASK,r32
  18.368 +
  18.369 +	cmp.ne p15,p0=r0,r34			// oset != NULL?
  18.370 +	tnat.nz p8,p0=r34
  18.371 +	add r31=IA64_TASK_SIGHAND_OFFSET,r16
  18.372 +	;;
  18.373 +	ld8 r3=[r2]				// read/prefetch current->blocked
  18.374 +	ld4 r9=[r9]
  18.375 +	tnat.nz.or p6,p0=r35
  18.376 +
  18.377 +	cmp.ne.or p6,p0=_NSIG_WORDS*8,r35
  18.378 +	tnat.nz.or p6,p0=r32
  18.379 +(p6)	br.spnt.few .fail_einval		// fail with EINVAL
  18.380 +	;;
  18.381 +#ifdef CONFIG_SMP
  18.382 +	ld8 r31=[r31]				// r31 <- current->sighand
  18.383 +#endif
  18.384 +	and r9=TIF_ALLWORK_MASK,r9
  18.385 +	tnat.nz.or p8,p0=r33
  18.386 +	;;
  18.387 +	cmp.ne p7,p0=0,r9
  18.388 +	cmp.eq p6,p0=r0,r33			// set == NULL?
  18.389 +	add r31=IA64_SIGHAND_SIGLOCK_OFFSET,r31	// r31 <- current->sighand->siglock
  18.390 +(p8)	br.spnt.few .fail_efault		// fail with EFAULT
  18.391 +(p7)	br.spnt.many fsys_fallback_syscall	// got pending kernel work...
  18.392 +(p6)	br.dpnt.many .store_mask		// -> short-circuit to just reading the signal mask
  18.393 +
  18.394 +	/* Argh, we actually have to do some work and _update_ the signal mask: */
  18.395 +
  18.396 +EX(.fail_efault, probe.r.fault r33, 3)		// verify user has read-access to *set
  18.397 +EX(.fail_efault, ld8 r14=[r33])			// r14 <- *set
  18.398 +	mov r17=(1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1))
  18.399 +	;;
  18.400 +
  18.401 +	rsm psr.i				// mask interrupt delivery
  18.402 +	mov ar.ccv=0
  18.403 +	andcm r14=r14,r17			// filter out SIGKILL & SIGSTOP
  18.404 +
  18.405 +#ifdef CONFIG_SMP
  18.406 +	mov r17=1
  18.407 +	;;
  18.408 +	cmpxchg4.acq r18=[r31],r17,ar.ccv	// try to acquire the lock
  18.409 +	mov r8=EINVAL			// default to EINVAL
  18.410 +	;;
  18.411 +	ld8 r3=[r2]			// re-read current->blocked now that we hold the lock
  18.412 +	cmp4.ne p6,p0=r18,r0
  18.413 +(p6)	br.cond.spnt.many .lock_contention
  18.414 +	;;
  18.415 +#else
  18.416 +	ld8 r3=[r2]			// re-read current->blocked now that we hold the lock
  18.417 +	mov r8=EINVAL			// default to EINVAL
  18.418 +#endif
  18.419 +	add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16
  18.420 +	add r19=IA64_TASK_SIGNAL_OFFSET,r16
  18.421 +	cmp4.eq p6,p0=SIG_BLOCK,r32
  18.422 +	;;
  18.423 +	ld8 r19=[r19]			// r19 <- current->signal
  18.424 +	cmp4.eq p7,p0=SIG_UNBLOCK,r32
  18.425 +	cmp4.eq p8,p0=SIG_SETMASK,r32
  18.426 +	;;
  18.427 +	ld8 r18=[r18]			// r18 <- current->pending.signal
  18.428 +	.pred.rel.mutex p6,p7,p8
  18.429 +(p6)	or r14=r3,r14			// SIG_BLOCK
  18.430 +(p7)	andcm r14=r3,r14		// SIG_UNBLOCK
  18.431 +
  18.432 +(p8)	mov r14=r14			// SIG_SETMASK
  18.433 +(p6)	mov r8=0			// clear error code
  18.434 +	// recalc_sigpending()
  18.435 +	add r17=IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,r19
  18.436 +
  18.437 +	add r19=IA64_SIGNAL_SHARED_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r19
  18.438 +	;;
  18.439 +	ld4 r17=[r17]		// r17 <- current->signal->group_stop_count
  18.440 +(p7)	mov r8=0		// clear error code
  18.441 +
  18.442 +	ld8 r19=[r19]		// r19 <- current->signal->shared_pending
  18.443 +	;;
  18.444 +	cmp4.gt p6,p7=r17,r0	// p6/p7 <- (current->signal->group_stop_count > 0)?
  18.445 +(p8)	mov r8=0		// clear error code
  18.446 +
  18.447 +	or r18=r18,r19		// r18 <- current->pending | current->signal->shared_pending
  18.448 +	;;
  18.449 +	// r18 <- (current->pending | current->signal->shared_pending) & ~current->blocked:
  18.450 +	andcm r18=r18,r14
  18.451 +	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
  18.452 +	;;
  18.453 +
  18.454 +(p7)	cmp.ne.or.andcm p6,p7=r18,r0		// p6/p7 <- signal pending
  18.455 +	mov r19=0					// i must not leak kernel bits...
  18.456 +(p6)	br.cond.dpnt.many .sig_pending
  18.457 +	;;
  18.458 +
  18.459 +1:	ld4 r17=[r9]				// r17 <- current->thread_info->flags
  18.460 +	;;
  18.461 +	mov ar.ccv=r17
  18.462 +	and r18=~_TIF_SIGPENDING,r17		// r18 <- r17 & ~(1 << TIF_SIGPENDING)
  18.463 +	;;
  18.464 +
  18.465 +	st8 [r2]=r14				// update current->blocked with new mask
  18.466 +	cmpxchg4.acq r8=[r9],r18,ar.ccv		// current->thread_info->flags <- r18
  18.467 +	;;
  18.468 +	cmp.ne p6,p0=r17,r8			// update failed?
  18.469 +(p6)	br.cond.spnt.few 1b			// yes -> retry
  18.470 +
  18.471 +#ifdef CONFIG_SMP
  18.472 +	st4.rel [r31]=r0			// release the lock
  18.473 +#endif
  18.474 +	ssm psr.i
  18.475 +	;;
  18.476 +
  18.477 +	srlz.d					// ensure psr.i is set again
  18.478 +	mov r18=0					// i must not leak kernel bits...
  18.479 +
  18.480 +.store_mask:
  18.481 +EX(.fail_efault, (p15) probe.w.fault r34, 3)	// verify user has write-access to *oset
  18.482 +EX(.fail_efault, (p15) st8 [r34]=r3)
  18.483 +	mov r2=0					// i must not leak kernel bits...
  18.484 +	mov r3=0					// i must not leak kernel bits...
  18.485 +	mov r8=0				// return 0
  18.486 +	mov r9=0					// i must not leak kernel bits...
  18.487 +	mov r14=0					// i must not leak kernel bits...
  18.488 +	mov r17=0					// i must not leak kernel bits...
  18.489 +	mov r31=0					// i must not leak kernel bits...
  18.490 +	FSYS_RETURN
  18.491 +
  18.492 +.sig_pending:
  18.493 +#ifdef CONFIG_SMP
  18.494 +	st4.rel [r31]=r0			// release the lock
  18.495 +#endif
  18.496 +	ssm psr.i
  18.497 +	;;
  18.498 +	srlz.d
  18.499 +	br.sptk.many fsys_fallback_syscall	// with signal pending, do the heavy-weight syscall
  18.500 +
  18.501 +#ifdef CONFIG_SMP
  18.502 +.lock_contention:
  18.503 +	/* Rather than spinning here, fall back on doing a heavy-weight syscall.  */
  18.504 +	ssm psr.i
  18.505 +	;;
  18.506 +	srlz.d
  18.507 +	br.sptk.many fsys_fallback_syscall
  18.508 +#endif
  18.509 +END(fsys_rt_sigprocmask)
  18.510 +
  18.511 +ENTRY(fsys_fallback_syscall)
  18.512 +	.prologue
  18.513 +	.altrp b6
  18.514 +	.body
  18.515 +	/*
  18.516 +	 * We only get here from light-weight syscall handlers.  Thus, we already
  18.517 +	 * know that r15 contains a valid syscall number.  No need to re-check.
  18.518 +	 */
  18.519 +	adds r17=-1024,r15
  18.520 +	movl r14=sys_call_table
  18.521 +	;;
  18.522 +#ifdef CONFIG_XEN
  18.523 +	movl r18=running_on_xen;;
  18.524 +	ld4 r18=[r18];;
  18.525 +	// p14 = running_on_xen
  18.526 +	// p15 = !running_on_xen
  18.527 +	cmp.ne p14,p15=r0,r18
  18.528 +	;;    
  18.529 +(p14)	movl r18=XSI_PSR_I_ADDR;;
  18.530 +(p14)	ld8 r18=[r18]
  18.531 +(p14)	mov r29=1;;
  18.532 +(p14)	st1 [r18]=r29
  18.533 +(p15)	rsm psr.i
  18.534 +#else    
  18.535 +	rsm psr.i
  18.536 +#endif    
  18.537 +	shladd r18=r17,3,r14
  18.538 +	;;
  18.539 +	ld8 r18=[r18]				// load normal (heavy-weight) syscall entry-point
  18.540 +#ifdef CONFIG_XEN
  18.541 +(p14)	mov r27=r8
  18.542 +(p14)	XEN_HYPER_GET_PSR
  18.543 +	;;
  18.544 +(p14)	mov r29=r8
  18.545 +(p14)	mov r8=r27
  18.546 +(p15)	mov r29=psr				// read psr (12 cyc load latency)
  18.547 +#else    
  18.548 +	mov r29=psr				// read psr (12 cyc load latency)
  18.549 +#endif    
  18.550 +	mov r27=ar.rsc
  18.551 +	mov r21=ar.fpsr
  18.552 +	mov r26=ar.pfs
  18.553 +END(fsys_fallback_syscall)
  18.554 +	/* FALL THROUGH */
  18.555 +GLOBAL_ENTRY(fsys_bubble_down)
  18.556 +	.prologue
  18.557 +	.altrp b6
  18.558 +	.body
  18.559 +	/*
  18.560 +	 * We get here for syscalls that don't have a lightweight
  18.561 +	 * handler.  For those, we need to bubble down into the kernel
  18.562 +	 * and that requires setting up a minimal pt_regs structure,
  18.563 +	 * and initializing the CPU state more or less as if an
  18.564 +	 * interruption had occurred.  To make syscall-restarts work,
  18.565 +	 * we setup pt_regs such that cr_iip points to the second
  18.566 +	 * instruction in syscall_via_break.  Decrementing the IP
  18.567 +	 * hence will restart the syscall via break and not
  18.568 +	 * decrementing IP will return us to the caller, as usual.
  18.569 +	 * Note that we preserve the value of psr.pp rather than
  18.570 +	 * initializing it from dcr.pp.  This makes it possible to
  18.571 +	 * distinguish fsyscall execution from other privileged
  18.572 +	 * execution.
  18.573 +	 *
  18.574 +	 * On entry:
  18.575 +	 *	- normal fsyscall handler register usage, except
  18.576 +	 *	  that we also have:
  18.577 +	 *	- r18: address of syscall entry point
  18.578 +	 *	- r21: ar.fpsr
  18.579 +	 *	- r26: ar.pfs
  18.580 +	 *	- r27: ar.rsc
  18.581 +	 *	- r29: psr
  18.582 +	 *
  18.583 +	 * We used to clear some PSR bits here but that requires slow
  18.584 +	 * serialization.  Fortuntely, that isn't really necessary.
  18.585 +	 * The rationale is as follows: we used to clear bits
  18.586 +	 * ~PSR_PRESERVED_BITS in PSR.L.  Since
  18.587 +	 * PSR_PRESERVED_BITS==PSR.{UP,MFL,MFH,PK,DT,PP,SP,RT,IC}, we
  18.588 +	 * ended up clearing PSR.{BE,AC,I,DFL,DFH,DI,DB,SI,TB}.
  18.589 +	 * However,
  18.590 +	 *
  18.591 +	 * PSR.BE : already is turned off in __kernel_syscall_via_epc()
  18.592 +	 * PSR.AC : don't care (kernel normally turns PSR.AC on)
  18.593 +	 * PSR.I  : already turned off by the time fsys_bubble_down gets
  18.594 +	 *	    invoked
  18.595 +	 * PSR.DFL: always 0 (kernel never turns it on)
  18.596 +	 * PSR.DFH: don't care --- kernel never touches f32-f127 on its own
  18.597 +	 *	    initiative
  18.598 +	 * PSR.DI : always 0 (kernel never turns it on)
  18.599 +	 * PSR.SI : always 0 (kernel never turns it on)
  18.600 +	 * PSR.DB : don't care --- kernel never enables kernel-level
  18.601 +	 *	    breakpoints
  18.602 +	 * PSR.TB : must be 0 already; if it wasn't zero on entry to
  18.603 +	 *          __kernel_syscall_via_epc, the branch to fsys_bubble_down
  18.604 +	 *          will trigger a taken branch; the taken-trap-handler then
  18.605 +	 *          converts the syscall into a break-based system-call.
  18.606 +	 */
  18.607 +	/*
  18.608 +	 * Reading psr.l gives us only bits 0-31, psr.it, and psr.mc.
  18.609 +	 * The rest we have to synthesize.
  18.610 +	 */
  18.611 +#	define PSR_ONE_BITS		((3 << IA64_PSR_CPL0_BIT)	\
  18.612 +					 | (0x1 << IA64_PSR_RI_BIT)	\
  18.613 +					 | IA64_PSR_BN | IA64_PSR_I)
  18.614 +
  18.615 +	invala					// M0|1
  18.616 +	movl r14=ia64_ret_from_syscall		// X
  18.617 +
  18.618 +	nop.m 0
  18.619 +	movl r28=__kernel_syscall_via_break	// X	create cr.iip
  18.620 +	;;
  18.621 +
  18.622 +	mov r2=r16				// A    get task addr to addl-addressable register
  18.623 +	adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 // A
  18.624 +	mov r31=pr				// I0   save pr (2 cyc)
  18.625 +	;;
  18.626 +	st1 [r16]=r0				// M2|3 clear current->thread.on_ustack flag
  18.627 +	addl r22=IA64_RBS_OFFSET,r2		// A    compute base of RBS
  18.628 +	add r3=TI_FLAGS+IA64_TASK_SIZE,r2	// A
  18.629 +	;;
  18.630 +	ld4 r3=[r3]				// M0|1 r3 = current_thread_info()->flags
  18.631 +	lfetch.fault.excl.nt1 [r22]		// M0|1 prefetch register backing-store
  18.632 +	nop.i 0
  18.633 +	;;
  18.634 +	mov ar.rsc=0				// M2   set enforced lazy mode, pl 0, LE, loadrs=0
  18.635 +	nop.m 0
  18.636 +	nop.i 0
  18.637 +	;;
  18.638 +	mov r23=ar.bspstore			// M2 (12 cyc) save ar.bspstore
  18.639 +	mov.m r24=ar.rnat			// M2 (5 cyc) read ar.rnat (dual-issues!)
  18.640 +	nop.i 0
  18.641 +	;;
  18.642 +	mov ar.bspstore=r22			// M2 (6 cyc) switch to kernel RBS
  18.643 +	movl r8=PSR_ONE_BITS			// X
  18.644 +	;;
  18.645 +	mov r25=ar.unat				// M2 (5 cyc) save ar.unat
  18.646 +	mov r19=b6				// I0   save b6 (2 cyc)
  18.647 +	mov r20=r1				// A    save caller's gp in r20
  18.648 +	;;
  18.649 +	or r29=r8,r29				// A    construct cr.ipsr value to save
  18.650 +	mov b6=r18				// I0   copy syscall entry-point to b6 (7 cyc)
  18.651 +	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 // A compute base of memory stack
  18.652 +
  18.653 +	mov r18=ar.bsp				// M2   save (kernel) ar.bsp (12 cyc)
  18.654 +	cmp.ne pKStk,pUStk=r0,r0		// A    set pKStk <- 0, pUStk <- 1
  18.655 +	br.call.sptk.many b7=ia64_syscall_setup	// B
  18.656 +	;;
  18.657 +	mov ar.rsc=0x3				// M2   set eager mode, pl 0, LE, loadrs=0
  18.658 +	mov rp=r14				// I0   set the real return addr
  18.659 +	and r3=_TIF_SYSCALL_TRACEAUDIT,r3	// A
  18.660 +	;;
  18.661 +#ifdef CONFIG_XEN
  18.662 +	movl r14=running_on_xen;;
  18.663 +	ld4 r14=[r14];;
  18.664 +	// p14 = running_on_xen
  18.665 +	// p15 = !running_on_xen
  18.666 +	cmp.ne p14,p15=r0,r14
  18.667 +	;; 
  18.668 +(p14)	movl r28=XSI_PSR_I_ADDR;;
  18.669 +(p14)	ld8 r28=[r28];;
  18.670 +(p14)	adds r28=-1,r28;;			// event_pending
  18.671 +(p14)	ld1 r14=[r28];;
  18.672 +(p14)	cmp.ne.unc p13,p14=r14,r0;;
  18.673 +(p13)	XEN_HYPER_SSM_I
  18.674 +(p14)	adds r28=1,r28;;			// event_mask
  18.675 +(p14)	st1 [r28]=r0;;
  18.676 +(p15)	ssm psr.i
  18.677 +#else
  18.678 +	ssm psr.i				// M2   we're on kernel stacks now, reenable irqs
  18.679 +#endif    
  18.680 +	cmp.eq p8,p0=r3,r0			// A
  18.681 +(p10)	br.cond.spnt.many ia64_ret_from_syscall	// B    return if bad call-frame or r15 is a NaT
  18.682 +
  18.683 +	nop.m 0
  18.684 +(p8)	br.call.sptk.many b6=b6			// B    (ignore return address)
  18.685 +	br.cond.spnt ia64_trace_syscall		// B
  18.686 +END(fsys_bubble_down)
  18.687 +
  18.688 +	.rodata
  18.689 +	.align 8
  18.690 +	.globl fsyscall_table
  18.691 +
  18.692 +	data8 fsys_bubble_down
  18.693 +fsyscall_table:
  18.694 +	data8 fsys_ni_syscall
  18.695 +	data8 0				// exit			// 1025
  18.696 +	data8 0				// read
  18.697 +	data8 0				// write
  18.698 +	data8 0				// open
  18.699 +	data8 0				// close
  18.700 +	data8 0				// creat		// 1030
  18.701 +	data8 0				// link
  18.702 +	data8 0				// unlink
  18.703 +	data8 0				// execve
  18.704 +	data8 0				// chdir
  18.705 +	data8 0				// fchdir		// 1035
  18.706 +	data8 0				// utimes
  18.707 +	data8 0				// mknod
  18.708 +	data8 0				// chmod
  18.709 +	data8 0				// chown
  18.710 +	data8 0				// lseek		// 1040
  18.711 +	data8 fsys_getpid		// getpid
  18.712 +	data8 fsys_getppid		// getppid
  18.713 +	data8 0				// mount
  18.714 +	data8 0				// umount
  18.715 +	data8 0				// setuid		// 1045
  18.716 +	data8 0				// getuid
  18.717 +	data8 0				// geteuid
  18.718 +	data8 0				// ptrace
  18.719 +	data8 0				// access
  18.720 +	data8 0				// sync			// 1050
  18.721 +	data8 0				// fsync
  18.722 +	data8 0				// fdatasync
  18.723 +	data8 0				// kill
  18.724 +	data8 0				// rename
  18.725 +	data8 0				// mkdir		// 1055
  18.726 +	data8 0				// rmdir
  18.727 +	data8 0				// dup
  18.728 +	data8 0				// pipe
  18.729 +	data8 0				// times
  18.730 +	data8 0				// brk			// 1060
  18.731 +	data8 0				// setgid
  18.732 +	data8 0				// getgid
  18.733 +	data8 0				// getegid
  18.734 +	data8 0				// acct
  18.735 +	data8 0				// ioctl		// 1065
  18.736 +	data8 0				// fcntl
  18.737 +	data8 0				// umask
  18.738 +	data8 0				// chroot
  18.739 +	data8 0				// ustat
  18.740 +	data8 0				// dup2			// 1070
  18.741 +	data8 0				// setreuid
  18.742 +	data8 0				// setregid
  18.743 +	data8 0				// getresuid
  18.744 +	data8 0				// setresuid
  18.745 +	data8 0				// getresgid		// 1075
  18.746 +	data8 0				// setresgid
  18.747 +	data8 0				// getgroups
  18.748 +	data8 0				// setgroups
  18.749 +	data8 0				// getpgid
  18.750 +	data8 0				// setpgid		// 1080
  18.751 +	data8 0				// setsid
  18.752 +	data8 0				// getsid
  18.753 +	data8 0				// sethostname
  18.754 +	data8 0				// setrlimit
  18.755 +	data8 0				// getrlimit		// 1085
  18.756 +	data8 0				// getrusage
  18.757 +	data8 fsys_gettimeofday		// gettimeofday
  18.758 +	data8 0				// settimeofday
  18.759 +	data8 0				// select
  18.760 +	data8 0				// poll			// 1090
  18.761 +	data8 0				// symlink
  18.762 +	data8 0				// readlink
  18.763 +	data8 0				// uselib
  18.764 +	data8 0				// swapon
  18.765 +	data8 0				// swapoff		// 1095
  18.766 +	data8 0				// reboot
  18.767 +	data8 0				// truncate
  18.768 +	data8 0				// ftruncate
  18.769 +	data8 0				// fchmod
  18.770 +	data8 0				// fchown		// 1100
  18.771 +	data8 0				// getpriority
  18.772 +	data8 0				// setpriority
  18.773 +	data8 0				// statfs
  18.774 +	data8 0				// fstatfs
  18.775 +	data8 0				// gettid		// 1105
  18.776 +	data8 0				// semget
  18.777 +	data8 0				// semop
  18.778 +	data8 0				// semctl
  18.779 +	data8 0				// msgget
  18.780 +	data8 0				// msgsnd		// 1110
  18.781 +	data8 0				// msgrcv
  18.782 +	data8 0				// msgctl
  18.783 +	data8 0				// shmget
  18.784 +	data8 0				// shmat
  18.785 +	data8 0				// shmdt		// 1115
  18.786 +	data8 0				// shmctl
  18.787 +	data8 0				// syslog
  18.788 +	data8 0				// setitimer
  18.789 +	data8 0				// getitimer
  18.790 +	data8 0					 		// 1120
  18.791 +	data8 0
  18.792 +	data8 0
  18.793 +	data8 0				// vhangup
  18.794 +	data8 0				// lchown
  18.795 +	data8 0				// remap_file_pages	// 1125
  18.796 +	data8 0				// wait4
  18.797 +	data8 0				// sysinfo
  18.798 +	data8 0				// clone
  18.799 +	data8 0				// setdomainname
  18.800 +	data8 0				// newuname		// 1130
  18.801 +	data8 0				// adjtimex
  18.802 +	data8 0
  18.803 +	data8 0				// init_module
  18.804 +	data8 0				// delete_module
  18.805 +	data8 0							// 1135
  18.806 +	data8 0
  18.807 +	data8 0				// quotactl
  18.808 +	data8 0				// bdflush
  18.809 +	data8 0				// sysfs
  18.810 +	data8 0				// personality		// 1140
  18.811 +	data8 0				// afs_syscall
  18.812 +	data8 0				// setfsuid
  18.813 +	data8 0				// setfsgid
  18.814 +	data8 0				// getdents
  18.815 +	data8 0				// flock		// 1145
  18.816 +	data8 0				// readv
  18.817 +	data8 0				// writev
  18.818 +	data8 0				// pread64
  18.819 +	data8 0				// pwrite64
  18.820 +	data8 0				// sysctl		// 1150
  18.821 +	data8 0				// mmap
  18.822 +	data8 0				// munmap
  18.823 +	data8 0				// mlock
  18.824 +	data8 0				// mlockall
  18.825 +	data8 0				// mprotect		// 1155
  18.826 +	data8 0				// mremap
  18.827 +	data8 0				// msync
  18.828 +	data8 0				// munlock
  18.829 +	data8 0				// munlockall
  18.830 +	data8 0				// sched_getparam	// 1160
  18.831 +	data8 0				// sched_setparam
  18.832 +	data8 0				// sched_getscheduler
  18.833 +	data8 0				// sched_setscheduler
  18.834 +	data8 0				// sched_yield
  18.835 +	data8 0				// sched_get_priority_max	// 1165
  18.836 +	data8 0				// sched_get_priority_min
  18.837 +	data8 0				// sched_rr_get_interval
  18.838 +	data8 0				// nanosleep
  18.839 +	data8 0				// nfsservctl
  18.840 +	data8 0				// prctl		// 1170
  18.841 +	data8 0				// getpagesize
  18.842 +	data8 0				// mmap2
  18.843 +	data8 0				// pciconfig_read
  18.844 +	data8 0				// pciconfig_write
  18.845 +	data8 0				// perfmonctl		// 1175
  18.846 +	data8 0				// sigaltstack
  18.847 +	data8 0				// rt_sigaction
  18.848 +	data8 0				// rt_sigpending
  18.849 +	data8 fsys_rt_sigprocmask	// rt_sigprocmask
  18.850 +	data8 0				// rt_sigqueueinfo	// 1180
  18.851 +	data8 0				// rt_sigreturn
  18.852 +	data8 0				// rt_sigsuspend
  18.853 +	data8 0				// rt_sigtimedwait
  18.854 +	data8 0				// getcwd
  18.855 +	data8 0				// capget		// 1185
  18.856 +	data8 0				// capset
  18.857 +	data8 0				// sendfile
  18.858 +	data8 0
  18.859 +	data8 0
  18.860 +	data8 0				// socket		// 1190
  18.861 +	data8 0				// bind
  18.862 +	data8 0				// connect
  18.863 +	data8 0				// listen
  18.864 +	data8 0				// accept
  18.865 +	data8 0				// getsockname		// 1195
  18.866 +	data8 0				// getpeername
  18.867 +	data8 0				// socketpair
  18.868 +	data8 0				// send
  18.869 +	data8 0				// sendto
  18.870 +	data8 0				// recv			// 1200
  18.871 +	data8 0				// recvfrom
  18.872 +	data8 0				// shutdown
  18.873 +	data8 0				// setsockopt
  18.874 +	data8 0				// getsockopt
  18.875 +	data8 0				// sendmsg		// 1205
  18.876 +	data8 0				// recvmsg
  18.877 +	data8 0				// pivot_root
  18.878 +	data8 0				// mincore
  18.879 +	data8 0				// madvise
  18.880 +	data8 0				// newstat		// 1210
  18.881 +	data8 0				// newlstat
  18.882 +	data8 0				// newfstat
  18.883 +	data8 0				// clone2
  18.884 +	data8 0				// getdents64
  18.885 +	data8 0				// getunwind		// 1215
  18.886 +	data8 0				// readahead
  18.887 +	data8 0				// setxattr
  18.888 +	data8 0				// lsetxattr
  18.889 +	data8 0				// fsetxattr
  18.890 +	data8 0				// getxattr		// 1220
  18.891 +	data8 0				// lgetxattr
  18.892 +	data8 0				// fgetxattr
  18.893 +	data8 0				// listxattr
  18.894 +	data8 0				// llistxattr
  18.895 +	data8 0				// flistxattr		// 1225
  18.896 +	data8 0				// removexattr
  18.897 +	data8 0				// lremovexattr
  18.898 +	data8 0				// fremovexattr
  18.899 +	data8 0				// tkill
  18.900 +	data8 0				// futex		// 1230
  18.901 +	data8 0				// sched_setaffinity
  18.902 +	data8 0				// sched_getaffinity
  18.903 +	data8 fsys_set_tid_address	// set_tid_address
  18.904 +	data8 0				// fadvise64_64
  18.905 +	data8 0				// tgkill		// 1235
  18.906 +	data8 0				// exit_group
  18.907 +	data8 0				// lookup_dcookie
  18.908 +	data8 0				// io_setup
  18.909 +	data8 0				// io_destroy
  18.910 +	data8 0				// io_getevents		// 1240
  18.911 +	data8 0				// io_submit
  18.912 +	data8 0				// io_cancel
  18.913 +	data8 0				// epoll_create
  18.914 +	data8 0				// epoll_ctl
  18.915 +	data8 0				// epoll_wait		// 1245
  18.916 +	data8 0				// restart_syscall
  18.917 +	data8 0				// semtimedop
  18.918 +	data8 0				// timer_create
  18.919 +	data8 0				// timer_settime
  18.920 +	data8 0				// timer_gettime 	// 1250
  18.921 +	data8 0				// timer_getoverrun
  18.922 +	data8 0				// timer_delete
  18.923 +	data8 0				// clock_settime
  18.924 +	data8 fsys_clock_gettime	// clock_gettime
  18.925 +
  18.926 +	// fill in zeros for the remaining entries
  18.927 +	.zero:
  18.928 +	.space fsyscall_table + 8*NR_syscalls - .zero, 0
    19.1 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/gate.S	Thu Jan 18 15:18:07 2007 +0000
    19.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/gate.S	Fri Jan 19 14:48:57 2007 +0000
    19.3 @@ -56,18 +56,6 @@
    19.4  [1:]	movl reg=0;					\
    19.5  	.xdata4 ".data.patch.running_on_xen", 1b-.
    19.6  
    19.7 -	.section ".data.patch.brl_xen_rsm_be_i", "a"
    19.8 -	.previous
    19.9 -#define BRL_COND_XEN_RSM_BE_I(pr)			\
   19.10 -[1:](pr)brl.cond.sptk 0;				\
   19.11 -	.xdata4 ".data.patch.brl_xen_rsm_be_i", 1b-.
   19.12 -
   19.13 -	.section ".data.patch.brl_xen_get_psr", "a"
   19.14 -	.previous
   19.15 -#define BRL_COND_XEN_GET_PSR(pr)			\
   19.16 -[1:](pr)brl.cond.sptk 0;				\
   19.17 -	.xdata4 ".data.patch.brl_xen_get_psr", 1b-.
   19.18 -
   19.19  	.section ".data.patch.brl_xen_ssm_i_0", "a"
   19.20  	.previous
   19.21  #define BRL_COND_XEN_SSM_I_0(pr)			\
   19.22 @@ -155,9 +143,9 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc)
   19.23  	cmp.ne isXen,isRaw=r0,r30
   19.24  	;;
   19.25  (isRaw)	rsm psr.be | psr.i
   19.26 -	BRL_COND_XEN_RSM_BE_I(isXen)
   19.27 -	.global .vdso_rsm_be_i_ret
   19.28 -.vdso_rsm_be_i_ret:
   19.29 +(isXen)	st1 [r22]=r20
   19.30 +(isXen)	rum psr.be
   19.31 +	;;
   19.32  #else
   19.33  	rsm psr.be | psr.i			// M2 (5 cyc to srlz.d)
   19.34  #endif
   19.35 @@ -170,9 +158,9 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc)
   19.36  	lfetch [r18]				// M0|1
   19.37  #ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT
   19.38  (isRaw)	mov r29=psr
   19.39 -	BRL_COND_XEN_GET_PSR(isXen)
   19.40 -	.global .vdso_get_psr_ret
   19.41 -.vdso_get_psr_ret:
   19.42 +(isXen)	XEN_HYPER_GET_PSR
   19.43 +	;;
   19.44 +(isXen)	mov r29=r8
   19.45  #else
   19.46  	mov r29=psr				// M2 (12 cyc)
   19.47  #endif
    20.1 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S	Thu Jan 18 15:18:07 2007 +0000
    20.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S	Fri Jan 19 14:48:57 2007 +0000
    20.3 @@ -49,14 +49,6 @@ SECTIONS
    20.4  				    *(.data.patch.running_on_xen)
    20.5  				    __end_gate_running_on_xen_patchlist = .;
    20.6  
    20.7 -				    __start_gate_brl_xen_rsm_be_i_patchlist = .;
    20.8 -				    *(.data.patch.brl_xen_rsm_be_i)
    20.9 -				    __end_gate_brl_xen_rsm_be_i_patchlist = .;
   20.10 -
   20.11 -				    __start_gate_brl_xen_get_psr_patchlist = .;
   20.12 -				    *(.data.patch.brl_xen_get_psr)
   20.13 -				    __end_gate_brl_xen_get_psr_patchlist = .;
   20.14 -
   20.15  				    __start_gate_brl_xen_ssm_i_0_patchlist = .;
   20.16  				    *(.data.patch.brl_xen_ssm_i_0)
   20.17  				    __end_gate_brl_xen_ssm_i_0_patchlist = .;
    21.1 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/patch.c	Thu Jan 18 15:18:07 2007 +0000
    21.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/patch.c	Fri Jan 19 14:48:57 2007 +0000
    21.3 @@ -236,13 +236,9 @@ patch_brl_symaddr(unsigned long start, u
    21.4  static void
    21.5  patch_brl_in_vdso(void)
    21.6  {
    21.7 -	EXTERN_PATCHLIST(xen_rsm_be_i);
    21.8 -	EXTERN_PATCHLIST(xen_get_psr);
    21.9  	EXTERN_PATCHLIST(xen_ssm_i_0);
   21.10  	EXTERN_PATCHLIST(xen_ssm_i_1);
   21.11  
   21.12 -	PATCH_BRL_SYMADDR(xen_rsm_be_i);
   21.13 -	PATCH_BRL_SYMADDR(xen_get_psr);
   21.14  	PATCH_BRL_SYMADDR(xen_ssm_i_0);
   21.15  	PATCH_BRL_SYMADDR(xen_ssm_i_1);
   21.16  }
    22.1 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c	Thu Jan 18 15:18:07 2007 +0000
    22.2 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c	Fri Jan 19 14:48:57 2007 +0000
    22.3 @@ -76,10 +76,18 @@ EXPORT_SYMBOL(__per_cpu_offset);
    22.4  #endif
    22.5  
    22.6  #ifdef CONFIG_XEN
    22.7 +static void
    22.8 +xen_panic_hypercall(struct unw_frame_info *info, void *arg)
    22.9 +{
   22.10 +	current->thread.ksp = (__u64)info->sw - 16;
   22.11 +	HYPERVISOR_shutdown(SHUTDOWN_crash);
   22.12 +	/* we're never actually going to get here... */
   22.13 +}
   22.14 +
   22.15  static int
   22.16  xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
   22.17  {
   22.18 -	HYPERVISOR_shutdown(SHUTDOWN_crash);
   22.19 +	unw_init_running(xen_panic_hypercall, NULL);
   22.20  	/* we're never actually going to get here... */
   22.21  	return NOTIFY_DONE;
   22.22  }
    23.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S	Thu Jan 18 15:18:07 2007 +0000
    23.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S	Fri Jan 19 14:48:57 2007 +0000
    23.3 @@ -8,336 +8,110 @@
    23.4  #include <asm/processor.h>
    23.5  #include <asm/asmmacro.h>
    23.6  
    23.7 -/* To clear vpsr.ic, vpsr.i needs to be cleared first */
    23.8 -#define XEN_CLEAR_PSR_IC				\
    23.9 -	mov r14=1;					\
   23.10 -	movl r15=XSI_PSR_I_ADDR;			\
   23.11 -	movl r2=XSI_PSR_IC;				\
   23.12 -	;;						\
   23.13 -	ld8 r15=[r15];					\
   23.14 -	ld4 r3=[r2];					\
   23.15 -	;;						\
   23.16 -	ld1 r16=[r15];					\
   23.17 -	;;						\
   23.18 -	st1 [r15]=r14;					\
   23.19 -	st4 [r2]=r0;					\
   23.20 -	;;
   23.21 -
   23.22 -/* First restore vpsr.ic, and then vpsr.i */
   23.23 -#define XEN_RESTORE_PSR_IC				\
   23.24 -	st4 [r2]=r3;					\
   23.25 -	st1 [r15]=r16;					\
   23.26 -	;;
   23.27 +GLOBAL_ENTRY(xen_get_psr)
   23.28 +	XEN_HYPER_GET_PSR
   23.29 +	br.ret.sptk.many rp
   23.30 +    ;;
   23.31 +END(xen_get_psr)
   23.32  
   23.33  GLOBAL_ENTRY(xen_get_ivr)
   23.34 -	movl r8=running_on_xen;;
   23.35 -	ld4 r8=[r8];;
   23.36 -	cmp.eq p7,p0=r8,r0;;
   23.37 -(p7)	mov r8=cr.ivr;;
   23.38 -(p7)	br.ret.sptk.many rp
   23.39 -	;;
   23.40 -	XEN_CLEAR_PSR_IC
   23.41 -	;;
   23.42  	XEN_HYPER_GET_IVR
   23.43 -	;;
   23.44 -	XEN_RESTORE_PSR_IC
   23.45 -	;;
   23.46  	br.ret.sptk.many rp
   23.47  	;;
   23.48  END(xen_get_ivr)
   23.49  
   23.50  GLOBAL_ENTRY(xen_get_tpr)
   23.51 -	movl r8=running_on_xen;;
   23.52 -	ld4 r8=[r8];;
   23.53 -	cmp.eq p7,p0=r8,r0;;
   23.54 -(p7)	mov r8=cr.tpr;;
   23.55 -(p7)	br.ret.sptk.many rp
   23.56 -	;;
   23.57 -	XEN_CLEAR_PSR_IC
   23.58 -	;;
   23.59  	XEN_HYPER_GET_TPR
   23.60 -	;;
   23.61 -	XEN_RESTORE_PSR_IC
   23.62 -	;;
   23.63  	br.ret.sptk.many rp
   23.64  	;;
   23.65  END(xen_get_tpr)
   23.66  
   23.67  GLOBAL_ENTRY(xen_set_tpr)
   23.68 -	movl r8=running_on_xen;;
   23.69 -	ld4 r8=[r8];;
   23.70 -	cmp.eq p7,p0=r8,r0;;
   23.71 -(p7)	mov cr.tpr=r32;;
   23.72 -(p7)	br.ret.sptk.many rp
   23.73 -	;;
   23.74  	mov r8=r32
   23.75 -	;;
   23.76 -	XEN_CLEAR_PSR_IC
   23.77 -	;;
   23.78  	XEN_HYPER_SET_TPR
   23.79 -	;;
   23.80 -	XEN_RESTORE_PSR_IC
   23.81 -	;;
   23.82  	br.ret.sptk.many rp
   23.83  	;;
   23.84  END(xen_set_tpr)
   23.85  
   23.86  GLOBAL_ENTRY(xen_eoi)
   23.87 -	movl r8=running_on_xen;;
   23.88 -	ld4 r8=[r8];;
   23.89 -	cmp.eq p7,p0=r8,r0;;
   23.90 -(p7)	mov cr.eoi=r0;;
   23.91 -(p7)	br.ret.sptk.many rp
   23.92 -	;;
   23.93  	mov r8=r32
   23.94 -	;;
   23.95 -	XEN_CLEAR_PSR_IC
   23.96 -	;;
   23.97  	XEN_HYPER_EOI
   23.98 -	;;
   23.99 -	XEN_RESTORE_PSR_IC
  23.100 -	;;
  23.101  	br.ret.sptk.many rp
  23.102  	;;
  23.103  END(xen_eoi)
  23.104  
  23.105  GLOBAL_ENTRY(xen_thash)
  23.106 -	movl r8=running_on_xen;;
  23.107 -	ld4 r8=[r8];;
  23.108 -	cmp.eq p7,p0=r8,r0;;
  23.109 -(p7)	thash r8=r32;;
  23.110 -(p7)	br.ret.sptk.many rp
  23.111 -	;;
  23.112  	mov r8=r32
  23.113 -	;;
  23.114 -	XEN_CLEAR_PSR_IC
  23.115 -	;;
  23.116  	XEN_HYPER_THASH
  23.117 -	;;
  23.118 -	XEN_RESTORE_PSR_IC
  23.119 -	;;
  23.120  	br.ret.sptk.many rp
  23.121  	;;
  23.122  END(xen_thash)
  23.123  
  23.124  GLOBAL_ENTRY(xen_set_itm)
  23.125 -	movl r8=running_on_xen;;
  23.126 -	ld4 r8=[r8];;
  23.127 -	cmp.eq p7,p0=r8,r0;;
  23.128 -(p7)	mov cr.itm=r32;;
  23.129 -(p7)	br.ret.sptk.many rp
  23.130 -	;;
  23.131  	mov r8=r32
  23.132 -	;;
  23.133 -	XEN_CLEAR_PSR_IC
  23.134 -	;;
  23.135  	XEN_HYPER_SET_ITM
  23.136 -	;;
  23.137 -	XEN_RESTORE_PSR_IC
  23.138 -	;;
  23.139  	br.ret.sptk.many rp
  23.140  	;;
  23.141  END(xen_set_itm)
  23.142  
  23.143  GLOBAL_ENTRY(xen_ptcga)
  23.144 -	movl r8=running_on_xen;;
  23.145 -	ld4 r8=[r8];;
  23.146 -	cmp.eq p7,p0=r8,r0;;
  23.147 -(p7)	ptc.ga r32,r33;;
  23.148 -(p7)	br.ret.sptk.many rp
  23.149 -	;;
  23.150  	mov r8=r32
  23.151  	mov r9=r33
  23.152 -	;;
  23.153 -	XEN_CLEAR_PSR_IC
  23.154 -	;;
  23.155  	XEN_HYPER_PTC_GA
  23.156 -	;;
  23.157 -	XEN_RESTORE_PSR_IC
  23.158 -	;;
  23.159  	br.ret.sptk.many rp
  23.160  	;;
  23.161  END(xen_ptcga)
  23.162  
  23.163  GLOBAL_ENTRY(xen_get_rr)
  23.164 -	movl r8=running_on_xen;;
  23.165 -	ld4 r8=[r8];;
  23.166 -	cmp.eq p7,p0=r8,r0;;
  23.167 -(p7)	mov r8=rr[r32];;
  23.168 -(p7)	br.ret.sptk.many rp
  23.169 -	;;
  23.170  	mov r8=r32
  23.171 -	;;
  23.172 -	XEN_CLEAR_PSR_IC
  23.173 -	;;
  23.174  	XEN_HYPER_GET_RR
  23.175 -	;;
  23.176 -	XEN_RESTORE_PSR_IC
  23.177 -	;;
  23.178  	br.ret.sptk.many rp
  23.179  	;;
  23.180  END(xen_get_rr)
  23.181  
  23.182  GLOBAL_ENTRY(xen_set_rr)
  23.183 -	movl r8=running_on_xen;;
  23.184 -	ld4 r8=[r8];;
  23.185 -	cmp.eq p7,p0=r8,r0;;
  23.186 -(p7)	mov rr[r32]=r33;;
  23.187 -(p7)	br.ret.sptk.many rp
  23.188 -	;;
  23.189  	mov r8=r32
  23.190  	mov r9=r33
  23.191 -	;;
  23.192 -	XEN_CLEAR_PSR_IC
  23.193 -	;;
  23.194  	XEN_HYPER_SET_RR
  23.195 -	;;
  23.196 -	XEN_RESTORE_PSR_IC
  23.197 -	;;
  23.198  	br.ret.sptk.many rp
  23.199  	;;
  23.200  END(xen_set_rr)
  23.201  
  23.202  GLOBAL_ENTRY(xen_set_kr)
  23.203 -	movl r8=running_on_xen;;
  23.204 -	ld4 r8=[r8];;
  23.205 -	cmp.ne p7,p0=r8,r0;;
  23.206 -(p7)	br.cond.spnt.few 1f;
  23.207 -	;;
  23.208 -	cmp.eq p7,p0=r8,r0
  23.209 -	adds r8=-1,r8;;
  23.210 -(p7)	mov ar0=r9
  23.211 -(p7)	br.ret.sptk.many rp;;
  23.212 -	cmp.eq p7,p0=r8,r0
  23.213 -	adds r8=-1,r8;;
  23.214 -(p7)	mov ar1=r9
  23.215 -(p7)	br.ret.sptk.many rp;;
  23.216 -	cmp.eq p7,p0=r8,r0
  23.217 -	adds r8=-1,r8;;
  23.218 -(p7)	mov ar2=r9
  23.219 -(p7)	br.ret.sptk.many rp;;
  23.220 -	cmp.eq p7,p0=r8,r0
  23.221 -	adds r8=-1,r8;;
  23.222 -(p7)	mov ar3=r9
  23.223 -(p7)	br.ret.sptk.many rp;;
  23.224 -	cmp.eq p7,p0=r8,r0
  23.225 -	adds r8=-1,r8;;
  23.226 -(p7)	mov ar4=r9
  23.227 -(p7)	br.ret.sptk.many rp;;
  23.228 -	cmp.eq p7,p0=r8,r0
  23.229 -	adds r8=-1,r8;;
  23.230 -(p7)	mov ar5=r9
  23.231 -(p7)	br.ret.sptk.many rp;;
  23.232 -	cmp.eq p7,p0=r8,r0
  23.233 -	adds r8=-1,r8;;
  23.234 -(p7)	mov ar6=r9
  23.235 -(p7)	br.ret.sptk.many rp;;
  23.236 -	cmp.eq p7,p0=r8,r0
  23.237 -	adds r8=-1,r8;;
  23.238 -(p7)	mov ar7=r9
  23.239 -(p7)	br.ret.sptk.many rp;;
  23.240 -
  23.241 -1:	mov r8=r32
  23.242 +	mov r8=r32
  23.243  	mov r9=r33
  23.244 -	;;
  23.245 -	XEN_CLEAR_PSR_IC
  23.246 -	;;
  23.247  	XEN_HYPER_SET_KR
  23.248 -	;;
  23.249 -	XEN_RESTORE_PSR_IC
  23.250 -	;;
  23.251  	br.ret.sptk.many rp
  23.252  END(xen_set_kr)
  23.253  
  23.254  GLOBAL_ENTRY(xen_fc)
  23.255 -	movl r8=running_on_xen;;
  23.256 -	ld4 r8=[r8];;
  23.257 -	cmp.eq p7,p0=r8,r0;;
  23.258 -(p7)	fc r32;;
  23.259 -(p7)	br.ret.sptk.many rp
  23.260 -	;;
  23.261  	mov r8=r32
  23.262 -	;;
  23.263 -	XEN_CLEAR_PSR_IC
  23.264 -	;;
  23.265  	XEN_HYPER_FC
  23.266 -	;;
  23.267 -	XEN_RESTORE_PSR_IC
  23.268 -	;;
  23.269  	br.ret.sptk.many rp
  23.270  END(xen_fc)
  23.271  
  23.272  GLOBAL_ENTRY(xen_get_cpuid)
  23.273 -	movl r8=running_on_xen;;
  23.274 -	ld4 r8=[r8];;
  23.275 -	cmp.eq p7,p0=r8,r0;;
  23.276 -(p7)	mov r8=cpuid[r32];;
  23.277 -(p7)	br.ret.sptk.many rp
  23.278 -	;;
  23.279  	mov r8=r32
  23.280 -	;;
  23.281 -	XEN_CLEAR_PSR_IC
  23.282 -	;;
  23.283  	XEN_HYPER_GET_CPUID
  23.284 -	;;
  23.285 -	XEN_RESTORE_PSR_IC
  23.286 -	;;
  23.287  	br.ret.sptk.many rp
  23.288  END(xen_get_cpuid)
  23.289  
  23.290  GLOBAL_ENTRY(xen_get_pmd)
  23.291 -	movl r8=running_on_xen;;
  23.292 -	ld4 r8=[r8];;
  23.293 -	cmp.eq p7,p0=r8,r0;;
  23.294 -(p7)	mov r8=pmd[r32];;
  23.295 -(p7)	br.ret.sptk.many rp
  23.296 -	;;
  23.297  	mov r8=r32
  23.298 -	;;
  23.299 -	XEN_CLEAR_PSR_IC
  23.300 -	;;
  23.301  	XEN_HYPER_GET_PMD
  23.302 -	;;
  23.303 -	XEN_RESTORE_PSR_IC
  23.304 -	;;
  23.305  	br.ret.sptk.many rp
  23.306  END(xen_get_pmd)
  23.307  
  23.308  #ifdef CONFIG_IA32_SUPPORT
  23.309  GLOBAL_ENTRY(xen_get_eflag)
  23.310 -	movl r8=running_on_xen;;
  23.311 -	ld4 r8=[r8];;
  23.312 -	cmp.eq p7,p0=r8,r0;;
  23.313 -(p7)	mov r8=ar24;;
  23.314 -(p7)	br.ret.sptk.many rp
  23.315 -	;;
  23.316 -	mov r8=r32
  23.317 -	;;
  23.318 -	XEN_CLEAR_PSR_IC
  23.319 -	;;
  23.320  	XEN_HYPER_GET_EFLAG
  23.321 -	;;
  23.322 -	XEN_RESTORE_PSR_IC
  23.323 -	;;
  23.324  	br.ret.sptk.many rp
  23.325  END(xen_get_eflag)
  23.326  	
  23.327  // some bits aren't set if pl!=0, see SDM vol1 3.1.8
  23.328  GLOBAL_ENTRY(xen_set_eflag)
  23.329 -	movl r8=running_on_xen;;
  23.330 -	ld4 r8=[r8];;
  23.331 -	cmp.eq p7,p0=r8,r0;;
  23.332 -(p7)	mov ar24=r32
  23.333 -(p7)	br.ret.sptk.many rp
  23.334 -	;;
  23.335  	mov r8=r32
  23.336 -	;;
  23.337 -	XEN_CLEAR_PSR_IC
  23.338 -	;;
  23.339  	XEN_HYPER_SET_EFLAG
  23.340 -	;;
  23.341 -	XEN_RESTORE_PSR_IC
  23.342 -	;;
  23.343  	br.ret.sptk.many rp
  23.344  END(xen_set_eflag)
  23.345  #endif
  23.346 @@ -355,27 +129,6 @@ END(xen_send_ipi)
  23.347  #ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT
  23.348  // Those are vdso specialized.
  23.349  // In fsys mode, call, ret can't be used.
  23.350 -GLOBAL_ENTRY(xen_rsm_be_i)
  23.351 -	st1 [r22]=r20
  23.352 -	st4 [r23]=r0
  23.353 -	XEN_HYPER_RSM_BE
  23.354 -	st4 [r23]=r20
  23.355 -	brl.cond.sptk	.vdso_rsm_be_i_ret
  23.356 -	;; 
  23.357 -END(xen_rsm_be_i)
  23.358 -
  23.359 -GLOBAL_ENTRY(xen_get_psr)
  23.360 -	mov r31=r8
  23.361 -	mov r25=IA64_PSR_IC
  23.362 -	st4 [r23]=r0
  23.363 -	XEN_HYPER_GET_PSR
  23.364 -	;; 
  23.365 -	st4 [r23]=r20
  23.366 -	or r29=r8,r25 // vpsr.ic was cleared for hyperprivop
  23.367 -	mov r8=r31
  23.368 -	brl.cond.sptk	.vdso_get_psr_ret
  23.369 -	;; 
  23.370 -END(xen_get_psr)
  23.371  
  23.372  	// see xen_ssm_i() in privop.h
  23.373  	// r22 = &vcpu->vcpu_info->evtchn_upcall_mask
  23.374 @@ -395,7 +148,6 @@ END(xen_get_psr)
  23.375  (p14)	cmp.ne.unc p11,p0=r0,r25;	\
  23.376  	;;				\
  23.377  (p11)	st1 [r22]=r20;			\
  23.378 -(p11)	st4 [r23]=r0;			\
  23.379  (p11)	XEN_HYPER_SSM_I;
  23.380  		
  23.381  GLOBAL_ENTRY(xen_ssm_i_0)
  23.382 @@ -409,4 +161,11 @@ GLOBAL_ENTRY(xen_ssm_i_1)
  23.383  	brl.cond.sptk	.vdso_ssm_i_1_ret
  23.384  	;; 
  23.385  END(xen_ssm_i_1)
  23.386 +
  23.387 +GLOBAL_ENTRY(__hypercall)
  23.388 +	mov r2=r37
  23.389 +	break 0x1000
  23.390 +	br.ret.sptk.many b0
  23.391 +	;; 
  23.392 +END(__hypercall)
  23.393  #endif
    24.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c	Thu Jan 18 15:18:07 2007 +0000
    24.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c	Fri Jan 19 14:48:57 2007 +0000
    24.3 @@ -25,7 +25,10 @@
    24.4  #include <linux/bootmem.h>
    24.5  #include <linux/module.h>
    24.6  #include <linux/vmalloc.h>
    24.7 +#include <linux/efi.h>
    24.8  #include <asm/page.h>
    24.9 +#include <asm/pgalloc.h>
   24.10 +#include <asm/meminit.h>
   24.11  #include <asm/hypervisor.h>
   24.12  #include <asm/hypercall.h>
   24.13  #include <xen/interface/memory.h>
   24.14 @@ -46,6 +49,8 @@ static int p2m_expose_init(void);
   24.15  #define p2m_expose_init() (-ENOSYS)
   24.16  #endif
   24.17  
   24.18 +EXPORT_SYMBOL(__hypercall);
   24.19 +
   24.20  //XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear()
   24.21  // move those to lib/contiguous_bitmap?
   24.22  //XXX discontigmem/sparsemem
   24.23 @@ -56,13 +61,90 @@ static int p2m_expose_init(void);
   24.24   */
   24.25  unsigned long *contiguous_bitmap;
   24.26  
   24.27 +#ifdef CONFIG_VIRTUAL_MEM_MAP
   24.28 +/* Following logic is stolen from create_mem_map_table() for virtual memmap */
   24.29 +static int
   24.30 +create_contiguous_bitmap(u64 start, u64 end, void *arg)
   24.31 +{
   24.32 +	unsigned long address, start_page, end_page;
   24.33 +	unsigned long bitmap_start, bitmap_end;
   24.34 +	unsigned char *bitmap;
   24.35 +	int node;
   24.36 +	pgd_t *pgd;
   24.37 +	pud_t *pud;
   24.38 +	pmd_t *pmd;
   24.39 +	pte_t *pte;
   24.40 +
   24.41 +	bitmap_start = (unsigned long)contiguous_bitmap +
   24.42 +	               ((__pa(start) >> PAGE_SHIFT) >> 3);
   24.43 +	bitmap_end = (unsigned long)contiguous_bitmap +
   24.44 +	             (((__pa(end) >> PAGE_SHIFT) + 2 * BITS_PER_LONG) >> 3);
   24.45 +
   24.46 +	start_page = bitmap_start & PAGE_MASK;
   24.47 +	end_page = PAGE_ALIGN(bitmap_end);
   24.48 +	node = paddr_to_nid(__pa(start));
   24.49 +
   24.50 +	bitmap = alloc_bootmem_pages_node(NODE_DATA(node),
   24.51 +	                                  end_page - start_page);
   24.52 +	BUG_ON(!bitmap);
   24.53 +	memset(bitmap, 0, end_page - start_page);
   24.54 +
   24.55 +	for (address = start_page; address < end_page; address += PAGE_SIZE) {
   24.56 +		pgd = pgd_offset_k(address);
   24.57 +		if (pgd_none(*pgd))
   24.58 +			pgd_populate(&init_mm, pgd,
   24.59 +			             alloc_bootmem_pages_node(NODE_DATA(node),
   24.60 +			                                      PAGE_SIZE));
   24.61 +		pud = pud_offset(pgd, address);
   24.62 +
   24.63 +		if (pud_none(*pud))
   24.64 +			pud_populate(&init_mm, pud,
   24.65 +			             alloc_bootmem_pages_node(NODE_DATA(node),
   24.66 +			                                      PAGE_SIZE));
   24.67 +		pmd = pmd_offset(pud, address);
   24.68 +
   24.69 +		if (pmd_none(*pmd))
   24.70 +			pmd_populate_kernel(&init_mm, pmd,
   24.71 +			                    alloc_bootmem_pages_node
   24.72 +			                    (NODE_DATA(node), PAGE_SIZE));
   24.73 +		pte = pte_offset_kernel(pmd, address);
   24.74 +
   24.75 +		if (pte_none(*pte))
   24.76 +			set_pte(pte,
   24.77 +			        pfn_pte(__pa(bitmap + (address - start_page))
   24.78 +			                >> PAGE_SHIFT, PAGE_KERNEL));
   24.79 +	}
   24.80 +	return 0;
   24.81 +}
   24.82 +#endif
   24.83 +
   24.84 +static void
   24.85 +__contiguous_bitmap_init(unsigned long size)
   24.86 +{
   24.87 +	contiguous_bitmap = alloc_bootmem_pages(size);
   24.88 +	BUG_ON(!contiguous_bitmap);
   24.89 +	memset(contiguous_bitmap, 0, size);
   24.90 +}
   24.91 +
   24.92  void
   24.93  contiguous_bitmap_init(unsigned long end_pfn)
   24.94  {
   24.95  	unsigned long size = (end_pfn + 2 * BITS_PER_LONG) >> 3;
   24.96 -	contiguous_bitmap = alloc_bootmem_low_pages(size);
   24.97 -	BUG_ON(!contiguous_bitmap);
   24.98 -	memset(contiguous_bitmap, 0, size);
   24.99 +#ifndef CONFIG_VIRTUAL_MEM_MAP
  24.100 +	__contiguous_bitmap_init(size);
  24.101 +#else
  24.102 +	unsigned long max_gap = 0;
  24.103 +
  24.104 +	efi_memmap_walk(find_largest_hole, (u64*)&max_gap);
  24.105 +	if (max_gap < LARGE_GAP) {
  24.106 +		__contiguous_bitmap_init(size);
  24.107 +	} else {
  24.108 +		unsigned long map_size = PAGE_ALIGN(size);
  24.109 +		vmalloc_end -= map_size;
  24.110 +		contiguous_bitmap = (unsigned long*)vmalloc_end;
  24.111 +		efi_memmap_walk(create_contiguous_bitmap, NULL);
  24.112 +	}
  24.113 +#endif
  24.114  }
  24.115  
  24.116  #if 0
    25.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S	Thu Jan 18 15:18:07 2007 +0000
    25.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S	Fri Jan 19 14:48:57 2007 +0000
    25.3 @@ -59,12 +59,6 @@ GLOBAL_ENTRY(ia64_switch_to)
    25.4  	shr.u r26=r20,IA64_GRANULE_SHIFT
    25.5  	cmp.eq p7,p6=r25,in0
    25.6  	;;
    25.7 -#ifdef CONFIG_XEN
    25.8 -	movl r8=XSI_PSR_IC
    25.9 -	;;
   25.10 -	st4 [r8]=r0	// force psr.ic off for hyperprivop(s)
   25.11 -	;;
   25.12 -#endif
   25.13  	/*
   25.14  	 * If we've already mapped this task's page, we can skip doing it again.
   25.15  	 */
   25.16 @@ -72,19 +66,13 @@ GLOBAL_ENTRY(ia64_switch_to)
   25.17  (p6)	br.cond.dpnt .map
   25.18  	;;
   25.19  .done:
   25.20 +	ld8 sp=[r21]			// load kernel stack pointer of new task
   25.21  #ifdef CONFIG_XEN
   25.22 -	// psr.ic already off
   25.23  	// update "current" application register
   25.24  	mov r8=IA64_KR_CURRENT
   25.25  	mov r9=in0;;
   25.26  	XEN_HYPER_SET_KR
   25.27 -	ld8 sp=[r21]			// load kernel stack pointer of new task
   25.28 -	movl r27=XSI_PSR_IC
   25.29 -	mov r8=1
   25.30 -	;;
   25.31 -	st4 [r27]=r8			// psr.ic back on
   25.32  #else
   25.33 -	ld8 sp=[r21]			// load kernel stack pointer of new task
   25.34  	mov IA64_KR(CURRENT)=in0	// update "current" application register
   25.35  #endif
   25.36  	mov r8=r13			// return pointer to previously running task
   25.37 @@ -99,7 +87,10 @@ GLOBAL_ENTRY(ia64_switch_to)
   25.38  
   25.39  .map:
   25.40  #ifdef CONFIG_XEN
   25.41 -	// psr.ic already off
   25.42 +    movl r25=XSI_PSR_IC			// clear psr.ic
   25.43 +    ;;
   25.44 +    st4 [r25]=r0
   25.45 +    ;;
   25.46  #else
   25.47  	rsm psr.ic			// interrupts (psr.i) are already disabled here
   25.48  #endif
   25.49 @@ -132,7 +123,13 @@ GLOBAL_ENTRY(ia64_switch_to)
   25.50  #endif
   25.51  	;;
   25.52  	itr.d dtr[r25]=r23		// wire in new mapping...
   25.53 -#ifndef CONFIG_XEN
   25.54 +#ifdef CONFIG_XEN
   25.55 +	mov r9=1
   25.56 +	movl r8=XSI_PSR_IC
   25.57 +	;;
   25.58 +	st4 [r8]=r9
   25.59 +	;;
   25.60 +#else    
   25.61  	ssm psr.ic			// reenable the psr.ic bit
   25.62  	;;
   25.63  	srlz.d
   25.64 @@ -415,7 +412,16 @@ ENTRY(ia64_leave_syscall)
   25.65  (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
   25.66  	;;
   25.67  	ld8 r26=[r2],PT(B0)-PT(AR_PFS)	// M0|1 load ar.pfs
   25.68 +#ifdef CONFIG_XEN
   25.69 +(pKStk)	mov r21=r8
   25.70 +(pKStk)	XEN_HYPER_GET_PSR
   25.71 +	;;
   25.72 +(pKStk)	mov r22=r8
   25.73 +(pKStk)	mov r8=r21
   25.74 +	;;
   25.75 +#else    
   25.76  (pKStk)	mov r22=psr			// M2   read PSR now that interrupts are disabled
   25.77 +#endif
   25.78  	nop 0
   25.79  	;;
   25.80  	ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
   25.81 @@ -645,7 +651,16 @@ GLOBAL_ENTRY(ia64_leave_kernel)
   25.82  	adds r16=PT(CR_IPSR)+16,r12
   25.83  	adds r17=PT(CR_IIP)+16,r12
   25.84  
   25.85 +#ifdef CONFIG_XEN    
   25.86 +(pKStk)	mov r29=r8
   25.87 +(pKStk)	XEN_HYPER_GET_PSR
   25.88 +	;;
   25.89 +(pKStk)	mov r22=r8
   25.90 +(pKStk)	mov r8=r29
   25.91 +	;;
   25.92 +#else
   25.93  (pKStk)	mov r22=psr		// M2 read PSR now that interrupts are disabled
   25.94 +#endif
   25.95  	nop.i 0
   25.96  	nop.i 0
   25.97  	;;
    26.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S	Thu Jan 18 15:18:07 2007 +0000
    26.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S	Fri Jan 19 14:48:57 2007 +0000
    26.3 @@ -709,11 +709,23 @@ ENTRY(page_fault)
    26.4  	;;
    26.5  #endif
    26.6  #ifdef CONFIG_XEN
    26.7 -	br.cond.sptk.many	xen_page_fault
    26.8 +    
    26.9 +#define MASK_TO_PEND_OFS    (-1)
   26.10 +    
   26.11 +(p15)	movl r14=XSI_PSR_I_ADDR
   26.12 +	;;
   26.13 +(p15)	ld8 r14=[r14]
   26.14  	;;
   26.15 -done_xen_page_fault:
   26.16 +(p15)	st1 [r14]=r0,MASK_TO_PEND_OFS		// if (p15) vpsr.i = 1
   26.17 +	;;		// if (p15) (vcpu->vcpu_info->evtchn_upcall_mask)=0
   26.18 +(p15)	ld1 r14=[r14]	// if (vcpu->vcpu_info->evtchn_upcall_pending)
   26.19 +	;;
   26.20 +(p15)	cmp.ne	p15,p0=r14,r0
   26.21 +	;;
   26.22 +(p15)	XEN_HYPER_SSM_I
   26.23 +#else
   26.24 +(p15)	ssm psr.i				// restore psr.i
   26.25  #endif
   26.26 -(p15)	ssm psr.i				// restore psr.i
   26.27  	movl r14=ia64_leave_kernel
   26.28  	;;
   26.29  	SAVE_REST
   26.30 @@ -729,25 +741,6 @@ END(page_fault)
   26.31  ENTRY(dkey_miss)
   26.32  	DBG_FAULT(7)
   26.33  	FAULT(7)
   26.34 -#ifdef CONFIG_XEN
   26.35 -	// Leaving this code inline above results in an IVT section overflow
   26.36 -	// There is no particular reason for this code to be here...
   26.37 -xen_page_fault:
   26.38 -(p15)	movl r3=XSI_PSR_I_ADDR
   26.39 -	;;
   26.40 -(p15)	ld8 r3=[r3]
   26.41 -	;;
   26.42 -(p15)	st1 [r3]=r0,-1	// if (p15) vpsr.i = 1
   26.43 -	mov r14=r0
   26.44 -	;;
   26.45 -(p15)	ld1 r14=[r3]				// if (pending_events)
   26.46 -	adds r3=8,r2				// re-set up second base pointer
   26.47 -	;;
   26.48 -(p15)	cmp.ne	p15,p0=r14,r0
   26.49 -	;;
   26.50 -	br.cond.sptk.many done_xen_page_fault
   26.51 -	;;
   26.52 -#endif
   26.53  END(dkey_miss)
   26.54  
   26.55  	.org ia64_ivt+0x2000
   26.56 @@ -1170,14 +1163,13 @@ 1:
   26.57  #ifdef CONFIG_XEN
   26.58  (p15)	ld8 r16=[r16]				// vpsr.i
   26.59  	;;
   26.60 -(p15)	st1 [r16]=r0,-1		// if (p15) vpsr.i = 1
   26.61 -	mov r2=r0
   26.62 +(p15)	st1 [r16]=r0,MASK_TO_PEND_OFS		// if (p15) vpsr.i = 1
   26.63 +	;;		// if (p15) (vcpu->vcpu_info->evtchn_upcall_mask)=0
   26.64 +(p15)	ld1 r2=[r16]	// if (vcpu->vcpu_info->evtchn_upcall_pending)
   26.65  	;;
   26.66 -(p15)	ld1 r2=[r16]				// if (pending_events)
   26.67 +(p15)	cmp.ne.unc p6,p0=r2,r0
   26.68  	;;
   26.69 -	cmp.ne	p6,p0=r2,r0
   26.70 -	;;
   26.71 -(p6)	ssm	psr.i				//   do a real ssm psr.i
   26.72 +(p6)	XEN_HYPER_SSM_I				//   do a real ssm psr.i
   26.73  #else
   26.74  (p15)	ssm psr.i				// M2   restore psr.i
   26.75  #endif
    27.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenminstate.h	Thu Jan 18 15:18:07 2007 +0000
    27.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenminstate.h	Fri Jan 19 14:48:57 2007 +0000
    27.3 @@ -151,16 +151,7 @@
    27.4  .mem.offset 8,0; st8.spill [r17]=r11,24;							\
    27.5          ;;											\
    27.6  	/* xen special handling for possibly lazy cover */					\
    27.7 -	movl r8=XSI_INCOMPL_REGFR;								\
    27.8 -	;;											\
    27.9 -	ld4 r30=[r8];										\
   27.10 -	;;											\
   27.11 -	/* set XSI_INCOMPL_REGFR 0 */								\
   27.12 -	st4 [r8]=r0;										\
   27.13 -	cmp.eq	p6,p7=r30,r0;									\
   27.14 -	;; /* not sure if this stop bit is necessary */						\
   27.15 -(p6)	adds r8=XSI_PRECOVER_IFS-XSI_INCOMPL_REGFR,r8;						\
   27.16 -(p7)	adds r8=XSI_IFS-XSI_INCOMPL_REGFR,r8;							\
   27.17 +	movl r8=XSI_PRECOVER_IFS;								\
   27.18  	;;											\
   27.19  	ld8 r30=[r8];										\
   27.20  	;;											\
    28.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenpal.S	Thu Jan 18 15:18:07 2007 +0000
    28.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenpal.S	Fri Jan 19 14:48:57 2007 +0000
    28.3 @@ -33,7 +33,16 @@ 1:	{
    28.4  	mov loc4=ar.rsc			// save RSE configuration
    28.5  	;;
    28.6  	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
    28.7 +#ifdef CONFIG_XEN
    28.8 +	mov r9 = r8
    28.9 +	XEN_HYPER_GET_PSR
   28.10 +	;;
   28.11 +	mov loc3 = r8
   28.12 +	mov r8 = r9
   28.13 +	;;
   28.14 +#else    
   28.15  	mov loc3 = psr
   28.16 +#endif    
   28.17  	mov loc0 = rp
   28.18  	.body
   28.19  	mov r30 = in2
   28.20 @@ -41,16 +50,16 @@ 1:	{
   28.21  #ifdef CONFIG_XEN
   28.22  	// this is low priority for paravirtualization, but is called
   28.23  	// from the idle loop so confuses privop counting
   28.24 -	movl r31=XSI_PSR_IC
   28.25 +	movl r31=XSI_PSR_I_ADDR
   28.26  	;;
   28.27 -(p6)	st4 [r31]=r0
   28.28 +	ld8 r31=[r31]
   28.29 +	mov r22=1
   28.30  	;;
   28.31 -(p7)	adds r31=XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS,r31
   28.32 -(p7)	mov r22=1
   28.33 +	st1 [r31]=r22
   28.34 +	;;  
   28.35 +(p6)	movl r31=XSI_PSR_IC
   28.36  	;;
   28.37 -(p7)	ld8 r31=[r31]
   28.38 -	;;
   28.39 -(p7)	st1 [r31]=r22
   28.40 +(p6)	st4.rel [r31]=r0
   28.41  	;;
   28.42  	mov r31 = in3
   28.43  	mov b7 = loc2
    29.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S	Thu Jan 18 15:18:07 2007 +0000
    29.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S	Fri Jan 19 14:48:57 2007 +0000
    29.3 @@ -38,17 +38,16 @@ END(early_xen_setup)
    29.4  /* Stub for suspend.
    29.5     Just force the stacked registers to be written in memory.  */	
    29.6  GLOBAL_ENTRY(xencomm_arch_hypercall_suspend)
    29.7 -	mov r15=r32
    29.8  	;; 
    29.9 -	alloc r20=ar.pfs,0,0,0,0
   29.10 +	alloc r20=ar.pfs,0,0,6,0
   29.11  	mov r2=__HYPERVISOR_sched_op
   29.12  	;; 
   29.13  	/* We don't want to deal with RSE.  */
   29.14  	flushrs
   29.15 -	mov r14=2 // SCHEDOP_shutdown
   29.16 +	mov r33=r32
   29.17 +	mov r32=2 // SCHEDOP_shutdown
   29.18  	;;
   29.19  	break 0x1000
   29.20  	;; 
   29.21 -	mov ar.pfs=r20
   29.22  	br.ret.sptk.many b0
   29.23  END(xencomm_arch_hypercall_suspend)
    30.1 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig	Thu Jan 18 15:18:07 2007 +0000
    30.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig	Fri Jan 19 14:48:57 2007 +0000
    30.3 @@ -238,14 +238,6 @@ config XEN_COMPAT_030002
    30.4  
    30.5  endmenu
    30.6  
    30.7 -config HAVE_ARCH_ALLOC_SKB
    30.8 -	bool
    30.9 -	default y
   30.10 -
   30.11 -config HAVE_ARCH_DEV_ALLOC_SKB
   30.12 -	bool
   30.13 -	default y
   30.14 -
   30.15  config HAVE_IRQ_IGNORE_UNHANDLED
   30.16  	bool
   30.17  	default y
    32.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h	Thu Jan 18 15:18:07 2007 +0000
    32.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h	Fri Jan 19 14:48:57 2007 +0000
    32.3 @@ -39,6 +39,9 @@
    32.4  
    32.5  #include <asm/xen/xcom_hcall.h>
    32.6  struct xencomm_handle;
    32.7 +extern unsigned long __hypercall(unsigned long a1, unsigned long a2,
    32.8 +                                 unsigned long a3, unsigned long a4,
    32.9 +                                 unsigned long a5, unsigned long cmd);
   32.10  
   32.11  /*
   32.12   * Assembler stubs for hyper-calls.
   32.13 @@ -47,115 +50,58 @@ struct xencomm_handle;
   32.14  #define _hypercall0(type, name)					\
   32.15  ({								\
   32.16  	long __res;						\
   32.17 -	__asm__ __volatile__ (";;\n"				\
   32.18 -			      "mov r2=%1\n"			\
   32.19 -			      "break 0x1000 ;;\n"		\
   32.20 -			      "mov %0=r8 ;;\n"			\
   32.21 -			      : "=r" (__res)			\
   32.22 -			      : "J" (__HYPERVISOR_##name)	\
   32.23 -			      : "r2","r8",			\
   32.24 -			        "memory" );			\
   32.25 +	__res=__hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);	\
   32.26  	(type)__res;						\
   32.27  })
   32.28  
   32.29  #define _hypercall1(type, name, a1)				\
   32.30  ({								\
   32.31  	long __res;						\
   32.32 -	__asm__ __volatile__ (";;\n"				\
   32.33 -			      "mov r14=%2\n"			\
   32.34 -			      "mov r2=%1\n"			\
   32.35 -			      "break 0x1000 ;;\n"		\
   32.36 -			      "mov %0=r8 ;;\n"			\
   32.37 -			      : "=r" (__res)			\
   32.38 -			      : "J" (__HYPERVISOR_##name),	\
   32.39 -				"rI" ((unsigned long)(a1))	\
   32.40 -			      : "r14","r2","r8",		\
   32.41 -				"memory" );			\
   32.42 +	__res = __hypercall((unsigned long)a1,			\
   32.43 +	                     0, 0, 0, 0, __HYPERVISOR_##name);	\
   32.44  	(type)__res;						\
   32.45  })
   32.46  
   32.47  #define _hypercall2(type, name, a1, a2)				\
   32.48  ({								\
   32.49  	long __res;						\
   32.50 -	__asm__ __volatile__ (";;\n"				\
   32.51 -			      "mov r14=%2\n"			\
   32.52 -			      "mov r15=%3\n"			\
   32.53 -			      "mov r2=%1\n"			\
   32.54 -			      "break 0x1000 ;;\n"		\
   32.55 -			      "mov %0=r8 ;;\n"			\
   32.56 -			      : "=r" (__res)			\
   32.57 -			      : "J" (__HYPERVISOR_##name),	\
   32.58 -				"rI" ((unsigned long)(a1)),	\
   32.59 -				"rI" ((unsigned long)(a2))	\
   32.60 -			      : "r14","r15","r2","r8",		\
   32.61 -				"memory" );			\
   32.62 +	__res = __hypercall((unsigned long)a1,			\
   32.63 +	                    (unsigned long)a2,			\
   32.64 +	                    0, 0, 0, __HYPERVISOR_##name);	\
   32.65  	(type)__res;						\
   32.66  })
   32.67  
   32.68  #define _hypercall3(type, name, a1, a2, a3)			\
   32.69  ({								\
   32.70  	long __res;						\
   32.71 -	__asm__ __volatile__ (";;\n"                            \
   32.72 -			      "mov r14=%2\n"                    \
   32.73 -			      "mov r15=%3\n"                    \
   32.74 -			      "mov r16=%4\n"                    \
   32.75 -			      "mov r2=%1\n"                     \
   32.76 -			      "break 0x1000 ;;\n"               \
   32.77 -			      "mov %0=r8 ;;\n"                  \
   32.78 -			      : "=r" (__res)                    \
   32.79 -			      : "J" (__HYPERVISOR_##name),      \
   32.80 -				"rI" ((unsigned long)(a1)),     \
   32.81 -				"rI" ((unsigned long)(a2)),     \
   32.82 -				"rI" ((unsigned long)(a3))      \
   32.83 -			      : "r14","r15","r16","r2","r8",	\
   32.84 -			        "memory" );                     \
   32.85 -	(type)__res;                                            \
   32.86 +	__res = __hypercall((unsigned long)a1,			\
   32.87 +	                    (unsigned long)a2,			\
   32.88 +	                    (unsigned long)a3,			\
   32.89 +	                    0, 0, __HYPERVISOR_##name);		\
   32.90 +	(type)__res;						\
   32.91  })
   32.92  
   32.93  #define _hypercall4(type, name, a1, a2, a3, a4)			\
   32.94  ({								\
   32.95  	long __res;						\
   32.96 -	__asm__ __volatile__ (";;\n"                            \
   32.97 -			      "mov r14=%2\n"                    \
   32.98 -			      "mov r15=%3\n"                    \
   32.99 -			      "mov r16=%4\n"                    \
  32.100 -			      "mov r17=%5\n"                    \
  32.101 -			      "mov r2=%1\n"                     \
  32.102 -			      "break 0x1000 ;;\n"               \
  32.103 -			      "mov %0=r8 ;;\n"                  \
  32.104 -			      : "=r" (__res)                    \
  32.105 -			      : "J" (__HYPERVISOR_##name),      \
  32.106 -				"rI" ((unsigned long)(a1)),     \
  32.107 -				"rI" ((unsigned long)(a2)),     \
  32.108 -				"rI" ((unsigned long)(a3)),     \
  32.109 -				"rI" ((unsigned long)(a4))      \
  32.110 -			      : "r14","r15","r16","r2","r8",	\
  32.111 -			        "r17","memory" );               \
  32.112 -	(type)__res;                                            \
  32.113 +	__res = __hypercall((unsigned long)a1,			\
  32.114 +	                    (unsigned long)a2,			\
  32.115 +	                    (unsigned long)a3,			\
  32.116 +	                    (unsigned long)a4,			\
  32.117 +	                    0, __HYPERVISOR_##name);		\
  32.118 +	(type)__res;						\
  32.119  })
  32.120  
  32.121  #define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
  32.122  ({								\
  32.123  	long __res;						\
  32.124 -	__asm__ __volatile__ (";;\n"                            \
  32.125 -			      "mov r14=%2\n"                    \
  32.126 -			      "mov r15=%3\n"                    \
  32.127 -			      "mov r16=%4\n"                    \
  32.128 -			      "mov r17=%5\n"                    \
  32.129 -			      "mov r18=%6\n"                    \
  32.130 -			      "mov r2=%1\n"                     \
  32.131 -			      "break 0x1000 ;;\n"               \
  32.132 -			      "mov %0=r8 ;;\n"                  \
  32.133 -			      : "=r" (__res)                    \
  32.134 -			      : "J" (__HYPERVISOR_##name),      \
  32.135 -				"rI" ((unsigned long)(a1)),     \
  32.136 -				"rI" ((unsigned long)(a2)),     \
  32.137 -				"rI" ((unsigned long)(a3)),     \
  32.138 -				"rI" ((unsigned long)(a4)),     \
  32.139 -				"rI" ((unsigned long)(a5))      \
  32.140 -			      : "r14","r15","r16","r2","r8",	\
  32.141 -			        "r17","r18","memory" );         \
  32.142 -	(type)__res;                                            \
  32.143 +	__res = __hypercall((unsigned long)a1,			\
  32.144 +	                    (unsigned long)a2,			\
  32.145 +	                    (unsigned long)a3,			\
  32.146 +	                    (unsigned long)a4,			\
  32.147 +	                    (unsigned long)a5,			\
  32.148 +	                    __HYPERVISOR_##name);		\
  32.149 +	(type)__res;						\
  32.150  })
  32.151  
  32.152  
    33.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Thu Jan 18 15:18:07 2007 +0000
    33.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Fri Jan 19 14:48:57 2007 +0000
    33.3 @@ -215,7 +215,8 @@ asmlinkage int xprintk(const char *fmt, 
    33.4  #endif /* CONFIG_XEN || CONFIG_VMX_GUEST */
    33.5  
    33.6  #ifdef CONFIG_XEN_PRIVILEGED_GUEST
    33.7 -#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN)
    33.8 +#define is_initial_xendomain()						\
    33.9 +	(is_running_on_xen() ? xen_start_info->flags & SIF_INITDOMAIN : 0)
   33.10  #else
   33.11  #define is_initial_xendomain() 0
   33.12  #endif
    34.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h	Thu Jan 18 15:18:07 2007 +0000
    34.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h	Fri Jan 19 14:48:57 2007 +0000
    34.3 @@ -68,7 +68,6 @@ machine_to_phys_for_dma(unsigned long ma
    34.4  static inline unsigned long
    34.5  mfn_to_local_pfn(unsigned long mfn)
    34.6  {
    34.7 -	extern unsigned long max_mapnr;
    34.8  	unsigned long pfn = mfn_to_pfn_for_dma(mfn);
    34.9  	if (!pfn_valid(pfn))
   34.10  		return INVALID_P2M_ENTRY;
    35.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h	Thu Jan 18 15:18:07 2007 +0000
    35.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h	Fri Jan 19 14:48:57 2007 +0000
    35.3 @@ -119,6 +119,7 @@ extern struct page *vmem_map;
    35.4  #endif
    35.5  
    35.6  #ifdef CONFIG_FLATMEM
    35.7 +extern unsigned long max_mapnr;
    35.8  # define pfn_valid(pfn)		(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
    35.9  #elif defined(CONFIG_DISCONTIGMEM)
   35.10  extern unsigned long min_low_pfn;
    36.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h	Thu Jan 18 15:18:07 2007 +0000
    36.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h	Fri Jan 19 14:48:57 2007 +0000
    36.3 @@ -45,12 +45,10 @@
    36.4  #define	XEN_HYPER_GET_PMD		break HYPERPRIVOP_GET_PMD
    36.5  #define	XEN_HYPER_GET_EFLAG		break HYPERPRIVOP_GET_EFLAG
    36.6  #define	XEN_HYPER_SET_EFLAG		break HYPERPRIVOP_SET_EFLAG
    36.7 -#define	XEN_HYPER_RSM_BE		break HYPERPRIVOP_RSM_BE
    36.8  #define	XEN_HYPER_GET_PSR		break HYPERPRIVOP_GET_PSR
    36.9  
   36.10  #define XSI_IFS			(XSI_BASE + XSI_IFS_OFS)
   36.11  #define XSI_PRECOVER_IFS	(XSI_BASE + XSI_PRECOVER_IFS_OFS)
   36.12 -#define XSI_INCOMPL_REGFR	(XSI_BASE + XSI_INCOMPL_REGFR_OFS)
   36.13  #define XSI_IFA			(XSI_BASE + XSI_IFA_OFS)
   36.14  #define XSI_ISR			(XSI_BASE + XSI_ISR_OFS)
   36.15  #define XSI_IIM			(XSI_BASE + XSI_IIM_OFS)
   36.16 @@ -123,8 +121,6 @@ extern void xen_set_eflag(unsigned long)
   36.17   * that we inline it */
   36.18  #define xen_hyper_ssm_i()						\
   36.19  ({									\
   36.20 -	xen_set_virtual_psr_i(0);					\
   36.21 -	xen_set_virtual_psr_ic(0);					\
   36.22  	XEN_HYPER_SSM_I;						\
   36.23  })
   36.24  
   36.25 @@ -139,8 +135,12 @@ extern void xen_set_eflag(unsigned long)
   36.26  #define xen_ssm_i()							\
   36.27  ({									\
   36.28  	int old = xen_get_virtual_psr_i();				\
   36.29 -	xen_set_virtual_psr_i(1);					\
   36.30 -	if (!old && xen_get_virtual_pend()) xen_hyper_ssm_i();		\
   36.31 +	if (!old) {							\
   36.32 +		if (xen_get_virtual_pend())				\
   36.33 +			xen_hyper_ssm_i();				\
   36.34 +		else							\
   36.35 +			xen_set_virtual_psr_i(1);			\
   36.36 +	}								\
   36.37  })
   36.38  
   36.39  #define xen_ia64_intrin_local_irq_restore(x)				\
   36.40 @@ -182,6 +182,7 @@ extern void xen_set_eflag(unsigned long)
   36.41   * be properly handled by Xen, some are frequent enough that we use
   36.42   * hyperprivops for performance. */
   36.43  
   36.44 +extern unsigned long xen_get_psr(void);
   36.45  extern unsigned long xen_get_ivr(void);
   36.46  extern unsigned long xen_get_tpr(void);
   36.47  extern void xen_set_itm(unsigned long);
   36.48 @@ -201,6 +202,11 @@ extern void xen_ptcga(unsigned long addr
   36.49  	__u64 ia64_intri_res;						\
   36.50  									\
   36.51  	switch(regnum) {						\
   36.52 +	case _IA64_REG_PSR:						\
   36.53 +		ia64_intri_res = (is_running_on_xen()) ?			\
   36.54 +			xen_get_psr() :					\
   36.55 +			__ia64_getreg(regnum);				\
   36.56 +		break;							\
   36.57  	case _IA64_REG_CR_IVR:						\
   36.58  		ia64_intri_res = (is_running_on_xen()) ?			\
   36.59  			xen_get_ivr() :					\
    37.1 --- a/linux-2.6-xen-sparse/include/linux/skbuff.h	Thu Jan 18 15:18:07 2007 +0000
    37.2 +++ b/linux-2.6-xen-sparse/include/linux/skbuff.h	Fri Jan 19 14:48:57 2007 +0000
    37.3 @@ -353,8 +353,7 @@ static inline struct sk_buff *alloc_skb_
    37.4  
    37.5  extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
    37.6  					    unsigned int size,
    37.7 -					    gfp_t priority,
    37.8 -					    int fclone);
    37.9 +					    gfp_t priority);
   37.10  extern void	       kfree_skbmem(struct sk_buff *skb);
   37.11  extern struct sk_buff *skb_clone(struct sk_buff *skb,
   37.12  				 gfp_t priority);
    38.1 --- a/linux-2.6-xen-sparse/net/core/skbuff.c	Thu Jan 18 15:18:07 2007 +0000
    38.2 +++ b/linux-2.6-xen-sparse/net/core/skbuff.c	Fri Jan 19 14:48:57 2007 +0000
    38.3 @@ -210,18 +210,14 @@ nodata:
    38.4   */
    38.5  struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
    38.6  				     unsigned int size,
    38.7 -				     gfp_t gfp_mask,
    38.8 -				     int fclone)
    38.9 +				     gfp_t gfp_mask)
   38.10  {
   38.11 -	kmem_cache_t *cache;
   38.12 -	struct skb_shared_info *shinfo;
   38.13  	struct sk_buff *skb;
   38.14  	u8 *data;
   38.15  
   38.16 -	cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
   38.17 -
   38.18  	/* Get the HEAD */
   38.19 -	skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA);
   38.20 +	skb = kmem_cache_alloc(skbuff_head_cache,
   38.21 +			       gfp_mask & ~__GFP_DMA);
   38.22  	if (!skb)
   38.23  		goto out;
   38.24  
   38.25 @@ -238,29 +234,18 @@ struct sk_buff *alloc_skb_from_cache(kme
   38.26  	skb->data = data;
   38.27  	skb->tail = data;
   38.28  	skb->end  = data + size;
   38.29 -	/* make sure we initialize shinfo sequentially */
   38.30 -	shinfo = skb_shinfo(skb);
   38.31 -	atomic_set(&shinfo->dataref, 1);
   38.32 -	shinfo->nr_frags  = 0;
   38.33 -	shinfo->gso_size = 0;
   38.34 -	shinfo->gso_segs = 0;
   38.35 -	shinfo->gso_type = 0;
   38.36 -	shinfo->ip6_frag_id = 0;
   38.37 -	shinfo->frag_list = NULL;
   38.38  
   38.39 -	if (fclone) {
   38.40 -		struct sk_buff *child = skb + 1;
   38.41 -		atomic_t *fclone_ref = (atomic_t *) (child + 1);
   38.42 -
   38.43 -		skb->fclone = SKB_FCLONE_ORIG;
   38.44 -		atomic_set(fclone_ref, 1);
   38.45 -
   38.46 -		child->fclone = SKB_FCLONE_UNAVAILABLE;
   38.47 -	}
   38.48 +	atomic_set(&(skb_shinfo(skb)->dataref), 1);
   38.49 +	skb_shinfo(skb)->nr_frags  = 0;
   38.50 +	skb_shinfo(skb)->gso_size = 0;
   38.51 +	skb_shinfo(skb)->gso_segs = 0;
   38.52 +	skb_shinfo(skb)->gso_type = 0;
   38.53 +	skb_shinfo(skb)->ip6_frag_id = 0;
   38.54 +	skb_shinfo(skb)->frag_list = NULL;
   38.55  out:
   38.56  	return skb;
   38.57  nodata:
   38.58 -	kmem_cache_free(cache, skb);
   38.59 +	kmem_cache_free(skbuff_head_cache, skb);
   38.60  	skb = NULL;
   38.61  	goto out;
   38.62  }
    39.1 --- a/tools/ioemu/hw/cirrus_vga.c	Thu Jan 18 15:18:07 2007 +0000
    39.2 +++ b/tools/ioemu/hw/cirrus_vga.c	Fri Jan 19 14:48:57 2007 +0000
    39.3 @@ -3010,11 +3010,44 @@ static CPUWriteMemoryFunc *cirrus_mmio_w
    39.4      cirrus_mmio_writel,
    39.5  };
    39.6  
    39.7 +void cirrus_stop_acc(CirrusVGAState *s)
    39.8 +{
    39.9 +    if (s->map_addr){
   39.10 +        int error;
   39.11 +        s->map_addr = 0;
   39.12 +        error = unset_vram_mapping(s->cirrus_lfb_addr,
   39.13 +                s->cirrus_lfb_end);
   39.14 +        fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
   39.15 +
   39.16 +        munmap(s->vram_ptr, VGA_RAM_SIZE);
   39.17 +    }
   39.18 +}
   39.19 +
   39.20 +void cirrus_restart_acc(CirrusVGAState *s)
   39.21 +{
   39.22 +    if (s->cirrus_lfb_addr && s->cirrus_lfb_end) {
   39.23 +        void *vram_pointer, *old_vram;
   39.24 +        fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n",
   39.25 +                s->cirrus_lfb_addr, s->cirrus_lfb_end);
   39.26 +        vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
   39.27 +        if (!vram_pointer){
   39.28 +            fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n");
   39.29 +        } else {
   39.30 +            old_vram = vga_update_vram((VGAState *)s, vram_pointer,
   39.31 +                    VGA_RAM_SIZE);
   39.32 +            qemu_free(old_vram);
   39.33 +            s->map_addr = s->cirrus_lfb_addr;
   39.34 +            s->map_end = s->cirrus_lfb_end;
   39.35 +        }
   39.36 +    }
   39.37 +}
   39.38 +
   39.39  /* load/save state */
   39.40  
   39.41  static void cirrus_vga_save(QEMUFile *f, void *opaque)
   39.42  {
   39.43      CirrusVGAState *s = opaque;
   39.44 +    uint8_t vga_acc;
   39.45  
   39.46      qemu_put_be32s(f, &s->latch);
   39.47      qemu_put_8s(f, &s->sr_index);
   39.48 @@ -3049,11 +3082,20 @@ static void cirrus_vga_save(QEMUFile *f,
   39.49      qemu_put_be32s(f, &s->hw_cursor_y);
   39.50      /* XXX: we do not save the bitblt state - we assume we do not save
   39.51         the state when the blitter is active */
   39.52 +
   39.53 +    vga_acc = (!!s->map_addr);
   39.54 +    qemu_put_8s(f, &vga_acc);
   39.55 +    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
   39.56 +    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
   39.57 +    qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
   39.58 +    if (vga_acc)
   39.59 +        cirrus_stop_acc(s);
   39.60  }
   39.61  
   39.62  static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
   39.63  {
   39.64      CirrusVGAState *s = opaque;
   39.65 +    uint8_t vga_acc = 0;
   39.66  
   39.67      if (version_id != 1)
   39.68          return -EINVAL;
   39.69 @@ -3092,6 +3134,14 @@ static int cirrus_vga_load(QEMUFile *f, 
   39.70      qemu_get_be32s(f, &s->hw_cursor_x);
   39.71      qemu_get_be32s(f, &s->hw_cursor_y);
   39.72  
   39.73 +    qemu_get_8s(f, &vga_acc);
   39.74 +    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
   39.75 +    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
   39.76 +    qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
   39.77 +    if (vga_acc){
   39.78 +        cirrus_restart_acc(s);
   39.79 +    }
   39.80 +
   39.81      /* force refresh */
   39.82      s->graphic_mode = -1;
   39.83      cirrus_update_bank_ptr(s, 0);
   39.84 @@ -3297,6 +3347,8 @@ void pci_cirrus_vga_init(PCIBus *bus, Di
   39.85                      ds, vga_ram_base, vga_ram_offset, vga_ram_size);
   39.86      cirrus_init_common(s, device_id, 1);
   39.87  
   39.88 +    register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d);
   39.89 +
   39.90      /* setup memory space */
   39.91      /* memory #0 LFB */
   39.92      /* memory #1 memory-mapped I/O */
    40.1 --- a/tools/ioemu/hw/ide.c	Thu Jan 18 15:18:07 2007 +0000
    40.2 +++ b/tools/ioemu/hw/ide.c	Fri Jan 19 14:48:57 2007 +0000
    40.3 @@ -2512,6 +2512,9 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
    40.4                pic_set_irq_new, isa_pic, 15);
    40.5      ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
    40.6      ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
    40.7 +
    40.8 +    register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
    40.9 +
   40.10  #ifdef DMA_MULTI_THREAD    
   40.11      dma_create_thread();
   40.12  #endif //DMA_MULTI_THREAD    
    41.1 --- a/tools/ioemu/hw/pci.c	Thu Jan 18 15:18:07 2007 +0000
    41.2 +++ b/tools/ioemu/hw/pci.c	Fri Jan 19 14:48:57 2007 +0000
    41.3 @@ -40,6 +40,8 @@ target_phys_addr_t pci_mem_base;
    41.4  static int pci_irq_index;
    41.5  static PCIBus *first_bus;
    41.6  
    41.7 +static void pci_update_mappings(PCIDevice *d);
    41.8 +
    41.9  PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
   41.10  {
   41.11      PCIBus *bus;
   41.12 @@ -71,6 +73,7 @@ int generic_pci_load(QEMUFile* f, void *
   41.13          return -EINVAL;
   41.14  
   41.15      qemu_get_buffer(f, s->config, 256);
   41.16 +    pci_update_mappings(s);
   41.17      return 0;
   41.18  }
   41.19  
    42.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Thu Jan 18 15:18:07 2007 +0000
    42.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Fri Jan 19 14:48:57 2007 +0000
    42.3 @@ -546,6 +546,7 @@ int main_loop(void)
    42.4  {
    42.5      extern int vm_running;
    42.6      extern int shutdown_requested;
    42.7 +    extern int suspend_requested;
    42.8      CPUState *env = cpu_single_env;
    42.9      int evtchn_fd = xc_evtchn_fd(xce_handle);
   42.10  
   42.11 @@ -563,12 +564,24 @@ int main_loop(void)
   42.12                  qemu_system_reset();
   42.13                  reset_requested = 0;
   42.14              }
   42.15 +            if (suspend_requested) {
   42.16 +                fprintf(logfile, "device model received suspend signal!\n");
   42.17 +                break;
   42.18 +            }
   42.19          }
   42.20  
   42.21          /* Wait up to 10 msec. */
   42.22          main_loop_wait(10);
   42.23      }
   42.24 -    destroy_hvm_domain();
   42.25 +    if (!suspend_requested)
   42.26 +        destroy_hvm_domain();
   42.27 +    else {
   42.28 +        char qemu_file[20];
   42.29 +        sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
   42.30 +        if (qemu_savevm(qemu_file) < 0)
   42.31 +            fprintf(stderr, "qemu save fail.\n");
   42.32 +    }
   42.33 +
   42.34      return 0;
   42.35  }
   42.36  
    43.1 --- a/tools/ioemu/vl.c	Thu Jan 18 15:18:07 2007 +0000
    43.2 +++ b/tools/ioemu/vl.c	Fri Jan 19 14:48:57 2007 +0000
    43.3 @@ -4441,6 +4441,11 @@ int qemu_loadvm(const char *filename)
    43.4          qemu_fseek(f, cur_pos + record_len, SEEK_SET);
    43.5      }
    43.6      fclose(f);
    43.7 +
    43.8 +    /* del tmp file */
    43.9 +    if (unlink(filename) == -1)
   43.10 +        fprintf(stderr, "delete tmp qemu state file failed.\n");
   43.11 +
   43.12      ret = 0;
   43.13   the_end:
   43.14      if (saved_vm_running)
   43.15 @@ -5027,6 +5032,7 @@ typedef struct QEMUResetEntry {
   43.16  static QEMUResetEntry *first_reset_entry;
   43.17  int reset_requested;
   43.18  int shutdown_requested;
   43.19 +int suspend_requested;
   43.20  static int powerdown_requested;
   43.21  
   43.22  void qemu_register_reset(QEMUResetHandler *func, void *opaque)
   43.23 @@ -5808,6 +5814,14 @@ int set_mm_mapping(int xc_handle, uint32
   43.24      return 0;
   43.25  }
   43.26  
   43.27 +void suspend(int sig)
   43.28 +{
   43.29 +   fprintf(logfile, "suspend sig handler called with requested=%d!\n", suspend_requested);
   43.30 +    if (sig != SIGUSR1)
   43.31 +        fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig);
   43.32 +    suspend_requested = 1;
   43.33 +}
   43.34 +
   43.35  #if defined(__i386__) || defined(__x86_64__)
   43.36  static struct map_cache *mapcache_entry;
   43.37  static unsigned long nr_buckets;
   43.38 @@ -6464,10 +6478,6 @@ int main(int argc, char **argv)
   43.39      }
   43.40  
   43.41  #if defined (__ia64__)
   43.42 -    /* ram_size passed from xend has added on GFW memory,
   43.43 -       so we must subtract it here */
   43.44 -    ram_size -= 16 * MEM_M;
   43.45 -
   43.46      if (ram_size > MMIO_START)
   43.47          ram_size += 1 * MEM_G; /* skip 3G-4G MMIO, LEGACY_IO_SPACE etc. */
   43.48  #endif
   43.49 @@ -6718,6 +6728,26 @@ int main(int argc, char **argv)
   43.50              vm_start();
   43.51          }
   43.52      }
   43.53 +
   43.54 +    /* register signal for the suspend request when save */
   43.55 +    {
   43.56 +        struct sigaction act;
   43.57 +        sigset_t set;
   43.58 +        act.sa_handler = suspend;
   43.59 +        act.sa_flags = SA_RESTART;
   43.60 +        sigemptyset(&act.sa_mask);
   43.61 +
   43.62 +        sigaction(SIGUSR1, &act, NULL);
   43.63 +
   43.64 +        /* control panel mask some signals when spawn qemu, need unmask here*/
   43.65 +        sigemptyset(&set);
   43.66 +        sigaddset(&set, SIGUSR1);
   43.67 +        sigaddset(&set, SIGTERM);
   43.68 +        if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
   43.69 +            fprintf(stderr, "unblock signal fail, possible issue for HVM save!\n");
   43.70 +
   43.71 +    }
   43.72 +
   43.73      main_loop();
   43.74      quit_timers();
   43.75      return 0;
    44.1 --- a/tools/libxc/Makefile	Thu Jan 18 15:18:07 2007 +0000
    44.2 +++ b/tools/libxc/Makefile	Fri Jan 19 14:48:57 2007 +0000
    44.3 @@ -27,7 +27,7 @@ GUEST_SRCS-y += xg_private.c
    44.4  GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c
    44.5  GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c
    44.6  GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
    44.7 -GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
    44.8 +GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
    44.9  
   44.10  -include $(XEN_TARGET_ARCH)/Makefile
   44.11  
    45.1 --- a/tools/libxc/ia64/xc_ia64_hvm_build.c	Thu Jan 18 15:18:07 2007 +0000
    45.2 +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c	Fri Jan 19 14:48:57 2007 +0000
    45.3 @@ -569,18 +569,13 @@ setup_guest(int xc_handle, uint32_t dom,
    45.4      xen_pfn_t *pfn_list;
    45.5      shared_iopage_t *sp;
    45.6      void *ioreq_buffer_page;
    45.7 -    // memsize equal to normal memory size(in configure file) + 16M
    45.8 -    // dom_memsize will pass to xc_ia64_build_hob(), so must be subbed 16M 
    45.9 -    unsigned long dom_memsize = ((memsize - 16) << 20);
   45.10 -    unsigned long nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
   45.11 -    unsigned long normal_pages = nr_pages - GFW_PAGES;
   45.12 +    unsigned long dom_memsize = memsize << 20;
   45.13 +    unsigned long nr_pages = memsize << (20 - PAGE_SHIFT);
   45.14      unsigned long vcpus;
   45.15      int rc;
   45.16 -    long i, j;
   45.17 +    long i;
   45.18      DECLARE_DOMCTL;
   45.19  
   45.20 -    // ROM size for guest firmware, ioreq page and xenstore page
   45.21 -    nr_pages += 3; 
   45.22  
   45.23      if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
   45.24          PERROR("Guest firmware size is incorrect [%ld]?", image_size);
   45.25 @@ -598,20 +593,20 @@ setup_guest(int xc_handle, uint32_t dom,
   45.26          pfn_list[i] = i;
   45.27  
   45.28      // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others.
   45.29 -    for (j = (MMIO_START >> PAGE_SHIFT); j < (dom_memsize >> PAGE_SHIFT); j++)
   45.30 -        pfn_list[j] += ((1 * MEM_G) >> PAGE_SHIFT);
   45.31 +    for (i = (MMIO_START >> PAGE_SHIFT); i < (dom_memsize >> PAGE_SHIFT); i++)
   45.32 +        pfn_list[i] += ((1 * MEM_G) >> PAGE_SHIFT);
   45.33  
   45.34      // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000. 
   45.35      rc = xc_domain_memory_populate_physmap(xc_handle, dom,
   45.36 -                                           (normal_pages > VGA_START_PAGE) ?
   45.37 -                                           VGA_START_PAGE : normal_pages,
   45.38 +                                           (nr_pages > VGA_START_PAGE) ?
   45.39 +                                           VGA_START_PAGE : nr_pages,
   45.40                                             0, 0, &pfn_list[0]);
   45.41  
   45.42      // We're not likely to attempt to create a domain with less than
   45.43      // 640k of memory, but test for completeness
   45.44      if (rc == 0 && nr_pages > VGA_END_PAGE)
   45.45          rc = xc_domain_memory_populate_physmap(xc_handle, dom,
   45.46 -                                               normal_pages - VGA_END_PAGE,
   45.47 +                                               nr_pages - VGA_END_PAGE,
   45.48                                                 0, 0, &pfn_list[VGA_END_PAGE]);
   45.49      if (rc != 0) {
   45.50          PERROR("Could not allocate normal memory for Vti guest.\n");
   45.51 @@ -621,24 +616,22 @@ setup_guest(int xc_handle, uint32_t dom,
   45.52      // We allocate additional pfn for GFW and other three pages, so
   45.53      // the pfn_list is not contiguous.  Due to this we must support
   45.54      // old interface xc_ia64_get_pfn_list().
   45.55 -    // Here i = (dom_memsize >> PAGE_SHIFT)
   45.56 -    for (j = 0; i < nr_pages - 3; i++, j++) 
   45.57 -        pfn_list[i] = (GFW_START >> PAGE_SHIFT) + j;
   45.58 +    for (i = 0; i < GFW_PAGES; i++) 
   45.59 +        pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i;
   45.60  
   45.61      rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES,
   45.62 -                                           0, 0, &pfn_list[normal_pages]);
   45.63 +                                           0, 0, &pfn_list[0]);
   45.64      if (rc != 0) {
   45.65          PERROR("Could not allocate GFW memory for Vti guest.\n");
   45.66          goto error_out;
   45.67      }
   45.68  
   45.69 -    // Here i = (dom_memsize >> PAGE_SHIFT) + GFW_PAGES
   45.70 -    pfn_list[i] = IO_PAGE_START >> PAGE_SHIFT;
   45.71 -    pfn_list[i+1] = STORE_PAGE_START >> PAGE_SHIFT;
   45.72 -    pfn_list[i+2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT; 
   45.73 +    pfn_list[0] = IO_PAGE_START >> PAGE_SHIFT;
   45.74 +    pfn_list[1] = STORE_PAGE_START >> PAGE_SHIFT;
   45.75 +    pfn_list[2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT; 
   45.76  
   45.77      rc = xc_domain_memory_populate_physmap(xc_handle, dom, 3,
   45.78 -                                           0, 0, &pfn_list[nr_pages - 3]);
   45.79 +                                           0, 0, &pfn_list[0]);
   45.80      if (rc != 0) {
   45.81          PERROR("Could not allocate IO page or store page or buffer io page.\n");
   45.82          goto error_out;
   45.83 @@ -675,13 +668,12 @@ setup_guest(int xc_handle, uint32_t dom,
   45.84          goto error_out;
   45.85      }
   45.86  
   45.87 -    xc_set_hvm_param(xc_handle, dom,
   45.88 -                     HVM_PARAM_STORE_PFN, pfn_list[nr_pages - 2]);
   45.89 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, pfn_list[1]);
   45.90  
   45.91      // Retrieve special pages like io, xenstore, etc. 
   45.92      sp = (shared_iopage_t *)xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
   45.93                                                   PROT_READ | PROT_WRITE,
   45.94 -                                                 pfn_list[nr_pages - 3]);
   45.95 +                                                 pfn_list[0]);
   45.96      if (sp == 0)
   45.97          goto error_out;
   45.98  
   45.99 @@ -689,7 +681,7 @@ setup_guest(int xc_handle, uint32_t dom,
  45.100      munmap(sp, PAGE_SIZE);
  45.101      ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  45.102                                               PROT_READ | PROT_WRITE,
  45.103 -                                             pfn_list[nr_pages - 1]); 
  45.104 +                                             pfn_list[2]); 
  45.105      memset(ioreq_buffer_page,0,PAGE_SIZE);
  45.106      munmap(ioreq_buffer_page, PAGE_SIZE);
  45.107      free(pfn_list);
    46.1 --- a/tools/libxc/xc_domain.c	Thu Jan 18 15:18:07 2007 +0000
    46.2 +++ b/tools/libxc/xc_domain.c	Fri Jan 19 14:48:57 2007 +0000
    46.3 @@ -235,6 +235,50 @@ int xc_domain_getinfolist(int xc_handle,
    46.4      return ret;
    46.5  }
    46.6  
    46.7 +/* get info from hvm guest for save */
    46.8 +int xc_domain_hvm_getcontext(int xc_handle,
    46.9 +                             uint32_t domid,
   46.10 +                             hvm_domain_context_t *hvm_ctxt)
   46.11 +{
   46.12 +    int rc;
   46.13 +    DECLARE_DOMCTL;
   46.14 +
   46.15 +    domctl.cmd = XEN_DOMCTL_gethvmcontext;
   46.16 +    domctl.domain = (domid_t)domid;
   46.17 +    set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
   46.18 +
   46.19 +    if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
   46.20 +        return rc;
   46.21 +
   46.22 +    rc = do_domctl(xc_handle, &domctl);
   46.23 +
   46.24 +    safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
   46.25 +
   46.26 +    return rc;
   46.27 +}
   46.28 +
   46.29 +/* set info to hvm guest for restore */
   46.30 +int xc_domain_hvm_setcontext(int xc_handle,
   46.31 +                             uint32_t domid,
   46.32 +                             hvm_domain_context_t *hvm_ctxt)
   46.33 +{
   46.34 +    int rc;
   46.35 +    DECLARE_DOMCTL;
   46.36 +
   46.37 +    domctl.cmd = XEN_DOMCTL_sethvmcontext;
   46.38 +    domctl.domain = domid;
   46.39 +    set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
   46.40 +
   46.41 +    if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
   46.42 +        return rc;
   46.43 +
   46.44 +    rc = do_domctl(xc_handle, &domctl);
   46.45 +
   46.46 +    safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
   46.47 +
   46.48 +    return rc;
   46.49 +}
   46.50 +
   46.51  int xc_vcpu_getcontext(int xc_handle,
   46.52                                 uint32_t domid,
   46.53                                 uint32_t vcpu,
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/libxc/xc_hvm_restore.c	Fri Jan 19 14:48:57 2007 +0000
    47.3 @@ -0,0 +1,360 @@
    47.4 +/******************************************************************************
    47.5 + * xc_hvm_restore.c
    47.6 + *
    47.7 + * Restore the state of a HVM guest.
    47.8 + *
    47.9 + * Copyright (c) 2003, K A Fraser.
   47.10 + * Copyright (c) 2006 Intel Corperation
   47.11 + * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
   47.12 + *
   47.13 + * This program is free software; you can redistribute it and/or modify it
   47.14 + * under the terms and conditions of the GNU General Public License,
   47.15 + * version 2, as published by the Free Software Foundation.
   47.16 + *
   47.17 + * This program is distributed in the hope it will be useful, but WITHOUT
   47.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   47.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   47.20 + * more details.
   47.21 + *
   47.22 + * You should have received a copy of the GNU General Public License along with
   47.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   47.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   47.25 + *
   47.26 + */
   47.27 +
   47.28 +#include <stdlib.h>
   47.29 +#include <unistd.h>
   47.30 +
   47.31 +#include "xg_private.h"
   47.32 +#include "xg_save_restore.h"
   47.33 +
   47.34 +#include <xen/hvm/ioreq.h>
   47.35 +#include <xen/hvm/params.h>
   47.36 +#include <xen/hvm/e820.h>
   47.37 +
   47.38 +/* max mfn of the whole machine */
   47.39 +static unsigned long max_mfn;
   47.40 +
   47.41 +/* virtual starting address of the hypervisor */
   47.42 +static unsigned long hvirt_start;
   47.43 +
   47.44 +/* #levels of page tables used by the currrent guest */
   47.45 +static unsigned int pt_levels;
   47.46 +
   47.47 +/* total number of pages used by the current guest */
   47.48 +static unsigned long max_pfn;
   47.49 +
   47.50 +/* A table mapping each PFN to its new MFN. */
   47.51 +static xen_pfn_t *p2m = NULL;
   47.52 +
   47.53 +static ssize_t
   47.54 +read_exact(int fd, void *buf, size_t count)
   47.55 +{
   47.56 +    int r = 0, s;
   47.57 +    unsigned char *b = buf;
   47.58 +
   47.59 +    while (r < count) {
   47.60 +        s = read(fd, &b[r], count - r);
   47.61 +        if ((s == -1) && (errno == EINTR))
   47.62 +            continue;
   47.63 +        if (s <= 0) {
   47.64 +            break;
   47.65 +        }
   47.66 +        r += s;
   47.67 +    }
   47.68 +
   47.69 +    return (r == count) ? 1 : 0;
   47.70 +}
   47.71 +
   47.72 +int xc_hvm_restore(int xc_handle, int io_fd,
   47.73 +                     uint32_t dom, unsigned long nr_pfns,
   47.74 +                     unsigned int store_evtchn, unsigned long *store_mfn,
   47.75 +                     unsigned int console_evtchn, unsigned long *console_mfn,
   47.76 +                     unsigned int pae, unsigned int apic)
   47.77 +{
   47.78 +    DECLARE_DOMCTL;
   47.79 +
   47.80 +    /* The new domain's shared-info frame number. */
   47.81 +    unsigned long shared_info_frame;
   47.82 +
   47.83 +    /* A copy of the CPU context of the guest. */
   47.84 +    vcpu_guest_context_t ctxt;
   47.85 +
   47.86 +    char *region_base;
   47.87 +
   47.88 +    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
   47.89 +
   47.90 +    xc_dominfo_t info;
   47.91 +    unsigned int rc = 1, n, i;
   47.92 +    uint32_t rec_len, nr_vcpus;
   47.93 +    hvm_domain_context_t hvm_ctxt;
   47.94 +    unsigned long long v_end, memsize;
   47.95 +    unsigned long shared_page_nr;
   47.96 +
   47.97 +    unsigned long mfn, pfn;
   47.98 +    unsigned int prev_pc, this_pc;
   47.99 +    int verify = 0;
  47.100 +
  47.101 +    /* Types of the pfns in the current region */
  47.102 +    unsigned long region_pfn_type[MAX_BATCH_SIZE];
  47.103 +
  47.104 +    /* hvm guest mem size (Mb) */
  47.105 +    memsize = (unsigned long long)*store_mfn;
  47.106 +    v_end = memsize << 20;
  47.107 +
  47.108 +    DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, console_evtchn=%d, *console_mfn=%ld, pae=%u, apic=%u.\n", 
  47.109 +            dom, nr_pfns, store_evtchn, *store_mfn, console_evtchn, *console_mfn, pae, apic);
  47.110 +
  47.111 +    max_pfn = nr_pfns;
  47.112 +
  47.113 +    if(!get_platform_info(xc_handle, dom,
  47.114 +                          &max_mfn, &hvirt_start, &pt_levels)) {
  47.115 +        ERROR("Unable to get platform info.");
  47.116 +        return 1;
  47.117 +    }
  47.118 +
  47.119 +    DPRINTF("xc_hvm_restore start: max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n",
  47.120 +            max_pfn,
  47.121 +            max_mfn,
  47.122 +            hvirt_start,
  47.123 +            pt_levels);
  47.124 +
  47.125 +    if (mlock(&ctxt, sizeof(ctxt))) {
  47.126 +        /* needed for build dom0 op, but might as well do early */
  47.127 +        ERROR("Unable to mlock ctxt");
  47.128 +        return 1;
  47.129 +    }
  47.130 +
  47.131 +
  47.132 +    p2m        = malloc(max_pfn * sizeof(xen_pfn_t));
  47.133 +
  47.134 +    if (p2m == NULL) {
  47.135 +        ERROR("memory alloc failed");
  47.136 +        errno = ENOMEM;
  47.137 +        goto out;
  47.138 +    }
  47.139 +
  47.140 +    /* Get the domain's shared-info frame. */
  47.141 +    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  47.142 +    domctl.domain = (domid_t)dom;
  47.143 +    if (xc_domctl(xc_handle, &domctl) < 0) {
  47.144 +        ERROR("Could not get information on new domain");
  47.145 +        goto out;
  47.146 +    }
  47.147 +    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
  47.148 +
  47.149 +    if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
  47.150 +        errno = ENOMEM;
  47.151 +        goto out;
  47.152 +    }
  47.153 +
  47.154 +    for ( i = 0; i < max_pfn; i++ )
  47.155 +        p2m[i] = i;
  47.156 +    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
  47.157 +        p2m[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
  47.158 +
  47.159 +    /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
  47.160 +    rc = xc_domain_memory_populate_physmap(
  47.161 +        xc_handle, dom, (max_pfn > 0xa0) ? 0xa0 : max_pfn,
  47.162 +        0, 0, &p2m[0x00]);
  47.163 +    if ( (rc == 0) && (max_pfn > 0xc0) )
  47.164 +        rc = xc_domain_memory_populate_physmap(
  47.165 +            xc_handle, dom, max_pfn - 0xc0, 0, 0, &p2m[0xc0]);
  47.166 +    if ( rc != 0 )
  47.167 +    {
  47.168 +        PERROR("Could not allocate memory for HVM guest.\n");
  47.169 +        goto out;
  47.170 +    }
  47.171 +
  47.172 +
  47.173 +    /**********XXXXXXXXXXXXXXXX******************/
  47.174 +    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
  47.175 +        ERROR("Could not get domain info");
  47.176 +        return 1;
  47.177 +    }
  47.178 +
  47.179 +    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  47.180 +    domctl.domain = (domid_t)dom;
  47.181 +    if (xc_domctl(xc_handle, &domctl) < 0) {
  47.182 +        ERROR("Could not get information on new domain");
  47.183 +        goto out;
  47.184 +    }
  47.185 +
  47.186 +    for ( i = 0; i < max_pfn; i++)
  47.187 +        p2m[i] = i;
  47.188 +
  47.189 +    prev_pc = 0;
  47.190 +
  47.191 +    n = 0;
  47.192 +    while (1) {
  47.193 +
  47.194 +        int j;
  47.195 +
  47.196 +        this_pc = (n * 100) / max_pfn;
  47.197 +        if ( (this_pc - prev_pc) >= 5 )
  47.198 +        {
  47.199 +            PPRINTF("\b\b\b\b%3d%%", this_pc);
  47.200 +            prev_pc = this_pc;
  47.201 +        }
  47.202 +
  47.203 +        if (!read_exact(io_fd, &j, sizeof(int))) {
  47.204 +            ERROR("HVM restore Error when reading batch size");
  47.205 +            goto out;
  47.206 +        }
  47.207 +
  47.208 +        PPRINTF("batch %d\n",j);
  47.209 +
  47.210 +        if (j == -1) {
  47.211 +            verify = 1;
  47.212 +            DPRINTF("Entering page verify mode\n");
  47.213 +            continue;
  47.214 +        }
  47.215 +
  47.216 +        if (j == 0)
  47.217 +            break;  /* our work here is done */
  47.218 +
  47.219 +        if (j > MAX_BATCH_SIZE) {
  47.220 +            ERROR("Max batch size exceeded. Giving up.");
  47.221 +            goto out;
  47.222 +        }
  47.223 +
  47.224 +        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
  47.225 +            ERROR("Error when reading region pfn types");
  47.226 +            goto out;
  47.227 +        }
  47.228 +
  47.229 +        region_base = xc_map_foreign_batch(
  47.230 +            xc_handle, dom, PROT_WRITE, region_pfn_type, j);
  47.231 +
  47.232 +        for ( i = 0; i < j; i++ )
  47.233 +        {
  47.234 +            void *page;
  47.235 +
  47.236 +            pfn = region_pfn_type[i];
  47.237 +            if ( pfn > max_pfn )
  47.238 +            {
  47.239 +                ERROR("pfn out of range");
  47.240 +                goto out;
  47.241 +            }
  47.242 +
  47.243 +            if ( pfn >= 0xa0 && pfn < 0xc0) {
  47.244 +                ERROR("hvm restore:pfn in vga hole");
  47.245 +                goto out;
  47.246 +            }
  47.247 +
  47.248 +
  47.249 +            mfn = p2m[pfn];
  47.250 +
  47.251 +            /* In verify mode, we use a copy; otherwise we work in place */
  47.252 +            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
  47.253 +
  47.254 +            if (!read_exact(io_fd, page, PAGE_SIZE)) {
  47.255 +                ERROR("Error when reading page (%x)", i);
  47.256 +                goto out;
  47.257 +            }
  47.258 +
  47.259 +            if (verify) {
  47.260 +
  47.261 +                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
  47.262 +
  47.263 +                if (res) {
  47.264 +
  47.265 +                    int v;
  47.266 +
  47.267 +                    DPRINTF("************** pfn=%lx mfn=%lx gotcs=%08lx "
  47.268 +                            "actualcs=%08lx\n", pfn, p2m[pfn],
  47.269 +                            csum_page(region_base + i*PAGE_SIZE),
  47.270 +                            csum_page(buf));
  47.271 +
  47.272 +                    for (v = 0; v < 4; v++) {
  47.273 +
  47.274 +                        unsigned long *p = (unsigned long *)
  47.275 +                            (region_base + i*PAGE_SIZE);
  47.276 +                        if (buf[v] != p[v])
  47.277 +                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
  47.278 +                    }
  47.279 +                }
  47.280 +            }
  47.281 +
  47.282 +        } /* end of 'batch' for loop */
  47.283 +        munmap(region_base, j*PAGE_SIZE);
  47.284 +        n+= j; /* crude stats */
  47.285 +
  47.286 +    }/*while 1*/
  47.287 +    
  47.288 +/*    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_APIC_ENABLED, apic);*/
  47.289 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
  47.290 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
  47.291 +
  47.292 +    if ( v_end > HVM_BELOW_4G_RAM_END )
  47.293 +        shared_page_nr = (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - 1;
  47.294 +    else
  47.295 +        shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
  47.296 +
  47.297 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1);
  47.298 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2);
  47.299 +    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr);
  47.300 +
  47.301 +    /* caculate the store_mfn , wrong val cause hang when introduceDomain */
  47.302 +    *store_mfn = (v_end >> PAGE_SHIFT) - 2;
  47.303 +    DPRINTF("hvm restore:calculate new store_mfn=0x%lx,v_end=0x%llx..\n", *store_mfn, v_end);
  47.304 +
  47.305 +    /* restore hvm context including pic/pit/shpage */
  47.306 +    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
  47.307 +        ERROR("error read hvm context size!\n");
  47.308 +        goto out;
  47.309 +    }
  47.310 +    if (rec_len != sizeof(hvm_ctxt)) {
  47.311 +        ERROR("hvm context size dismatch!\n");
  47.312 +        goto out;
  47.313 +    }
  47.314 +
  47.315 +    if (!read_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt))) {
  47.316 +        ERROR("error read hvm context!\n");
  47.317 +        goto out;
  47.318 +    }
  47.319 +
  47.320 +    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, &hvm_ctxt))) {
  47.321 +        ERROR("error set hvm context!\n");
  47.322 +        goto out;
  47.323 +    }
  47.324 +
  47.325 +    if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  47.326 +        ERROR("error read nr vcpu !\n");
  47.327 +        goto out;
  47.328 +    }
  47.329 +    DPRINTF("hvm restore:get nr_vcpus=%d.\n", nr_vcpus);
  47.330 +
  47.331 +    for (i =0; i < nr_vcpus; i++) {
  47.332 +        if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
  47.333 +            ERROR("error read vcpu context size!\n");
  47.334 +            goto out;
  47.335 +        }
  47.336 +        if (rec_len != sizeof(ctxt)) {
  47.337 +            ERROR("vcpu context size dismatch!\n");
  47.338 +            goto out;
  47.339 +        }
  47.340 +
  47.341 +        if (!read_exact(io_fd, &(ctxt), sizeof(ctxt))) {
  47.342 +            ERROR("error read vcpu context.\n");
  47.343 +            goto out;
  47.344 +        }
  47.345 +
  47.346 +        if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) {
  47.347 +            ERROR("Could not set vcpu context, rc=%d", rc);
  47.348 +            goto out;
  47.349 +        }
  47.350 +    }
  47.351 +
  47.352 +    rc = 0;
  47.353 +    goto out;
  47.354 +
  47.355 + out:
  47.356 +    if ( (rc != 0) && (dom != 0) )
  47.357 +        xc_domain_destroy(xc_handle, dom);
  47.358 +    free(p2m);
  47.359 +
  47.360 +    DPRINTF("Restore exit with rc=%d\n", rc);
  47.361 +
  47.362 +    return rc;
  47.363 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/tools/libxc/xc_hvm_save.c	Fri Jan 19 14:48:57 2007 +0000
    48.3 @@ -0,0 +1,727 @@
    48.4 +/******************************************************************************
    48.5 + * xc_hvm_save.c
    48.6 + *
    48.7 + * Save the state of a running HVM guest.
    48.8 + *
    48.9 + * Copyright (c) 2003, K A Fraser.
   48.10 + * Copyright (c) 2006 Intel Corperation
   48.11 + * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
   48.12 + *
   48.13 + * This program is free software; you can redistribute it and/or modify it
   48.14 + * under the terms and conditions of the GNU General Public License,
   48.15 + * version 2, as published by the Free Software Foundation.
   48.16 + *
   48.17 + * This program is distributed in the hope it will be useful, but WITHOUT
   48.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   48.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   48.20 + * more details.
   48.21 + *
   48.22 + * You should have received a copy of the GNU General Public License along with
   48.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   48.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   48.25 + *
   48.26 + */
   48.27 +
   48.28 +#include <inttypes.h>
   48.29 +#include <time.h>
   48.30 +#include <stdlib.h>
   48.31 +#include <unistd.h>
   48.32 +#include <sys/time.h>
   48.33 +
   48.34 +#include "xc_private.h"
   48.35 +#include "xg_private.h"
   48.36 +#include "xg_save_restore.h"
   48.37 +
   48.38 +/*
   48.39 +** Default values for important tuning parameters. Can override by passing
   48.40 +** non-zero replacement values to xc_hvm_save().
   48.41 +**
   48.42 +** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too.
   48.43 +**
   48.44 +*/
   48.45 +#define DEF_MAX_ITERS   29   /* limit us to 30 times round loop   */
   48.46 +#define DEF_MAX_FACTOR   3   /* never send more than 3x nr_pfns   */
   48.47 +
   48.48 +/* max mfn of the whole machine */
   48.49 +static unsigned long max_mfn;
   48.50 +
   48.51 +/* virtual starting address of the hypervisor */
   48.52 +static unsigned long hvirt_start;
   48.53 +
   48.54 +/* #levels of page tables used by the currrent guest */
   48.55 +static unsigned int pt_levels;
   48.56 +
   48.57 +/* total number of pages used by the current guest */
   48.58 +static unsigned long max_pfn;
   48.59 +
   48.60 +/*
   48.61 +** During (live) save/migrate, we maintain a number of bitmaps to track
   48.62 +** which pages we have to send, to fixup, and to skip.
   48.63 +*/
   48.64 +
   48.65 +#define BITS_PER_LONG (sizeof(unsigned long) * 8)
   48.66 +#define BITMAP_SIZE   ((max_pfn + BITS_PER_LONG - 1) / 8)
   48.67 +
   48.68 +#define BITMAP_ENTRY(_nr,_bmap) \
   48.69 +   ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
   48.70 +
   48.71 +#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG)
   48.72 +
   48.73 +static inline int test_bit (int nr, volatile void * addr)
   48.74 +{
   48.75 +    return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1;
   48.76 +}
   48.77 +
   48.78 +static inline void clear_bit (int nr, volatile void * addr)
   48.79 +{
   48.80 +    BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr));
   48.81 +}
   48.82 +
   48.83 +static inline int permute( int i, int nr, int order_nr  )
   48.84 +{
   48.85 +    /* Need a simple permutation function so that we scan pages in a
   48.86 +       pseudo random order, enabling us to get a better estimate of
   48.87 +       the domain's page dirtying rate as we go (there are often
   48.88 +       contiguous ranges of pfns that have similar behaviour, and we
   48.89 +       want to mix them up. */
   48.90 +
   48.91 +    /* e.g. nr->oder 15->4 16->4 17->5 */
   48.92 +    /* 512MB domain, 128k pages, order 17 */
   48.93 +
   48.94 +    /*
   48.95 +      QPONMLKJIHGFEDCBA
   48.96 +             QPONMLKJIH
   48.97 +      GFEDCBA
   48.98 +     */
   48.99 +
  48.100 +    /*
  48.101 +      QPONMLKJIHGFEDCBA
  48.102 +                  EDCBA
  48.103 +             QPONM
  48.104 +      LKJIHGF
  48.105 +      */
  48.106 +
  48.107 +    do { i = ((i>>(order_nr-10)) | ( i<<10 ) ) & ((1<<order_nr)-1); }
  48.108 +    while ( i >= nr ); /* this won't ever loop if nr is a power of 2 */
  48.109 +
  48.110 +    return i;
  48.111 +}
  48.112 +
  48.113 +static uint64_t tv_to_us(struct timeval *new)
  48.114 +{
  48.115 +    return (new->tv_sec * 1000000) + new->tv_usec;
  48.116 +}
  48.117 +
  48.118 +static uint64_t llgettimeofday(void)
  48.119 +{
  48.120 +    struct timeval now;
  48.121 +    gettimeofday(&now, NULL);
  48.122 +    return tv_to_us(&now);
  48.123 +}
  48.124 +
  48.125 +static uint64_t tv_delta(struct timeval *new, struct timeval *old)
  48.126 +{
  48.127 +    return ((new->tv_sec - old->tv_sec)*1000000 ) +
  48.128 +        (new->tv_usec - old->tv_usec);
  48.129 +}
  48.130 +
  48.131 +
  48.132 +#define RATE_IS_MAX() (0)
  48.133 +#define ratewrite(_io_fd, _buf, _n) write((_io_fd), (_buf), (_n))
  48.134 +#define initialize_mbit_rate()
  48.135 +
  48.136 +static inline ssize_t write_exact(int fd, void *buf, size_t count)
  48.137 +{
  48.138 +    if(write(fd, buf, count) != count)
  48.139 +        return 0;
  48.140 +    return 1;
  48.141 +}
  48.142 +
  48.143 +static int print_stats(int xc_handle, uint32_t domid, int pages_sent,
  48.144 +                       xc_shadow_op_stats_t *stats, int print)
  48.145 +{
  48.146 +    static struct timeval wall_last;
  48.147 +    static long long      d0_cpu_last;
  48.148 +    static long long      d1_cpu_last;
  48.149 +
  48.150 +    struct timeval        wall_now;
  48.151 +    long long             wall_delta;
  48.152 +    long long             d0_cpu_now, d0_cpu_delta;
  48.153 +    long long             d1_cpu_now, d1_cpu_delta;
  48.154 +
  48.155 +    gettimeofday(&wall_now, NULL);
  48.156 +
  48.157 +    d0_cpu_now = xc_domain_get_cpu_usage(xc_handle, 0, /* FIXME */ 0)/1000;
  48.158 +    d1_cpu_now = xc_domain_get_cpu_usage(xc_handle, domid, /* FIXME */ 0)/1000;
  48.159 +
  48.160 +    if ( (d0_cpu_now == -1) || (d1_cpu_now == -1) )
  48.161 +        DPRINTF("ARRHHH!!\n");
  48.162 +
  48.163 +    wall_delta = tv_delta(&wall_now,&wall_last)/1000;
  48.164 +
  48.165 +    if (wall_delta == 0) wall_delta = 1;
  48.166 +
  48.167 +    d0_cpu_delta = (d0_cpu_now - d0_cpu_last)/1000;
  48.168 +    d1_cpu_delta = (d1_cpu_now - d1_cpu_last)/1000;
  48.169 +
  48.170 +    if (print)
  48.171 +        DPRINTF(
  48.172 +                "delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
  48.173 +                "dirtied %dMb/s %" PRId32 " pages\n",
  48.174 +                wall_delta,
  48.175 +                (int)((d0_cpu_delta*100)/wall_delta),
  48.176 +                (int)((d1_cpu_delta*100)/wall_delta),
  48.177 +                (int)((pages_sent*PAGE_SIZE)/(wall_delta*(1000/8))),
  48.178 +                (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))),
  48.179 +                stats->dirty_count);
  48.180 +
  48.181 +    d0_cpu_last = d0_cpu_now;
  48.182 +    d1_cpu_last = d1_cpu_now;
  48.183 +    wall_last   = wall_now;
  48.184 +
  48.185 +    return 0;
  48.186 +}
  48.187 +
  48.188 +static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn,
  48.189 +                          unsigned long *arr, int runs)
  48.190 +{
  48.191 +    long long start, now;
  48.192 +    xc_shadow_op_stats_t stats;
  48.193 +    int j;
  48.194 +
  48.195 +    start = llgettimeofday();
  48.196 +
  48.197 +    for (j = 0; j < runs; j++) {
  48.198 +        int i;
  48.199 +
  48.200 +        xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
  48.201 +                          arr, max_pfn, NULL, 0, NULL);
  48.202 +        DPRINTF("#Flush\n");
  48.203 +        for ( i = 0; i < 40; i++ ) {
  48.204 +            usleep(50000);
  48.205 +            now = llgettimeofday();
  48.206 +            xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_PEEK,
  48.207 +                              NULL, 0, NULL, 0, &stats);
  48.208 +
  48.209 +            DPRINTF("now= %lld faults= %"PRId32" dirty= %"PRId32"\n",
  48.210 +                    ((now-start)+500)/1000,
  48.211 +                    stats.fault_count, stats.dirty_count);
  48.212 +        }
  48.213 +    }
  48.214 +
  48.215 +    return -1;
  48.216 +}
  48.217 +
  48.218 +static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
  48.219 +                             int dom, xc_dominfo_t *info,
  48.220 +                             vcpu_guest_context_t *ctxt)
  48.221 +{
  48.222 +    int i = 0;
  48.223 +
  48.224 +    if (!(*suspend)(dom)) {
  48.225 +        ERROR("Suspend request failed");
  48.226 +        return -1;
  48.227 +    }
  48.228 +
  48.229 + retry:
  48.230 +
  48.231 +    if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) {
  48.232 +        ERROR("Could not get domain info");
  48.233 +        return -1;
  48.234 +    }
  48.235 +
  48.236 +    if ( xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, ctxt))
  48.237 +        ERROR("Could not get vcpu context");
  48.238 +
  48.239 +
  48.240 +    if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
  48.241 +        return 0; // success
  48.242 +
  48.243 +    if (info->paused) {
  48.244 +        // try unpausing domain, wait, and retest
  48.245 +        xc_domain_unpause( xc_handle, dom );
  48.246 +
  48.247 +        ERROR("Domain was paused. Wait and re-test.");
  48.248 +        usleep(10000);  // 10ms
  48.249 +
  48.250 +        goto retry;
  48.251 +    }
  48.252 +
  48.253 +
  48.254 +    if( ++i < 100 ) {
  48.255 +        ERROR("Retry suspend domain.");
  48.256 +        usleep(10000);  // 10ms
  48.257 +        goto retry;
  48.258 +    }
  48.259 +
  48.260 +    ERROR("Unable to suspend domain.");
  48.261 +
  48.262 +    return -1;
  48.263 +}
  48.264 +
  48.265 +int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
  48.266 +                  uint32_t max_factor, uint32_t flags, int (*suspend)(int))
  48.267 +{
  48.268 +    xc_dominfo_t info;
  48.269 +
  48.270 +    int rc = 1, i, last_iter, iter = 0;
  48.271 +    int live  = (flags & XCFLAGS_LIVE);
  48.272 +    int debug = (flags & XCFLAGS_DEBUG);
  48.273 +    int sent_last_iter, skip_this_iter;
  48.274 +
  48.275 +    /* The new domain's shared-info frame number. */
  48.276 +    unsigned long shared_info_frame;
  48.277 +
  48.278 +    /* A copy of the CPU context of the guest. */
  48.279 +    vcpu_guest_context_t ctxt;
  48.280 +
  48.281 +    /* A table containg the type of each PFN (/not/ MFN!). */
  48.282 +    unsigned long *pfn_type = NULL;
  48.283 +    unsigned long *pfn_batch = NULL;
  48.284 +
  48.285 +    /* A copy of hvm domain context */
  48.286 +    hvm_domain_context_t hvm_ctxt;
  48.287 +
  48.288 +    /* Live mapping of shared info structure */
  48.289 +    shared_info_t *live_shinfo = NULL;
  48.290 +
  48.291 +    /* base of the region in which domain memory is mapped */
  48.292 +    unsigned char *region_base = NULL;
  48.293 +
  48.294 +    uint32_t nr_pfns, rec_size, nr_vcpus;
  48.295 +    unsigned long *page_array = NULL;
  48.296 +
  48.297 +    /* power of 2 order of max_pfn */
  48.298 +    int order_nr;
  48.299 +
  48.300 +    /* bitmap of pages:
  48.301 +       - that should be sent this iteration (unless later marked as skip);
  48.302 +       - to skip this iteration because already dirty; */
  48.303 +    unsigned long *to_send = NULL, *to_skip = NULL;
  48.304 +
  48.305 +    xc_shadow_op_stats_t stats;
  48.306 +
  48.307 +    unsigned long total_sent    = 0;
  48.308 +
  48.309 +    DPRINTF("xc_hvm_save:dom=%d, max_iters=%d, max_factor=%d, flags=0x%x, live=%d, debug=%d.\n",
  48.310 +            dom, max_iters, max_factor, flags,
  48.311 +            live, debug);
  48.312 +
  48.313 +    /* If no explicit control parameters given, use defaults */
  48.314 +    if(!max_iters)
  48.315 +        max_iters = DEF_MAX_ITERS;
  48.316 +    if(!max_factor)
  48.317 +        max_factor = DEF_MAX_FACTOR;
  48.318 +
  48.319 +    initialize_mbit_rate();
  48.320 +
  48.321 +    if(!get_platform_info(xc_handle, dom,
  48.322 +                          &max_mfn, &hvirt_start, &pt_levels)) {
  48.323 +        ERROR("HVM:Unable to get platform info.");
  48.324 +        return 1;
  48.325 +    }
  48.326 +
  48.327 +    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
  48.328 +        ERROR("HVM:Could not get domain info");
  48.329 +        return 1;
  48.330 +    }
  48.331 +    nr_vcpus = info.nr_online_vcpus;
  48.332 +
  48.333 +    if (mlock(&ctxt, sizeof(ctxt))) {
  48.334 +        ERROR("HVM:Unable to mlock ctxt");
  48.335 +        return 1;
  48.336 +    }
  48.337 +
  48.338 +    /* Only have to worry about vcpu 0 even for SMP */
  48.339 +    if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
  48.340 +        ERROR("HVM:Could not get vcpu context");
  48.341 +        goto out;
  48.342 +    }
  48.343 +    shared_info_frame = info.shared_info_frame;
  48.344 +
  48.345 +    /* A cheesy test to see whether the domain contains valid state. */
  48.346 +    if (ctxt.ctrlreg[3] == 0)
  48.347 +    {
  48.348 +        ERROR("Domain is not in a valid HVM guest state");
  48.349 +        goto out;
  48.350 +    }
  48.351 +
  48.352 +   /* cheesy sanity check */
  48.353 +    if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
  48.354 +        ERROR("Invalid HVM state record -- pfn count out of range: %lu",
  48.355 +            (info.max_memkb >> (PAGE_SHIFT - 10)));
  48.356 +        goto out;
  48.357 +    }
  48.358 +
  48.359 +    /* Map the shared info frame */
  48.360 +    if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  48.361 +                                            PROT_READ, shared_info_frame))) {
  48.362 +        ERROR("HVM:Couldn't map live_shinfo");
  48.363 +        goto out;
  48.364 +    }
  48.365 +
  48.366 +    max_pfn = live_shinfo->arch.max_pfn;
  48.367 +
  48.368 +    DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
  48.369 +
  48.370 +    /* nr_pfns: total pages excluding vga acc mem
  48.371 +     * max_pfn: nr_pfns + 0x20 vga hole(0xa0~0xc0)
  48.372 +     * getdomaininfo.tot_pages: all the allocated pages for this domain
  48.373 +     */
  48.374 +    if (live) {
  48.375 +        ERROR("hvm domain doesn't support live migration now.\n");
  48.376 +        goto out;
  48.377 +
  48.378 +        if (xc_shadow_control(xc_handle, dom,
  48.379 +                              XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
  48.380 +                              NULL, 0, NULL, 0, NULL) < 0) {
  48.381 +            ERROR("Couldn't enable shadow mode");
  48.382 +            goto out;
  48.383 +        }
  48.384 +
  48.385 +        /* excludes vga acc mem */
  48.386 +        nr_pfns = info.nr_pages - 0x800;
  48.387 +
  48.388 +        last_iter = 0;
  48.389 +        DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
  48.390 +    } else {
  48.391 +        /* This is a non-live suspend. Issue the call back to get the
  48.392 +           domain suspended */
  48.393 +
  48.394 +        last_iter = 1;
  48.395 +
  48.396 +        /* suspend hvm domain */
  48.397 +        if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt)) {
  48.398 +            ERROR("HVM Domain appears not to have suspended");
  48.399 +            goto out;
  48.400 +        }
  48.401 +        nr_pfns = info.nr_pages;
  48.402 +        DPRINTF("after suspend hvm domain nr_pages=0x%x.\n", nr_pfns);
  48.403 +    }
  48.404 +
  48.405 +    DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n",
  48.406 +            nr_pfns,
  48.407 +            info.nr_pages,
  48.408 +            info.max_memkb,
  48.409 +            live);
  48.410 +
  48.411 +    nr_pfns = info.nr_pages;
  48.412 +
  48.413 +    /*XXX: caculate the VGA hole*/
  48.414 +    max_pfn = nr_pfns + 0x20;
  48.415 +
  48.416 +    skip_this_iter = 0;/*XXX*/
  48.417 +    /* pretend we sent all the pages last iteration */
  48.418 +    sent_last_iter = max_pfn;
  48.419 +
  48.420 +    /* calculate the power of 2 order of max_pfn, e.g.
  48.421 +       15->4 16->4 17->5 */
  48.422 +    for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++)
  48.423 +        continue;
  48.424 +
  48.425 +    /* Setup to_send / to_fix and to_skip bitmaps */
  48.426 +    to_send = malloc(BITMAP_SIZE);
  48.427 +    to_skip = malloc(BITMAP_SIZE);
  48.428 +
  48.429 +    if (!to_send ||!to_skip) {
  48.430 +        ERROR("Couldn't allocate to_send array");
  48.431 +        goto out;
  48.432 +    }
  48.433 +
  48.434 +    memset(to_send, 0xff, BITMAP_SIZE);
  48.435 +
  48.436 +    if (lock_pages(to_send, BITMAP_SIZE)) {
  48.437 +        ERROR("Unable to lock to_send");
  48.438 +        return 1;
  48.439 +    }
  48.440 +
  48.441 +    /* (to fix is local only) */
  48.442 +    if (lock_pages(to_skip, BITMAP_SIZE)) {
  48.443 +        ERROR("Unable to lock to_skip");
  48.444 +        return 1;
  48.445 +    }
  48.446 +
  48.447 +    analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
  48.448 +
  48.449 +    /* get all the HVM domain pfns */
  48.450 +    if ( (page_array = (unsigned long *) malloc (sizeof(unsigned long) * max_pfn)) == NULL) {
  48.451 +        ERROR("HVM:malloc fail!\n");
  48.452 +        goto out;
  48.453 +    }
  48.454 +
  48.455 +    for ( i = 0; i < max_pfn; i++)
  48.456 +        page_array[i] = i;
  48.457 +
  48.458 +
  48.459 +    /* We want zeroed memory so use calloc rather than malloc. */
  48.460 +    pfn_type  = calloc(MAX_BATCH_SIZE, sizeof(*pfn_type));
  48.461 +    pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch));
  48.462 +
  48.463 +    if ((pfn_type == NULL) || (pfn_batch == NULL)) {
  48.464 +        ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays");
  48.465 +        errno = ENOMEM;
  48.466 +        goto out;
  48.467 +    }
  48.468 +
  48.469 +    if (lock_pages(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) {
  48.470 +        ERROR("Unable to lock");
  48.471 +        goto out;
  48.472 +    }
  48.473 +
  48.474 +    /* Start writing out the saved-domain record. */
  48.475 +    if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
  48.476 +        ERROR("write: max_pfn");
  48.477 +        goto out;
  48.478 +    }
  48.479 +
  48.480 +    while(1) {
  48.481 +
  48.482 +        unsigned int prev_pc, sent_this_iter, N, batch;
  48.483 +
  48.484 +        iter++;
  48.485 +        sent_this_iter = 0;
  48.486 +        skip_this_iter = 0;
  48.487 +        prev_pc = 0;
  48.488 +        N=0;
  48.489 +
  48.490 +        DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
  48.491 +
  48.492 +        while( N < max_pfn ){
  48.493 +
  48.494 +            unsigned int this_pc = (N * 100) / max_pfn;
  48.495 +
  48.496 +            if ((this_pc - prev_pc) >= 5) {
  48.497 +                DPRINTF("\b\b\b\b%3d%%", this_pc);
  48.498 +                prev_pc = this_pc;
  48.499 +            }
  48.500 +
  48.501 +            /* slightly wasteful to peek the whole array evey time,
  48.502 +               but this is fast enough for the moment. */
  48.503 +            if (!last_iter && xc_shadow_control(
  48.504 +                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
  48.505 +                    to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
  48.506 +                ERROR("Error peeking HVM shadow bitmap");
  48.507 +                goto out;
  48.508 +            }
  48.509 +
  48.510 +
  48.511 +            /* load pfn_type[] with the mfn of all the pages we're doing in
  48.512 +               this batch. */
  48.513 +            for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
  48.514 +
  48.515 +                int n = permute(N, max_pfn, order_nr);
  48.516 +
  48.517 +                if (debug) {
  48.518 +                    DPRINTF("%d pfn= %08lx mfn= %08lx %d \n",
  48.519 +                            iter, (unsigned long)n, page_array[n],
  48.520 +                            test_bit(n, to_send));
  48.521 +                }
  48.522 +
  48.523 +                if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip))
  48.524 +                    skip_this_iter++; /* stats keeping */
  48.525 +
  48.526 +                if (!((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
  48.527 +                      (test_bit(n, to_send) && last_iter)))
  48.528 +                    continue;
  48.529 +
  48.530 +                if (n >= 0xa0 && n < 0xc0) {
  48.531 +/*                    DPRINTF("get a vga hole pfn= %x.\n", n);*/
  48.532 +                    continue;
  48.533 +                }
  48.534 +                /*
  48.535 +                ** we get here if:
  48.536 +                **  1. page is marked to_send & hasn't already been re-dirtied
  48.537 +                **  2. (ignore to_skip in last iteration)
  48.538 +                */
  48.539 +
  48.540 +                pfn_batch[batch] = n;
  48.541 +                pfn_type[batch]  = page_array[n];
  48.542 +
  48.543 +                batch++;
  48.544 +            }
  48.545 +
  48.546 +            if (batch == 0)
  48.547 +                goto skip; /* vanishingly unlikely... */
  48.548 +
  48.549 +            /* map_foreign use pfns now !*/
  48.550 +            if ((region_base = xc_map_foreign_batch(
  48.551 +                     xc_handle, dom, PROT_READ, pfn_batch, batch)) == 0) {
  48.552 +                ERROR("map batch failed");
  48.553 +                goto out;
  48.554 +            }
  48.555 +
  48.556 +            /* write num of pfns */
  48.557 +            if(!write_exact(io_fd, &batch, sizeof(unsigned int))) {
  48.558 +                ERROR("Error when writing to state file (2)");
  48.559 +                goto out;
  48.560 +            }
  48.561 +
  48.562 +            /* write all the pfns */
  48.563 +            if(!write_exact(io_fd, pfn_batch, sizeof(unsigned long)*batch)) {
  48.564 +                ERROR("Error when writing to state file (3)");
  48.565 +                goto out;
  48.566 +            }
  48.567 +
  48.568 +            if (ratewrite(io_fd, region_base, PAGE_SIZE * batch) != PAGE_SIZE * batch) {
  48.569 +                ERROR("ERROR when writting to state file (4)");
  48.570 +                goto out;
  48.571 +            }
  48.572 +
  48.573 +
  48.574 +            sent_this_iter += batch;
  48.575 +
  48.576 +            munmap(region_base, batch*PAGE_SIZE);
  48.577 +
  48.578 +        } /* end of this while loop for this iteration */
  48.579 +
  48.580 +      skip:
  48.581 +
  48.582 +        total_sent += sent_this_iter;
  48.583 +
  48.584 +        DPRINTF("\r %d: sent %d, skipped %d, ",
  48.585 +                iter, sent_this_iter, skip_this_iter );
  48.586 +
  48.587 +        if (last_iter) {
  48.588 +            print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
  48.589 +
  48.590 +            DPRINTF("Total pages sent= %ld (%.2fx)\n",
  48.591 +                    total_sent, ((float)total_sent)/max_pfn );
  48.592 +        }
  48.593 +
  48.594 +        if (last_iter && debug){
  48.595 +            int minusone = -1;
  48.596 +            memset(to_send, 0xff, BITMAP_SIZE);
  48.597 +            debug = 0;
  48.598 +            DPRINTF("Entering debug resend-all mode\n");
  48.599 +
  48.600 +            /* send "-1" to put receiver into debug mode */
  48.601 +            if(!write_exact(io_fd, &minusone, sizeof(int))) {
  48.602 +                ERROR("Error when writing to state file (6)");
  48.603 +                goto out;
  48.604 +            }
  48.605 +
  48.606 +            continue;
  48.607 +        }
  48.608 +
  48.609 +        if (last_iter) break;
  48.610 +
  48.611 +        if (live) {
  48.612 +
  48.613 +
  48.614 +            if(
  48.615 +                ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
  48.616 +                (iter >= max_iters) ||
  48.617 +                (sent_this_iter+skip_this_iter < 50) ||
  48.618 +                (total_sent > max_pfn*max_factor) ) {
  48.619 +
  48.620 +                DPRINTF("Start last iteration for HVM domain\n");
  48.621 +                last_iter = 1;
  48.622 +
  48.623 +                if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
  48.624 +                                      &ctxt)) {
  48.625 +                    ERROR("Domain appears not to have suspended");
  48.626 +                    goto out;
  48.627 +                }
  48.628 +
  48.629 +                DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
  48.630 +                        info.shared_info_frame,
  48.631 +                        (unsigned long)ctxt.user_regs.eip,
  48.632 +                        (unsigned long)ctxt.user_regs.edx);
  48.633 +            }
  48.634 +
  48.635 +            if (xc_shadow_control(xc_handle, dom, 
  48.636 +                                  XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
  48.637 +                                  max_pfn, NULL, 0, &stats) != max_pfn) {
  48.638 +                ERROR("Error flushing shadow PT");
  48.639 +                goto out;
  48.640 +            }
  48.641 +
  48.642 +            sent_last_iter = sent_this_iter;
  48.643 +
  48.644 +            print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
  48.645 +
  48.646 +        }
  48.647 +
  48.648 +
  48.649 +    } /* end of while 1 */
  48.650 +
  48.651 +
  48.652 +    DPRINTF("All HVM memory is saved\n");
  48.653 +
  48.654 +    /* Zero terminate */
  48.655 +    i = 0;
  48.656 +    if (!write_exact(io_fd, &i, sizeof(int))) {
  48.657 +        ERROR("Error when writing to state file (6)");
  48.658 +        goto out;
  48.659 +    }
  48.660 +
  48.661 +    /* save hvm hypervisor state including pic/pit/shpage */
  48.662 +    if (mlock(&hvm_ctxt, sizeof(hvm_ctxt))) {
  48.663 +        ERROR("Unable to mlock ctxt");
  48.664 +        return 1;
  48.665 +    }
  48.666 +
  48.667 +    if (xc_domain_hvm_getcontext(xc_handle, dom, &hvm_ctxt)){
  48.668 +        ERROR("HVM:Could not get hvm context");
  48.669 +        goto out;
  48.670 +    }
  48.671 +
  48.672 +    rec_size = sizeof(hvm_ctxt);
  48.673 +    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  48.674 +        ERROR("error write hvm ctxt size");
  48.675 +        goto out;
  48.676 +    }
  48.677 +
  48.678 +    if ( !write_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt)) ) {
  48.679 +        ERROR("write HVM info failed!\n");
  48.680 +    }
  48.681 +
  48.682 +    /* save vcpu/vmcs context */
  48.683 +    if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  48.684 +        ERROR("error write nr vcpus");
  48.685 +        goto out;
  48.686 +    }
  48.687 +
  48.688 +    /*XXX: need a online map to exclude down cpu */
  48.689 +    for (i = 0; i < nr_vcpus; i++) {
  48.690 +
  48.691 +        if (xc_vcpu_getcontext(xc_handle, dom, i, &ctxt)) {
  48.692 +            ERROR("HVM:Could not get vcpu context");
  48.693 +            goto out;
  48.694 +        }
  48.695 +
  48.696 +        rec_size = sizeof(ctxt);
  48.697 +        DPRINTF("write %d vcpucontext of total %d.\n", i, nr_vcpus); 
  48.698 +        if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  48.699 +            ERROR("error write vcpu ctxt size");
  48.700 +            goto out;
  48.701 +        }
  48.702 +
  48.703 +        if (!write_exact(io_fd, &(ctxt), sizeof(ctxt)) ) {
  48.704 +            ERROR("write vmcs failed!\n");
  48.705 +            goto out;
  48.706 +        }
  48.707 +    }
  48.708 + 
  48.709 +    /* Success! */
  48.710 +    rc = 0;
  48.711 +
  48.712 + out:
  48.713 +
  48.714 +    if (live) {
  48.715 +        if(xc_shadow_control(xc_handle, dom, 
  48.716 +                             XEN_DOMCTL_SHADOW_OP_OFF,
  48.717 +                             NULL, 0, NULL, 0, NULL) < 0) {
  48.718 +            DPRINTF("Warning - couldn't disable shadow mode");
  48.719 +        }
  48.720 +    }
  48.721 +
  48.722 +    free(page_array);
  48.723 +
  48.724 +    free(pfn_type);
  48.725 +    free(pfn_batch);
  48.726 +    free(to_send);
  48.727 +    free(to_skip);
  48.728 +
  48.729 +    return !!rc;
  48.730 +}
    49.1 --- a/tools/libxc/xenctrl.h	Thu Jan 18 15:18:07 2007 +0000
    49.2 +++ b/tools/libxc/xenctrl.h	Fri Jan 19 14:48:57 2007 +0000
    49.3 @@ -313,6 +313,30 @@ int xc_domain_getinfolist(int xc_handle,
    49.4                            xc_domaininfo_t *info);
    49.5  
    49.6  /**
    49.7 + * This function returns information about the context of a hvm domain
    49.8 + * @parm xc_handle a handle to an open hypervisor interface
    49.9 + * @parm domid the domain to get information from
   49.10 + * @parm hvm_ctxt a pointer to a structure to store the execution context of the
   49.11 + *            hvm domain
   49.12 + * @return 0 on success, -1 on failure
   49.13 + */
   49.14 +int xc_domain_hvm_getcontext(int xc_handle,
   49.15 +                             uint32_t domid,
   49.16 +                             hvm_domain_context_t *hvm_ctxt);
   49.17 +
   49.18 +/**
   49.19 + * This function will set the context for hvm domain
   49.20 + *
   49.21 + * @parm xc_handle a handle to an open hypervisor interface
   49.22 + * @parm domid the domain to set the hvm domain context for
   49.23 + * @parm hvm_ctxt pointer to the the hvm context with the values to set
   49.24 + * @return 0 on success, -1 on failure
   49.25 + */
   49.26 +int xc_domain_hvm_setcontext(int xc_handle,
   49.27 +                             uint32_t domid,
   49.28 +                             hvm_domain_context_t *hvm_ctxt);
   49.29 +
   49.30 +/**
   49.31   * This function returns information about the execution context of a
   49.32   * particular vcpu of a domain.
   49.33   *
    50.1 --- a/tools/libxc/xenguest.h	Thu Jan 18 15:18:07 2007 +0000
    50.2 +++ b/tools/libxc/xenguest.h	Fri Jan 19 14:48:57 2007 +0000
    50.3 @@ -11,6 +11,7 @@
    50.4  
    50.5  #define XCFLAGS_LIVE      1
    50.6  #define XCFLAGS_DEBUG     2
    50.7 +#define XCFLAGS_HVM       4
    50.8  
    50.9  
   50.10  /**
   50.11 @@ -25,6 +26,13 @@ int xc_linux_save(int xc_handle, int io_
   50.12                    uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
   50.13                    int (*suspend)(int domid));
   50.14  
   50.15 +/**
   50.16 + * This function will save a hvm domain running unmodified guest.
   50.17 + * @return 0 on success, -1 on failure
   50.18 + */
   50.19 +int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
   50.20 +                  uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
   50.21 +                  int (*suspend)(int domid));
   50.22  
   50.23  /**
   50.24   * This function will restore a saved domain running Linux.
   50.25 @@ -43,6 +51,18 @@ int xc_linux_restore(int xc_handle, int 
   50.26                       unsigned long *console_mfn);
   50.27  
   50.28  /**
   50.29 + * This function will restore a saved hvm domain running unmodified guest.
   50.30 + *
   50.31 + * @parm store_mfn pass mem size & returned with the mfn of the store page
   50.32 + * @return 0 on success, -1 on failure
   50.33 + */
   50.34 +int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
   50.35 +                      unsigned long nr_pfns, unsigned int store_evtchn,
   50.36 +                      unsigned long *store_mfn, unsigned int console_evtchn,
   50.37 +                      unsigned long *console_mfn,
   50.38 +                      unsigned int pae, unsigned int apic);
   50.39 +
   50.40 +/**
   50.41   * This function will create a domain for a paravirtualized Linux
   50.42   * using file names pointing to kernel and ramdisk
   50.43   *
    51.1 --- a/tools/pygrub/src/pygrub	Thu Jan 18 15:18:07 2007 +0000
    51.2 +++ b/tools/pygrub/src/pygrub	Fri Jan 19 14:48:57 2007 +0000
    51.3 @@ -503,7 +503,7 @@ def run_grub(file, entry, fs):
    51.4  # If nothing has been specified, look for a Solaris domU. If found, perform the
    51.5  # necessary tweaks.
    51.6  def sniff_solaris(fs, cfg):
    51.7 -    if not fs.file_exists("/platform/i86xen/kernel/unix"):
    51.8 +    if not fs.file_exists("/platform/i86xpv/kernel/unix"):
    51.9          return cfg
   51.10      
   51.11      # darned python
   51.12 @@ -516,10 +516,10 @@ def sniff_solaris(fs, cfg):
   51.13              longmode = True
   51.14  
   51.15      if not cfg["kernel"]:
   51.16 -        cfg["kernel"] = "/platform/i86xen/kernel/unix"
   51.17 +        cfg["kernel"] = "/platform/i86xpv/kernel/unix"
   51.18          cfg["ramdisk"] = "/platform/i86pc/boot_archive"
   51.19          if longmode:
   51.20 -            cfg["kernel"] = "/platform/i86xen/kernel/amd64/unix"
   51.21 +            cfg["kernel"] = "/platform/i86xpv/kernel/amd64/unix"
   51.22              cfg["ramdisk"] = "/platform/i86pc/amd64/boot_archive"
   51.23  
   51.24      # Unpleasant. Typically we'll have 'root=foo -k' or 'root=foo /kernel -k',
    52.1 --- a/tools/python/setup.py	Thu Jan 18 15:18:07 2007 +0000
    52.2 +++ b/tools/python/setup.py	Fri Jan 19 14:48:57 2007 +0000
    52.3 @@ -30,6 +30,13 @@ xs = Extension("xs",
    52.4                 libraries          = libraries,
    52.5                 sources            = [ "xen/lowlevel/xs/xs.c" ])
    52.6  
    52.7 +scf = Extension("scf",
    52.8 +               extra_compile_args = extra_compile_args,
    52.9 +               include_dirs       = include_dirs + [ "xen/lowlevel/scf" ],
   52.10 +               library_dirs       = library_dirs,
   52.11 +               libraries          = libraries,
   52.12 +               sources            = [ "xen/lowlevel/scf/scf.c" ])
   52.13 +             
   52.14  acm = Extension("acm",
   52.15                 extra_compile_args = extra_compile_args,
   52.16                 include_dirs       = include_dirs + [ "xen/lowlevel/acm" ],
   52.17 @@ -37,6 +44,10 @@ acm = Extension("acm",
   52.18                 libraries          = libraries,
   52.19                 sources            = [ "xen/lowlevel/acm/acm.c" ])
   52.20  
   52.21 +modules = [ xc, xs, acm ]
   52.22 +if os.uname()[0] == 'SunOS':
   52.23 +    modules.append(scf)
   52.24 +
   52.25  setup(name            = 'xen',
   52.26        version         = '3.0',
   52.27        description     = 'Xen',
   52.28 @@ -56,7 +67,7 @@ setup(name            = 'xen',
   52.29                           'xen.xm.tests'
   52.30                           ],
   52.31        ext_package = "xen.lowlevel",
   52.32 -      ext_modules = [ xc, xs, acm ]
   52.33 +      ext_modules = modules
   52.34        )
   52.35  
   52.36  os.chdir('logging')
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/tools/python/xen/lowlevel/scf/scf.c	Fri Jan 19 14:48:57 2007 +0000
    53.3 @@ -0,0 +1,156 @@
    53.4 +/*
    53.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    53.6 + * of this software and associated documentation files (the "Software"), to
    53.7 + * deal in the Software without restriction, including without limitation the
    53.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    53.9 + * sell copies of the Software, and to permit persons to whom the Software is
   53.10 + * furnished to do so, subject to the following conditions:
   53.11 + *
   53.12 + * The above copyright notice and this permission notice shall be included in
   53.13 + * all copies or substantial portions of the Software.
   53.14 + *
   53.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   53.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   53.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   53.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   53.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   53.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   53.21 + * DEALINGS IN THE SOFTWARE.
   53.22 + *
   53.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   53.24 + * Use is subject to license terms.
   53.25 + */
   53.26 +
   53.27 +#include <Python.h>
   53.28 +
   53.29 +#include <libscf.h>
   53.30 +#include <stdio.h>
   53.31 +
   53.32 +#define	XEND_FMRI "svc:/system/xen/xend:default"
   53.33 +#define	XEND_PG "config"
   53.34 +
   53.35 +static PyObject *scf_exc;
   53.36 +
   53.37 +static void *
   53.38 +scf_exception(const char *err, const char *value)
   53.39 +{
   53.40 +	int scferr = scf_error();
   53.41 +	const char *scfstrerr = scf_strerror(scferr);
   53.42 +	PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
   53.43 +	PyErr_SetObject(scf_exc, obj);
   53.44 +	return (NULL);
   53.45 +}
   53.46 +
   53.47 +static PyObject *
   53.48 +pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
   53.49 +{
   53.50 +	static char *kwlist[] = { "name", NULL };
   53.51 +	scf_simple_prop_t *prop;
   53.52 +	uint8_t *val;
   53.53 +	char *name;
   53.54 +
   53.55 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
   53.56 +		return (NULL);
   53.57 +
   53.58 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
   53.59 +
   53.60 +	if (prop == NULL)
   53.61 +		return (scf_exception("scf_simple_prop_get() failed", name));
   53.62 +
   53.63 +	if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
   53.64 +		return (scf_exception("scf_simple_prop_next_boolean() failed",
   53.65 +		    name));
   53.66 +
   53.67 +	if (*val) {
   53.68 +		scf_simple_prop_free(prop);
   53.69 +		Py_INCREF(Py_True);
   53.70 +		return (Py_True);
   53.71 +	}
   53.72 +
   53.73 +	scf_simple_prop_free(prop);
   53.74 +	Py_INCREF(Py_False);
   53.75 +	return (Py_False);
   53.76 +}
   53.77 +
   53.78 +static PyObject *
   53.79 +pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
   53.80 +{
   53.81 +	static char *kwlist[] = { "name", NULL };
   53.82 +	scf_simple_prop_t *prop;
   53.83 +	PyObject *obj;
   53.84 +	int64_t *val;
   53.85 +	char *name;
   53.86 +
   53.87 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
   53.88 +		return (NULL);
   53.89 +
   53.90 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
   53.91 +
   53.92 +	if (prop == NULL)
   53.93 +		return (scf_exception("scf_simple_prop_get() failed", name));
   53.94 +
   53.95 +	if ((val = scf_simple_prop_next_integer(prop)) == NULL)
   53.96 +		return (scf_exception("scf_simple_prop_next_integer() failed",
   53.97 +		    name));
   53.98 +
   53.99 +	obj = PyInt_FromLong((long)*val);
  53.100 +	scf_simple_prop_free(prop);
  53.101 +	return (obj);
  53.102 +}
  53.103 +
  53.104 +static PyObject *
  53.105 +pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
  53.106 +{
  53.107 +	static char *kwlist[] = { "name", NULL };
  53.108 +	scf_simple_prop_t *prop;
  53.109 +	PyObject *obj;
  53.110 +	char *name;
  53.111 +	char *str;
  53.112 +
  53.113 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
  53.114 +		return (NULL);
  53.115 +
  53.116 +	prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
  53.117 +
  53.118 +	if (prop == NULL)
  53.119 +		return (scf_exception("scf_simple_prop_get() failed", name));
  53.120 +
  53.121 +	if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
  53.122 +		scf_simple_prop_free(prop);
  53.123 +		return (scf_exception("scf_simple_prop_next_astring() failed",
  53.124 +		    name));
  53.125 +	}
  53.126 +
  53.127 +	obj = PyString_FromString(str);
  53.128 +	scf_simple_prop_free(prop);
  53.129 +	return (obj);
  53.130 +}
  53.131 +
  53.132 +PyDoc_STRVAR(pyscf_get_bool__doc__,
  53.133 +   "get_bool(name) - get the value of the named boolean property");
  53.134 +PyDoc_STRVAR(pyscf_get_int__doc__,
  53.135 +   "get_int(name) - get the value of the named integer property");
  53.136 +PyDoc_STRVAR(pyscf_get_string__doc__,
  53.137 +   "get_string(name) - get the value of the named string property");
  53.138 +
  53.139 +static struct PyMethodDef pyscf_module_methods[] = {
  53.140 +	{ "get_bool", (PyCFunction) pyscf_get_bool,
  53.141 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
  53.142 +	{ "get_int", (PyCFunction) pyscf_get_int,
  53.143 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
  53.144 +	{ "get_string", (PyCFunction) pyscf_get_string,
  53.145 +	  METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
  53.146 +	{ NULL, NULL, 0, NULL }	
  53.147 +};
  53.148 +
  53.149 +PyMODINIT_FUNC
  53.150 +initscf(void)
  53.151 +{
  53.152 +	PyObject *m;
  53.153 +	m = Py_InitModule("scf", pyscf_module_methods);
  53.154 +
  53.155 +	scf_exc = PyErr_NewException("scf.error", NULL, NULL);
  53.156 +	Py_INCREF(scf_exc);
  53.157 +	PyModule_AddObject(m, "error", scf_exc);
  53.158 +	PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
  53.159 +}
    54.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Thu Jan 18 15:18:07 2007 +0000
    54.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Fri Jan 19 14:48:57 2007 +0000
    54.3 @@ -160,6 +160,20 @@ static PyObject *pyxc_domain_destroy(XcO
    54.4      return dom_op(self, args, xc_domain_destroy);
    54.5  }
    54.6  
    54.7 +static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
    54.8 +{
    54.9 +    uint32_t dom, reason;
   54.10 +
   54.11 +    if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
   54.12 +      return NULL;
   54.13 +
   54.14 +    if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
   54.15 +        return pyxc_error_to_exception();
   54.16 +    
   54.17 +    Py_INCREF(zero);
   54.18 +    return zero;
   54.19 +}
   54.20 +
   54.21  
   54.22  static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
   54.23                                         PyObject *args,
   54.24 @@ -1029,6 +1043,14 @@ static PyMethodDef pyxc_methods[] = {
   54.25        " dom [int]:    Identifier of domain to be destroyed.\n\n"
   54.26        "Returns: [int] 0 on success; -1 on error.\n" },
   54.27  
   54.28 +    { "domain_shutdown", 
   54.29 +      (PyCFunction)pyxc_domain_shutdown,
   54.30 +      METH_VARARGS, "\n"
   54.31 +      "Shutdown a domain.\n"
   54.32 +      " dom       [int, 0]:      Domain identifier to use.\n"
   54.33 +      " reason     [int, 0]:      Reason for shutdown.\n"
   54.34 +      "Returns: [int] 0 on success; -1 on error.\n" },
   54.35 +
   54.36      { "vcpu_setaffinity", 
   54.37        (PyCFunction)pyxc_vcpu_setaffinity, 
   54.38        METH_VARARGS | METH_KEYWORDS, "\n"
    55.1 --- a/tools/python/xen/util/xmlrpclib2.py	Thu Jan 18 15:18:07 2007 +0000
    55.2 +++ b/tools/python/xen/util/xmlrpclib2.py	Fri Jan 19 14:48:57 2007 +0000
    55.3 @@ -256,6 +256,7 @@ class UnixXMLRPCRequestHandler(XMLRPCReq
    55.4  
    55.5  class UnixXMLRPCServer(TCPXMLRPCServer):
    55.6      address_family = socket.AF_UNIX
    55.7 +    allow_address_reuse = True
    55.8  
    55.9      def __init__(self, addr, allowed, xenapi, logRequests = 1):
   55.10          mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
    56.1 --- a/tools/python/xen/web/httpserver.py	Thu Jan 18 15:18:07 2007 +0000
    56.2 +++ b/tools/python/xen/web/httpserver.py	Fri Jan 19 14:48:57 2007 +0000
    56.3 @@ -294,8 +294,6 @@ class HttpServer:
    56.4  
    56.5      backlog = 5
    56.6  
    56.7 -    closed = False
    56.8 -
    56.9      def __init__(self, root, interface, port=8080):
   56.10          self.root = root
   56.11          self.interface = interface
   56.12 @@ -303,6 +301,7 @@ class HttpServer:
   56.13          # ready indicates when we are ready to begin accept connections
   56.14          # it should be set after a successful bind
   56.15          self.ready = False
   56.16 +        self.closed = False
   56.17  
   56.18      def run(self):
   56.19          self.bind()
   56.20 @@ -317,7 +316,6 @@ class HttpServer:
   56.21      def stop(self):
   56.22          self.close()
   56.23  
   56.24 -
   56.25      def bind(self):
   56.26          self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   56.27          flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
   56.28 @@ -334,7 +332,10 @@ class HttpServer:
   56.29  
   56.30      def close(self):
   56.31          self.closed = True
   56.32 +        self.ready = False
   56.33          try:
   56.34 +            # shutdown socket explicitly to allow reuse
   56.35 +            self.socket.shutdown(socket.SHUT_RDWR)
   56.36              self.socket.close()
   56.37          except:
   56.38              pass
   56.39 @@ -345,6 +346,9 @@ class HttpServer:
   56.40      def getResource(self, req):
   56.41          return self.root.getRequestResource(req)
   56.42  
   56.43 +    def shutdown(self):
   56.44 +        self.close()
   56.45 +
   56.46  
   56.47  class UnixHttpServer(HttpServer):
   56.48  
    57.1 --- a/tools/python/xen/xend/Vifctl.py	Thu Jan 18 15:18:07 2007 +0000
    57.2 +++ b/tools/python/xen/xend/Vifctl.py	Fri Jan 19 14:48:57 2007 +0000
    57.3 @@ -20,7 +20,7 @@
    57.4  """
    57.5  import os
    57.6  
    57.7 -import XendRoot
    57.8 +import XendOptions
    57.9  
   57.10  
   57.11  def network(op):
   57.12 @@ -30,7 +30,7 @@ def network(op):
   57.13      """
   57.14      if op not in ['start', 'stop']:
   57.15          raise ValueError('Invalid operation: ' + op)
   57.16 -    script = XendRoot.instance().get_network_script()
   57.17 +    script = XendOptions.instance().get_network_script()
   57.18      if script:
   57.19          script.insert(1, op)
   57.20          os.spawnv(os.P_WAIT, script[0], script)
    58.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Thu Jan 18 15:18:07 2007 +0000
    58.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Fri Jan 19 14:48:57 2007 +0000
    58.3 @@ -22,11 +22,14 @@ from xen.xend.XendConfig import XendConf
    58.4  from xen.xend.XendConstants import *
    58.5  
    58.6  SIGNATURE = "LinuxGuestRecord"
    58.7 +QEMU_SIGNATURE = "QemuDeviceModelRecord"
    58.8 +dm_batch = 512
    58.9  XC_SAVE = "xc_save"
   58.10  XC_RESTORE = "xc_restore"
   58.11  
   58.12  
   58.13  sizeof_int = calcsize("i")
   58.14 +sizeof_unsigned_int = calcsize("I")
   58.15  sizeof_unsigned_long = calcsize("L")
   58.16  
   58.17  
   58.18 @@ -69,6 +72,11 @@ def save(fd, dominfo, network, live, dst
   58.19                      "could not write guest state file: config len")
   58.20          write_exact(fd, config, "could not write guest state file: config")
   58.21  
   58.22 +        image_cfg = dominfo.info.get('image', {})
   58.23 +        hvm = image_cfg.has_key('hvm')
   58.24 +
   58.25 +        if hvm:
   58.26 +            log.info("save hvm domain")
   58.27          # xc_save takes three customization parameters: maxit, max_f, and
   58.28          # flags the last controls whether or not save is 'live', while the
   58.29          # first two further customize behaviour when 'live' save is
   58.30 @@ -76,7 +84,7 @@ def save(fd, dominfo, network, live, dst
   58.31          # libxenguest; see the comments and/or code in xc_linux_save() for
   58.32          # more information.
   58.33          cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
   58.34 -               str(dominfo.getDomid()), "0", "0", str(int(live)) ]
   58.35 +               str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
   58.36          log.debug("[xc_save]: %s", string.join(cmd))
   58.37  
   58.38          def saveInputHandler(line, tochild):
   58.39 @@ -90,12 +98,29 @@ def save(fd, dominfo, network, live, dst
   58.40                  log.info("Domain %d suspended.", dominfo.getDomid())
   58.41                  dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
   58.42                                         domain_name)
   58.43 +                #send signal to device model for save
   58.44 +                if hvm:
   58.45 +                    log.info("release_devices for hvm domain")
   58.46 +                    dominfo._releaseDevices(True)
   58.47                  tochild.write("done\n")
   58.48                  tochild.flush()
   58.49                  log.debug('Written done')
   58.50  
   58.51          forkHelper(cmd, fd, saveInputHandler, False)
   58.52  
   58.53 +        # put qemu device model state
   58.54 +        if hvm:
   58.55 +            write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
   58.56 +            qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(), os.O_RDONLY)
   58.57 +            while True:
   58.58 +                buf = os.read(qemu_fd, dm_batch)
   58.59 +                if len(buf):
   58.60 +                    write_exact(fd, buf, "could not write device model state")
   58.61 +                else:
   58.62 +                    break
   58.63 +            os.close(qemu_fd)
   58.64 +            os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid())
   58.65 +
   58.66          dominfo.destroyDomain()
   58.67          try:
   58.68              dominfo.setName(domain_name)
   58.69 @@ -149,19 +174,43 @@ def restore(xd, fd, dominfo = None, paus
   58.70  
   58.71      nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 
   58.72  
   58.73 +    # if hvm, pass mem size to calculate the store_mfn
   58.74 +    image_cfg = dominfo.info.get('image', {})
   58.75 +    is_hvm  = image_cfg.has_key('hvm')
   58.76 +    if is_hvm:
   58.77 +        hvm  = dominfo.info['memory_static_min']
   58.78 +        apic = dominfo.info['image']['hvm'].get('apic', 0)
   58.79 +        pae  = dominfo.info['image']['hvm'].get('pae',  0)
   58.80 +        log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
   58.81 +                 dominfo.domid, hvm, apic, pae)
   58.82 +    else:
   58.83 +        hvm  = 0
   58.84 +        apic = 0
   58.85 +        pae  = 0
   58.86 +
   58.87      try:
   58.88          l = read_exact(fd, sizeof_unsigned_long,
   58.89                         "not a valid guest state file: pfn count read")
   58.90          max_pfn = unpack("L", l)[0]    # native sizeof long
   58.91 +
   58.92          if max_pfn > 16*1024*1024:     # XXX 
   58.93              raise XendError(
   58.94                  "not a valid guest state file: pfn count out of range")
   58.95  
   58.96 -        balloon.free(xc.pages_to_kib(nr_pfns))
   58.97 +        shadow = dominfo.info['shadow_memory']
   58.98 +        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
   58.99 +                  "nr_pfns=0x%x.", dominfo.info['shadow_memory'],
  58.100 +                  dominfo.info['memory_static_max'],
  58.101 +                  dominfo.info['memory_static_min'], nr_pfns)
  58.102 +
  58.103 +        balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
  58.104 +
  58.105 +        shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
  58.106 +        dominfo.info['shadow_memory'] = shadow_cur
  58.107  
  58.108          cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
  58.109                          fd, dominfo.getDomid(), max_pfn,
  58.110 -                        store_port, console_port])
  58.111 +                        store_port, console_port, hvm, pae, apic])
  58.112          log.debug("[xc_restore]: %s", string.join(cmd))
  58.113  
  58.114          handler = RestoreInputHandler()
  58.115 @@ -171,10 +220,30 @@ def restore(xd, fd, dominfo = None, paus
  58.116          if handler.store_mfn is None or handler.console_mfn is None:
  58.117              raise XendError('Could not read store/console MFN')
  58.118  
  58.119 -        os.read(fd, 1)           # Wait for source to close connection
  58.120          dominfo.waitForDevices() # Wait for backends to set up
  58.121          if not paused:
  58.122              dominfo.unpause()
  58.123 +
  58.124 +         # get qemu state and create a tmp file for dm restore
  58.125 +        if is_hvm:
  58.126 +            qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
  58.127 +                                        "invalid device model signature read")
  58.128 +            if qemu_signature != QEMU_SIGNATURE:
  58.129 +                raise XendError("not a valid device model state: found '%s'" %
  58.130 +                                qemu_signature)
  58.131 +            qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
  58.132 +                              os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
  58.133 +            while True:
  58.134 +                buf = os.read(fd, dm_batch)
  58.135 +                if len(buf):
  58.136 +                    write_exact(qemu_fd, buf,
  58.137 +                                "could not write dm state to tmp file")
  58.138 +                else:
  58.139 +                    break
  58.140 +            os.close(qemu_fd)
  58.141 +
  58.142 +
  58.143 +        os.read(fd, 1)           # Wait for source to close connection
  58.144          
  58.145          dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
  58.146          
    59.1 --- a/tools/python/xen/xend/XendConfig.py	Thu Jan 18 15:18:07 2007 +0000
    59.2 +++ b/tools/python/xen/xend/XendConfig.py	Fri Jan 19 14:48:57 2007 +0000
    59.3 @@ -78,6 +78,25 @@ def scrub_password(data):
    59.4      else:
    59.5          return data
    59.6  
    59.7 +#
    59.8 +# CPU fields:
    59.9 +#
   59.10 +# vcpus_number -- the maximum number of vcpus that this domain may ever have.
   59.11 +#                 aka XendDomainInfo.getVCpuCount().
   59.12 +# vcpus        -- the legacy configuration name for above.
   59.13 +# max_vcpu_id  -- vcpus_number - 1.  This is given to us by Xen.
   59.14 +#
   59.15 +# cpus         -- the list of pCPUs available to each vCPU.
   59.16 +#
   59.17 +#   vcpu_avail:  a bitmap telling the guest domain whether it may use each of
   59.18 +#                its VCPUs.  This is translated to
   59.19 +#                <dompath>/cpu/<id>/availability = {online,offline} for use
   59.20 +#                by the guest domain.
   59.21 +# online_vpcus -- the number of VCPUs currently up, as reported by Xen.  This
   59.22 +#                 is changed by changing vcpu_avail, and waiting for the
   59.23 +#                 domain to respond.
   59.24 +#
   59.25 +
   59.26  
   59.27  # Mapping from XendConfig configuration keys to the old
   59.28  # legacy configuration keys that map directly.
   59.29 @@ -185,7 +204,7 @@ LEGACY_CFG_TYPES = {
   59.30      'uuid':          str,
   59.31      'name':          str,
   59.32      'vcpus':         int,
   59.33 -    'vcpu_avail':    int,
   59.34 +    'vcpu_avail':    long,
   59.35      'memory':        int,
   59.36      'shadow_memory': int,
   59.37      'maxmem':        int,
   59.38 @@ -355,9 +374,6 @@ class XendConfig(dict):
   59.39              'cpu_weight': 256,
   59.40              'cpu_cap': 0,
   59.41              'vcpus_number': 1,
   59.42 -            'online_vcpus': 1,
   59.43 -            'max_vcpu_id': 0,
   59.44 -            'vcpu_avail': 1,
   59.45              'console_refs': [],
   59.46              'vif_refs': [],
   59.47              'vbd_refs': [],
   59.48 @@ -389,7 +405,7 @@ class XendConfig(dict):
   59.49                                        event)
   59.50  
   59.51      def _vcpus_sanity_check(self):
   59.52 -        if self.get('vcpus_number') != None:
   59.53 +        if 'vcpus_number' in self and 'vcpu_avail' not in self:
   59.54              self['vcpu_avail'] = (1 << self['vcpus_number']) - 1
   59.55  
   59.56      def _uuid_sanity_check(self):
   59.57 @@ -405,7 +421,7 @@ class XendConfig(dict):
   59.58      def _dominfo_to_xapi(self, dominfo):
   59.59          self['domid'] = dominfo['domid']
   59.60          self['online_vcpus'] = dominfo['online_vcpus']
   59.61 -        self['max_vcpu_id'] = dominfo['max_vcpu_id']
   59.62 +        self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
   59.63          self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
   59.64          self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
   59.65          self['cpu_time'] = dominfo['cpu_time']/1e9
   59.66 @@ -636,9 +652,6 @@ class XendConfig(dict):
   59.67          self['memory_dynamic_max'] = self['memory_static_max']
   59.68          self['memory_dynamic_min'] = self['memory_static_min']
   59.69  
   59.70 -        # make sure max_vcpu_id is set correctly
   59.71 -        self['max_vcpu_id'] = self['vcpus_number'] - 1
   59.72 -
   59.73          # set device references in the configuration
   59.74          self['devices'] = cfg.get('devices', {})
   59.75          
   59.76 @@ -720,13 +733,11 @@ class XendConfig(dict):
   59.77          _set_cfg_if_exists('on_xend_stop')
   59.78          _set_cfg_if_exists('on_xend_start')
   59.79          _set_cfg_if_exists('vcpu_avail')
   59.80 -        _set_cfg_if_exists('max_vcpu_id') # needed for vcpuDomDetails
   59.81          _set_cfg_if_exists('cpu_weight')
   59.82          _set_cfg_if_exists('cpu_cap')
   59.83          
   59.84          # Parse and store runtime configuration 
   59.85          _set_cfg_if_exists('start_time')
   59.86 -        _set_cfg_if_exists('online_vcpus')
   59.87          _set_cfg_if_exists('cpu_time')
   59.88          _set_cfg_if_exists('shutdown_reason')
   59.89          _set_cfg_if_exists('up_time')
   59.90 @@ -1115,19 +1126,17 @@ class XendConfig(dict):
   59.91          # configuration
   59.92          log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp))
   59.93  
   59.94 -        kernel_args = ""
   59.95 +        # user-specified args must come last: previous releases did this and
   59.96 +        # some domU kernels rely upon the ordering.
   59.97 +        kernel_args = sxp.child_value(image_sxp, 'args', '')
   59.98  
   59.99          # attempt to extract extra arguments from SXP config
  59.100          arg_ip = sxp.child_value(image_sxp, 'ip')
  59.101          if arg_ip and not re.search(r'ip=[^ ]+', kernel_args):
  59.102 -            kernel_args += 'ip=%s ' % arg_ip
  59.103 +            kernel_args = 'ip=%s ' % arg_ip + kernel_args
  59.104          arg_root = sxp.child_value(image_sxp, 'root')
  59.105          if arg_root and not re.search(r'root=', kernel_args):
  59.106 -            kernel_args += 'root=%s ' % arg_root
  59.107 -
  59.108 -        # user-specified args must come last: previous releases did this and
  59.109 -        # some domU kernels rely upon the ordering.
  59.110 -        kernel_args += sxp.child_value(image_sxp, 'args', '')
  59.111 +            kernel_args = 'root=%s ' % arg_root + kernel_args
  59.112  
  59.113          if bootloader:
  59.114              self['_temp_using_bootloader'] = '1'
    60.1 --- a/tools/python/xen/xend/XendDomain.py	Thu Jan 18 15:18:07 2007 +0000
    60.2 +++ b/tools/python/xen/xend/XendDomain.py	Fri Jan 19 14:48:57 2007 +0000
    60.3 @@ -32,7 +32,7 @@ import threading
    60.4  import xen.lowlevel.xc
    60.5  
    60.6  
    60.7 -from xen.xend import XendRoot, XendCheckpoint, XendDomainInfo
    60.8 +from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo
    60.9  from xen.xend.PrettyPrint import prettyprint
   60.10  from xen.xend.XendConfig import XendConfig
   60.11  from xen.xend.XendError import XendError, XendInvalidDomain, VmError
   60.12 @@ -51,7 +51,7 @@ from xen.util import mkdir, security
   60.13  from xen.xend import uuid
   60.14  
   60.15  xc = xen.lowlevel.xc.xc()
   60.16 -xroot = XendRoot.instance() 
   60.17 +xoptions = XendOptions.instance() 
   60.18  
   60.19  __all__ = [ "XendDomain" ]
   60.20  
   60.21 @@ -214,7 +214,7 @@ class XendDomain:
   60.22          @rtype: String
   60.23          @return: Path.
   60.24          """
   60.25 -        dom_path = xroot.get_xend_domains_path()
   60.26 +        dom_path = xoptions.get_xend_domains_path()
   60.27          if domuuid:
   60.28              dom_path = os.path.join(dom_path, domuuid)
   60.29          return dom_path
   60.30 @@ -361,7 +361,7 @@ class XendDomain:
   60.31  
   60.32      def _setDom0CPUCount(self):
   60.33          """Sets the number of VCPUs dom0 has. Retreived from the
   60.34 -        Xend configuration, L{XendRoot}.
   60.35 +        Xend configuration, L{XendOptions}.
   60.36  
   60.37          @requires: Expects to be protected by domains_lock.
   60.38          @rtype: None
   60.39 @@ -369,7 +369,7 @@ class XendDomain:
   60.40          dom0 = self.privilegedDomain()
   60.41  
   60.42          # get max number of vcpus to use for dom0 from config
   60.43 -        target = int(xroot.get_dom0_vcpus())
   60.44 +        target = int(xoptions.get_dom0_vcpus())
   60.45          log.debug("number of vcpus to use is %d", target)
   60.46     
   60.47          # target == 0 means use all processors
   60.48 @@ -1164,7 +1164,7 @@ class XendDomain:
   60.49              dominfo.checkLiveMigrateMemory()
   60.50  
   60.51          if port == 0:
   60.52 -            port = xroot.get_xend_relocation_port()
   60.53 +            port = xoptions.get_xend_relocation_port()
   60.54          try:
   60.55              sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   60.56              sock.connect((dst, port))
    61.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Jan 18 15:18:07 2007 +0000
    61.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Jan 19 14:48:57 2007 +0000
    61.3 @@ -38,7 +38,7 @@ from xen.util.blkif import blkdev_uname_
    61.4  from xen.util import security
    61.5  
    61.6  from xen.xend import balloon, sxp, uuid, image, arch, osdep
    61.7 -from xen.xend import XendRoot, XendNode, XendConfig
    61.8 +from xen.xend import XendOptions, XendNode, XendConfig
    61.9  
   61.10  from xen.xend.XendConfig import scrub_password
   61.11  from xen.xend.XendBootloader import bootloader
   61.12 @@ -54,31 +54,12 @@ MIGRATE_TIMEOUT = 30.0
   61.13  BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
   61.14  
   61.15  xc = xen.lowlevel.xc.xc()
   61.16 -xroot = XendRoot.instance()
   61.17 +xoptions = XendOptions.instance()
   61.18  
   61.19  log = logging.getLogger("xend.XendDomainInfo")
   61.20  #log.setLevel(logging.TRACE)
   61.21  
   61.22  
   61.23 -#
   61.24 -# There are a number of CPU-related fields:
   61.25 -#
   61.26 -#   vcpus:       the number of virtual CPUs this domain is configured to use.
   61.27 -#   vcpu_avail:  a bitmap telling the guest domain whether it may use each of
   61.28 -#                its VCPUs.  This is translated to
   61.29 -#                <dompath>/cpu/<id>/availability = {online,offline} for use
   61.30 -#                by the guest domain.
   61.31 -#   cpumap:      a list of bitmaps, one for each VCPU, giving the physical
   61.32 -#                CPUs that that VCPU may use.
   61.33 -#   cpu:         a configuration setting requesting that VCPU 0 is pinned to
   61.34 -#                the specified physical CPU.
   61.35 -#
   61.36 -# vcpus and vcpu_avail settings persist with the VM (i.e. they are persistent
   61.37 -# across save, restore, migrate, and restart).  The other settings are only
   61.38 -# specific to the domain, so are lost when the VM moves.
   61.39 -#
   61.40 -
   61.41 -
   61.42  def create(config):
   61.43      """Creates and start a VM using the supplied configuration. 
   61.44  
   61.45 @@ -451,6 +432,16 @@ class XendDomainInfo:
   61.46          self._removeVm('xend/previous_restart_time')
   61.47          self.storeDom("control/shutdown", reason)
   61.48  
   61.49 +        ## shutdown hypercall for hvm domain desides xenstore write
   61.50 +        image_cfg = self.info.get('image', {})
   61.51 +        hvm = image_cfg.has_key('hvm')
   61.52 +        if hvm:
   61.53 +            for code in DOMAIN_SHUTDOWN_REASONS.keys():
   61.54 +                if DOMAIN_SHUTDOWN_REASONS[code] == reason:
   61.55 +                    break
   61.56 +            xc.domain_shutdown(self.domid, code)
   61.57 +
   61.58 +
   61.59      def pause(self):
   61.60          """Pause domain
   61.61          
   61.62 @@ -614,7 +605,7 @@ class XendDomainInfo:
   61.63                      ['name',       self.info['name_label']],
   61.64                      ['vcpu_count', self.info['vcpus_number']]]
   61.65  
   61.66 -            for i in range(0, self.info['max_vcpu_id']+1):
   61.67 +            for i in range(0, self.info['vcpus_number']):
   61.68                  info = xc.vcpu_getinfo(self.domid, i)
   61.69  
   61.70                  sxpr.append(['vcpu',
   61.71 @@ -739,7 +730,7 @@ class XendDomainInfo:
   61.72              'domid':              str(self.domid),
   61.73              'vm':                 self.vmpath,
   61.74              'name':               self.info['name_label'],
   61.75 -            'console/limit':      str(xroot.get_console_limit() * 1024),
   61.76 +            'console/limit':      str(xoptions.get_console_limit() * 1024),
   61.77              'memory/target':      str(self.info['memory_static_min'] * 1024)
   61.78              }
   61.79  
   61.80 @@ -898,8 +889,9 @@ class XendDomainInfo:
   61.81                  self._writeDom(self._vcpuDomDetails())
   61.82          else:
   61.83              self.info['vcpus_number'] = vcpus
   61.84 -            self.info['online_vcpus'] = vcpus
   61.85              xen.xend.XendDomain.instance().managed_config_save(self)
   61.86 +        log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
   61.87 +                 vcpus)
   61.88  
   61.89      def getLabel(self):
   61.90          return security.get_security_info(self.info, 'label')
   61.91 @@ -976,7 +968,7 @@ class XendDomainInfo:
   61.92                           self.info['name_label'], self.domid)
   61.93                  self._writeVm(LAST_SHUTDOWN_REASON, 'crash')
   61.94  
   61.95 -                if xroot.get_enable_dump():
   61.96 +                if xoptions.get_enable_dump():
   61.97                      try:
   61.98                          self.dumpCore()
   61.99                      except XendError:
  61.100 @@ -1228,8 +1220,11 @@ class XendDomainInfo:
  61.101          if self.image:
  61.102              self.image.createDeviceModel()
  61.103  
  61.104 -    def _releaseDevices(self):
  61.105 +    def _releaseDevices(self, suspend = False):
  61.106          """Release all domain's devices.  Nothrow guarantee."""
  61.107 +        if suspend and self.image:
  61.108 +            self.image.destroy(suspend)
  61.109 +            return
  61.110  
  61.111          while True:
  61.112              t = xstransact("%s/device" % self.dompath)
  61.113 @@ -1381,7 +1376,7 @@ class XendDomainInfo:
  61.114              # this is done prior to memory allocation to aide in memory
  61.115              # distribution for NUMA systems.
  61.116              if self.info['cpus'] is not None and len(self.info['cpus']) > 0:
  61.117 -                for v in range(0, self.info['max_vcpu_id']+1):
  61.118 +                for v in range(0, self.info['vcpus_number']):
  61.119                      xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
  61.120  
  61.121              # Use architecture- and image-specific calculations to determine
  61.122 @@ -1395,6 +1390,7 @@ class XendDomainInfo:
  61.123                  self.info['shadow_memory'] * 1024,
  61.124                  self.info['memory_static_max'] * 1024)
  61.125  
  61.126 +            log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
  61.127              # Round shadow up to a multiple of a MiB, as shadow_mem_control
  61.128              # takes MiB and we must not round down and end up under-providing.
  61.129              shadow = ((shadow + 1023) / 1024) * 1024
  61.130 @@ -1494,6 +1490,16 @@ class XendDomainInfo:
  61.131          self.console_mfn = console_mfn
  61.132  
  61.133          self._introduceDomain()
  61.134 +        image_cfg = self.info.get('image', {})
  61.135 +        hvm = image_cfg.has_key('hvm')
  61.136 +        if hvm:
  61.137 +            self.image = image.create(self,
  61.138 +                    self.info,
  61.139 +                    self.info['image'],
  61.140 +                    self.info['devices'])
  61.141 +            if self.image:
  61.142 +                self.image.createDeviceModel(True)
  61.143 +                self.image.register_shutdown_watch()
  61.144          self._storeDomDetails()
  61.145          self._registerWatches()
  61.146          self.refreshShutdown()
  61.147 @@ -2028,8 +2034,8 @@ class XendDomainInfo:
  61.148          # TODO: spec says that key is int, however, python does not allow
  61.149          #       non-string keys to dictionaries.
  61.150          vcpu_util = {}
  61.151 -        if 'max_vcpu_id' in self.info and self.domid != None:
  61.152 -            for i in range(0, self.info['max_vcpu_id']+1):
  61.153 +        if 'vcpus_number' in self.info and self.domid != None:
  61.154 +            for i in range(0, self.info['vcpus_number']):
  61.155                  info = xc.vcpu_getinfo(self.domid, i)
  61.156                  vcpu_util[str(i)] = info['cpu_time']/1000000000.0
  61.157                  
    62.1 --- a/tools/python/xen/xend/XendNode.py	Thu Jan 18 15:18:07 2007 +0000
    62.2 +++ b/tools/python/xen/xend/XendNode.py	Fri Jan 19 14:48:57 2007 +0000
    62.3 @@ -24,7 +24,7 @@ from xen.util import Brctl
    62.4  
    62.5  from xen.xend import uuid
    62.6  from xen.xend.XendError import XendError, NetworkAlreadyConnected
    62.7 -from xen.xend.XendRoot import instance as xendroot
    62.8 +from xen.xend.XendOptions import instance as xendoptions
    62.9  from xen.xend.XendStorageRepository import XendStorageRepository
   62.10  from xen.xend.XendLogging import log
   62.11  from xen.xend.XendPIF import *
   62.12 @@ -45,7 +45,7 @@ class XendNode:
   62.13          """
   62.14          
   62.15          self.xc = xen.lowlevel.xc.xc()
   62.16 -        self.state_store = XendStateStore(xendroot().get_xend_state_path())
   62.17 +        self.state_store = XendStateStore(xendoptions().get_xend_state_path())
   62.18  
   62.19          # load host state from XML file
   62.20          saved_host = self.state_store.load_state('host')
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/tools/python/xen/xend/XendOptions.py	Fri Jan 19 14:48:57 2007 +0000
    63.3 @@ -0,0 +1,373 @@
    63.4 +#============================================================================
    63.5 +# This library is free software; you can redistribute it and/or
    63.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    63.7 +# License as published by the Free Software Foundation.
    63.8 +#
    63.9 +# This library is distributed in the hope that it will be useful,
   63.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   63.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   63.12 +# Lesser General Public License for more details.
   63.13 +#
   63.14 +# You should have received a copy of the GNU Lesser General Public
   63.15 +# License along with this library; if not, write to the Free Software
   63.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   63.17 +#============================================================================
   63.18 +# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
   63.19 +# Copyright (C) 2005 XenSource Ltd
   63.20 +#============================================================================
   63.21 +
   63.22 +"""Xend root class.
   63.23 +Creates the servers and handles configuration.
   63.24 +
   63.25 +Other classes get config variables by importing this module,
   63.26 +using instance() to get a XendOptions instance, and then
   63.27 +the config functions (e.g. get_xend_port()) to get
   63.28 +configured values.
   63.29 +"""
   63.30 +
   63.31 +import os
   63.32 +import os.path
   63.33 +import string
   63.34 +import sys
   63.35 +
   63.36 +from xen.xend import sxp, osdep, XendLogging
   63.37 +from xen.xend.XendError import XendError
   63.38 +
   63.39 +if os.uname()[0] == 'SunOS':
   63.40 +    from xen.lowlevel import scf
   63.41 +
   63.42 +class XendOptions:
   63.43 +    """Configuration options."""
   63.44 +
   63.45 +    """Where network control scripts live."""
   63.46 +    network_script_dir = osdep.scripts_dir
   63.47 +
   63.48 +    """Where block control scripts live."""
   63.49 +    block_script_dir = osdep.scripts_dir
   63.50 +
   63.51 +    """Default path to the log file. """
   63.52 +    logfile_default = "/var/log/xen/xend.log"
   63.53 +
   63.54 +    """Default level of information to be logged."""
   63.55 +    loglevel_default = 'DEBUG'
   63.56 +
   63.57 +    """Default Xen-API server configuration. """
   63.58 +    xen_api_server_default = [['unix']]
   63.59 +
   63.60 +    """Default for the flag indicating whether xend should run an http server
   63.61 +    (deprecated)."""
   63.62 +    xend_http_server_default = 'no'
   63.63 +
   63.64 +    xend_tcp_xmlrpc_server_default = 'no'
   63.65 +
   63.66 +    xend_unix_xmlrpc_server_default = 'yes'
   63.67 +
   63.68 +    """Default interface address xend listens at. """
   63.69 +    xend_address_default      = ''
   63.70 +
   63.71 +    """Default for the flag indicating whether xend should run a relocation server."""
   63.72 +    xend_relocation_server_default = 'no'
   63.73 +
   63.74 +    """Default interface address the xend relocation server listens at. """
   63.75 +    xend_relocation_address_default = ''
   63.76 +
   63.77 +    """Default port xend serves HTTP at. """
   63.78 +    xend_port_default         = 8000
   63.79 +
   63.80 +    """Default port xend serves relocation at. """
   63.81 +    xend_relocation_port_default = 8002
   63.82 +
   63.83 +    xend_relocation_hosts_allow_default = ''
   63.84 +
   63.85 +    """Default for the flag indicating whether xend should run a unix-domain
   63.86 +    server (deprecated)."""
   63.87 +    xend_unix_server_default = 'no'
   63.88 +
   63.89 +    """Default external migration tool """
   63.90 +    external_migration_tool_default = ''
   63.91 +
   63.92 +    """Default path the unix-domain server listens at."""
   63.93 +    xend_unix_path_default = '/var/lib/xend/xend-socket'
   63.94 +
   63.95 +    dom0_min_mem_default = 0
   63.96 +
   63.97 +    dom0_vcpus_default = 0
   63.98 +
   63.99 +    vncpasswd_default = None
  63.100 +
  63.101 +    """Default interface to listen for VNC connections on"""
  63.102 +    xend_vnc_listen_default = '127.0.0.1'
  63.103 +
  63.104 +    """Default session storage path."""
  63.105 +    xend_domains_path_default = '/var/lib/xend/domains'
  63.106 +
  63.107 +    """Default xend management state storage."""
  63.108 +    xend_state_path_default = '/var/lib/xend/state'
  63.109 +
  63.110 +    """Default type of backend network interfaces"""
  63.111 +    netback_type = osdep.netback_type
  63.112 +
  63.113 +    """Default script to configure a backend network interface"""
  63.114 +    vif_script = osdep.vif_script
  63.115 +
  63.116 +    def __init__(self):
  63.117 +        self.configure()
  63.118 +
  63.119 +    def _logError(self, fmt, *args):
  63.120 +        """Logging function to log to stderr. We use this for XendOptions log
  63.121 +        messages because they may be logged before the logger has been
  63.122 +        configured.  Other components can safely use the logger.
  63.123 +        """
  63.124 +        print >>sys.stderr, "xend [ERROR]", fmt % args
  63.125 +
  63.126 +
  63.127 +    def configure(self):
  63.128 +        self.set_config()
  63.129 +        XendLogging.init(self.get_config_string("logfile",
  63.130 +                                               self.logfile_default),
  63.131 +                         self.get_config_string("loglevel",
  63.132 +                                               self.loglevel_default))
  63.133 +
  63.134 +    def set_config(self):
  63.135 +        raise NotImplementedError()
  63.136 +
  63.137 +    def get_config_bool(self, name, val=None):
  63.138 +        raise NotImplementedError()
  63.139 +         
  63.140 +    def get_config_int(self, name, val=None):
  63.141 +        raise NotImplementedError()
  63.142 +
  63.143 +    def get_config_string(self, name, val=None):
  63.144 +        raise NotImplementedError()
  63.145 +
  63.146 +    def get_xen_api_server(self):
  63.147 +        raise NotImplementedError()
  63.148 +
  63.149 +    def get_xend_http_server(self):
  63.150 +        """Get the flag indicating whether xend should run an http server.
  63.151 +        """
  63.152 +        return self.get_config_bool("xend-http-server", self.xend_http_server_default)
  63.153 +
  63.154 +    def get_xend_tcp_xmlrpc_server(self):
  63.155 +        return self.get_config_bool("xend-tcp-xmlrpc-server",
  63.156 +                                    self.xend_tcp_xmlrpc_server_default)
  63.157 +
  63.158 +    def get_xend_unix_xmlrpc_server(self):
  63.159 +        return self.get_config_bool("xend-unix-xmlrpc-server",
  63.160 +                                    self.xend_unix_xmlrpc_server_default)
  63.161 +
  63.162 +    def get_xend_relocation_server(self):
  63.163 +        """Get the flag indicating whether xend should run a relocation server.
  63.164 +        """
  63.165 +        return self.get_config_bool("xend-relocation-server",
  63.166 +                                    self.xend_relocation_server_default)
  63.167 +
  63.168 +    def get_xend_port(self):
  63.169 +        """Get the port xend listens at for its HTTP interface.
  63.170 +        """
  63.171 +        return self.get_config_int('xend-port', self.xend_port_default)
  63.172 +
  63.173 +    def get_xend_relocation_port(self):
  63.174 +        """Get the port xend listens at for connection to its relocation server.
  63.175 +        """
  63.176 +        return self.get_config_int('xend-relocation-port',
  63.177 +                                   self.xend_relocation_port_default)
  63.178 +
  63.179 +    def get_xend_relocation_hosts_allow(self):
  63.180 +        return self.get_config_string("xend-relocation-hosts-allow",
  63.181 +                                     self.xend_relocation_hosts_allow_default)
  63.182 +
  63.183 +    def get_xend_address(self):
  63.184 +        """Get the address xend listens at for its HTTP port.
  63.185 +        This defaults to the empty string which allows all hosts to connect.
  63.186 +        If this is set to 'localhost' only the localhost will be able to connect
  63.187 +        to the HTTP port.
  63.188 +        """
  63.189 +        return self.get_config_string('xend-address', self.xend_address_default)
  63.190 +
  63.191 +    def get_xend_relocation_address(self):
  63.192 +        """Get the address xend listens at for its relocation server port.
  63.193 +        This defaults to the empty string which allows all hosts to connect.
  63.194 +        If this is set to 'localhost' only the localhost will be able to connect
  63.195 +        to the relocation port.
  63.196 +        """
  63.197 +        return self.get_config_string('xend-relocation-address', self.xend_relocation_address_default)
  63.198 +
  63.199 +    def get_xend_unix_server(self):
  63.200 +        """Get the flag indicating whether xend should run a unix-domain server.
  63.201 +        """
  63.202 +        return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
  63.203 +
  63.204 +    def get_xend_unix_path(self):
  63.205 +        """Get the path the xend unix-domain server listens at.
  63.206 +        """
  63.207 +        return self.get_config_string("xend-unix-path", self.xend_unix_path_default)
  63.208 +
  63.209 +    def get_xend_domains_path(self):
  63.210 +        """ Get the path for persistent domain configuration storage
  63.211 +        """
  63.212 +        return self.get_config_string("xend-domains-path", self.xend_domains_path_default)
  63.213 +
  63.214 +    def get_xend_state_path(self):
  63.215 +        """ Get the path for persistent domain configuration storage
  63.216 +        """
  63.217 +        return self.get_config_string("xend-state-path", self.xend_state_path_default)    
  63.218 +
  63.219 +    def get_network_script(self):
  63.220 +        """@return the script used to alter the network configuration when
  63.221 +        Xend starts and stops, or None if no such script is specified."""
  63.222 +        
  63.223 +        s = self.get_config_string('network-script')
  63.224 +
  63.225 +        if s:
  63.226 +            result = s.split(" ")
  63.227 +            result[0] = os.path.join(self.network_script_dir, result[0])
  63.228 +            return result
  63.229 +        else:
  63.230 +            return None
  63.231 +
  63.232 +    def get_external_migration_tool(self):
  63.233 +        """@return the name of the tool to handle virtual TPM migration."""
  63.234 +        return self.get_config_string('external-migration-tool', self.external_migration_tool_default)
  63.235 +
  63.236 +    def get_enable_dump(self):
  63.237 +        return self.get_config_bool('enable-dump', 'no')
  63.238 +
  63.239 +    def get_vif_script(self):
  63.240 +        return self.get_config_string('vif-script', self.vif_script)
  63.241 +
  63.242 +    def get_dom0_min_mem(self):
  63.243 +        return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
  63.244 +
  63.245 +    def get_dom0_vcpus(self):
  63.246 +        return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
  63.247 +
  63.248 +    def get_console_limit(self):
  63.249 +        return self.get_config_int('console-limit', 1024)
  63.250 +
  63.251 +    def get_vnclisten_address(self):
  63.252 +        return self.get_config_string('vnc-listen', self.xend_vnc_listen_default)
  63.253 +
  63.254 +    def get_vncpasswd_default(self):
  63.255 +        return self.get_config_string('vncpasswd',
  63.256 +                                     self.vncpasswd_default)
  63.257 +
  63.258 +class XendOptionsFile(XendOptions):
  63.259 +
  63.260 +    """Default path to the config file."""
  63.261 +    config_default = "/etc/xen/xend-config.sxp"
  63.262 +
  63.263 +    """Environment variable used to override config_default."""
  63.264 +    config_var     = "XEND_CONFIG"
  63.265 +
  63.266 +    def set_config(self):
  63.267 +        """If the config file exists, read it. If not, ignore it.
  63.268 +
  63.269 +        The config file is a sequence of sxp forms.
  63.270 +        """
  63.271 +        self.config_path = os.getenv(self.config_var, self.config_default)
  63.272 +        if os.path.exists(self.config_path):
  63.273 +            try:
  63.274 +                fin = file(self.config_path, 'rb')
  63.275 +                try:
  63.276 +                    config = sxp.parse(fin)
  63.277 +                finally:
  63.278 +                    fin.close()
  63.279 +                if config is None:
  63.280 +                    config = ['xend-config']
  63.281 +                else:
  63.282 +                    config.insert(0, 'xend-config')
  63.283 +                self.config = config
  63.284 +            except Exception, ex:
  63.285 +                self._logError('Reading config file %s: %s',
  63.286 +                               self.config_path, str(ex))
  63.287 +                raise
  63.288 +        else:
  63.289 +            self._logError('Config file does not exist: %s',
  63.290 +                           self.config_path)
  63.291 +            self.config = ['xend-config']
  63.292 +
  63.293 +    def get_config_value(self, name, val=None):
  63.294 +        """Get the value of an atomic configuration element.
  63.295 +
  63.296 +        @param name: element name
  63.297 +        @param val:  default value (optional, defaults to None)
  63.298 +        @return: value
  63.299 +        """
  63.300 +        return sxp.child_value(self.config, name, val=val)
  63.301 +
  63.302 +    def get_config_bool(self, name, val=None):
  63.303 +        v = string.lower(str(self.get_config_value(name, val)))
  63.304 +        if v in ['yes', 'y', '1', 'on',  'true',  't']:
  63.305 +            return True
  63.306 +        if v in ['no',  'n', '0', 'off', 'false', 'f']:
  63.307 +            return False
  63.308 +        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
  63.309 +
  63.310 +    def get_config_int(self, name, val=None):
  63.311 +        v = self.get_config_value(name, val)
  63.312 +        try:
  63.313 +            return int(v)
  63.314 +        except Exception:
  63.315 +            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
  63.316 +
  63.317 +    def get_config_string(self, name, val=None):
  63.318 +        return self.get_config_value(name, val)
  63.319 +
  63.320 +    def get_xen_api_server(self):
  63.321 +        """Get the Xen-API server configuration.
  63.322 +        """
  63.323 +        return self.get_config_value('xen-api-server',
  63.324 +                                     self.xen_api_server_default)
  63.325 +
  63.326 +if os.uname()[0] == 'SunOS':
  63.327 +    class XendOptionsSMF(XendOptions):
  63.328 +
  63.329 +        def set_config(self):
  63.330 +            pass
  63.331 +
  63.332 +        def get_config_bool(self, name, val=None):
  63.333 +            try:
  63.334 +                return scf.get_bool(name)
  63.335 +            except scf.error, e:
  63.336 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
  63.337 +                    return val
  63.338 +                else:
  63.339 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
  63.340 +
  63.341 +        def get_config_int(self, name, val=None):
  63.342 +            try:
  63.343 +                return scf.get_int(name)
  63.344 +            except scf.error, e:
  63.345 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
  63.346 +                    return val
  63.347 +                else:
  63.348 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
  63.349 +
  63.350 +        def get_config_string(self, name, val=None):
  63.351 +            try:
  63.352 +                return scf.get_string(name)
  63.353 +            except scf.error, e:
  63.354 +                if e[0] == scf.SCF_ERROR_NOT_FOUND:
  63.355 +                    return val
  63.356 +                else:
  63.357 +                    raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
  63.358 +
  63.359 +        def get_xen_api_server(self):
  63.360 +            # When the new server is a supported configuration, we should
  63.361 +            # expand this.
  63.362 +            return [["unix"]]
  63.363 +
  63.364 +def instance():
  63.365 +    """Get an instance of XendOptions.
  63.366 +    Use this instead of the constructor.
  63.367 +    """
  63.368 +    global inst
  63.369 +    try:
  63.370 +        inst
  63.371 +    except:
  63.372 +        if os.uname()[0] == 'SunOS':
  63.373 +            inst = XendOptionsSMF()
  63.374 +        else:
  63.375 +            inst = XendOptionsFile()
  63.376 +    return inst
    64.1 --- a/tools/python/xen/xend/XendProtocol.py	Thu Jan 18 15:18:07 2007 +0000
    64.2 +++ b/tools/python/xen/xend/XendProtocol.py	Fri Jan 19 14:48:57 2007 +0000
    64.3 @@ -24,7 +24,7 @@ import types
    64.4  from encode import *
    64.5  from xen.xend import sxp
    64.6  
    64.7 -from xen.xend import XendRoot
    64.8 +from xen.xend import XendOptions
    64.9  
   64.10  DEBUG = 0
   64.11  
   64.12 @@ -34,7 +34,7 @@ HTTP_ACCEPTED                        = 2
   64.13  HTTP_NO_CONTENT                      = 204
   64.14  
   64.15  
   64.16 -xroot = XendRoot.instance()
   64.17 +xoptions = XendOptions.instance()
   64.18  
   64.19  
   64.20  class XendError(RuntimeError):
   64.21 @@ -218,7 +218,7 @@ class UnixXendClientProtocol(HttpXendCli
   64.22  
   64.23      def __init__(self, path=None):
   64.24          if path is None:
   64.25 -            path = xroot.get_xend_unix_path()
   64.26 +            path = xoptions.get_xend_unix_path()
   64.27          self.path = path
   64.28  
   64.29      def makeConnection(self, _):
    65.1 --- a/tools/python/xen/xend/XendRoot.py	Thu Jan 18 15:18:07 2007 +0000
    65.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.3 @@ -1,322 +0,0 @@
    65.4 -#============================================================================
    65.5 -# This library is free software; you can redistribute it and/or
    65.6 -# modify it under the terms of version 2.1 of the GNU Lesser General Public
    65.7 -# License as published by the Free Software Foundation.
    65.8 -#
    65.9 -# This library is distributed in the hope that it will be useful,
   65.10 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
   65.11 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   65.12 -# Lesser General Public License for more details.
   65.13 -#
   65.14 -# You should have received a copy of the GNU Lesser General Public
   65.15 -# License along with this library; if not, write to the Free Software
   65.16 -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   65.17 -#============================================================================
   65.18 -# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
   65.19 -# Copyright (C) 2005 XenSource Ltd
   65.20 -#============================================================================
   65.21 -
   65.22 -"""Xend root class.
   65.23 -Creates the servers and handles configuration.
   65.24 -
   65.25 -Other classes get config variables by importing this module,
   65.26 -using instance() to get a XendRoot instance, and then
   65.27 -the config functions (e.g. get_xend_port()) to get
   65.28 -configured values.
   65.29 -"""
   65.30 -
   65.31 -import os
   65.32 -import os.path
   65.33 -import string
   65.34 -import sys
   65.35 -
   65.36 -from xen.xend import sxp, osdep, XendLogging
   65.37 -from xen.xend.XendError import XendError
   65.38 -
   65.39 -class XendRoot:
   65.40 -    """Root of the management classes."""
   65.41 -
   65.42 -    """Default path to the config file."""
   65.43 -    config_default = "/etc/xen/xend-config.sxp"
   65.44 -
   65.45 -    """Environment variable used to override config_default."""
   65.46 -    config_var     = "XEND_CONFIG"
   65.47 -
   65.48 -    """Where network control scripts live."""
   65.49 -    network_script_dir = osdep.scripts_dir
   65.50 -
   65.51 -    """Where block control scripts live."""
   65.52 -    block_script_dir = osdep.scripts_dir
   65.53 -
   65.54 -    """Default path to the log file. """
   65.55 -    logfile_default = "/var/log/xen/xend.log"
   65.56 -
   65.57 -    """Default level of information to be logged."""
   65.58 -    loglevel_default = 'DEBUG'
   65.59 -
   65.60 -    """Default Xen-API server configuration. """
   65.61 -    xen_api_server_default = [['unix']]
   65.62 -
   65.63 -    """Default for the flag indicating whether xend should run an http server
   65.64 -    (deprecated)."""
   65.65 -    xend_http_server_default = 'no'
   65.66 -
   65.67 -    xend_tcp_xmlrpc_server_default = 'no'
   65.68 -
   65.69 -    xend_unix_xmlrpc_server_default = 'yes'
   65.70 -
   65.71 -    """Default interface address xend listens at. """
   65.72 -    xend_address_default      = ''
   65.73 -
   65.74 -    """Default for the flag indicating whether xend should run a relocation server."""
   65.75 -    xend_relocation_server_default = 'no'
   65.76 -
   65.77 -    """Default interface address the xend relocation server listens at. """
   65.78 -    xend_relocation_address_default = ''
   65.79 -
   65.80 -    """Default port xend serves HTTP at. """
   65.81 -    xend_port_default         = '8000'
   65.82 -
   65.83 -    """Default port xend serves relocation at. """
   65.84 -    xend_relocation_port_default = '8002'
   65.85 -
   65.86 -    xend_relocation_hosts_allow_default = ''
   65.87 -
   65.88 -    """Default for the flag indicating whether xend should run a unix-domain
   65.89 -    server (deprecated)."""
   65.90 -    xend_unix_server_default = 'no'
   65.91 -
   65.92 -    """Default external migration tool """
   65.93 -    external_migration_tool_default = ''
   65.94 -
   65.95 -    """Default path the unix-domain server listens at."""
   65.96 -    xend_unix_path_default = '/var/lib/xend/xend-socket'
   65.97 -
   65.98 -    dom0_min_mem_default = '0'
   65.99 -
  65.100 -    dom0_vcpus_default = '0'
  65.101 -
  65.102 -    vncpasswd_default = None
  65.103 -
  65.104 -    """Default interface to listen for VNC connections on"""
  65.105 -    xend_vnc_listen_default = '127.0.0.1'
  65.106 -
  65.107 -    """Default session storage path."""
  65.108 -    xend_domains_path_default = '/var/lib/xend/domains'
  65.109 -
  65.110 -    """Default xend management state storage."""
  65.111 -    xend_state_path_default = '/var/lib/xend/state'
  65.112 -
  65.113 -    components = {}
  65.114 -
  65.115 -    def __init__(self):
  65.116 -        self.config_path = None
  65.117 -        self.config = None
  65.118 -        self.configure()
  65.119 -
  65.120 -
  65.121 -    def _logError(self, fmt, *args):
  65.122 -        """Logging function to log to stderr. We use this for XendRoot log
  65.123 -        messages because they may be logged before the logger has been
  65.124 -        configured.  Other components can safely use the logger.
  65.125 -        """
  65.126 -        print >>sys.stderr, "xend [ERROR]", fmt % args
  65.127 -
  65.128 -
  65.129 -    def configure(self):
  65.130 -        self.set_config()
  65.131 -        XendLogging.init(self.get_config_value("logfile",
  65.132 -                                               self.logfile_default),
  65.133 -                         self.get_config_value("loglevel",
  65.134 -                                               self.loglevel_default))
  65.135 -
  65.136 -
  65.137 -    def set_config(self):
  65.138 -        """If the config file exists, read it. If not, ignore it.
  65.139 -
  65.140 -        The config file is a sequence of sxp forms.
  65.141 -        """
  65.142 -        self.config_path = os.getenv(self.config_var, self.config_default)
  65.143 -        if os.path.exists(self.config_path):
  65.144 -            try:
  65.145 -                fin = file(self.config_path, 'rb')
  65.146 -                try:
  65.147 -                    config = sxp.parse(fin)
  65.148 -                finally:
  65.149 -                    fin.close()
  65.150 -                if config is None:
  65.151 -                    config = ['xend-config']
  65.152 -                else:
  65.153 -                    config.insert(0, 'xend-config')
  65.154 -                self.config = config
  65.155 -            except Exception, ex:
  65.156 -                self._logError('Reading config file %s: %s',
  65.157 -                               self.config_path, str(ex))
  65.158 -                raise
  65.159 -        else:
  65.160 -            self._logError('Config file does not exist: %s',
  65.161 -                           self.config_path)
  65.162 -            self.config = ['xend-config']
  65.163 -
  65.164 -    def get_config(self, name=None):
  65.165 -        """Get the configuration element with the given name, or
  65.166 -        the whole configuration if no name is given.
  65.167 -
  65.168 -        @param name: element name (optional)
  65.169 -        @return: config or none
  65.170 -        """
  65.171 -        if name is None:
  65.172 -            val = self.config
  65.173 -        else:
  65.174 -            val = sxp.child(self.config, name)
  65.175 -        return val
  65.176 -
  65.177 -    def get_config_value(self, name, val=None):
  65.178 -        """Get the value of an atomic configuration element.
  65.179 -
  65.180 -        @param name: element name
  65.181 -        @param val:  default value (optional, defaults to None)
  65.182 -        @return: value
  65.183 -        """
  65.184 -        return sxp.child_value(self.config, name, val=val)
  65.185 -
  65.186 -    def get_config_bool(self, name, val=None):
  65.187 -        v = string.lower(str(self.get_config_value(name, val)))
  65.188 -        if v in ['yes', 'y', '1', 'on',  'true',  't']:
  65.189 -            return True
  65.190 -        if v in ['no',  'n', '0', 'off', 'false', 'f']:
  65.191 -            return False
  65.192 -        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
  65.193 -
  65.194 -    def get_config_int(self, name, val=None):
  65.195 -        v = self.get_config_value(name, val)
  65.196 -        try:
  65.197 -            return int(v)
  65.198 -        except Exception:
  65.199 -            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
  65.200 -
  65.201 -    def get_xen_api_server(self):
  65.202 -        """Get the Xen-API server configuration.
  65.203 -        """
  65.204 -        return self.get_config_value('xen-api-server',
  65.205 -                                     self.xen_api_server_default)
  65.206 -
  65.207 -    def get_xend_http_server(self):
  65.208 -        """Get the flag indicating whether xend should run an http server.
  65.209 -        """
  65.210 -        return self.get_config_bool("xend-http-server", self.xend_http_server_default)
  65.211 -
  65.212 -    def get_xend_tcp_xmlrpc_server(self):
  65.213 -        return self.get_config_bool("xend-tcp-xmlrpc-server",
  65.214 -                                    self.xend_tcp_xmlrpc_server_default)
  65.215 -
  65.216 -    def get_xend_unix_xmlrpc_server(self):
  65.217 -        return self.get_config_bool("xend-unix-xmlrpc-server",
  65.218 -                                    self.xend_unix_xmlrpc_server_default)
  65.219 -
  65.220 -    def get_xend_relocation_server(self):
  65.221 -        """Get the flag indicating whether xend should run a relocation server.
  65.222 -        """
  65.223 -        return self.get_config_bool("xend-relocation-server",
  65.224 -                                    self.xend_relocation_server_default)
  65.225 -
  65.226 -    def get_xend_port(self):
  65.227 -        """Get the port xend listens at for its HTTP interface.
  65.228 -        """
  65.229 -        return self.get_config_int('xend-port', self.xend_port_default)
  65.230 -
  65.231 -    def get_xend_relocation_port(self):
  65.232 -        """Get the port xend listens at for connection to its relocation server.
  65.233 -        """
  65.234 -        return self.get_config_int('xend-relocation-port',
  65.235 -                                   self.xend_relocation_port_default)
  65.236 -
  65.237 -    def get_xend_relocation_hosts_allow(self):
  65.238 -        return self.get_config_value("xend-relocation-hosts-allow",
  65.239 -                                     self.xend_relocation_hosts_allow_default)
  65.240 -
  65.241 -    def get_xend_address(self):
  65.242 -        """Get the address xend listens at for its HTTP port.
  65.243 -        This defaults to the empty string which allows all hosts to connect.
  65.244 -        If this is set to 'localhost' only the localhost will be able to connect
  65.245 -        to the HTTP port.
  65.246 -        """
  65.247 -        return self.get_config_value('xend-address', self.xend_address_default)
  65.248 -
  65.249 -    def get_xend_relocation_address(self):
  65.250 -        """Get the address xend listens at for its relocation server port.
  65.251 -        This defaults to the empty string which allows all hosts to connect.
  65.252 -        If this is set to 'localhost' only the localhost will be able to connect
  65.253 -        to the relocation port.
  65.254 -        """
  65.255 -        return self.get_config_value('xend-relocation-address', self.xend_relocation_address_default)
  65.256 -
  65.257 -    def get_xend_unix_server(self):
  65.258 -        """Get the flag indicating whether xend should run a unix-domain server.
  65.259 -        """
  65.260 -        return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
  65.261 -
  65.262 -    def get_xend_unix_path(self):
  65.263 -        """Get the path the xend unix-domain server listens at.
  65.264 -        """
  65.265 -        return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
  65.266 -
  65.267 -    def get_xend_domains_path(self):
  65.268 -        """ Get the path for persistent domain configuration storage
  65.269 -        """
  65.270 -        return self.get_config_value("xend-domains-path", self.xend_domains_path_default)
  65.271 -
  65.272 -    def get_xend_state_path(self):
  65.273 -        """ Get the path for persistent domain configuration storage
  65.274 -        """
  65.275 -        return self.get_config_value("xend-state-path", self.xend_state_path_default)    
  65.276 -
  65.277 -    def get_network_script(self):
  65.278 -        """@return the script used to alter the network configuration when
  65.279 -        Xend starts and stops, or None if no such script is specified."""
  65.280 -        
  65.281 -        s = self.get_config_value('network-script')
  65.282 -
  65.283 -        if s:
  65.284 -            result = s.split(" ")
  65.285 -            result[0] = os.path.join(self.network_script_dir, result[0])
  65.286 -            return result
  65.287 -        else:
  65.288 -            return None
  65.289 -
  65.290 -    def get_external_migration_tool(self):
  65.291 -        """@return the name of the tool to handle virtual TPM migration."""
  65.292 -        return self.get_config_value('external-migration-tool', self.external_migration_tool_default)
  65.293 -
  65.294 -    def get_enable_dump(self):
  65.295 -        return self.get_config_bool('enable-dump', 'no')
  65.296 -
  65.297 -    def get_vif_script(self):
  65.298 -        return self.get_config_value('vif-script', 'vif-bridge')
  65.299 -
  65.300 -    def get_dom0_min_mem(self):
  65.301 -        return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
  65.302 -
  65.303 -    def get_dom0_vcpus(self):
  65.304 -        return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
  65.305 -
  65.306 -    def get_console_limit(self):
  65.307 -        return self.get_config_int('console-limit', 1024)
  65.308 -
  65.309 -    def get_vnclisten_address(self):
  65.310 -        return self.get_config_value('vnc-listen', self.xend_vnc_listen_default)
  65.311 -
  65.312 -    def get_vncpasswd_default(self):
  65.313 -        return self.get_config_value('vncpasswd',
  65.314 -                                     self.vncpasswd_default)
  65.315 -
  65.316 -def instance():
  65.317 -    """Get an instance of XendRoot.
  65.318 -    Use this instead of the constructor.
  65.319 -    """
  65.320 -    global inst
  65.321 -    try:
  65.322 -        inst
  65.323 -    except:
  65.324 -        inst = XendRoot()
  65.325 -    return inst
    66.1 --- a/tools/python/xen/xend/balloon.py	Thu Jan 18 15:18:07 2007 +0000
    66.2 +++ b/tools/python/xen/xend/balloon.py	Fri Jan 19 14:48:57 2007 +0000
    66.3 @@ -22,7 +22,7 @@ import time
    66.4  import xen.lowlevel.xc
    66.5  
    66.6  import XendDomain
    66.7 -import XendRoot
    66.8 +import XendOptions
    66.9  from XendLogging import log
   66.10  from XendError import VmError
   66.11  
   66.12 @@ -107,11 +107,11 @@ def free(need_mem):
   66.13      # usage, so we recheck the required alloc each time around the loop, but
   66.14      # track the last used value so that we don't trigger too many watches.
   66.15  
   66.16 -    xroot = XendRoot.instance()
   66.17 +    xoptions = XendOptions.instance()
   66.18      xc = xen.lowlevel.xc.xc()
   66.19  
   66.20      try:
   66.21 -        dom0_min_mem = xroot.get_dom0_min_mem() * 1024
   66.22 +        dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
   66.23  
   66.24          retries = 0
   66.25          sleep_time = SLEEP_TIME_GROWTH
    67.1 --- a/tools/python/xen/xend/image.py	Thu Jan 18 15:18:07 2007 +0000
    67.2 +++ b/tools/python/xen/xend/image.py	Fri Jan 19 14:48:57 2007 +0000
    67.3 @@ -173,7 +173,7 @@ class ImageHandler:
    67.4          """Build the domain. Define in subclass."""
    67.5          raise NotImplementedError()
    67.6  
    67.7 -    def createDeviceModel(self):
    67.8 +    def createDeviceModel(self, restore = False):
    67.9          """Create device model for the domain (define in subclass if needed)."""
   67.10          pass
   67.11      
   67.12 @@ -377,11 +377,12 @@ class HVMImageHandler(ImageHandler):
   67.13      # xm config file
   67.14      def parseDeviceModelArgs(self, imageConfig, deviceConfig):
   67.15          dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
   67.16 -                   'localtime', 'serial', 'stdvga', 'isa', 'vcpus',
   67.17 +                   'localtime', 'serial', 'stdvga', 'isa',
   67.18                     'acpi', 'usb', 'usbdevice', 'keymap' ]
   67.19 -        ret = []
   67.20          hvmDeviceConfig = imageConfig['hvm']['devices']
   67.21 -        
   67.22 +
   67.23 +        ret = ['-vcpus', str(self.vm.getVCpuCount())]
   67.24 +
   67.25          for a in dmargs:
   67.26              v = hvmDeviceConfig.get(a)
   67.27  
   67.28 @@ -461,14 +462,14 @@ class HVMImageHandler(ImageHandler):
   67.29              vnclisten = imageConfig.get('vnclisten')
   67.30  
   67.31              if not(vnclisten):
   67.32 -                vnclisten = (xen.xend.XendRoot.instance().
   67.33 +                vnclisten = (xen.xend.XendOptions.instance().
   67.34                               get_vnclisten_address())
   67.35              if vnclisten:
   67.36                  ret += ['-vnclisten', vnclisten]
   67.37  
   67.38              vncpasswd = vncpasswd_vmconfig
   67.39              if vncpasswd is None:
   67.40 -                vncpasswd = (xen.xend.XendRoot.instance().
   67.41 +                vncpasswd = (xen.xend.XendOptions.instance().
   67.42                               get_vncpasswd_default())
   67.43                  if vncpasswd is None:
   67.44                      raise VmError('vncpasswd is not set up in ' +
   67.45 @@ -478,7 +479,7 @@ class HVMImageHandler(ImageHandler):
   67.46  
   67.47          return ret
   67.48  
   67.49 -    def createDeviceModel(self):
   67.50 +    def createDeviceModel(self, restore = False):
   67.51          if self.pid:
   67.52              return
   67.53          # Execute device model.
   67.54 @@ -487,6 +488,8 @@ class HVMImageHandler(ImageHandler):
   67.55          args = args + ([ "-d",  "%d" % self.vm.getDomid(),
   67.56                    "-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
   67.57          args = args + self.dmargs
   67.58 +        if restore:
   67.59 +            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % self.vm.getDomid() ])
   67.60          env = dict(os.environ)
   67.61          if self.display:
   67.62              env['DISPLAY'] = self.display
   67.63 @@ -505,12 +508,16 @@ class HVMImageHandler(ImageHandler):
   67.64          self.register_reboot_feature_watch()
   67.65          self.pid = self.vm.gatherDom(('image/device-model-pid', int))
   67.66  
   67.67 -    def destroy(self):
   67.68 +    def destroy(self, suspend = False):
   67.69          self.unregister_shutdown_watch()
   67.70          self.unregister_reboot_feature_watch();
   67.71          if self.pid:
   67.72              try:
   67.73 -                os.kill(self.pid, signal.SIGKILL)
   67.74 +                sig = signal.SIGKILL
   67.75 +                if suspend:
   67.76 +                    log.info("use sigusr1 to signal qemu %d", self.pid)
   67.77 +                    sig = signal.SIGUSR1
   67.78 +                os.kill(self.pid, sig)
   67.79              except OSError, exn:
   67.80                  log.exception(exn)
   67.81              try:
   67.82 @@ -599,6 +606,9 @@ class IA64_HVM_ImageHandler(HVMImageHand
   67.83          extra_pages = 1024 + 3
   67.84          return mem_kb + extra_pages * page_kb
   67.85  
   67.86 +    def getRequiredInitialReservation(self):
   67.87 +        return self.vm.getMemoryTarget()
   67.88 +
   67.89      def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
   67.90          # Explicit shadow memory is not a concept 
   67.91          return 0
    68.1 --- a/tools/python/xen/xend/osdep.py	Thu Jan 18 15:18:07 2007 +0000
    68.2 +++ b/tools/python/xen/xend/osdep.py	Fri Jan 19 14:48:57 2007 +0000
    68.3 @@ -33,9 +33,19 @@ import os
    68.4      "SunOS": "/usr/lib/xen/bin/pygrub"
    68.5  }
    68.6  
    68.7 +_netback_type = {
    68.8 +    "SunOS": "SUNW_mac"
    68.9 +}
   68.10 +
   68.11 +_vif_script = {
   68.12 +    "SunOS": "vif-vnic"
   68.13 +}
   68.14 +
   68.15  def _get(var, default=None):
   68.16      return var.get(os.uname()[0], default)
   68.17  
   68.18  scripts_dir = _get(_scripts_dir, "/etc/xen/scripts")
   68.19  xend_autorestart = _get(_xend_autorestart)
   68.20  pygrub_path = _get(_pygrub_path, "/usr/bin/pygrub")
   68.21 +netback_type = _get(_netback_type, "netfront")
   68.22 +vif_script = _get(_vif_script, "vif-bridge")
    69.1 --- a/tools/python/xen/xend/server/DevController.py	Thu Jan 18 15:18:07 2007 +0000
    69.2 +++ b/tools/python/xen/xend/server/DevController.py	Fri Jan 19 14:48:57 2007 +0000
    69.3 @@ -19,7 +19,7 @@
    69.4  from threading import Event
    69.5  import types
    69.6  
    69.7 -from xen.xend import sxp, XendRoot
    69.8 +from xen.xend import sxp, XendOptions
    69.9  from xen.xend.XendError import VmError
   69.10  from xen.xend.XendLogging import log
   69.11  
   69.12 @@ -50,7 +50,7 @@ xenbusState = {
   69.13      'Closed'       : 6,
   69.14      }
   69.15  
   69.16 -xroot = XendRoot.instance()
   69.17 +xoptions = XendOptions.instance()
   69.18  
   69.19  xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys())))
   69.20  
   69.21 @@ -324,7 +324,7 @@ class DevController:
   69.22                        Make sure that the migration has finished and only
   69.23                        then return from the call.
   69.24          """
   69.25 -        tool = xroot.get_external_migration_tool()
   69.26 +        tool = xoptions.get_external_migration_tool()
   69.27          if tool:
   69.28              log.info("Calling external migration tool for step %d" % step)
   69.29              fd = os.popen("%s -type %s -step %d -host %s -domname %s" %
   69.30 @@ -341,7 +341,7 @@ class DevController:
   69.31          """ Recover from device migration. The given step was the
   69.32              last one that was successfully executed.
   69.33          """
   69.34 -        tool = xroot.get_external_migration_tool()
   69.35 +        tool = xoptions.get_external_migration_tool()
   69.36          if tool:
   69.37              log.info("Calling external migration tool")
   69.38              fd = os.popen("%s -type %s -step %d -host %s -domname %s -recover" %
    70.1 --- a/tools/python/xen/xend/server/SrvRoot.py	Thu Jan 18 15:18:07 2007 +0000
    70.2 +++ b/tools/python/xen/xend/server/SrvRoot.py	Fri Jan 19 14:48:57 2007 +0000
    70.3 @@ -25,7 +25,7 @@ class SrvRoot(SrvDir):
    70.4      """Server sub-components. Each entry is (name, class), where
    70.5      'name' is the entry name and  'class' is the name of its class.
    70.6      """
    70.7 -    #todo Get this list from the XendRoot config.
    70.8 +    #todo Get this list from the XendOptions config.
    70.9      subdirs = [
   70.10          ('node',    'SrvNode'       ),
   70.11          ('domain',  'SrvDomainDir'  ),
    71.1 --- a/tools/python/xen/xend/server/SrvServer.py	Thu Jan 18 15:18:07 2007 +0000
    71.2 +++ b/tools/python/xen/xend/server/SrvServer.py	Fri Jan 19 14:48:57 2007 +0000
    71.3 @@ -48,7 +48,7 @@ from threading import Thread
    71.4  
    71.5  from xen.web.httpserver import HttpServer, UnixHttpServer
    71.6  
    71.7 -from xen.xend import XendNode, XendRoot, XendAPI
    71.8 +from xen.xend import XendNode, XendOptions, XendAPI
    71.9  from xen.xend import Vifctl
   71.10  from xen.xend.XendLogging import log
   71.11  from xen.xend.XendClient import XEN_API_SOCKET
   71.12 @@ -57,7 +57,7 @@ from xen.web.SrvDir import SrvDir
   71.13  from SrvRoot import SrvRoot
   71.14  from XMLRPCServer import XMLRPCServer
   71.15  
   71.16 -xroot = XendRoot.instance()
   71.17 +xoptions = XendOptions.instance()
   71.18  
   71.19  
   71.20  class XendServers:
   71.21 @@ -65,6 +65,7 @@ class XendServers:
   71.22      def __init__(self, root):
   71.23          self.servers = []
   71.24          self.root = root
   71.25 +        self.running = False
   71.26          self.cleaningUp = False
   71.27          self.reloadingConfig = False
   71.28  
   71.29 @@ -79,6 +80,7 @@ class XendServers:
   71.30                  server.shutdown()
   71.31              except:
   71.32                  pass
   71.33 +        self.running = False
   71.34  
   71.35      def reloadConfig(self, signum = 0, frame = None):
   71.36          log.debug("SrvServer.reloadConfig()")
   71.37 @@ -107,13 +109,12 @@ class XendServers:
   71.38                  if server.ready:
   71.39                      continue
   71.40  
   71.41 -                thread = Thread(target=server.run, name=server.__class__.__name__)
   71.42 -                if isinstance(server, HttpServer):
   71.43 -                    thread.setDaemon(True)
   71.44 +                thread = Thread(target=server.run,
   71.45 +                                name=server.__class__.__name__)
   71.46 +                thread.setDaemon(True)
   71.47                  thread.start()
   71.48                  threads.append(thread)
   71.49  
   71.50 -
   71.51              # check for when all threads have initialized themselves and then
   71.52              # close the status pipe
   71.53  
   71.54 @@ -143,47 +144,32 @@ class XendServers:
   71.55                  status.close()
   71.56                  status = None
   71.57  
   71.58 -            # Interruptible Thread.join - Python Bug #1167930
   71.59 -            #   Replaces: for t in threads: t.join()
   71.60 -            #   Reason:   The above will cause python signal handlers to be
   71.61 -            #             blocked so we're not able to catch SIGTERM in any
   71.62 -            #             way for cleanup
   71.63 -            runningThreads = threads
   71.64 -            while len(runningThreads) > 0:
   71.65 -                try:
   71.66 -                    for t in threads:
   71.67 -                        t.join(1.0)
   71.68 -                    runningThreads = [t for t in threads
   71.69 -                                      if t.isAlive() and not t.isDaemon()]
   71.70 -                    if self.cleaningUp and len(runningThreads) > 0:
   71.71 -                        log.debug("Waiting for %s." %
   71.72 -                                  [x.getName() for x in runningThreads])
   71.73 -                except:
   71.74 -                    pass
   71.75 -
   71.76 +            # loop to keep main thread alive until it receives a SIGTERM
   71.77 +            self.running = True
   71.78 +            while self.running:
   71.79 +                time.sleep(100000000)
   71.80 +                
   71.81              if self.reloadingConfig:
   71.82                  log.info("Restarting all XML-RPC and Xen-API servers...")
   71.83                  self.cleaningUp = False
   71.84                  self.reloadingConfig = False
   71.85 -                xroot.set_config()
   71.86 -                new_servers = [x for x in self.servers
   71.87 -                               if isinstance(x, HttpServer)]
   71.88 -                self.servers = new_servers
   71.89 +                xoptions.set_config()
   71.90 +                self.servers = []
   71.91                  _loadConfig(self, self.root, True)
   71.92              else:
   71.93                  break
   71.94  
   71.95  def _loadConfig(servers, root, reload):
   71.96 -    if not reload and xroot.get_xend_http_server():
   71.97 +    if xoptions.get_xend_http_server():
   71.98          servers.add(HttpServer(root,
   71.99 -                               xroot.get_xend_address(),
  71.100 -                               xroot.get_xend_port()))
  71.101 -    if not reload and xroot.get_xend_unix_server():
  71.102 -        path = xroot.get_xend_unix_path()
  71.103 +                               xoptions.get_xend_address(),
  71.104 +                               xoptions.get_xend_port()))
  71.105 +    if  xoptions.get_xend_unix_server():
  71.106 +        path = xoptions.get_xend_unix_path()
  71.107          log.info('unix path=' + path)
  71.108          servers.add(UnixHttpServer(root, path))
  71.109  
  71.110 -    api_cfg = xroot.get_xen_api_server()
  71.111 +    api_cfg = xoptions.get_xen_api_server()
  71.112      if api_cfg:
  71.113          try:
  71.114              addrs = [(str(x[0]).split(':'),
  71.115 @@ -218,10 +204,10 @@ def _loadConfig(servers, root, reload):
  71.116          except TypeError, exn:
  71.117              log.error('Xen-API server configuration %s is invalid.', api_cfg)
  71.118  
  71.119 -    if xroot.get_xend_tcp_xmlrpc_server():
  71.120 +    if xoptions.get_xend_tcp_xmlrpc_server():
  71.121          servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, True))
  71.122  
  71.123 -    if xroot.get_xend_unix_xmlrpc_server():
  71.124 +    if xoptions.get_xend_unix_xmlrpc_server():
  71.125          servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
  71.126  
  71.127  
    72.1 --- a/tools/python/xen/xend/server/XMLRPCServer.py	Thu Jan 18 15:18:07 2007 +0000
    72.2 +++ b/tools/python/xen/xend/server/XMLRPCServer.py	Fri Jan 19 14:48:57 2007 +0000
    72.3 @@ -179,21 +179,24 @@ class XMLRPCServer:
    72.4          # Custom runloop so we can cleanup when exiting.
    72.5          # -----------------------------------------------------------------
    72.6          try:
    72.7 -            self.server.socket.settimeout(1.0)
    72.8              while self.running:
    72.9                  self.server.handle_request()
   72.10          finally:
   72.11 -            self.cleanup()
   72.12 +            self.shutdown()
   72.13  
   72.14      def cleanup(self):
   72.15 -        log.debug("XMLRPCServer.cleanup()")
   72.16 +        log.debug('XMLRPCServer.cleanup()')
   72.17          try:
   72.18 -            self.server.socket.close()
   72.19 +            if hasattr(self, 'server'):
   72.20 +                # shutdown socket explicitly to allow reuse
   72.21 +                self.server.socket.shutdown(socket.SHUT_RDWR)
   72.22 +                self.server.socket.close()
   72.23          except Exception, exn:
   72.24              log.exception(exn)
   72.25              pass
   72.26  
   72.27      def shutdown(self):
   72.28          self.running = False
   72.29 -        self.ready = False
   72.30 -
   72.31 +        if self.ready:
   72.32 +            self.ready = False
   72.33 +            self.cleanup()
    73.1 --- a/tools/python/xen/xend/server/netif.py	Thu Jan 18 15:18:07 2007 +0000
    73.2 +++ b/tools/python/xen/xend/server/netif.py	Fri Jan 19 14:48:57 2007 +0000
    73.3 @@ -24,10 +24,10 @@ import os
    73.4  import random
    73.5  import re
    73.6  
    73.7 -from xen.xend import XendRoot
    73.8 +from xen.xend import XendOptions
    73.9  from xen.xend.server.DevController import DevController
   73.10  
   73.11 -xroot = XendRoot.instance()
   73.12 +xoptions = XendOptions.instance()
   73.13  
   73.14  def randomMAC():
   73.15      """Generate a random MAC address.
   73.16 @@ -138,8 +138,8 @@ class NetifController(DevController):
   73.17      def getDeviceDetails(self, config):
   73.18          """@see DevController.getDeviceDetails"""
   73.19  
   73.20 -        script = os.path.join(xroot.network_script_dir,
   73.21 -                              config.get('script', xroot.get_vif_script()))
   73.22 +        script = os.path.join(xoptions.network_script_dir,
   73.23 +                              config.get('script', xoptions.get_vif_script()))
   73.24          typ     = config.get('type')
   73.25          bridge  = config.get('bridge')
   73.26          mac     = config.get('mac')
   73.27 @@ -150,9 +150,8 @@ class NetifController(DevController):
   73.28  
   73.29          devid = self.allocateDeviceID()
   73.30  
   73.31 -        # The default type is 'netfront'.
   73.32          if not typ:
   73.33 -            typ = 'netfront'
   73.34 +            typ = xoptions.netback_type
   73.35              
   73.36          if not mac:
   73.37              mac = randomMAC()
   73.38 @@ -190,7 +189,7 @@ class NetifController(DevController):
   73.39          (script, ip, bridge, mac, typ, vifname, rate, uuid) = devinfo
   73.40  
   73.41          if script:
   73.42 -            network_script_dir = xroot.network_script_dir + os.sep
   73.43 +            network_script_dir = xoptions.network_script_dir + os.sep
   73.44              result['script'] = script.replace(network_script_dir, "")
   73.45          if ip:
   73.46              result['ip'] = ip
    74.1 --- a/tools/python/xen/xend/server/relocate.py	Thu Jan 18 15:18:07 2007 +0000
    74.2 +++ b/tools/python/xen/xend/server/relocate.py	Fri Jan 19 14:48:57 2007 +0000
    74.3 @@ -24,7 +24,7 @@ from xen.web import protocol, tcp, unix
    74.4  
    74.5  from xen.xend import sxp
    74.6  from xen.xend import XendDomain
    74.7 -from xen.xend import XendRoot
    74.8 +from xen.xend import XendOptions
    74.9  from xen.xend.XendError import XendError
   74.10  from xen.xend.XendLogging import log
   74.11  
   74.12 @@ -114,15 +114,15 @@ class RelocationProtocol(protocol.Protoc
   74.13  
   74.14  
   74.15  def listenRelocation():
   74.16 -    xroot = XendRoot.instance()
   74.17 -    if xroot.get_xend_unix_server():
   74.18 +    xoptions = XendOptions.instance()
   74.19 +    if xoptions.get_xend_unix_server():
   74.20          path = '/var/lib/xend/relocation-socket'
   74.21          unix.UnixListener(path, RelocationProtocol)
   74.22 -    if xroot.get_xend_relocation_server():
   74.23 -        port = xroot.get_xend_relocation_port()
   74.24 -        interface = xroot.get_xend_relocation_address()
   74.25 +    if xoptions.get_xend_relocation_server():
   74.26 +        port = xoptions.get_xend_relocation_port()
   74.27 +        interface = xoptions.get_xend_relocation_address()
   74.28  
   74.29 -        hosts_allow = xroot.get_xend_relocation_hosts_allow()
   74.30 +        hosts_allow = xoptions.get_xend_relocation_hosts_allow()
   74.31          if hosts_allow == '':
   74.32              hosts_allow = None
   74.33          else:
    75.1 --- a/tools/python/xen/xend/server/tests/test_controllers.py	Thu Jan 18 15:18:07 2007 +0000
    75.2 +++ b/tools/python/xen/xend/server/tests/test_controllers.py	Fri Jan 19 14:48:57 2007 +0000
    75.3 @@ -2,9 +2,9 @@ import os
    75.4  import re
    75.5  import unittest
    75.6  
    75.7 -import xen.xend.XendRoot
    75.8 +import xen.xend.XendOptions
    75.9  
   75.10 -xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
   75.11 +xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
   75.12  
   75.13  from xen.xend.server import netif
   75.14  
   75.15 @@ -13,7 +13,7 @@ FAKE_DOMID = 42
   75.16  FAKE_DEVID = 63
   75.17  
   75.18  
   75.19 -xroot = xen.xend.XendRoot.instance()
   75.20 +xoptions = xen.xend.XendOptions.instance()
   75.21  
   75.22  
   75.23  class test_controllers(unittest.TestCase):
   75.24 @@ -36,8 +36,8 @@ class test_controllers(unittest.TestCase
   75.25  
   75.26          self.assertEqual(backdets['handle'], str(FAKE_DEVID))
   75.27          self.assertEqual(backdets['script'],
   75.28 -                         os.path.join(xroot.network_script_dir,
   75.29 -                                      xroot.get_vif_script()))
   75.30 +                         os.path.join(xoptions.network_script_dir,
   75.31 +                                      xoptions.get_vif_script()))
   75.32          self.assertValidMac(backdets['mac'], expectedMac)
   75.33  
   75.34          self.assertEqual(frontdets['handle'], str(FAKE_DEVID))
    76.1 --- a/tools/python/xen/xend/server/tpmif.py	Thu Jan 18 15:18:07 2007 +0000
    76.2 +++ b/tools/python/xen/xend/server/tpmif.py	Fri Jan 19 14:48:57 2007 +0000
    76.3 @@ -20,7 +20,7 @@
    76.4  
    76.5  """Support for virtual TPM interfaces."""
    76.6  
    76.7 -from xen.xend import XendRoot
    76.8 +from xen.xend import XendOptions
    76.9  from xen.xend.XendLogging import log
   76.10  from xen.xend.XendError import XendError
   76.11  from xen.xend.XendConstants import DEV_MIGRATE_TEST, VTPM_DELETE_SCRIPT
   76.12 @@ -29,7 +29,7 @@ from xen.xend.server.DevController impor
   76.13  import os
   76.14  import re
   76.15  
   76.16 -xroot = XendRoot.instance()
   76.17 +xoptions = XendOptions.instance()
   76.18  
   76.19  def destroy_vtpmstate(name):
   76.20      if os.path.exists(VTPM_DELETE_SCRIPT):
   76.21 @@ -88,7 +88,7 @@ class TPMifController(DevController):
   76.22      def migrate(self, deviceConfig, network, dst, step, domName):
   76.23          """@see DevContoller.migrate"""
   76.24          if network:
   76.25 -            tool = xroot.get_external_migration_tool()
   76.26 +            tool = xoptions.get_external_migration_tool()
   76.27              if tool != '':
   76.28                  log.info("Request to network-migrate device to %s. step=%d.",
   76.29                           dst, step)
   76.30 @@ -116,7 +116,7 @@ class TPMifController(DevController):
   76.31      def recover_migrate(self, deviceConfig, network, dst, step, domName):
   76.32          """@see DevContoller.recover_migrate"""
   76.33          if network:
   76.34 -            tool = xroot.get_external_migration_tool()
   76.35 +            tool = xoptions.get_external_migration_tool()
   76.36              if tool != '':
   76.37                  log.info("Request to recover network-migrated device. last good step=%d.",
   76.38                           step)
    77.1 --- a/tools/python/xen/xend/server/vfbif.py	Thu Jan 18 15:18:07 2007 +0000
    77.2 +++ b/tools/python/xen/xend/server/vfbif.py	Fri Jan 19 14:48:57 2007 +0000
    77.3 @@ -52,7 +52,7 @@ class VfbifController(DevController):
    77.4              if config.has_key("vncpasswd"):
    77.5                  passwd = config["vncpasswd"]
    77.6              else:
    77.7 -                passwd = xen.xend.XendRoot.instance().get_vncpasswd_default()
    77.8 +                passwd = xen.xend.XendOptions.instance().get_vncpasswd_default()
    77.9              if passwd:
   77.10                  self.vm.storeVm("vncpasswd", passwd)
   77.11                  log.debug("Stored a VNC password for vfb access")
   77.12 @@ -66,7 +66,7 @@ class VfbifController(DevController):
   77.13              elif config.has_key("vncdisplay"):
   77.14                  args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))]
   77.15              vnclisten = config.get("vnclisten",
   77.16 -                                   xen.xend.XendRoot.instance().get_vnclisten_address())
   77.17 +                                   xen.xend.XendOptions.instance().get_vnclisten_address())
   77.18              args += [ "--listen", vnclisten ]
   77.19              spawn_detached(args[0], args + std_args, os.environ)
   77.20          elif t == "sdl":
    78.1 --- a/tools/python/xen/xm/create.py	Thu Jan 18 15:18:07 2007 +0000
    78.2 +++ b/tools/python/xen/xm/create.py	Fri Jan 19 14:48:57 2007 +0000
    78.3 @@ -190,6 +190,10 @@ gopts.var('vcpus', val='VCPUS',
    78.4            fn=set_int, default=1,
    78.5            use="# of Virtual CPUS in domain.")
    78.6  
    78.7 +gopts.var('vcpu_avail', val='VCPUS',
    78.8 +          fn=set_long, default=None,
    78.9 +          use="Bitmask for virtual CPUs to make available immediately.")
   78.10 +
   78.11  gopts.var('cpu_cap', val='CAP',
   78.12            fn=set_int, default=None,
   78.13            use="""Set the maximum amount of cpu.
   78.14 @@ -740,7 +744,7 @@ def make_config(vals):
   78.15  
   78.16      map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
   78.17                     'restart', 'on_poweroff',
   78.18 -                   'on_reboot', 'on_crash', 'vcpus', 'features',
   78.19 +                   'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
   78.20                     'on_xend_start', 'on_xend_stop'])
   78.21  
   78.22      if vals.uuid is not None:
    79.1 --- a/tools/python/xen/xm/main.py	Thu Jan 18 15:18:07 2007 +0000
    79.2 +++ b/tools/python/xen/xm/main.py	Fri Jan 19 14:48:57 2007 +0000
    79.3 @@ -693,12 +693,15 @@ def parse_doms_info(info):
    79.4          up_time = time.time() - start_time
    79.5  
    79.6      return {
    79.7 -        'domid'    : get_info('domid',        str,   ''),
    79.8 -        'name'     : get_info('name',         str,   '??'),
    79.9 +        'domid'    : get_info('domid',              str,   ''),
   79.10 +        'name'     : get_info('name',               str,   '??'),
   79.11          'mem'      : get_info('memory_dynamic_min', int,   0),
   79.12 -        'vcpus'    : get_info('online_vcpus',        int,   0),
   79.13 -        'state'    : get_info('state',        str,    ''),
   79.14 -        'cpu_time' : get_info('cpu_time',     float, 0),
   79.15 +        'state'    : get_info('state',              str,   ''),
   79.16 +        'cpu_time' : get_info('cpu_time',           float, 0.0),
   79.17 +        # VCPUs is the number online when the VM is up, or the number
   79.18 +        # configured otherwise.
   79.19 +        'vcpus'    : get_info('online_vcpus', int,
   79.20 +                              get_info('vcpus', int, 0)),
   79.21          'up_time'  : up_time,
   79.22          'seclabel' : security.get_security_printlabel(info),
   79.23          }
    80.1 --- a/tools/python/xen/xm/opts.py	Thu Jan 18 15:18:07 2007 +0000
    80.2 +++ b/tools/python/xen/xm/opts.py	Fri Jan 19 14:48:57 2007 +0000
    80.3 @@ -571,6 +571,14 @@ def set_int(opt, k, v):
    80.4          opt.opts.err('Invalid value: ' + str(v))
    80.5      opt.set(v)
    80.6  
    80.7 +def set_long(opt, k, v):
    80.8 +    """Set an option to a long integer value."""
    80.9 +    try:
   80.10 +        v = long(v)
   80.11 +    except:
   80.12 +        opt.opts.err('Invalid value: ' + str(v))
   80.13 +    opt.set(v)
   80.14 +
   80.15  def set_float(opt, k, v):
   80.16      """Set an option to a float value."""
   80.17      try:
    81.1 --- a/tools/python/xen/xm/tests/test_create.py	Thu Jan 18 15:18:07 2007 +0000
    81.2 +++ b/tools/python/xen/xm/tests/test_create.py	Fri Jan 19 14:48:57 2007 +0000
    81.3 @@ -3,9 +3,9 @@ import os.path
    81.4  import tempfile
    81.5  import unittest
    81.6  
    81.7 -import xen.xend.XendRoot
    81.8 +import xen.xend.XendOptions
    81.9  
   81.10 -xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
   81.11 +xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
   81.12  
   81.13  import xen.xm.create
   81.14  
    82.1 --- a/tools/xcutils/xc_restore.c	Thu Jan 18 15:18:07 2007 +0000
    82.2 +++ b/tools/xcutils/xc_restore.c	Fri Jan 19 14:48:57 2007 +0000
    82.3 @@ -19,12 +19,13 @@ int
    82.4  main(int argc, char **argv)
    82.5  {
    82.6      unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
    82.7 +    unsigned int hvm, pae, apic;
    82.8      int ret;
    82.9      unsigned long store_mfn, console_mfn;
   82.10  
   82.11 -    if (argc != 6)
   82.12 +    if (argc != 9)
   82.13  	errx(1,
   82.14 -	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn",
   82.15 +	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae apic",
   82.16  	     argv[0]);
   82.17  
   82.18      xc_fd = xc_interface_open();
   82.19 @@ -36,9 +37,19 @@ main(int argc, char **argv)
   82.20      nr_pfns = atoi(argv[3]);
   82.21      store_evtchn = atoi(argv[4]);
   82.22      console_evtchn = atoi(argv[5]);
   82.23 +    hvm  = atoi(argv[6]);
   82.24 +    pae  = atoi(argv[7]);
   82.25 +    apic = atoi(argv[8]);
   82.26  
   82.27 -    ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
   82.28 -			   &store_mfn, console_evtchn, &console_mfn);
   82.29 +    if (hvm) {
   82.30 +         /* pass the memsize to xc_hvm_restore to find the store_mfn */
   82.31 +        store_mfn = hvm;
   82.32 +        ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
   82.33 +                &store_mfn, console_evtchn, &console_mfn, pae, apic);
   82.34 +    } else 
   82.35 +        ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
   82.36 +                &store_mfn, console_evtchn, &console_mfn);
   82.37 +
   82.38      if (ret == 0) {
   82.39  	printf("store-mfn %li\n", store_mfn);
   82.40  	printf("console-mfn %li\n", console_mfn);
    83.1 --- a/tools/xcutils/xc_save.c	Thu Jan 18 15:18:07 2007 +0000
    83.2 +++ b/tools/xcutils/xc_save.c	Fri Jan 19 14:48:57 2007 +0000
    83.3 @@ -51,7 +51,10 @@ main(int argc, char **argv)
    83.4      max_f = atoi(argv[4]);
    83.5      flags = atoi(argv[5]);
    83.6  
    83.7 -    ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
    83.8 +    if (flags & XCFLAGS_HVM)
    83.9 +        ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
   83.10 +    else 
   83.11 +        ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
   83.12  
   83.13      xc_interface_close(xc_fd);
   83.14  
    84.1 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Thu Jan 18 15:18:07 2007 +0000
    84.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Fri Jan 19 14:48:57 2007 +0000
    84.3 @@ -182,12 +182,17 @@ static int get_hypercall_stubs(void)
    84.4  static uint64_t get_callback_via(struct pci_dev *pdev)
    84.5  {
    84.6  #ifdef __ia64__
    84.7 -	int irq;
    84.8 +	int irq, rid;
    84.9  	for (irq = 0; irq < 16; irq++) {
   84.10  		if (isa_irq_to_vector(irq) == pdev->irq)
   84.11  			return irq;
   84.12  	}
   84.13 -	return 0;
   84.14 +	/* use Requester-ID as callback_irq */
   84.15 +	/* RID: '<#bus(8)><#dev(5)><#func(3)>' (cf. PCI-Express spec) */
   84.16 +	rid = ((pdev->bus->number & 0xff) << 8) | pdev->devfn;
   84.17 +	printk(KERN_INFO DRV_NAME ":use Requester-ID(%04x) as callback irq\n",
   84.18 +	       rid);
   84.19 +	return rid | IA64_CALLBACK_IRQ_RID;
   84.20  #else /* !__ia64__ */
   84.21  	if (pdev->irq < 16)
   84.22  		return pdev->irq; /* ISA IRQ */
    85.1 --- a/xen/arch/ia64/asm-offsets.c	Thu Jan 18 15:18:07 2007 +0000
    85.2 +++ b/xen/arch/ia64/asm-offsets.c	Fri Jan 19 14:48:57 2007 +0000
    85.3 @@ -56,10 +56,12 @@ void foo(void)
    85.4  	DEFINE(IA64_TASK_THREAD_ON_USTACK_OFFSET, offsetof (struct vcpu, arch._thread.on_ustack));
    85.5  
    85.6  	DEFINE(IA64_VCPU_DOMAIN_OFFSET, offsetof (struct vcpu, domain));
    85.7 +	DEFINE(IA64_VCPU_HYPERCALL_CONTINUATION_OFS, offsetof (struct vcpu, arch.hypercall_continuation));
    85.8  	DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_rr0));
    85.9  	DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0));
   85.10  	DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm));
   85.11  	DEFINE(IA64_VCPU_IVA_OFFSET, offsetof (struct vcpu, arch.iva));
   85.12 +	DEFINE(IA64_VCPU_EVENT_CALLBACK_IP_OFFSET, offsetof (struct vcpu, arch.event_callback_ip));
   85.13  	DEFINE(IA64_VCPU_IRR0_OFFSET, offsetof (struct vcpu, arch.irr[0]));
   85.14  	DEFINE(IA64_VCPU_IRR3_OFFSET, offsetof (struct vcpu, arch.irr[3]));
   85.15  	DEFINE(IA64_VCPU_INSVC3_OFFSET, offsetof (struct vcpu, arch.insvc[3]));
    86.1 --- a/xen/arch/ia64/asm-xsi-offsets.c	Thu Jan 18 15:18:07 2007 +0000
    86.2 +++ b/xen/arch/ia64/asm-xsi-offsets.c	Fri Jan 19 14:48:57 2007 +0000
    86.3 @@ -62,7 +62,7 @@ void foo(void)
    86.4  	DEFINE_MAPPED_REG_OFS(XSI_ITV_OFS, itv);
    86.5  	DEFINE_MAPPED_REG_OFS(XSI_PTA_OFS, pta);
    86.6  	DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled);
    86.7 -	DEFINE_MAPPED_REG_OFS(XSI_INCOMPL_REGFR_OFS, incomplete_regframe);
    86.8 +	DEFINE_MAPPED_REG_OFS(XSI_VPSR_PP_OFS, vpsr_pp);
    86.9  	DEFINE_MAPPED_REG_OFS(XSI_METAPHYS_OFS, metaphysical_mode);
   86.10  	DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum);
   86.11  	DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]);
    87.1 --- a/xen/arch/ia64/linux-xen/Makefile	Thu Jan 18 15:18:07 2007 +0000
    87.2 +++ b/xen/arch/ia64/linux-xen/Makefile	Fri Jan 19 14:48:57 2007 +0000
    87.3 @@ -1,3 +1,6 @@
    87.4 +subdir-y += sn
    87.5 +
    87.6 +obj-y += cmdline.o
    87.7  obj-y += efi.o
    87.8  obj-y += entry.o
    87.9  obj-y += irq_ia64.o
    88.1 --- a/xen/arch/ia64/linux-xen/README.origin	Thu Jan 18 15:18:07 2007 +0000
    88.2 +++ b/xen/arch/ia64/linux-xen/README.origin	Fri Jan 19 14:48:57 2007 +0000
    88.3 @@ -5,6 +5,7 @@
    88.4  # (e.g. with #ifdef XEN or XEN in a comment) so that they can be
    88.5  # easily updated to future versions of the corresponding Linux files.
    88.6  
    88.7 +cmdline.c		-> linux/lib/cmdline.c
    88.8  efi.c			-> linux/arch/ia64/kernel/efi.c
    88.9  entry.h			-> linux/arch/ia64/kernel/entry.h
   88.10  entry.S			-> linux/arch/ia64/kernel/entry.S
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/xen/arch/ia64/linux-xen/cmdline.c	Fri Jan 19 14:48:57 2007 +0000
    89.3 @@ -0,0 +1,131 @@
    89.4 +/*
    89.5 + * linux/lib/cmdline.c
    89.6 + * Helper functions generally used for parsing kernel command line
    89.7 + * and module options.
    89.8 + *
    89.9 + * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.
   89.10 + *
   89.11 + * This source code is licensed under the GNU General Public License,
   89.12 + * Version 2.  See the file COPYING for more details.
   89.13 + *
   89.14 + * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
   89.15 + *
   89.16 + */
   89.17 +
   89.18 +#include <linux/module.h>
   89.19 +#include <linux/kernel.h>
   89.20 +#include <linux/string.h>
   89.21 +#ifdef XEN
   89.22 +#include <xen/lib.h>
   89.23 +#endif
   89.24 +
   89.25 +
   89.26 +/**
   89.27 + *	get_option - Parse integer from an option string
   89.28 + *	@str: option string
   89.29 + *	@pint: (output) integer value parsed from @str
   89.30 + *
   89.31 + *	Read an int from an option string; if available accept a subsequent
   89.32 + *	comma as well.
   89.33 + *
   89.34 + *	Return values:
   89.35 + *	0 : no int in string
   89.36 + *	1 : int found, no subsequent comma
   89.37 + *	2 : int found including a subsequent comma
   89.38 + */
   89.39 +
   89.40 +int get_option (char **str, int *pint)
   89.41 +{
   89.42 +	char *cur = *str;
   89.43 +
   89.44 +	if (!cur || !(*cur))
   89.45 +		return 0;
   89.46 +#ifndef XEN
   89.47 +	*pint = simple_strtol (cur, str, 0);
   89.48 +#else
   89.49 +	*pint = simple_strtol (cur, (const char**)str, 0);
   89.50 +#endif
   89.51 +	if (cur == *str)
   89.52 +		return 0;
   89.53 +	if (**str == ',') {
   89.54 +		(*str)++;
   89.55 +		return 2;
   89.56 +	}
   89.57 +
   89.58 +	return 1;
   89.59 +}
   89.60 +
   89.61 +/**
   89.62 + *	get_options - Parse a string into a list of integers
   89.63 + *	@str: String to be parsed
   89.64 + *	@nints: size of integer array
   89.65 + *	@ints: integer array
   89.66 + *
   89.67 + *	This function parses a string containing a comma-separated
   89.68 + *	list of integers.  The parse halts when the array is
   89.69 + *	full, or when no more numbers can be retrieved from the
   89.70 + *	string.
   89.71 + *
   89.72 + *	Return value is the character in the string which caused
   89.73 + *	the parse to end (typically a null terminator, if @str is
   89.74 + *	completely parseable).
   89.75 + */
   89.76 + 
   89.77 +char *get_options(const char *str, int nints, int *ints)
   89.78 +{
   89.79 +	int res, i = 1;
   89.80 +
   89.81 +	while (i < nints) {
   89.82 +		res = get_option ((char **)&str, ints + i);
   89.83 +		if (res == 0)
   89.84 +			break;
   89.85 +		i++;
   89.86 +		if (res == 1)
   89.87 +			break;
   89.88 +	}
   89.89 +	ints[0] = i - 1;
   89.90 +	return (char *)str;
   89.91 +}
   89.92 +
   89.93 +/**
   89.94 + *	memparse - parse a string with mem suffixes into a number
   89.95 + *	@ptr: Where parse begins
   89.96 + *	@retptr: (output) Pointer to next char after parse completes
   89.97 + *
   89.98 + *	Parses a string into a number.  The number stored at @ptr is
   89.99 + *	potentially suffixed with %K (for kilobytes, or 1024 bytes),
  89.100 + *	%M (for megabytes, or 1048576 bytes), or %G (for gigabytes, or
  89.101 + *	1073741824).  If the number is suffixed with K, M, or G, then
  89.102 + *	the return value is the number multiplied by one kilobyte, one
  89.103 + *	megabyte, or one gigabyte, respectively.
  89.104 + */
  89.105 +
  89.106 +unsigned long long memparse (char *ptr, char **retptr)
  89.107 +{
  89.108 +#ifndef XEN
  89.109 +	unsigned long long ret = simple_strtoull (ptr, retptr, 0);
  89.110 +#else
  89.111 +	unsigned long long ret = simple_strtoull (ptr, (const char**)retptr, 0);
  89.112 +#endif
  89.113 +
  89.114 +	switch (**retptr) {
  89.115 +	case 'G':
  89.116 +	case 'g':
  89.117 +		ret <<= 10;
  89.118 +	case 'M':
  89.119 +	case 'm':
  89.120 +		ret <<= 10;
  89.121 +	case 'K':
  89.122 +	case 'k':
  89.123 +		ret <<= 10;
  89.124 +		(*retptr)++;
  89.125 +	default:
  89.126 +		break;
  89.127 +	}
  89.128 +	return ret;
  89.129 +}
  89.130 +
  89.131 +
  89.132 +EXPORT_SYMBOL(memparse);
  89.133 +EXPORT_SYMBOL(get_option);
  89.134 +EXPORT_SYMBOL(get_options);
    90.1 --- a/xen/arch/ia64/linux-xen/entry.S	Thu Jan 18 15:18:07 2007 +0000
    90.2 +++ b/xen/arch/ia64/linux-xen/entry.S	Fri Jan 19 14:48:57 2007 +0000
    90.3 @@ -676,7 +676,9 @@ GLOBAL_ENTRY(ia64_ret_from_syscall)
    90.4  	cmp.ge p6,p7=r8,r0			// syscall executed successfully?
    90.5  	adds r2=PT(R8)+16,sp			// r2 = &pt_regs.r8
    90.6  	mov r10=r0				// clear error indication in r10
    90.7 +#ifndef XEN    
    90.8  (p7)	br.cond.spnt handle_syscall_error	// handle potential syscall failure
    90.9 +#endif
   90.10  END(ia64_ret_from_syscall)
   90.11  	// fall through
   90.12  /*
   90.13 @@ -764,7 +766,9 @@ ENTRY(ia64_leave_syscall)
   90.14  	ld8 r19=[r2],PT(B6)-PT(LOADRS)		// load ar.rsc value for "loadrs"
   90.15  	nop.i 0
   90.16  	;;
   90.17 +#ifndef XEN    
   90.18  	mov r16=ar.bsp				// M2  get existing backing store pointer
   90.19 +#endif    
   90.20  	ld8 r18=[r2],PT(R9)-PT(B6)		// load b6
   90.21  #ifndef XEN
   90.22  (p6)	and r15=TIF_WORK_MASK,r31		// any work other than TIF_SYSCALL_TRACE?
   90.23 @@ -814,7 +818,11 @@ ENTRY(ia64_leave_syscall)
   90.24  	mov f8=f0				// F    clear f8
   90.25  	;;
   90.26  	ld8.fill r12=[r2]			// M0|1 restore r12 (sp)
   90.27 +#ifdef XEN    
   90.28 +	ld8.fill r2=[r3]			// M0|1
   90.29 +#else    
   90.30  	ld8.fill r15=[r3]			// M0|1 restore r15
   90.31 +#endif    
   90.32  	mov b6=r18				// I0   restore b6
   90.33  
   90.34  #ifdef XEN
   90.35 @@ -827,7 +835,9 @@ ENTRY(ia64_leave_syscall)
   90.36  
   90.37  	srlz.d				// M0   ensure interruption collection is off (for cover)
   90.38  	shr.u r18=r19,16		// I0|1 get byte size of existing "dirty" partition
   90.39 +#ifndef XEN    
   90.40  	cover				// B    add current frame into dirty partition & set cr.ifs
   90.41 +#endif    
   90.42  	;;
   90.43  (pUStk) ld4 r17=[r17]			// M0|1 r17 = cpu_data->phys_stacked_size_p8
   90.44  	mov r19=ar.bsp			// M2   get new backing store pointer
   90.45 @@ -893,24 +903,19 @@ GLOBAL_ENTRY(ia64_leave_kernel)
   90.46  .work_processed_kernel:
   90.47  #ifdef XEN
   90.48  	;;
   90.49 -(pUStk) ssm psr.i
   90.50 -(pUStk)    br.call.sptk.many b0=do_softirq
   90.51 -(pUStk) rsm psr.i
   90.52 -    ;;
   90.53 -	alloc loc0=ar.pfs,0,1,1,0
   90.54 -	adds out0=16,r12
   90.55 +(pUStk)	ssm psr.i
   90.56 +(pUStk)	br.call.sptk.many b0=do_softirq
   90.57 +(pUStk)	ssm psr.i
   90.58 +	;;
   90.59 +(pUStk)	br.call.sptk.many b0=reflect_event
   90.60 +	;;
   90.61  	adds r7 = PT(EML_UNAT)+16,r12
   90.62  	;;
   90.63  	ld8 r7 = [r7]
   90.64  	;;
   90.65 -(pUStk)	br.call.sptk.many b0=reflect_event
   90.66 -//(pUStk)	br.call.sptk.many b0=deliver_pending_interrupt
   90.67 -    ;;
   90.68 -	mov ar.pfs=loc0
   90.69  	mov ar.unat=r7  /* load eml_unat  */
   90.70  	mov r31=r0
   90.71  
   90.72 -
   90.73  #else
   90.74  	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
   90.75  	;;
   90.76 @@ -1184,8 +1189,11 @@ skip_rbs_switch:
   90.77  	mov cr.ipsr=r29		// M2
   90.78  	mov ar.pfs=r26		// I0
   90.79  (pLvSys)mov r17=r0		// A  clear r17 for leave_syscall, no-op otherwise
   90.80 -
   90.81 +#ifdef XEN
   90.82 +	mov cr.ifs=r30		// M2
   90.83 +#else    
   90.84  (p9)	mov cr.ifs=r30		// M2
   90.85 +#endif
   90.86  	mov b0=r21		// I0
   90.87  (pLvSys)mov r18=r0		// A  clear r18 for leave_syscall, no-op otherwise
   90.88  
   90.89 @@ -1195,7 +1203,11 @@ skip_rbs_switch:
   90.90  	;;
   90.91  (pUStk)	mov ar.rnat=r24		// M2 must happen with RSE in lazy mode
   90.92  	nop 0
   90.93 +#ifdef XEN    
   90.94 +(pLvSys)mov r15=r0
   90.95 +#else
   90.96  (pLvSys)mov r2=r0
   90.97 +#endif
   90.98  
   90.99  	mov ar.rsc=r27		// M2
  90.100  	mov pr=r31,-1		// I0
  90.101 @@ -1459,7 +1471,89 @@ 1:	mov gp=loc2				// restore gp
  90.102  	br.ret.sptk.many rp
  90.103  END(unw_init_running)
  90.104  
  90.105 -#ifndef XEN
  90.106 +#ifdef XEN
  90.107 +GLOBAL_ENTRY(ia64_do_multicall_call)
  90.108 +	movl r2=ia64_hypercall_table;;
  90.109 +	shladd r2=r38,3,r2;;
  90.110 +	ld8 r2=[r2];;
  90.111 +	mov b6=r2
  90.112 +	br.sptk.many b6;;
  90.113 +END(ia64_do_multicall_call)
  90.114 +
  90.115 +    
  90.116 +	.rodata
  90.117 +	.align 8
  90.118 +	.globl ia64_hypercall_table
  90.119 +ia64_hypercall_table:
  90.120 +	data8 do_ni_hypercall		/* do_set_trap_table *//*  0 */
  90.121 +	data8 do_ni_hypercall		/* do_mmu_update */
  90.122 +	data8 do_ni_hypercall		/* do_set_gdt */
  90.123 +	data8 do_ni_hypercall		/* do_stack_switch */
  90.124 +	data8 do_ni_hypercall		/* do_set_callbacks */
  90.125 +	data8 do_ni_hypercall		/* do_fpu_taskswitch *//*  5 */
  90.126 +	data8 do_sched_op_compat
  90.127 +	data8 do_ni_hypercall
  90.128 +	data8 do_ni_hypercall		/* do_set_debugreg */
  90.129 +	data8 do_ni_hypercall		/* do_get_debugreg */
  90.130 +	data8 do_ni_hypercall		/* do_update_descriptor * 10 */
  90.131 +	data8 do_ni_hypercall		/* do_ni_hypercall */
  90.132 +	data8 do_memory_op
  90.133 +	data8 do_multicall
  90.134 +	data8 do_ni_hypercall		/* do_update_va_mapping */
  90.135 +	data8 do_ni_hypercall		/* do_set_timer_op */  /* 15 */
  90.136 +	data8 do_ni_hypercall
  90.137 +	data8 do_xen_version
  90.138 +	data8 do_console_io
  90.139 +	data8 do_ni_hypercall
  90.140 +	data8 do_grant_table_op				       /* 20 */
  90.141 +	data8 do_ni_hypercall		/* do_vm_assist */
  90.142 +	data8 do_ni_hypercall		/* do_update_va_mapping_othe */
  90.143 +	data8 do_ni_hypercall		/* (x86 only) */
  90.144 +	data8 do_ni_hypercall		/* do_vcpu_op */
  90.145 +	data8 do_ni_hypercall		/* (x86_64 only) */    /* 25 */
  90.146 +	data8 do_ni_hypercall		/* do_mmuext_op */
  90.147 +	data8 do_ni_hypercall		/* do_acm_op */
  90.148 +	data8 do_ni_hypercall		/* do_nmi_op */
  90.149 +	data8 do_sched_op
  90.150 +	data8 do_callback_op		/*  */                 /* 30 */
  90.151 +	data8 do_xenoprof_op		/*  */
  90.152 +	data8 do_event_channel_op
  90.153 +	data8 do_physdev_op
  90.154 +	data8 do_hvm_op			/*  */
  90.155 +	data8 do_sysctl			/*  */                  /* 35 */
  90.156 +	data8 do_domctl			/*  */
  90.157 +	data8 do_ni_hypercall		/*  */
  90.158 +	data8 do_ni_hypercall		/*  */
  90.159 +	data8 do_ni_hypercall		/*  */
  90.160 +	data8 do_ni_hypercall		/*  */                 /* 40 */
  90.161 +	data8 do_ni_hypercall		/*  */
  90.162 +	data8 do_ni_hypercall		/*  */
  90.163 +	data8 do_ni_hypercall		/*  */
  90.164 +	data8 do_ni_hypercall		/*  */
  90.165 +	data8 do_ni_hypercall		/*  */                 /* 45 */
  90.166 +	data8 do_ni_hypercall		/*  */
  90.167 +	data8 do_ni_hypercall		/*  */
  90.168 +	data8 do_dom0vp_op              /* dom0vp_op */
  90.169 +	data8 do_pirq_guest_eoi		/* arch_1 */
  90.170 +	data8 do_ni_hypercall		/* arch_2 */           /* 50 */
  90.171 +	data8 do_ni_hypercall		/* arch_3 */
  90.172 +	data8 do_ni_hypercall		/* arch_4 */
  90.173 +	data8 do_ni_hypercall		/* arch_5 */
  90.174 +	data8 do_ni_hypercall		/* arch_6 */
  90.175 +	data8 do_ni_hypercall		/* arch_7 */           /* 55 */
  90.176 +	data8 do_ni_hypercall
  90.177 +	data8 do_ni_hypercall
  90.178 +	data8 do_ni_hypercall
  90.179 +	data8 do_ni_hypercall
  90.180 +	data8 do_ni_hypercall                                  /* 60 */
  90.181 +	data8 do_ni_hypercall
  90.182 +	data8 do_ni_hypercall
  90.183 +	data8 do_ni_hypercall
  90.184 +
  90.185 +	// guard against failures to increase NR_hypercalls
  90.186 +	.org ia64_hypercall_table + 8*NR_hypercalls
  90.187 +
  90.188 +#else
  90.189  	.rodata
  90.190  	.align 8
  90.191  	.globl sys_call_table
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/xen/arch/ia64/linux-xen/sn/Makefile	Fri Jan 19 14:48:57 2007 +0000
    91.3 @@ -0,0 +1,1 @@
    91.4 +subdir-y += kernel
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/Makefile	Fri Jan 19 14:48:57 2007 +0000
    92.3 @@ -0,0 +1,5 @@
    92.4 +obj-y += sn2_smp.o
    92.5 +obj-y += setup.o
    92.6 +obj-y += iomv.o
    92.7 +obj-y += irq.o
    92.8 +obj-y += io_init.o
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/README.origin	Fri Jan 19 14:48:57 2007 +0000
    93.3 @@ -0,0 +1,12 @@
    93.4 +# Source files in this directory are near-identical copies of linux-2.6.19
    93.5 +# files:
    93.6 +
    93.7 +# NOTE: ALL changes to these files should be clearly marked
    93.8 +# (e.g. with #ifdef XEN or XEN in a comment) so that they can be
    93.9 +# easily updated to future versions of the corresponding Linux files.
   93.10 +
   93.11 +io_init.c		-> linux/arch/ia64/sn/kernel/io_init.c
   93.12 +iomv.c			-> linux/arch/ia64/sn/kernel/iomv.c
   93.13 +irq.c			-> linux/arch/ia64/sn/kernel/irq.c
   93.14 +setup.c			-> linux/arch/ia64/sn/kernel/setup.c
   93.15 +sn2_smp.c		-> linux/arch/ia64/sn/kernel/sn2/sn2_smp.c
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/io_init.c	Fri Jan 19 14:48:57 2007 +0000
    94.3 @@ -0,0 +1,783 @@
    94.4 +/*
    94.5 + * This file is subject to the terms and conditions of the GNU General Public
    94.6 + * License.  See the file "COPYING" in the main directory of this archive
    94.7 + * for more details.
    94.8 + *
    94.9 + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
   94.10 + */
   94.11 +
   94.12 +#include <linux/bootmem.h>
   94.13 +#include <linux/nodemask.h>
   94.14 +#ifdef XEN
   94.15 +#include <linux/init.h>
   94.16 +#endif
   94.17 +#include <asm/sn/types.h>
   94.18 +#include <asm/sn/addrs.h>
   94.19 +#include <asm/sn/sn_feature_sets.h>
   94.20 +#include <asm/sn/geo.h>
   94.21 +#include <asm/sn/io.h>
   94.22 +#include <asm/sn/l1.h>
   94.23 +#include <asm/sn/module.h>
   94.24 +#include <asm/sn/pcibr_provider.h>
   94.25 +#include <asm/sn/pcibus_provider_defs.h>
   94.26 +#ifndef XEN
   94.27 +#include <asm/sn/pcidev.h>
   94.28 +#endif
   94.29 +#include <asm/sn/simulator.h>
   94.30 +#include <asm/sn/sn_sal.h>
   94.31 +#ifndef XEN
   94.32 +#include <asm/sn/tioca_provider.h>
   94.33 +#include <asm/sn/tioce_provider.h>
   94.34 +#endif
   94.35 +#ifdef XEN
   94.36 +#include "asm/sn/hubdev.h"
   94.37 +#include "asm/sn/xwidgetdev.h"
   94.38 +#else
   94.39 +#include "xtalk/hubdev.h"
   94.40 +#include "xtalk/xwidgetdev.h"
   94.41 +#endif
   94.42 +
   94.43 +
   94.44 +extern void sn_init_cpei_timer(void);
   94.45 +extern void register_sn_procfs(void);
   94.46 +#ifdef XEN
   94.47 +extern void sn_irq_lh_init(void);
   94.48 +#endif
   94.49 +
   94.50 +static struct list_head sn_sysdata_list;
   94.51 +
   94.52 +/* sysdata list struct */
   94.53 +struct sysdata_el {
   94.54 +	struct list_head entry;
   94.55 +	void *sysdata;
   94.56 +};
   94.57 +
   94.58 +struct slab_info {
   94.59 +	struct hubdev_info hubdev;
   94.60 +};
   94.61 +
   94.62 +struct brick {
   94.63 +	moduleid_t id;		/* Module ID of this module        */
   94.64 +	struct slab_info slab_info[MAX_SLABS + 1];
   94.65 +};
   94.66 +
   94.67 +int sn_ioif_inited;		/* SN I/O infrastructure initialized? */
   94.68 +
   94.69 +struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES];	/* indexed by asic type */
   94.70 +
   94.71 +#ifndef XEN
   94.72 +static int max_segment_number;		 /* Default highest segment number */
   94.73 +static int max_pcibus_number = 255;	/* Default highest pci bus number */
   94.74 +
   94.75 +/*
   94.76 + * Hooks and struct for unsupported pci providers
   94.77 + */
   94.78 +
   94.79 +static dma_addr_t
   94.80 +sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
   94.81 +{
   94.82 +	return 0;
   94.83 +}
   94.84 +
   94.85 +static void
   94.86 +sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
   94.87 +{
   94.88 +	return;
   94.89 +}
   94.90 +
   94.91 +static void *
   94.92 +sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
   94.93 +{
   94.94 +	return NULL;
   94.95 +}
   94.96 +
   94.97 +static struct sn_pcibus_provider sn_pci_default_provider = {
   94.98 +	.dma_map = sn_default_pci_map,
   94.99 +	.dma_map_consistent = sn_default_pci_map,
  94.100 +	.dma_unmap = sn_default_pci_unmap,
  94.101 +	.bus_fixup = sn_default_pci_bus_fixup,
  94.102 +};
  94.103 +#endif
  94.104 +
  94.105 +/*
  94.106 + * Retrieve the DMA Flush List given nasid, widget, and device.
  94.107 + * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
  94.108 + */
  94.109 +static inline u64
  94.110 +sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
  94.111 +			     u64 address)
  94.112 +{
  94.113 +	struct ia64_sal_retval ret_stuff;
  94.114 +	ret_stuff.status = 0;
  94.115 +	ret_stuff.v0 = 0;
  94.116 +
  94.117 +	SAL_CALL_NOLOCK(ret_stuff,
  94.118 +			(u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
  94.119 +			(u64) nasid, (u64) widget_num,
  94.120 +			(u64) device_num, (u64) address, 0, 0, 0);
  94.121 +	return ret_stuff.status;
  94.122 +}
  94.123 +
  94.124 +/*
  94.125 + * Retrieve the hub device info structure for the given nasid.
  94.126 + */
  94.127 +static inline u64 sal_get_hubdev_info(u64 handle, u64 address)
  94.128 +{
  94.129 +	struct ia64_sal_retval ret_stuff;
  94.130 +	ret_stuff.status = 0;
  94.131 +	ret_stuff.v0 = 0;
  94.132 +
  94.133 +	SAL_CALL_NOLOCK(ret_stuff,
  94.134 +			(u64) SN_SAL_IOIF_GET_HUBDEV_INFO,
  94.135 +			(u64) handle, (u64) address, 0, 0, 0, 0, 0);
  94.136 +	return ret_stuff.v0;
  94.137 +}
  94.138 +
  94.139 +/*
  94.140 + * Retrieve the pci bus information given the bus number.
  94.141 + */
  94.142 +static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
  94.143 +{
  94.144 +	struct ia64_sal_retval ret_stuff;
  94.145 +	ret_stuff.status = 0;
  94.146 +	ret_stuff.v0 = 0;
  94.147 +
  94.148 +	SAL_CALL_NOLOCK(ret_stuff,
  94.149 +			(u64) SN_SAL_IOIF_GET_PCIBUS_INFO,
  94.150 +			(u64) segment, (u64) busnum, (u64) address, 0, 0, 0, 0);
  94.151 +	return ret_stuff.v0;
  94.152 +}
  94.153 +
  94.154 +#ifndef XEN
  94.155 +/*
  94.156 + * Retrieve the pci device information given the bus and device|function number.
  94.157 + */
  94.158 +static inline u64
  94.159 +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
  94.160 +		    u64 sn_irq_info)
  94.161 +{
  94.162 +	struct ia64_sal_retval ret_stuff;
  94.163 +	ret_stuff.status = 0;
  94.164 +	ret_stuff.v0 = 0;
  94.165 +
  94.166 +	SAL_CALL_NOLOCK(ret_stuff,
  94.167 +			(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
  94.168 +			(u64) segment, (u64) bus_number, (u64) devfn,
  94.169 +			(u64) pci_dev,
  94.170 +			sn_irq_info, 0, 0);
  94.171 +	return ret_stuff.v0;
  94.172 +}
  94.173 +
  94.174 +/*
  94.175 + * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
  94.176 + *			  device.
  94.177 + */
  94.178 +inline struct pcidev_info *
  94.179 +sn_pcidev_info_get(struct pci_dev *dev)
  94.180 +{
  94.181 +	struct pcidev_info *pcidev;
  94.182 +
  94.183 +	list_for_each_entry(pcidev,
  94.184 +			    &(SN_PCI_CONTROLLER(dev)->pcidev_info), pdi_list) {
  94.185 +		if (pcidev->pdi_linux_pcidev == dev) {
  94.186 +			return pcidev;
  94.187 +		}
  94.188 +	}
  94.189 +	return NULL;
  94.190 +}
  94.191 +
  94.192 +/* Older PROM flush WAR
  94.193 + *
  94.194 + * 01/16/06 -- This war will be in place until a new official PROM is released.
  94.195 + * Additionally note that the struct sn_flush_device_war also has to be
  94.196 + * removed from arch/ia64/sn/include/xtalk/hubdev.h
  94.197 + */
  94.198 +static u8 war_implemented = 0;
  94.199 +
  94.200 +static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
  94.201 +			       struct sn_flush_device_common *common)
  94.202 +{
  94.203 +	struct sn_flush_device_war *war_list;
  94.204 +	struct sn_flush_device_war *dev_entry;
  94.205 +	struct ia64_sal_retval isrv = {0,0,0,0};
  94.206 +
  94.207 +	if (!war_implemented) {
  94.208 +		printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
  94.209 +		       "PROM flush WAR\n");
  94.210 +		war_implemented = 1;
  94.211 +	}
  94.212 +
  94.213 +	war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
  94.214 +	if (!war_list)
  94.215 +		BUG();
  94.216 +
  94.217 +	SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
  94.218 +			nasid, widget, __pa(war_list), 0, 0, 0 ,0);
  94.219 +	if (isrv.status)
  94.220 +		panic("sn_device_fixup_war failed: %s\n",
  94.221 +		      ia64_sal_strerror(isrv.status));
  94.222 +
  94.223 +	dev_entry = war_list + device;
  94.224 +	memcpy(common,dev_entry, sizeof(*common));
  94.225 +	kfree(war_list);
  94.226 +
  94.227 +	return isrv.status;
  94.228 +}
  94.229 +
  94.230 +/*
  94.231 + * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
  94.232 + *	each node in the system.
  94.233 + */
  94.234 +static void __init sn_fixup_ionodes(void)
  94.235 +{
  94.236 +	struct sn_flush_device_kernel *sn_flush_device_kernel;
  94.237 +	struct sn_flush_device_kernel *dev_entry;
  94.238 +	struct hubdev_info *hubdev;
  94.239 +	u64 status;
  94.240 +	u64 nasid;
  94.241 +	int i, widget, device, size;
  94.242 +
  94.243 +	/*
  94.244 +	 * Get SGI Specific HUB chipset information.
  94.245 +	 * Inform Prom that this kernel can support domain bus numbering.
  94.246 +	 */
  94.247 +	for (i = 0; i < num_cnodes; i++) {
  94.248 +		hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
  94.249 +		nasid = cnodeid_to_nasid(i);
  94.250 +		hubdev->max_segment_number = 0xffffffff;
  94.251 +		hubdev->max_pcibus_number = 0xff;
  94.252 +		status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev));
  94.253 +		if (status)
  94.254 +			continue;
  94.255 +
  94.256 +		/* Save the largest Domain and pcibus numbers found. */
  94.257 +		if (hubdev->max_segment_number) {
  94.258 +			/*
  94.259 +			 * Dealing with a Prom that supports segments.
  94.260 +			 */
  94.261 +			max_segment_number = hubdev->max_segment_number;
  94.262 +			max_pcibus_number = hubdev->max_pcibus_number;
  94.263 +		}
  94.264 +
  94.265 +		/* Attach the error interrupt handlers */
  94.266 +		if (nasid & 1)
  94.267 +			ice_error_init(hubdev);
  94.268 +		else
  94.269 +			hub_error_init(hubdev);
  94.270 +
  94.271 +		for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
  94.272 +			hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
  94.273 +
  94.274 +		if (!hubdev->hdi_flush_nasid_list.widget_p)
  94.275 +			continue;
  94.276 +
  94.277 +		size = (HUB_WIDGET_ID_MAX + 1) *
  94.278 +			sizeof(struct sn_flush_device_kernel *);
  94.279 +		hubdev->hdi_flush_nasid_list.widget_p =
  94.280 +			kzalloc(size, GFP_KERNEL);
  94.281 +		if (!hubdev->hdi_flush_nasid_list.widget_p)
  94.282 +			BUG();
  94.283 +
  94.284 +		for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
  94.285 +			size = DEV_PER_WIDGET *
  94.286 +				sizeof(struct sn_flush_device_kernel);
  94.287 +			sn_flush_device_kernel = kzalloc(size, GFP_KERNEL);
  94.288 +			if (!sn_flush_device_kernel)
  94.289 +				BUG();
  94.290 +
  94.291 +			dev_entry = sn_flush_device_kernel;
  94.292 +			for (device = 0; device < DEV_PER_WIDGET;
  94.293 +			     device++,dev_entry++) {
  94.294 +				size = sizeof(struct sn_flush_device_common);
  94.295 +				dev_entry->common = kzalloc(size, GFP_KERNEL);
  94.296 +				if (!dev_entry->common)
  94.297 +					BUG();
  94.298 +
  94.299 +				if (sn_prom_feature_available(
  94.300 +						       PRF_DEVICE_FLUSH_LIST))
  94.301 +					status = sal_get_device_dmaflush_list(
  94.302 +						     nasid, widget, device,
  94.303 +						     (u64)(dev_entry->common));
  94.304 +				else
  94.305 +#ifdef XEN
  94.306 +					BUG();
  94.307 +#else
  94.308 +					status = sn_device_fixup_war(nasid,
  94.309 +						     widget, device,
  94.310 +						     dev_entry->common);
  94.311 +#endif
  94.312 +				if (status != SALRET_OK)
  94.313 +					panic("SAL call failed: %s\n",
  94.314 +					      ia64_sal_strerror(status));
  94.315 +
  94.316 +				spin_lock_init(&dev_entry->sfdl_flush_lock);
  94.317 +			}
  94.318 +
  94.319 +			if (sn_flush_device_kernel)
  94.320 +				hubdev->hdi_flush_nasid_list.widget_p[widget] =
  94.321 +						       sn_flush_device_kernel;
  94.322 +	        }
  94.323 +	}
  94.324 +}
  94.325 +
  94.326 +/*
  94.327 + * sn_pci_window_fixup() - Create a pci_window for each device resource.
  94.328 + *			   Until ACPI support is added, we need this code
  94.329 + *			   to setup pci_windows for use by
  94.330 + *			   pcibios_bus_to_resource(),
  94.331 + *			   pcibios_resource_to_bus(), etc.
  94.332 + */
  94.333 +static void
  94.334 +sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
  94.335 +		    s64 * pci_addrs)
  94.336 +{
  94.337 +	struct pci_controller *controller = PCI_CONTROLLER(dev->bus);
  94.338 +	unsigned int i;
  94.339 +	unsigned int idx;
  94.340 +	unsigned int new_count;
  94.341 +	struct pci_window *new_window;
  94.342 +
  94.343 +	if (count == 0)
  94.344 +		return;
  94.345 +	idx = controller->windows;
  94.346 +	new_count = controller->windows + count;
  94.347 +	new_window = kcalloc(new_count, sizeof(struct pci_window), GFP_KERNEL);
  94.348 +	if (new_window == NULL)
  94.349 +		BUG();
  94.350 +	if (controller->window) {
  94.351 +		memcpy(new_window, controller->window,
  94.352 +		       sizeof(struct pci_window) * controller->windows);
  94.353 +		kfree(controller->window);
  94.354 +	}
  94.355 +
  94.356 +	/* Setup a pci_window for each device resource. */
  94.357 +	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
  94.358 +		if (pci_addrs[i] == -1)
  94.359 +			continue;
  94.360 +
  94.361 +		new_window[idx].offset = dev->resource[i].start - pci_addrs[i];
  94.362 +		new_window[idx].resource = dev->resource[i];
  94.363 +		idx++;
  94.364 +	}
  94.365 +
  94.366 +	controller->windows = new_count;
  94.367 +	controller->window = new_window;
  94.368 +}
  94.369 +
  94.370 +void sn_pci_unfixup_slot(struct pci_dev *dev)
  94.371 +{
  94.372 +	struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
  94.373 +
  94.374 +	sn_irq_unfixup(dev);
  94.375 +	pci_dev_put(host_pci_dev);
  94.376 +	pci_dev_put(dev);
  94.377 +}
  94.378 +
  94.379 +/*
  94.380 + * sn_pci_fixup_slot() - This routine sets up a slot's resources
  94.381 + * consistent with the Linux PCI abstraction layer.  Resources acquired
  94.382 + * from our PCI provider include PIO maps to BAR space and interrupt
  94.383 + * objects.
  94.384 + */
  94.385 +void sn_pci_fixup_slot(struct pci_dev *dev)
  94.386 +{
  94.387 +	unsigned int count = 0;
  94.388 +	int idx;
  94.389 +	int segment = pci_domain_nr(dev->bus);
  94.390 +	int status = 0;
  94.391 +	struct pcibus_bussoft *bs;
  94.392 + 	struct pci_bus *host_pci_bus;
  94.393 + 	struct pci_dev *host_pci_dev;
  94.394 +	struct pcidev_info *pcidev_info;
  94.395 +	s64 pci_addrs[PCI_ROM_RESOURCE + 1];
  94.396 + 	struct sn_irq_info *sn_irq_info;
  94.397 + 	unsigned long size;
  94.398 + 	unsigned int bus_no, devfn;
  94.399 +
  94.400 +	pci_dev_get(dev); /* for the sysdata pointer */
  94.401 +	pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
  94.402 +	if (!pcidev_info)
  94.403 +		BUG();		/* Cannot afford to run out of memory */
  94.404 +
  94.405 +	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
  94.406 +	if (!sn_irq_info)
  94.407 +		BUG();		/* Cannot afford to run out of memory */
  94.408 +
  94.409 +	/* Call to retrieve pci device information needed by kernel. */
  94.410 +	status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, 
  94.411 +				     dev->devfn,
  94.412 +				     (u64) __pa(pcidev_info),
  94.413 +				     (u64) __pa(sn_irq_info));
  94.414 +	if (status)
  94.415 +		BUG(); /* Cannot get platform pci device information */
  94.416 +
  94.417 +	/* Add pcidev_info to list in sn_pci_controller struct */
  94.418 +	list_add_tail(&pcidev_info->pdi_list,
  94.419 +		      &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info));
  94.420 +
  94.421 +	/* Copy over PIO Mapped Addresses */
  94.422 +	for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
  94.423 +		unsigned long start, end, addr;
  94.424 +
  94.425 +		if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
  94.426 +			pci_addrs[idx] = -1;
  94.427 +			continue;
  94.428 +		}
  94.429 +
  94.430 +		start = dev->resource[idx].start;
  94.431 +		end = dev->resource[idx].end;
  94.432 +		size = end - start;
  94.433 +		if (size == 0) {
  94.434 +			pci_addrs[idx] = -1;
  94.435 +			continue;
  94.436 +		}
  94.437 +		pci_addrs[idx] = start;
  94.438 +		count++;
  94.439 +		addr = pcidev_info->pdi_pio_mapped_addr[idx];
  94.440 +		addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET;
  94.441 +		dev->resource[idx].start = addr;
  94.442 +		dev->resource[idx].end = addr + size;
  94.443 +		if (dev->resource[idx].flags & IORESOURCE_IO)
  94.444 +			dev->resource[idx].parent = &ioport_resource;
  94.445 +		else
  94.446 +			dev->resource[idx].parent = &iomem_resource;
  94.447 +	}
  94.448 +	/* Create a pci_window in the pci_controller struct for
  94.449 +	 * each device resource.
  94.450 +	 */
  94.451 +	if (count > 0)
  94.452 +		sn_pci_window_fixup(dev, count, pci_addrs);
  94.453 +
  94.454 +	/*
  94.455 +	 * Using the PROMs values for the PCI host bus, get the Linux
  94.456 + 	 * PCI host_pci_dev struct and set up host bus linkages
  94.457 + 	 */
  94.458 +
  94.459 +	bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
  94.460 +	devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
  94.461 + 	host_pci_bus = pci_find_bus(segment, bus_no);
  94.462 + 	host_pci_dev = pci_get_slot(host_pci_bus, devfn);
  94.463 +
  94.464 +	pcidev_info->host_pci_dev = host_pci_dev;
  94.465 +	pcidev_info->pdi_linux_pcidev = dev;
  94.466 +	pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev);
  94.467 +	bs = SN_PCIBUS_BUSSOFT(dev->bus);
  94.468 +	pcidev_info->pdi_pcibus_info = bs;
  94.469 +
  94.470 +	if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
  94.471 +		SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
  94.472 +	} else {
  94.473 +		SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
  94.474 +	}
  94.475 +
  94.476 +	/* Only set up IRQ stuff if this device has a host bus context */
  94.477 +	if (bs && sn_irq_info->irq_irq) {
  94.478 +		pcidev_info->pdi_sn_irq_info = sn_irq_info;
  94.479 +		dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq;
  94.480 +		sn_irq_fixup(dev, sn_irq_info);
  94.481 +	} else {
  94.482 +		pcidev_info->pdi_sn_irq_info = NULL;
  94.483 +		kfree(sn_irq_info);
  94.484 +	}
  94.485 +}
  94.486 +
  94.487 +/*
  94.488 + * sn_pci_controller_fixup() - This routine sets up a bus's resources
  94.489 + * consistent with the Linux PCI abstraction layer.
  94.490 + */
  94.491 +void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
  94.492 +{
  94.493 +	int status;
  94.494 +	int nasid, cnode;
  94.495 +	struct pci_controller *controller;
  94.496 +	struct sn_pci_controller *sn_controller;
  94.497 +	struct pcibus_bussoft *prom_bussoft_ptr;
  94.498 +	struct hubdev_info *hubdev_info;
  94.499 +	void *provider_soft;
  94.500 +	struct sn_pcibus_provider *provider;
  94.501 +
  94.502 + 	status = sal_get_pcibus_info((u64) segment, (u64) busnum,
  94.503 + 				     (u64) ia64_tpa(&prom_bussoft_ptr));
  94.504 + 	if (status > 0)
  94.505 +		return;		/*bus # does not exist */
  94.506 +	prom_bussoft_ptr = __va(prom_bussoft_ptr);
  94.507 +
  94.508 +	/* Allocate a sn_pci_controller, which has a pci_controller struct
  94.509 +	 * as the first member.
  94.510 +	 */
  94.511 +	sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL);
  94.512 +	if (!sn_controller)
  94.513 +		BUG();
  94.514 +	INIT_LIST_HEAD(&sn_controller->pcidev_info);
  94.515 +	controller = &sn_controller->pci_controller;
  94.516 +	controller->segment = segment;
  94.517 +
  94.518 +	if (bus == NULL) {
  94.519 + 		bus = pci_scan_bus(busnum, &pci_root_ops, controller);
  94.520 + 		if (bus == NULL)
  94.521 + 			goto error_return; /* error, or bus already scanned */
  94.522 + 		bus->sysdata = NULL;
  94.523 +	}
  94.524 +
  94.525 +	if (bus->sysdata)
  94.526 +		goto error_return; /* sysdata already alloc'd */
  94.527 +
  94.528 +	/*
  94.529 +	 * Per-provider fixup.  Copies the contents from prom to local
  94.530 +	 * area and links SN_PCIBUS_BUSSOFT().
  94.531 +	 */
  94.532 +
  94.533 +	if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES)
  94.534 +		goto error_return; /* unsupported asic type */
  94.535 +
  94.536 +	if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
  94.537 +		goto error_return; /* no further fixup necessary */
  94.538 +
  94.539 +	provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
  94.540 +	if (provider == NULL)
  94.541 +		goto error_return; /* no provider registerd for this asic */
  94.542 +
  94.543 +	bus->sysdata = controller;
  94.544 +	if (provider->bus_fixup)
  94.545 +		provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller);
  94.546 +	else
  94.547 +		provider_soft = NULL;
  94.548 +
  94.549 +	if (provider_soft == NULL) {
  94.550 +		/* fixup failed or not applicable */
  94.551 +		bus->sysdata = NULL;
  94.552 +		goto error_return;
  94.553 +	}
  94.554 +
  94.555 +	/*
  94.556 +	 * Setup pci_windows for legacy IO and MEM space.
  94.557 +	 * (Temporary until ACPI support is in place.)
  94.558 +	 */
  94.559 +	controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL);
  94.560 +	if (controller->window == NULL)
  94.561 +		BUG();
  94.562 +	controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io;
  94.563 +	controller->window[0].resource.name = "legacy_io";
  94.564 +	controller->window[0].resource.flags = IORESOURCE_IO;
  94.565 +	controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io;
  94.566 +	controller->window[0].resource.end =
  94.567 +	    controller->window[0].resource.start + 0xffff;
  94.568 +	controller->window[0].resource.parent = &ioport_resource;
  94.569 +	controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem;
  94.570 +	controller->window[1].resource.name = "legacy_mem";
  94.571 +	controller->window[1].resource.flags = IORESOURCE_MEM;
  94.572 +	controller->window[1].resource.start = prom_bussoft_ptr->bs_legacy_mem;
  94.573 +	controller->window[1].resource.end =
  94.574 +	    controller->window[1].resource.start + (1024 * 1024) - 1;
  94.575 +	controller->window[1].resource.parent = &iomem_resource;
  94.576 +	controller->windows = 2;
  94.577 +
  94.578 +	/*
  94.579 +	 * Generic bus fixup goes here.  Don't reference prom_bussoft_ptr
  94.580 +	 * after this point.
  94.581 +	 */
  94.582 +
  94.583 +	PCI_CONTROLLER(bus)->platform_data = provider_soft;
  94.584 +	nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
  94.585 +	cnode = nasid_to_cnodeid(nasid);
  94.586 +	hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
  94.587 +	SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
  94.588 +	    &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
  94.589 +
  94.590 +	/*
  94.591 +	 * If the node information we obtained during the fixup phase is invalid
  94.592 +	 * then set controller->node to -1 (undetermined)
  94.593 +	 */
  94.594 +	if (controller->node >= num_online_nodes()) {
  94.595 +		struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
  94.596 +
  94.597 +		printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
  94.598 +				    "L_IO=%lx L_MEM=%lx BASE=%lx\n",
  94.599 +			b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
  94.600 +			b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
  94.601 +		printk(KERN_WARNING "on node %d but only %d nodes online."
  94.602 +			"Association set to undetermined.\n",
  94.603 +			controller->node, num_online_nodes());
  94.604 +		controller->node = -1;
  94.605 +	}
  94.606 +	return;
  94.607 +
  94.608 +error_return:
  94.609 +
  94.610 +	kfree(sn_controller);
  94.611 +	return;
  94.612 +}
  94.613 +
  94.614 +void sn_bus_store_sysdata(struct pci_dev *dev)
  94.615 +{
  94.616 +	struct sysdata_el *element;
  94.617 +
  94.618 +	element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
  94.619 +	if (!element) {
  94.620 +		dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
  94.621 +		return;
  94.622 +	}
  94.623 +	element->sysdata = SN_PCIDEV_INFO(dev);
  94.624 +	list_add(&element->entry, &sn_sysdata_list);
  94.625 +}
  94.626 +
  94.627 +void sn_bus_free_sysdata(void)
  94.628 +{
  94.629 +	struct sysdata_el *element;
  94.630 +	struct list_head *list, *safe;
  94.631 +
  94.632 +	list_for_each_safe(list, safe, &sn_sysdata_list) {
  94.633 +		element = list_entry(list, struct sysdata_el, entry);
  94.634 +		list_del(&element->entry);
  94.635 +		list_del(&(((struct pcidev_info *)
  94.636 +			     (element->sysdata))->pdi_list));
  94.637 +		kfree(element->sysdata);
  94.638 +		kfree(element);
  94.639 +	}
  94.640 +	return;
  94.641 +}
  94.642 +#endif
  94.643 +
  94.644 +/*
  94.645 + * Ugly hack to get PCI setup until we have a proper ACPI namespace.
  94.646 + */
  94.647 +
  94.648 +#define PCI_BUSES_TO_SCAN 256
  94.649 +
  94.650 +static int __init sn_pci_init(void)
  94.651 +{
  94.652 +#ifndef XEN
  94.653 +	int i, j;
  94.654 +	struct pci_dev *pci_dev = NULL;
  94.655 +#endif
  94.656 +
  94.657 +	if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
  94.658 +		return 0;
  94.659 +
  94.660 +#ifndef XEN
  94.661 +	/*
  94.662 +	 * prime sn_pci_provider[].  Individial provider init routines will
  94.663 +	 * override their respective default entries.
  94.664 +	 */
  94.665 +
  94.666 +	for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
  94.667 +		sn_pci_provider[i] = &sn_pci_default_provider;
  94.668 +
  94.669 +	pcibr_init_provider();
  94.670 +	tioca_init_provider();
  94.671 +	tioce_init_provider();
  94.672 +#endif
  94.673 +
  94.674 +	/*
  94.675 +	 * This is needed to avoid bounce limit checks in the blk layer
  94.676 +	 */
  94.677 +	ia64_max_iommu_merge_mask = ~PAGE_MASK;
  94.678 +#ifndef XEN
  94.679 +	sn_fixup_ionodes();
  94.680 +#endif
  94.681 +	sn_irq_lh_init();
  94.682 +	INIT_LIST_HEAD(&sn_sysdata_list);
  94.683 +#ifndef XEN
  94.684 +	sn_init_cpei_timer();
  94.685 +
  94.686 +#ifdef CONFIG_PROC_FS
  94.687 +	register_sn_procfs();
  94.688 +#endif
  94.689 +
  94.690 +	/* busses are not known yet ... */
  94.691 +	for (i = 0; i <= max_segment_number; i++)
  94.692 +		for (j = 0; j <= max_pcibus_number; j++)
  94.693 +			sn_pci_controller_fixup(i, j, NULL);
  94.694 +
  94.695 +	/*
  94.696 +	 * Generic Linux PCI Layer has created the pci_bus and pci_dev 
  94.697 +	 * structures - time for us to add our SN PLatform specific 
  94.698 +	 * information.
  94.699 +	 */
  94.700 +
  94.701 +	while ((pci_dev =
  94.702 +		pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL)
  94.703 +		sn_pci_fixup_slot(pci_dev);
  94.704 +#endif
  94.705 +
  94.706 +	sn_ioif_inited = 1;	/* sn I/O infrastructure now initialized */
  94.707 +
  94.708 +	return 0;
  94.709 +}
  94.710 +
  94.711 +/*
  94.712 + * hubdev_init_node() - Creates the HUB data structure and link them to it's 
  94.713 + *	own NODE specific data area.
  94.714 + */
  94.715 +void hubdev_init_node(nodepda_t * npda, cnodeid_t node)
  94.716 +{
  94.717 +	struct hubdev_info *hubdev_info;
  94.718 +	int size;
  94.719 +#ifndef XEN
  94.720 +	pg_data_t *pg;
  94.721 +#else
  94.722 +	struct pglist_data *pg;
  94.723 +#endif
  94.724 +
  94.725 +	size = sizeof(struct hubdev_info);
  94.726 +
  94.727 +	if (node >= num_online_nodes())	/* Headless/memless IO nodes */
  94.728 +		pg = NODE_DATA(0);
  94.729 +	else
  94.730 +		pg = NODE_DATA(node);
  94.731 +
  94.732 +	hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size);
  94.733 +
  94.734 +	npda->pdinfo = (void *)hubdev_info;
  94.735 +}
  94.736 +
  94.737 +geoid_t
  94.738 +cnodeid_get_geoid(cnodeid_t cnode)
  94.739 +{
  94.740 +	struct hubdev_info *hubdev;
  94.741 +
  94.742 +	hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
  94.743 +	return hubdev->hdi_geoid;
  94.744 +}
  94.745 +
  94.746 +#ifndef XEN
  94.747 +void sn_generate_path(struct pci_bus *pci_bus, char *address)
  94.748 +{
  94.749 +	nasid_t nasid;
  94.750 +	cnodeid_t cnode;
  94.751 +	geoid_t geoid;
  94.752 +	moduleid_t moduleid;
  94.753 +	u16 bricktype;
  94.754 +
  94.755 +	nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
  94.756 +	cnode = nasid_to_cnodeid(nasid);
  94.757 +	geoid = cnodeid_get_geoid(cnode);
  94.758 +	moduleid = geo_module(geoid);
  94.759 +
  94.760 +	sprintf(address, "module_%c%c%c%c%.2d",
  94.761 +		'0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
  94.762 +		'0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
  94.763 +		'0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
  94.764 +		MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
  94.765 +
  94.766 +	/* Tollhouse requires slot id to be displayed */
  94.767 +	bricktype = MODULE_GET_BTYPE(moduleid);
  94.768 +	if ((bricktype == L1_BRICKTYPE_191010) ||
  94.769 +	    (bricktype == L1_BRICKTYPE_1932))
  94.770 +			sprintf(address, "%s^%d", address, geo_slot(geoid));
  94.771 +}
  94.772 +#endif
  94.773 +
  94.774 +#ifdef XEN
  94.775 +__initcall(sn_pci_init);
  94.776 +#else
  94.777 +subsys_initcall(sn_pci_init);
  94.778 +#endif
  94.779 +#ifndef XEN
  94.780 +EXPORT_SYMBOL(sn_pci_fixup_slot);
  94.781 +EXPORT_SYMBOL(sn_pci_unfixup_slot);
  94.782 +EXPORT_SYMBOL(sn_pci_controller_fixup);
  94.783 +EXPORT_SYMBOL(sn_bus_store_sysdata);
  94.784 +EXPORT_SYMBOL(sn_bus_free_sysdata);
  94.785 +EXPORT_SYMBOL(sn_generate_path);
  94.786 +#endif
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/iomv.c	Fri Jan 19 14:48:57 2007 +0000
    95.3 @@ -0,0 +1,82 @@
    95.4 +/* 
    95.5 + * This file is subject to the terms and conditions of the GNU General Public
    95.6 + * License.  See the file "COPYING" in the main directory of this archive
    95.7 + * for more details.
    95.8 + *
    95.9 + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
   95.10 + */
   95.11 +
   95.12 +#include <linux/module.h>
   95.13 +#include <asm/io.h>
   95.14 +#include <asm/delay.h>
   95.15 +#ifndef XEN
   95.16 +#include <asm/vga.h>
   95.17 +#endif
   95.18 +#include <asm/sn/nodepda.h>
   95.19 +#include <asm/sn/simulator.h>
   95.20 +#include <asm/sn/pda.h>
   95.21 +#include <asm/sn/sn_cpuid.h>
   95.22 +#include <asm/sn/shub_mmr.h>
   95.23 +
   95.24 +#define IS_LEGACY_VGA_IOPORT(p) \
   95.25 +	(((p) >= 0x3b0 && (p) <= 0x3bb) || ((p) >= 0x3c0 && (p) <= 0x3df))
   95.26 +
   95.27 +#ifdef XEN
   95.28 +#define vga_console_iobase	0
   95.29 +#endif
   95.30 +
   95.31 +/**
   95.32 + * sn_io_addr - convert an in/out port to an i/o address
   95.33 + * @port: port to convert
   95.34 + *
   95.35 + * Legacy in/out instructions are converted to ld/st instructions
   95.36 + * on IA64.  This routine will convert a port number into a valid 
   95.37 + * SN i/o address.  Used by sn_in*() and sn_out*().
   95.38 + */
   95.39 +void *sn_io_addr(unsigned long port)
   95.40 +{
   95.41 +	if (!IS_RUNNING_ON_SIMULATOR()) {
   95.42 +		if (IS_LEGACY_VGA_IOPORT(port))
   95.43 +			port += vga_console_iobase;
   95.44 +		/* On sn2, legacy I/O ports don't point at anything */
   95.45 +		if (port < (64 * 1024))
   95.46 +			return NULL;
   95.47 +		return ((void *)(port | __IA64_UNCACHED_OFFSET));
   95.48 +	} else {
   95.49 +		/* but the simulator uses them... */
   95.50 +		unsigned long addr;
   95.51 +
   95.52 +		/*
   95.53 +		 * word align port, but need more than 10 bits
   95.54 +		 * for accessing registers in bedrock local block
   95.55 +		 * (so we don't do port&0xfff)
   95.56 +		 */
   95.57 +		addr = (is_shub2() ? 0xc00000028c000000UL : 0xc0000087cc000000UL) | ((port >> 2) << 12);
   95.58 +		if ((port >= 0x1f0 && port <= 0x1f7) || port == 0x3f6 || port == 0x3f7)
   95.59 +			addr |= port;
   95.60 +		return (void *)addr;
   95.61 +	}
   95.62 +}
   95.63 +
   95.64 +EXPORT_SYMBOL(sn_io_addr);
   95.65 +
   95.66 +/**
   95.67 + * __sn_mmiowb - I/O space memory barrier
   95.68 + *
   95.69 + * See include/asm-ia64/io.h and Documentation/DocBook/deviceiobook.tmpl
   95.70 + * for details.
   95.71 + *
   95.72 + * On SN2, we wait for the PIO_WRITE_STATUS SHub register to clear.
   95.73 + * See PV 871084 for details about the WAR about zero value.
   95.74 + *
   95.75 + */
   95.76 +void __sn_mmiowb(void)
   95.77 +{
   95.78 +	volatile unsigned long *adr = pda->pio_write_status_addr;
   95.79 +	unsigned long val = pda->pio_write_status_val;
   95.80 +
   95.81 +	while ((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != val)
   95.82 +		cpu_relax();
   95.83 +}
   95.84 +
   95.85 +EXPORT_SYMBOL(__sn_mmiowb);
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/irq.c	Fri Jan 19 14:48:57 2007 +0000
    96.3 @@ -0,0 +1,542 @@
    96.4 +/*
    96.5 + * Platform dependent support for SGI SN
    96.6 + *
    96.7 + * This file is subject to the terms and conditions of the GNU General Public
    96.8 + * License.  See the file "COPYING" in the main directory of this archive
    96.9 + * for more details.
   96.10 + *
   96.11 + * Copyright (c) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
   96.12 + */
   96.13 +
   96.14 +#include <linux/irq.h>
   96.15 +#include <linux/spinlock.h>
   96.16 +#include <linux/init.h>
   96.17 +#ifdef XEN
   96.18 +#include <linux/pci.h>
   96.19 +#include <asm/hw_irq.h>
   96.20 +#endif
   96.21 +#include <asm/sn/addrs.h>
   96.22 +#include <asm/sn/arch.h>
   96.23 +#include <asm/sn/intr.h>
   96.24 +#include <asm/sn/pcibr_provider.h>
   96.25 +#include <asm/sn/pcibus_provider_defs.h>
   96.26 +#ifndef XEN
   96.27 +#include <asm/sn/pcidev.h>
   96.28 +#endif
   96.29 +#include <asm/sn/shub_mmr.h>
   96.30 +#include <asm/sn/sn_sal.h>
   96.31 +
   96.32 +#ifdef XEN
   96.33 +#define move_native_irq(foo)	do {} while(0)
   96.34 +#endif
   96.35 +
   96.36 +static void force_interrupt(int irq);
   96.37 +#ifndef XEN
   96.38 +static void register_intr_pda(struct sn_irq_info *sn_irq_info);
   96.39 +static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
   96.40 +#endif
   96.41 +
   96.42 +int sn_force_interrupt_flag = 1;
   96.43 +extern int sn_ioif_inited;
   96.44 +struct list_head **sn_irq_lh;
   96.45 +static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */
   96.46 +
   96.47 +u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
   96.48 +				     struct sn_irq_info *sn_irq_info,
   96.49 +				     int req_irq, nasid_t req_nasid,
   96.50 +				     int req_slice)
   96.51 +{
   96.52 +	struct ia64_sal_retval ret_stuff;
   96.53 +	ret_stuff.status = 0;
   96.54 +	ret_stuff.v0 = 0;
   96.55 +
   96.56 +	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
   96.57 +			(u64) SAL_INTR_ALLOC, (u64) local_nasid,
   96.58 +			(u64) local_widget, __pa(sn_irq_info), (u64) req_irq,
   96.59 +			(u64) req_nasid, (u64) req_slice);
   96.60 +
   96.61 +	return ret_stuff.status;
   96.62 +}
   96.63 +
   96.64 +void sn_intr_free(nasid_t local_nasid, int local_widget,
   96.65 +				struct sn_irq_info *sn_irq_info)
   96.66 +{
   96.67 +	struct ia64_sal_retval ret_stuff;
   96.68 +	ret_stuff.status = 0;
   96.69 +	ret_stuff.v0 = 0;
   96.70 +
   96.71 +	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
   96.72 +			(u64) SAL_INTR_FREE, (u64) local_nasid,
   96.73 +			(u64) local_widget, (u64) sn_irq_info->irq_irq,
   96.74 +			(u64) sn_irq_info->irq_cookie, 0, 0);
   96.75 +}
   96.76 +
   96.77 +static unsigned int sn_startup_irq(unsigned int irq)
   96.78 +{
   96.79 +	return 0;
   96.80 +}
   96.81 +
   96.82 +static void sn_shutdown_irq(unsigned int irq)
   96.83 +{
   96.84 +}
   96.85 +
   96.86 +static void sn_disable_irq(unsigned int irq)
   96.87 +{
   96.88 +}
   96.89 +
   96.90 +static void sn_enable_irq(unsigned int irq)
   96.91 +{
   96.92 +}
   96.93 +
   96.94 +static void sn_ack_irq(unsigned int irq)
   96.95 +{
   96.96 +	u64 event_occurred, mask;
   96.97 +
   96.98 +	irq = irq & 0xff;
   96.99 +	event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
  96.100 +	mask = event_occurred & SH_ALL_INT_MASK;
  96.101 +	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
  96.102 +	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
  96.103 +
  96.104 +	move_native_irq(irq);
  96.105 +}
  96.106 +
  96.107 +static void sn_end_irq(unsigned int irq)
  96.108 +{
  96.109 +	int ivec;
  96.110 +	u64 event_occurred;
  96.111 +
  96.112 +	ivec = irq & 0xff;
  96.113 +	if (ivec == SGI_UART_VECTOR) {
  96.114 +		event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED));
  96.115 +		/* If the UART bit is set here, we may have received an
  96.116 +		 * interrupt from the UART that the driver missed.  To
  96.117 +		 * make sure, we IPI ourselves to force us to look again.
  96.118 +		 */
  96.119 +		if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
  96.120 +			platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR,
  96.121 +					  IA64_IPI_DM_INT, 0);
  96.122 +		}
  96.123 +	}
  96.124 +	__clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs);
  96.125 +	if (sn_force_interrupt_flag)
  96.126 +		force_interrupt(irq);
  96.127 +}
  96.128 +
  96.129 +#ifndef XEN
  96.130 +static void sn_irq_info_free(struct rcu_head *head);
  96.131 +
  96.132 +struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
  96.133 +				       nasid_t nasid, int slice)
  96.134 +{
  96.135 +	int vector;
  96.136 +	int cpuphys;
  96.137 +	int64_t bridge;
  96.138 +	int local_widget, status;
  96.139 +	nasid_t local_nasid;
  96.140 +	struct sn_irq_info *new_irq_info;
  96.141 +	struct sn_pcibus_provider *pci_provider;
  96.142 +
  96.143 +	new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
  96.144 +	if (new_irq_info == NULL)
  96.145 +		return NULL;
  96.146 +
  96.147 +	memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
  96.148 +
  96.149 +	bridge = (u64) new_irq_info->irq_bridge;
  96.150 +	if (!bridge) {
  96.151 +		kfree(new_irq_info);
  96.152 +		return NULL; /* irq is not a device interrupt */
  96.153 +	}
  96.154 +
  96.155 +	local_nasid = NASID_GET(bridge);
  96.156 +
  96.157 +	if (local_nasid & 1)
  96.158 +		local_widget = TIO_SWIN_WIDGETNUM(bridge);
  96.159 +	else
  96.160 +		local_widget = SWIN_WIDGETNUM(bridge);
  96.161 +
  96.162 +	vector = sn_irq_info->irq_irq;
  96.163 +	/* Free the old PROM new_irq_info structure */
  96.164 +	sn_intr_free(local_nasid, local_widget, new_irq_info);
  96.165 +	/* Update kernels new_irq_info with new target info */
  96.166 +	unregister_intr_pda(new_irq_info);
  96.167 +
  96.168 +	/* allocate a new PROM new_irq_info struct */
  96.169 +	status = sn_intr_alloc(local_nasid, local_widget,
  96.170 +			       new_irq_info, vector,
  96.171 +			       nasid, slice);
  96.172 +
  96.173 +	/* SAL call failed */
  96.174 +	if (status) {
  96.175 +		kfree(new_irq_info);
  96.176 +		return NULL;
  96.177 +	}
  96.178 +
  96.179 +	cpuphys = nasid_slice_to_cpuid(nasid, slice);
  96.180 +	new_irq_info->irq_cpuid = cpuphys;
  96.181 +	register_intr_pda(new_irq_info);
  96.182 +
  96.183 +	pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
  96.184 +
  96.185 +	/*
  96.186 +	 * If this represents a line interrupt, target it.  If it's
  96.187 +	 * an msi (irq_int_bit < 0), it's already targeted.
  96.188 +	 */
  96.189 +	if (new_irq_info->irq_int_bit >= 0 &&
  96.190 +	    pci_provider && pci_provider->target_interrupt)
  96.191 +		(pci_provider->target_interrupt)(new_irq_info);
  96.192 +
  96.193 +	spin_lock(&sn_irq_info_lock);
  96.194 +#ifdef XEN
  96.195 +	list_replace(&sn_irq_info->list, &new_irq_info->list);
  96.196 +#else
  96.197 +	list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
  96.198 +#endif
  96.199 +	spin_unlock(&sn_irq_info_lock);
  96.200 +#ifndef XEN
  96.201 +	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
  96.202 +#endif
  96.203 +
  96.204 +#ifdef CONFIG_SMP
  96.205 +	set_irq_affinity_info((vector & 0xff), cpuphys, 0);
  96.206 +#endif
  96.207 +
  96.208 +	return new_irq_info;
  96.209 +}
  96.210 +
  96.211 +static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
  96.212 +{
  96.213 +	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
  96.214 +	nasid_t nasid;
  96.215 +	int slice;
  96.216 +
  96.217 +	nasid = cpuid_to_nasid(first_cpu(mask));
  96.218 +	slice = cpuid_to_slice(first_cpu(mask));
  96.219 +
  96.220 +	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
  96.221 +				 sn_irq_lh[irq], list)
  96.222 +		(void)sn_retarget_vector(sn_irq_info, nasid, slice);
  96.223 +}
  96.224 +#endif
  96.225 +
  96.226 +struct hw_interrupt_type irq_type_sn = {
  96.227 +#ifndef XEN
  96.228 +	.name		= "SN hub",
  96.229 +#endif
  96.230 +	.startup	= sn_startup_irq,
  96.231 +	.shutdown	= sn_shutdown_irq,
  96.232 +	.enable		= sn_enable_irq,
  96.233 +	.disable	= sn_disable_irq,
  96.234 +	.ack		= sn_ack_irq,
  96.235 +	.end		= sn_end_irq,
  96.236 +#ifndef XEN
  96.237 +	.set_affinity	= sn_set_affinity_irq
  96.238 +#endif
  96.239 +};
  96.240 +
  96.241 +unsigned int sn_local_vector_to_irq(u8 vector)
  96.242 +{
  96.243 +	return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
  96.244 +}
  96.245 +
  96.246 +void sn_irq_init(void)
  96.247 +{
  96.248 +#ifndef XEN
  96.249 +	int i;
  96.250 +	irq_desc_t *base_desc = irq_desc;
  96.251 +
  96.252 +	ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
  96.253 +	ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
  96.254 +
  96.255 +	for (i = 0; i < NR_IRQS; i++) {
  96.256 +		if (base_desc[i].chip == &no_irq_type) {
  96.257 +			base_desc[i].chip = &irq_type_sn;
  96.258 +		}
  96.259 +	}
  96.260 +#endif
  96.261 +}
  96.262 +
  96.263 +#ifndef XEN
  96.264 +static void register_intr_pda(struct sn_irq_info *sn_irq_info)
  96.265 +{
  96.266 +	int irq = sn_irq_info->irq_irq;
  96.267 +	int cpu = sn_irq_info->irq_cpuid;
  96.268 +
  96.269 +	if (pdacpu(cpu)->sn_last_irq < irq) {
  96.270 +		pdacpu(cpu)->sn_last_irq = irq;
  96.271 +	}
  96.272 +
  96.273 +	if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq)
  96.274 +		pdacpu(cpu)->sn_first_irq = irq;
  96.275 +}
  96.276 +
  96.277 +static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
  96.278 +{
  96.279 +	int irq = sn_irq_info->irq_irq;
  96.280 +	int cpu = sn_irq_info->irq_cpuid;
  96.281 +	struct sn_irq_info *tmp_irq_info;
  96.282 +	int i, foundmatch;
  96.283 +
  96.284 +#ifndef XEN
  96.285 +	rcu_read_lock();
  96.286 +#else
  96.287 +	spin_lock(&sn_irq_info_lock);
  96.288 +#endif
  96.289 +	if (pdacpu(cpu)->sn_last_irq == irq) {
  96.290 +		foundmatch = 0;
  96.291 +		for (i = pdacpu(cpu)->sn_last_irq - 1;
  96.292 +		     i && !foundmatch; i--) {
  96.293 +#ifdef XEN
  96.294 +			list_for_each_entry(tmp_irq_info,
  96.295 +						sn_irq_lh[i],
  96.296 +						list) {
  96.297 +#else
  96.298 +			list_for_each_entry_rcu(tmp_irq_info,
  96.299 +						sn_irq_lh[i],
  96.300 +						list) {
  96.301 +#endif
  96.302 +				if (tmp_irq_info->irq_cpuid == cpu) {
  96.303 +					foundmatch = 1;
  96.304 +					break;
  96.305 +				}
  96.306 +			}
  96.307 +		}
  96.308 +		pdacpu(cpu)->sn_last_irq = i;
  96.309 +	}
  96.310 +
  96.311 +	if (pdacpu(cpu)->sn_first_irq == irq) {
  96.312 +		foundmatch = 0;
  96.313 +		for (i = pdacpu(cpu)->sn_first_irq + 1;
  96.314 +		     i < NR_IRQS && !foundmatch; i++) {
  96.315 +#ifdef XEN
  96.316 +			list_for_each_entry(tmp_irq_info,
  96.317 +						sn_irq_lh[i],
  96.318 +						list) {
  96.319 +#else
  96.320 +			list_for_each_entry_rcu(tmp_irq_info,
  96.321 +						sn_irq_lh[i],
  96.322 +						list) {
  96.323 +#endif
  96.324 +				if (tmp_irq_info->irq_cpuid == cpu) {
  96.325 +					foundmatch = 1;
  96.326 +					break;
  96.327 +				}
  96.328 +			}
  96.329 +		}
  96.330 +		pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i);
  96.331 +	}
  96.332 +#ifndef XEN
  96.333 +	rcu_read_unlock();
  96.334 +#else
  96.335 +	spin_unlock(&sn_irq_info_lock);
  96.336 +#endif
  96.337 +}
  96.338 +#endif /* XEN */
  96.339 +
  96.340 +#ifndef XEN
  96.341 +static void sn_irq_info_free(struct rcu_head *head)
  96.342 +{
  96.343 +	struct sn_irq_info *sn_irq_info;
  96.344 +
  96.345 +	sn_irq_info = container_of(head, struct sn_irq_info, rcu);
  96.346 +	kfree(sn_irq_info);
  96.347 +}
  96.348 +#endif
  96.349 +
  96.350 +#ifndef XEN
  96.351 +void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
  96.352 +{
  96.353 +	nasid_t nasid = sn_irq_info->irq_nasid;
  96.354 +	int slice = sn_irq_info->irq_slice;
  96.355 +	int cpu = nasid_slice_to_cpuid(nasid, slice);
  96.356 +
  96.357 +	pci_dev_get(pci_dev);
  96.358 +	sn_irq_info->irq_cpuid = cpu;
  96.359 +	sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev);
  96.360 +
  96.361 +	/* link it into the sn_irq[irq] list */
  96.362 +	spin_lock(&sn_irq_info_lock);
  96.363 +#ifdef XEN
  96.364 +	list_add(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
  96.365 +#else
  96.366 +	list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
  96.367 +#endif
  96.368 +#ifndef XEN
  96.369 +	reserve_irq_vector(sn_irq_info->irq_irq);
  96.370 +#endif
  96.371 +	spin_unlock(&sn_irq_info_lock);
  96.372 +
  96.373 +	register_intr_pda(sn_irq_info);
  96.374 +}
  96.375 +
  96.376 +void sn_irq_unfixup(struct pci_dev *pci_dev)
  96.377 +{
  96.378 +	struct sn_irq_info *sn_irq_info;
  96.379 +
  96.380 +	/* Only cleanup IRQ stuff if this device has a host bus context */
  96.381 +	if (!SN_PCIDEV_BUSSOFT(pci_dev))
  96.382 +		return;
  96.383 +
  96.384 +	sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info;
  96.385 +	if (!sn_irq_info)
  96.386 +		return;
  96.387 +	if (!sn_irq_info->irq_irq) {
  96.388 +		kfree(sn_irq_info);
  96.389 +		return;
  96.390 +	}
  96.391 +
  96.392 +	unregister_intr_pda(sn_irq_info);
  96.393 +	spin_lock(&sn_irq_info_lock);
  96.394 +#ifdef XEN
  96.395 +	list_del(&sn_irq_info->list);
  96.396 +#else
  96.397 +	list_del_rcu(&sn_irq_info->list);
  96.398 +#endif
  96.399 +	spin_unlock(&sn_irq_info_lock);
  96.400 +	if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
  96.401 +		free_irq_vector(sn_irq_info->irq_irq);
  96.402 +#ifndef XEN
  96.403 +	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
  96.404 +#endif
  96.405 +	pci_dev_put(pci_dev);
  96.406 +
  96.407 +}
  96.408 +#endif
  96.409 +
  96.410 +static inline void
  96.411 +sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
  96.412 +{
  96.413 +	struct sn_pcibus_provider *pci_provider;
  96.414 +
  96.415 +	pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
  96.416 +	if (pci_provider && pci_provider->force_interrupt)
  96.417 +		(*pci_provider->force_interrupt)(sn_irq_info);
  96.418 +}
  96.419 +
  96.420 +static void force_interrupt(int irq)
  96.421 +{
  96.422 +	struct sn_irq_info *sn_irq_info;
  96.423 +
  96.424 +#ifndef XEN
  96.425 +	if (!sn_ioif_inited)
  96.426 +		return;
  96.427 +#endif
  96.428 +
  96.429 +#ifdef XEN
  96.430 +	spin_lock(&sn_irq_info_lock);
  96.431 +#else
  96.432 +	rcu_read_lock();
  96.433 +#endif
  96.434 +#ifdef XEN
  96.435 +	list_for_each_entry(sn_irq_info, sn_irq_lh[irq], list)
  96.436 +#else
  96.437 +	list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
  96.438 +#endif
  96.439 +		sn_call_force_intr_provider(sn_irq_info);
  96.440 +
  96.441 +#ifdef XEN
  96.442 +	spin_unlock(&sn_irq_info_lock);
  96.443 +#else
  96.444 +	rcu_read_unlock();
  96.445 +#endif
  96.446 +}
  96.447 +
  96.448 +#ifndef XEN
  96.449 +/*
  96.450 + * Check for lost interrupts.  If the PIC int_status reg. says that
  96.451 + * an interrupt has been sent, but not handled, and the interrupt
  96.452 + * is not pending in either the cpu irr regs or in the soft irr regs,
  96.453 + * and the interrupt is not in service, then the interrupt may have
  96.454 + * been lost.  Force an interrupt on that pin.  It is possible that
  96.455 + * the interrupt is in flight, so we may generate a spurious interrupt,
  96.456 + * but we should never miss a real lost interrupt.
  96.457 + */
  96.458 +static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
  96.459 +{
  96.460 +	u64 regval;
  96.461 +	struct pcidev_info *pcidev_info;
  96.462 +	struct pcibus_info *pcibus_info;
  96.463 +
  96.464 +	/*
  96.465 +	 * Bridge types attached to TIO (anything but PIC) do not need this WAR
  96.466 +	 * since they do not target Shub II interrupt registers.  If that
  96.467 +	 * ever changes, this check needs to accomodate.
  96.468 +	 */
  96.469 +	if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
  96.470 +		return;
  96.471 +
  96.472 +	pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
  96.473 +	if (!pcidev_info)
  96.474 +		return;
  96.475 +
  96.476 +	pcibus_info =
  96.477 +	    (struct pcibus_info *)pcidev_info->pdi_host_pcidev_info->
  96.478 +	    pdi_pcibus_info;
  96.479 +	regval = pcireg_intr_status_get(pcibus_info);
  96.480 +
  96.481 +	if (!ia64_get_irr(irq_to_vector(irq))) {
  96.482 +		if (!test_bit(irq, pda->sn_in_service_ivecs)) {
  96.483 +			regval &= 0xff;
  96.484 +			if (sn_irq_info->irq_int_bit & regval &
  96.485 +			    sn_irq_info->irq_last_intr) {
  96.486 +				regval &= ~(sn_irq_info->irq_int_bit & regval);
  96.487 +				sn_call_force_intr_provider(sn_irq_info);
  96.488 +			}
  96.489 +		}
  96.490 +	}
  96.491 +	sn_irq_info->irq_last_intr = regval;
  96.492 +}
  96.493 +#endif
  96.494 +
  96.495 +void sn_lb_int_war_check(void)
  96.496 +{
  96.497 +#ifndef XEN
  96.498 +	struct sn_irq_info *sn_irq_info;
  96.499 +	int i;
  96.500 +
  96.501 +#ifdef XEN
  96.502 +	if (pda->sn_first_irq == 0)
  96.503 +#else
  96.504 +	if (!sn_ioif_inited || pda->sn_first_irq == 0)
  96.505 +#endif
  96.506 +		return;
  96.507 +
  96.508 +#ifdef XEN
  96.509 +	spin_lock(&sn_irq_info_lock);
  96.510 +#else
  96.511 +	rcu_read_lock();
  96.512 +#endif
  96.513 +	for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
  96.514 +#ifdef XEN
  96.515 +		list_for_each_entry(sn_irq_info, sn_irq_lh[i], list) {
  96.516 +#else
  96.517 +		list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
  96.518 +#endif
  96.519 +			sn_check_intr(i, sn_irq_info);
  96.520 +		}
  96.521 +	}
  96.522 +#ifdef XEN
  96.523 +	spin_unlock(&sn_irq_info_lock);
  96.524 +#else
  96.525 +	rcu_read_unlock();
  96.526 +#endif
  96.527 +#endif
  96.528 +}
  96.529 +
  96.530 +void __init sn_irq_lh_init(void)
  96.531 +{
  96.532 +	int i;
  96.533 +
  96.534 +	sn_irq_lh = kmalloc(sizeof(struct list_head *) * NR_IRQS, GFP_KERNEL);
  96.535 +	if (!sn_irq_lh)
  96.536 +		panic("SN PCI INIT: Failed to allocate memory for PCI init\n");
  96.537 +
  96.538 +	for (i = 0; i < NR_IRQS; i++) {
  96.539 +		sn_irq_lh[i] = kmalloc(sizeof(struct list_head), GFP_KERNEL);
  96.540 +		if (!sn_irq_lh[i])
  96.541 +			panic("SN PCI INIT: Failed IRQ memory allocation\n");
  96.542 +
  96.543 +		INIT_LIST_HEAD(sn_irq_lh[i]);
  96.544 +	}
  96.545 +}
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/setup.c	Fri Jan 19 14:48:57 2007 +0000
    97.3 @@ -0,0 +1,808 @@
    97.4 +/*
    97.5 + * This file is subject to the terms and conditions of the GNU General Public
    97.6 + * License.  See the file "COPYING" in the main directory of this archive
    97.7 + * for more details.
    97.8 + *
    97.9 + * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved.
   97.10 + */
   97.11 +
   97.12 +#include <linux/module.h>
   97.13 +#include <linux/init.h>
   97.14 +#include <linux/delay.h>
   97.15 +#include <linux/kernel.h>
   97.16 +#ifndef XEN
   97.17 +#include <linux/kdev_t.h>
   97.18 +#endif
   97.19 +#include <linux/string.h>
   97.20 +#ifndef XEN
   97.21 +#include <linux/screen_info.h>
   97.22 +#endif
   97.23 +#include <linux/console.h>
   97.24 +#include <linux/timex.h>
   97.25 +#include <linux/sched.h>
   97.26 +#include <linux/ioport.h>
   97.27 +#include <linux/mm.h>
   97.28 +#include <linux/serial.h>
   97.29 +#include <linux/irq.h>
   97.30 +#include <linux/bootmem.h>
   97.31 +#include <linux/mmzone.h>
   97.32 +#include <linux/interrupt.h>
   97.33 +#include <linux/acpi.h>
   97.34 +#include <linux/compiler.h>
   97.35 +#include <linux/sched.h>
   97.36 +#ifndef XEN
   97.37 +#include <linux/root_dev.h>
   97.38 +#endif
   97.39 +#include <linux/nodemask.h>
   97.40 +#include <linux/pm.h>
   97.41 +#include <linux/efi.h>
   97.42 +
   97.43 +#include <asm/io.h>
   97.44 +#include <asm/sal.h>
   97.45 +#include <asm/machvec.h>
   97.46 +#include <asm/system.h>
   97.47 +#include <asm/processor.h>
   97.48 +#ifndef XEN
   97.49 +#include <asm/vga.h>
   97.50 +#endif
   97.51 +#include <asm/sn/arch.h>
   97.52 +#include <asm/sn/addrs.h>
   97.53 +#include <asm/sn/pda.h>
   97.54 +#include <asm/sn/nodepda.h>
   97.55 +#include <asm/sn/sn_cpuid.h>
   97.56 +#include <asm/sn/simulator.h>
   97.57 +#include <asm/sn/leds.h>
   97.58 +#ifndef XEN
   97.59 +#include <asm/sn/bte.h>
   97.60 +#endif
   97.61 +#include <asm/sn/shub_mmr.h>
   97.62 +#ifndef XEN
   97.63 +#include <asm/sn/clksupport.h>
   97.64 +#endif
   97.65 +#include <asm/sn/sn_sal.h>
   97.66 +#include <asm/sn/geo.h>
   97.67 +#include <asm/sn/sn_feature_sets.h>
   97.68 +#ifndef XEN
   97.69 +#include "xtalk/xwidgetdev.h"
   97.70 +#include "xtalk/hubdev.h"
   97.71 +#else
   97.72 +#include "asm/sn/xwidgetdev.h"
   97.73 +#include "asm/sn/hubdev.h"
   97.74 +#endif
   97.75 +#include <asm/sn/klconfig.h>
   97.76 +#ifdef XEN
   97.77 +#include <asm/sn/shubio.h>
   97.78 +
   97.79 +/* Xen has no clue about NUMA ....  grrrr */
   97.80 +#define pxm_to_node(foo)		0
   97.81 +#define node_to_pxm(foo)		0
   97.82 +#define numa_node_id()			0
   97.83 +#endif
   97.84 +
   97.85 +
   97.86 +DEFINE_PER_CPU(struct pda_s, pda_percpu);
   97.87 +
   97.88 +#define MAX_PHYS_MEMORY		(1UL << IA64_MAX_PHYS_BITS)	/* Max physical address supported */
   97.89 +
   97.90 +extern void bte_init_node(nodepda_t *, cnodeid_t);
   97.91 +
   97.92 +extern void sn_timer_init(void);
   97.93 +extern unsigned long last_time_offset;
   97.94 +extern void (*ia64_mark_idle) (int);
   97.95 +extern void snidle(int);
   97.96 +extern unsigned long long (*ia64_printk_clock)(void);
   97.97 +
   97.98 +unsigned long sn_rtc_cycles_per_second;
   97.99 +EXPORT_SYMBOL(sn_rtc_cycles_per_second);
  97.100 +
  97.101 +DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
  97.102 +EXPORT_PER_CPU_SYMBOL(__sn_hub_info);
  97.103 +
  97.104 +DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]);
  97.105 +EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);
  97.106 +
  97.107 +DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);
  97.108 +EXPORT_PER_CPU_SYMBOL(__sn_nodepda);
  97.109 +
  97.110 +char sn_system_serial_number_string[128];
  97.111 +EXPORT_SYMBOL(sn_system_serial_number_string);
  97.112 +u64 sn_partition_serial_number;
  97.113 +EXPORT_SYMBOL(sn_partition_serial_number);
  97.114 +u8 sn_partition_id;
  97.115 +EXPORT_SYMBOL(sn_partition_id);
  97.116 +u8 sn_system_size;
  97.117 +EXPORT_SYMBOL(sn_system_size);
  97.118 +u8 sn_sharing_domain_size;
  97.119 +EXPORT_SYMBOL(sn_sharing_domain_size);
  97.120 +u8 sn_coherency_id;
  97.121 +EXPORT_SYMBOL(sn_coherency_id);
  97.122 +u8 sn_region_size;
  97.123 +EXPORT_SYMBOL(sn_region_size);
  97.124 +int sn_prom_type;	/* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
  97.125 +
  97.126 +short physical_node_map[MAX_NUMALINK_NODES];
  97.127 +static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
  97.128 +
  97.129 +EXPORT_SYMBOL(physical_node_map);
  97.130 +
  97.131 +int num_cnodes;
  97.132 +
  97.133 +static void sn_init_pdas(char **);
  97.134 +static void build_cnode_tables(void);
  97.135 +
  97.136 +static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
  97.137 +
  97.138 +#ifndef XEN
  97.139 +/*
  97.140 + * The format of "screen_info" is strange, and due to early i386-setup
  97.141 + * code. This is just enough to make the console code think we're on a
  97.142 + * VGA color display.
  97.143 + */
  97.144 +struct screen_info sn_screen_info = {
  97.145 +	.orig_x = 0,
  97.146 +	.orig_y = 0,
  97.147 +	.orig_video_mode = 3,
  97.148 +	.orig_video_cols = 80,
  97.149 +	.orig_video_ega_bx = 3,
  97.150 +	.orig_video_lines = 25,
  97.151 +	.orig_video_isVGA = 1,
  97.152 +	.orig_video_points = 16
  97.153 +};
  97.154 +#endif
  97.155 +
  97.156 +/*
  97.157 + * This routine can only be used during init, since
  97.158 + * smp_boot_data is an init data structure.
  97.159 + * We have to use smp_boot_data.cpu_phys_id to find
  97.160 + * the physical id of the processor because the normal
  97.161 + * cpu_physical_id() relies on data structures that
  97.162 + * may not be initialized yet.
  97.163 + */
  97.164 +
  97.165 +static int __init pxm_to_nasid(int pxm)
  97.166 +{
  97.167 +	int i;
  97.168 +	int nid;
  97.169 +
  97.170 +	nid = pxm_to_node(pxm);
  97.171 +	for (i = 0; i < num_node_memblks; i++) {
  97.172 +		if (node_memblk[i].nid == nid) {
  97.173 +			return NASID_GET(node_memblk[i].start_paddr);
  97.174 +		}
  97.175 +	}
  97.176 +	return -1;
  97.177 +}
  97.178 +
  97.179 +/**
  97.180 + * early_sn_setup - early setup routine for SN platforms
  97.181 + *
  97.182 + * Sets up an initial console to aid debugging.  Intended primarily
  97.183 + * for bringup.  See start_kernel() in init/main.c.
  97.184 + */
  97.185 +
  97.186 +void __init early_sn_setup(void)
  97.187 +{
  97.188 +	efi_system_table_t *efi_systab;
  97.189 +	efi_config_table_t *config_tables;
  97.190 +	struct ia64_sal_systab *sal_systab;
  97.191 +	struct ia64_sal_desc_entry_point *ep;
  97.192 +	char *p;
  97.193 +	int i, j;
  97.194 +
  97.195 +	/*
  97.196 +	 * Parse enough of the SAL tables to locate the SAL entry point. Since, console
  97.197 +	 * IO on SN2 is done via SAL calls, early_printk won't work without this.
  97.198 +	 *
  97.199 +	 * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c.
  97.200 +	 * Any changes to those file may have to be made hereas well.
  97.201 +	 */
  97.202 +	efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab);
  97.203 +	config_tables = __va(efi_systab->tables);
  97.204 +	for (i = 0; i < efi_systab->nr_tables; i++) {
  97.205 +		if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) ==
  97.206 +		    0) {
  97.207 +			sal_systab = __va(config_tables[i].table);
  97.208 +			p = (char *)(sal_systab + 1);
  97.209 +			for (j = 0; j < sal_systab->entry_count; j++) {
  97.210 +				if (*p == SAL_DESC_ENTRY_POINT) {
  97.211 +					ep = (struct ia64_sal_desc_entry_point
  97.212 +					      *)p;
  97.213 +					ia64_sal_handler_init(__va
  97.214 +							      (ep->sal_proc),
  97.215 +							      __va(ep->gp));
  97.216 +					return;
  97.217 +				}
  97.218 +				p += SAL_DESC_SIZE(*p);
  97.219 +			}
  97.220 +		}
  97.221 +	}
  97.222 +	/* Uh-oh, SAL not available?? */
  97.223 +	printk(KERN_ERR "failed to find SAL entry point\n");
  97.224 +}
  97.225 +
  97.226 +extern int platform_intr_list[];
  97.227 +static int __initdata shub_1_1_found;
  97.228 +
  97.229 +/*
  97.230 + * sn_check_for_wars
  97.231 + *
  97.232 + * Set flag for enabling shub specific wars
  97.233 + */
  97.234 +
  97.235 +static inline int __init is_shub_1_1(int nasid)
  97.236 +{
  97.237 +	unsigned long id;
  97.238 +	int rev;
  97.239 +
  97.240 +	if (is_shub2())
  97.241 +		return 0;
  97.242 +	id = REMOTE_HUB_L(nasid, SH1_SHUB_ID);
  97.243 +	rev = (id & SH1_SHUB_ID_REVISION_MASK) >> SH1_SHUB_ID_REVISION_SHFT;
  97.244 +	return rev <= 2;
  97.245 +}
  97.246 +
  97.247 +static void __init sn_check_for_wars(void)
  97.248 +{
  97.249 +	int cnode;
  97.250 +
  97.251 +	if (is_shub2()) {
  97.252 +		/* none yet */
  97.253 +	} else {
  97.254 +		for_each_online_node(cnode) {
  97.255 +			if (is_shub_1_1(cnodeid_to_nasid(cnode)))
  97.256 +				shub_1_1_found = 1;
  97.257 +		}
  97.258 +	}
  97.259 +}
  97.260 +
  97.261 +#ifndef XEN
  97.262 +/*
  97.263 + * Scan the EFI PCDP table (if it exists) for an acceptable VGA console
  97.264 + * output device.  If one exists, pick it and set sn_legacy_{io,mem} to
  97.265 + * reflect the bus offsets needed to address it.
  97.266 + *
  97.267 + * Since pcdp support in SN is not supported in the 2.4 kernel (or at least
  97.268 + * the one lbs is based on) just declare the needed structs here.
  97.269 + *
  97.270 + * Reference spec http://www.dig64.org/specifications/DIG64_PCDPv20.pdf
  97.271 + *
  97.272 + * Returns 0 if no acceptable vga is found, !0 otherwise.
  97.273 + *
  97.274 + * Note:  This stuff is duped here because Altix requires the PCDP to
  97.275 + * locate a usable VGA device due to lack of proper ACPI support.  Structures
  97.276 + * could be used from drivers/firmware/pcdp.h, but it was decided that moving
  97.277 + * this file to a more public location just for Altix use was undesireable.
  97.278 + */
  97.279 +
  97.280 +struct hcdp_uart_desc {
  97.281 +	u8	pad[45];
  97.282 +};
  97.283 +
  97.284 +struct pcdp {
  97.285 +	u8	signature[4];	/* should be 'HCDP' */
  97.286 +	u32	length;
  97.287 +	u8	rev;		/* should be >=3 for pcdp, <3 for hcdp */
  97.288 +	u8	sum;
  97.289 +	u8	oem_id[6];
  97.290 +	u64	oem_tableid;
  97.291 +	u32	oem_rev;
  97.292 +	u32	creator_id;
  97.293 +	u32	creator_rev;
  97.294 +	u32	num_type0;
  97.295 +	struct hcdp_uart_desc uart[0];	/* num_type0 of these */
  97.296 +	/* pcdp descriptors follow */
  97.297 +}  __attribute__((packed));
  97.298 +
  97.299 +struct pcdp_device_desc {
  97.300 +	u8	type;
  97.301 +	u8	primary;
  97.302 +	u16	length;
  97.303 +	u16	index;
  97.304 +	/* interconnect specific structure follows */
  97.305 +	/* device specific structure follows that */
  97.306 +}  __attribute__((packed));
  97.307 +
  97.308 +struct pcdp_interface_pci {
  97.309 +	u8	type;		/* 1 == pci */
  97.310 +	u8	reserved;
  97.311 +	u16	length;
  97.312 +	u8	segment;
  97.313 +	u8	bus;
  97.314 +	u8 	dev;
  97.315 +	u8	fun;
  97.316 +	u16	devid;
  97.317 +	u16	vendid;
  97.318 +	u32	acpi_interrupt;
  97.319 +	u64	mmio_tra;
  97.320 +	u64	ioport_tra;
  97.321 +	u8	flags;
  97.322 +	u8	translation;
  97.323 +}  __attribute__((packed));
  97.324 +
  97.325 +struct pcdp_vga_device {
  97.326 +	u8	num_eas_desc;
  97.327 +	/* ACPI Extended Address Space Desc follows */
  97.328 +}  __attribute__((packed));
  97.329 +
  97.330 +/* from pcdp_device_desc.primary */
  97.331 +#define PCDP_PRIMARY_CONSOLE	0x01
  97.332 +
  97.333 +/* from pcdp_device_desc.type */
  97.334 +#define PCDP_CONSOLE_INOUT	0x0
  97.335 +#define PCDP_CONSOLE_DEBUG	0x1
  97.336 +#define PCDP_CONSOLE_OUT	0x2
  97.337 +#define PCDP_CONSOLE_IN		0x3
  97.338 +#define PCDP_CONSOLE_TYPE_VGA	0x8
  97.339 +
  97.340 +#define PCDP_CONSOLE_VGA	(PCDP_CONSOLE_TYPE_VGA | PCDP_CONSOLE_OUT)
  97.341 +
  97.342 +/* from pcdp_interface_pci.type */
  97.343 +#define PCDP_IF_PCI		1
  97.344 +
  97.345 +/* from pcdp_interface_pci.translation */
  97.346 +#define PCDP_PCI_TRANS_IOPORT	0x02
  97.347 +#define PCDP_PCI_TRANS_MMIO	0x01
  97.348 +
  97.349 +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
  97.350 +static void
  97.351 +sn_scan_pcdp(void)
  97.352 +{
  97.353 +	u8 *bp;
  97.354 +	struct pcdp *pcdp;
  97.355 +	struct pcdp_device_desc device;
  97.356 +	struct pcdp_interface_pci if_pci;
  97.357 +	extern struct efi efi;
  97.358 +
  97.359 +	if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
  97.360 +		return;		/* no hcdp/pcdp table */
  97.361 +
  97.362 +	pcdp = __va(efi.hcdp);
  97.363 +
  97.364 +	if (pcdp->rev < 3)
  97.365 +		return;		/* only support PCDP (rev >= 3) */
  97.366 +
  97.367 +	for (bp = (u8 *)&pcdp->uart[pcdp->num_type0];
  97.368 +	     bp < (u8 *)pcdp + pcdp->length;
  97.369 +	     bp += device.length) {
  97.370 +		memcpy(&device, bp, sizeof(device));
  97.371 +		if (! (device.primary & PCDP_PRIMARY_CONSOLE))
  97.372 +			continue;	/* not primary console */
  97.373 +
  97.374 +		if (device.type != PCDP_CONSOLE_VGA)
  97.375 +			continue;	/* not VGA descriptor */
  97.376 +
  97.377 +		memcpy(&if_pci, bp+sizeof(device), sizeof(if_pci));
  97.378 +		if (if_pci.type != PCDP_IF_PCI)
  97.379 +			continue;	/* not PCI interconnect */
  97.380 +
  97.381 +		if (if_pci.translation & PCDP_PCI_TRANS_IOPORT)
  97.382 +			vga_console_iobase =
  97.383 +				if_pci.ioport_tra | __IA64_UNCACHED_OFFSET;
  97.384 +
  97.385 +		if (if_pci.translation & PCDP_PCI_TRANS_MMIO)
  97.386 +			vga_console_membase =
  97.387 +				if_pci.mmio_tra | __IA64_UNCACHED_OFFSET;
  97.388 +
  97.389 +		break; /* once we find the primary, we're done */
  97.390 +	}
  97.391 +}
  97.392 +#endif
  97.393 +
  97.394 +static unsigned long sn2_rtc_initial;
  97.395 +
  97.396 +static unsigned long long ia64_sn2_printk_clock(void)
  97.397 +{
  97.398 +	unsigned long rtc_now = rtc_time();
  97.399 +
  97.400 +	return (rtc_now - sn2_rtc_initial) *
  97.401 +		(1000000000 / sn_rtc_cycles_per_second);
  97.402 +}
  97.403 +#endif
  97.404 +
  97.405 +/**
  97.406 + * sn_setup - SN platform setup routine
  97.407 + * @cmdline_p: kernel command line
  97.408 + *
  97.409 + * Handles platform setup for SN machines.  This includes determining
  97.410 + * the RTC frequency (via a SAL call), initializing secondary CPUs, and
  97.411 + * setting up per-node data areas.  The console is also initialized here.
  97.412 + */
  97.413 +#ifdef XEN
  97.414 +void __cpuinit sn_cpu_init(void);
  97.415 +#endif
  97.416 +
  97.417 +void __init sn_setup(char **cmdline_p)
  97.418 +{
  97.419 +#ifndef XEN
  97.420 +	long status, ticks_per_sec, drift;
  97.421 +#else
  97.422 +	unsigned long status, ticks_per_sec, drift;
  97.423 +#endif
  97.424 +	u32 version = sn_sal_rev();
  97.425 +#ifndef XEN
  97.426 +	extern void sn_cpu_init(void);
  97.427 +
  97.428 +	sn2_rtc_initial = rtc_time();
  97.429 +	ia64_sn_plat_set_error_handling_features();	// obsolete
  97.430 +	ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
  97.431 +	ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
  97.432 +
  97.433 +
  97.434 +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
  97.435 +	/*
  97.436 +	 * Handle SN vga console.
  97.437 +	 *
  97.438 +	 * SN systems do not have enough ACPI table information
  97.439 +	 * being passed from prom to identify VGA adapters and the legacy
  97.440 +	 * addresses to access them.  Until that is done, SN systems rely
  97.441 +	 * on the PCDP table to identify the primary VGA console if one
  97.442 +	 * exists.
  97.443 +	 *
  97.444 +	 * However, kernel PCDP support is optional, and even if it is built
  97.445 +	 * into the kernel, it will not be used if the boot cmdline contains
  97.446 +	 * console= directives.
  97.447 +	 *
  97.448 +	 * So, to work around this mess, we duplicate some of the PCDP code
  97.449 +	 * here so that the primary VGA console (as defined by PCDP) will
  97.450 +	 * work on SN systems even if a different console (e.g. serial) is
  97.451 +	 * selected on the boot line (or CONFIG_EFI_PCDP is off).
  97.452 +	 */
  97.453 +
  97.454 +	if (! vga_console_membase)
  97.455 +		sn_scan_pcdp();
  97.456 +
  97.457 +	if (vga_console_membase) {
  97.458 +		/* usable vga ... make tty0 the preferred default console */
  97.459 +		if (!strstr(*cmdline_p, "console="))
  97.460 +			add_preferred_console("tty", 0, NULL);
  97.461 +	} else {
  97.462 +		printk(KERN_DEBUG "SGI: Disabling VGA console\n");
  97.463 +		if (!strstr(*cmdline_p, "console="))
  97.464 +			add_preferred_console("ttySG", 0, NULL);
  97.465 +#ifdef CONFIG_DUMMY_CONSOLE
  97.466 +		conswitchp = &dummy_con;
  97.467 +#else
  97.468 +		conswitchp = NULL;
  97.469 +#endif				/* CONFIG_DUMMY_CONSOLE */
  97.470 +	}
  97.471 +#endif				/* def(CONFIG_VT) && def(CONFIG_VGA_CONSOLE) */
  97.472 +
  97.473 +	MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
  97.474 +#endif
  97.475 +
  97.476 +	/*
  97.477 +	 * Build the tables for managing cnodes.
  97.478 +	 */
  97.479 +	build_cnode_tables();
  97.480 +
  97.481 +	status =
  97.482 +	    ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
  97.483 +			       &drift);
  97.484 +	if (status != 0 || ticks_per_sec < 100000) {
  97.485 +		printk(KERN_WARNING
  97.486 +		       "unable to determine platform RTC clock frequency, guessing.\n");
  97.487 +		/* PROM gives wrong value for clock freq. so guess */
  97.488 +		sn_rtc_cycles_per_second = 1000000000000UL / 30000UL;
  97.489 +	} else
  97.490 +		sn_rtc_cycles_per_second = ticks_per_sec;
  97.491 +#ifndef XEN
  97.492 +
  97.493 +	platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR;
  97.494 +
  97.495 +	ia64_printk_clock = ia64_sn2_printk_clock;
  97.496 +#endif
  97.497 +
  97.498 +	printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
  97.499 +
  97.500 +	/*
  97.501 +	 * we set the default root device to /dev/hda
  97.502 +	 * to make simulation easy
  97.503 +	 */
  97.504 +#ifndef XEN
  97.505 +	ROOT_DEV = Root_HDA1;
  97.506 +#endif
  97.507 +
  97.508 +	/*
  97.509 +	 * Create the PDAs and NODEPDAs for all the cpus.
  97.510 +	 */
  97.511 +	sn_init_pdas(cmdline_p);
  97.512 +
  97.513 +#ifndef XEN
  97.514 +	ia64_mark_idle = &snidle;
  97.515 +#endif
  97.516 +
  97.517 +	/*
  97.518 +	 * For the bootcpu, we do this here. All other cpus will make the
  97.519 +	 * call as part of cpu_init in slave cpu initialization.
  97.520 +	 */
  97.521 +	sn_cpu_init();
  97.522 +
  97.523 +#ifndef XEN
  97.524 +#ifdef CONFIG_SMP
  97.525 +	init_smp_config();
  97.526 +#endif
  97.527 +	screen_info = sn_screen_info;
  97.528 +
  97.529 +	sn_timer_init();
  97.530 +
  97.531 +	/*
  97.532 +	 * set pm_power_off to a SAL call to allow
  97.533 +	 * sn machines to power off. The SAL call can be replaced
  97.534 +	 * by an ACPI interface call when ACPI is fully implemented
  97.535 +	 * for sn.
  97.536 +	 */
  97.537 +	pm_power_off = ia64_sn_power_down;
  97.538 +	current->thread.flags |= IA64_THREAD_MIGRATION;
  97.539 +#endif
  97.540 +}
  97.541 +
  97.542 +/**
  97.543 + * sn_init_pdas - setup node data areas
  97.544 + *
  97.545 + * One time setup for Node Data Area.  Called by sn_setup().
  97.546 + */
  97.547 +static void __init sn_init_pdas(char **cmdline_p)
  97.548 +{
  97.549 +	cnodeid_t cnode;
  97.550 +
  97.551 +	/*
  97.552 +	 * Allocate & initalize the nodepda for each node.
  97.553 +	 */
  97.554 +	for_each_online_node(cnode) {
  97.555 +		nodepdaindr[cnode] =
  97.556 +		    alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t));
  97.557 +		memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
  97.558 +		memset(nodepdaindr[cnode]->phys_cpuid, -1,
  97.559 +		    sizeof(nodepdaindr[cnode]->phys_cpuid));
  97.560 +		spin_lock_init(&nodepdaindr[cnode]->ptc_lock);
  97.561 +	}
  97.562 +
  97.563 +	/*
  97.564 +	 * Allocate & initialize nodepda for TIOs.  For now, put them on node 0.
  97.565 +	 */
  97.566 +	for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
  97.567 +		nodepdaindr[cnode] =
  97.568 +		    alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
  97.569 +		memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
  97.570 +	}
  97.571 +
  97.572 +	/*
  97.573 +	 * Now copy the array of nodepda pointers to each nodepda.
  97.574 +	 */
  97.575 +	for (cnode = 0; cnode < num_cnodes; cnode++)
  97.576 +		memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr,
  97.577 +		       sizeof(nodepdaindr));
  97.578 +
  97.579 +#ifndef XEN
  97.580 +	/*
  97.581 +	 * Set up IO related platform-dependent nodepda fields.
  97.582 +	 * The following routine actually sets up the hubinfo struct
  97.583 +	 * in nodepda.
  97.584 +	 */
  97.585 +	for_each_online_node(cnode) {
  97.586 +		bte_init_node(nodepdaindr[cnode], cnode);
  97.587 +	}
  97.588 +
  97.589 +	/*
  97.590 +	 * Initialize the per node hubdev.  This includes IO Nodes and
  97.591 +	 * headless/memless nodes.
  97.592 +	 */
  97.593 +	for (cnode = 0; cnode < num_cnodes; cnode++) {
  97.594 +		hubdev_init_node(nodepdaindr[cnode], cnode);
  97.595 +	}
  97.596 +#endif
  97.597 +}
  97.598 +
  97.599 +/**
  97.600 + * sn_cpu_init - initialize per-cpu data areas
  97.601 + * @cpuid: cpuid of the caller
  97.602 + *
  97.603 + * Called during cpu initialization on each cpu as it starts.
  97.604 + * Currently, initializes the per-cpu data area for SNIA.
  97.605 + * Also sets up a few fields in the nodepda.  Also known as
  97.606 + * platform_cpu_init() by the ia64 machvec code.
  97.607 + */
  97.608 +void __cpuinit sn_cpu_init(void)
  97.609 +{
  97.610 +	int cpuid;
  97.611 +	int cpuphyid;
  97.612 +	int nasid;
  97.613 +	int subnode;
  97.614 +	int slice;
  97.615 +	int cnode;
  97.616 +	int i;
  97.617 +	static int wars_have_been_checked;
  97.618 +
  97.619 +	cpuid = smp_processor_id();
  97.620 +#ifndef XEN
  97.621 +	if (cpuid == 0 && IS_MEDUSA()) {
  97.622 +		if (ia64_sn_is_fake_prom())
  97.623 +			sn_prom_type = 2;
  97.624 +		else
  97.625 +			sn_prom_type = 1;
  97.626 +		printk(KERN_INFO "Running on medusa with %s PROM\n",
  97.627 +		       (sn_prom_type == 1) ? "real" : "fake");
  97.628 +	}
  97.629 +#endif
  97.630 +
  97.631 +	memset(pda, 0, sizeof(pda));
  97.632 +	if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
  97.633 +				&sn_hub_info->nasid_bitmask,
  97.634 +				&sn_hub_info->nasid_shift,
  97.635 +				&sn_system_size, &sn_sharing_domain_size,
  97.636 +				&sn_partition_id, &sn_coherency_id,
  97.637 +				&sn_region_size))
  97.638 +		BUG();
  97.639 +	sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
  97.640 +
  97.641 +	/*
  97.642 +	 * Don't check status. The SAL call is not supported on all PROMs
  97.643 +	 * but a failure is harmless.
  97.644 +	 */
  97.645 +	(void) ia64_sn_set_cpu_number(cpuid);
  97.646 +
  97.647 +	/*
  97.648 +	 * The boot cpu makes this call again after platform initialization is
  97.649 +	 * complete.
  97.650 +	 */
  97.651 +	if (nodepdaindr[0] == NULL)
  97.652 +		return;
  97.653 +
  97.654 +	for (i = 0; i < MAX_PROM_FEATURE_SETS; i++)
  97.655 +		if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)
  97.656 +			break;
  97.657 +
  97.658 +	cpuphyid = get_sapicid();
  97.659 +
  97.660 +	if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice))
  97.661 +		BUG();
  97.662 +
  97.663 +	for (i=0; i < MAX_NUMNODES; i++) {
  97.664 +		if (nodepdaindr[i]) {
  97.665 +			nodepdaindr[i]->phys_cpuid[cpuid].nasid = nasid;
  97.666 +			nodepdaindr[i]->phys_cpuid[cpuid].slice = slice;
  97.667 +			nodepdaindr[i]->phys_cpuid[cpuid].subnode = subnode;
  97.668 +		}
  97.669 +	}
  97.670 +
  97.671 +	cnode = nasid_to_cnodeid(nasid);
  97.672 +
  97.673 +	sn_nodepda = nodepdaindr[cnode];
  97.674 +
  97.675 +	pda->led_address =
  97.676 +	    (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
  97.677 +	pda->led_state = LED_ALWAYS_SET;
  97.678 +	pda->hb_count = HZ / 2;
  97.679 +	pda->hb_state = 0;
  97.680 +	pda->idle_flag = 0;
  97.681 +
  97.682 +	if (cpuid != 0) {
  97.683 +		/* copy cpu 0's sn_cnodeid_to_nasid table to this cpu's */
  97.684 +		memcpy(sn_cnodeid_to_nasid,
  97.685 +		       (&per_cpu(__sn_cnodeid_to_nasid, 0)),
  97.686 +		       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
  97.687 +	}
  97.688 +
  97.689 +	/*
  97.690 +	 * Check for WARs.
  97.691 +	 * Only needs to be done once, on BSP.
  97.692 +	 * Has to be done after loop above, because it uses this cpu's
  97.693 +	 * sn_cnodeid_to_nasid table which was just initialized if this
  97.694 +	 * isn't cpu 0.
  97.695 +	 * Has to be done before assignment below.
  97.696 +	 */
  97.697 +	if (!wars_have_been_checked) {
  97.698 +		sn_check_for_wars();
  97.699 +		wars_have_been_checked = 1;
  97.700 +	}
  97.701 +	sn_hub_info->shub_1_1_found = shub_1_1_found;
  97.702 +
  97.703 +	/*
  97.704 +	 * Set up addresses of PIO/MEM write status registers.
  97.705 +	 */
  97.706 +	{
  97.707 +		u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
  97.708 +		u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_2,
  97.709 +			SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
  97.710 +		u64 *pio;
  97.711 +		pio = is_shub1() ? pio1 : pio2;
  97.712 +		pda->pio_write_status_addr =
  97.713 +		   (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
  97.714 +		pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
  97.715 +	}
  97.716 +
  97.717 +#ifndef XEN  /* local_node_data is not allocated .... yet */
  97.718 +	/*
  97.719 +	 * WAR addresses for SHUB 1.x.
  97.720 +	 */
  97.721 +	if (local_node_data->active_cpu_count++ == 0 && is_shub1()) {
  97.722 +		int buddy_nasid;
  97.723 +		buddy_nasid =
  97.724 +		    cnodeid_to_nasid(numa_node_id() ==
  97.725 +				     num_online_nodes() - 1 ? 0 : numa_node_id() + 1);
  97.726 +		pda->pio_shub_war_cam_addr =
  97.727 +		    (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid,
  97.728 +							      SH1_PI_CAM_CONTROL);
  97.729 +	}
  97.730 +#endif
  97.731 +}
  97.732 +
  97.733 +/*
  97.734 + * Build tables for converting between NASIDs and cnodes.
  97.735 + */
  97.736 +static inline int __init board_needs_cnode(int type)
  97.737 +{
  97.738 +	return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
  97.739 +}
  97.740 +
  97.741 +void __init build_cnode_tables(void)
  97.742 +{
  97.743 +	int nasid;
  97.744 +	int node;
  97.745 +	lboard_t *brd;
  97.746 +
  97.747 +	memset(physical_node_map, -1, sizeof(physical_node_map));
  97.748 +	memset(sn_cnodeid_to_nasid, -1,
  97.749 +			sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
  97.750 +
  97.751 +	/*
  97.752 +	 * First populate the tables with C/M bricks. This ensures that
  97.753 +	 * cnode == node for all C & M bricks.
  97.754 +	 */
  97.755 +	for_each_online_node(node) {
  97.756 +		nasid = pxm_to_nasid(node_to_pxm(node));
  97.757 +		sn_cnodeid_to_nasid[node] = nasid;
  97.758 +		physical_node_map[nasid] = node;
  97.759 +	}
  97.760 +
  97.761 +	/*
  97.762 +	 * num_cnodes is total number of C/M/TIO bricks. Because of the 256 node
  97.763 +	 * limit on the number of nodes, we can't use the generic node numbers 
  97.764 +	 * for this. Note that num_cnodes is incremented below as TIOs or
  97.765 +	 * headless/memoryless nodes are discovered.
  97.766 +	 */
  97.767 +	num_cnodes = num_online_nodes();
  97.768 +
  97.769 +	/* fakeprom does not support klgraph */
  97.770 +	if (IS_RUNNING_ON_FAKE_PROM())
  97.771 +		return;
  97.772 +
  97.773 +	/* Find TIOs & headless/memoryless nodes and add them to the tables */
  97.774 +	for_each_online_node(node) {
  97.775 +		kl_config_hdr_t *klgraph_header;
  97.776 +		nasid = cnodeid_to_nasid(node);
  97.777 +		klgraph_header = ia64_sn_get_klconfig_addr(nasid);
  97.778 +		if (klgraph_header == NULL)
  97.779 +			BUG();
  97.780 +		brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
  97.781 +		while (brd) {
  97.782 +			if (board_needs_cnode(brd->brd_type) && physical_node_map[brd->brd_nasid] < 0) {
  97.783 +				sn_cnodeid_to_nasid[num_cnodes] = brd->brd_nasid;
  97.784 +				physical_node_map[brd->brd_nasid] = num_cnodes++;
  97.785 +			}
  97.786 +			brd = find_lboard_next(brd);
  97.787 +		}
  97.788 +	}
  97.789 +}
  97.790 +
  97.791 +int
  97.792 +nasid_slice_to_cpuid(int nasid, int slice)
  97.793 +{
  97.794 +	long cpu;
  97.795 +
  97.796 +	for (cpu = 0; cpu < NR_CPUS; cpu++)
  97.797 +		if (cpuid_to_nasid(cpu) == nasid &&
  97.798 +					cpuid_to_slice(cpu) == slice)
  97.799 +			return cpu;
  97.800 +
  97.801 +	return -1;
  97.802 +}
  97.803 +
  97.804 +int sn_prom_feature_available(int id)
  97.805 +{
  97.806 +	if (id >= BITS_PER_LONG * MAX_PROM_FEATURE_SETS)
  97.807 +		return 0;
  97.808 +	return test_bit(id, sn_prom_features);
  97.809 +}
  97.810 +EXPORT_SYMBOL(sn_prom_feature_available);
  97.811 +
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/xen/arch/ia64/linux-xen/sn/kernel/sn2_smp.c	Fri Jan 19 14:48:57 2007 +0000
    98.3 @@ -0,0 +1,548 @@
    98.4 +/*
    98.5 + * SN2 Platform specific SMP Support
    98.6 + *
    98.7 + * This file is subject to the terms and conditions of the GNU General Public
    98.8 + * License.  See the file "COPYING" in the main directory of this archive
    98.9 + * for more details.
   98.10 + *
   98.11 + * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved.
   98.12 + */
   98.13 +
   98.14 +#include <linux/init.h>
   98.15 +#include <linux/kernel.h>
   98.16 +#include <linux/spinlock.h>
   98.17 +#include <linux/threads.h>
   98.18 +#include <linux/sched.h>
   98.19 +#include <linux/smp.h>
   98.20 +#include <linux/interrupt.h>
   98.21 +#include <linux/irq.h>
   98.22 +#include <linux/mmzone.h>
   98.23 +#include <linux/module.h>
   98.24 +#include <linux/bitops.h>
   98.25 +#include <linux/nodemask.h>
   98.26 +#include <linux/proc_fs.h>
   98.27 +#include <linux/seq_file.h>
   98.28 +
   98.29 +#include <asm/processor.h>
   98.30 +#include <asm/irq.h>
   98.31 +#include <asm/sal.h>
   98.32 +#include <asm/system.h>
   98.33 +#include <asm/delay.h>
   98.34 +#include <asm/io.h>
   98.35 +#include <asm/smp.h>
   98.36 +#include <asm/tlb.h>
   98.37 +#include <asm/numa.h>
   98.38 +#include <asm/hw_irq.h>
   98.39 +#include <asm/current.h>
   98.40 +#ifdef XEN
   98.41 +#include <asm/sn/arch.h>
   98.42 +#endif
   98.43 +#include <asm/sn/sn_cpuid.h>
   98.44 +#include <asm/sn/sn_sal.h>
   98.45 +#include <asm/sn/addrs.h>
   98.46 +#include <asm/sn/shub_mmr.h>
   98.47 +#include <asm/sn/nodepda.h>
   98.48 +#include <asm/sn/rw_mmr.h>
   98.49 +
   98.50 +DEFINE_PER_CPU(struct ptc_stats, ptcstats);
   98.51 +DECLARE_PER_CPU(struct ptc_stats, ptcstats);
   98.52 +
   98.53 +static  __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
   98.54 +
   98.55 +extern unsigned long
   98.56 +sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
   98.57 +			       volatile unsigned long *, unsigned long,
   98.58 +			       volatile unsigned long *, unsigned long);
   98.59 +void
   98.60 +sn2_ptc_deadlock_recovery(short *, short, short, int,
   98.61 +			  volatile unsigned long *, unsigned long,
   98.62 +			  volatile unsigned long *, unsigned long);
   98.63 +
   98.64 +/*
   98.65 + * Note: some is the following is captured here to make degugging easier
   98.66 + * (the macros make more sense if you see the debug patch - not posted)
   98.67 + */
   98.68 +#define sn2_ptctest	0
   98.69 +#define local_node_uses_ptc_ga(sh1)	((sh1) ? 1 : 0)
   98.70 +#define max_active_pio(sh1)		((sh1) ? 32 : 7)
   98.71 +#define reset_max_active_on_deadlock()	1
   98.72 +#ifndef XEN
   98.73 +#define PTC_LOCK(sh1)			((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock)
   98.74 +#else
   98.75 +#define PTC_LOCK(sh1)			&sn2_global_ptc_lock
   98.76 +#endif
   98.77 +
   98.78 +struct ptc_stats {
   98.79 +	unsigned long ptc_l;
   98.80 +	unsigned long change_rid;
   98.81 +	unsigned long shub_ptc_flushes;
   98.82 +	unsigned long nodes_flushed;
   98.83 +	unsigned long deadlocks;
   98.84 +	unsigned long deadlocks2;
   98.85 +	unsigned long lock_itc_clocks;
   98.86 +	unsigned long shub_itc_clocks;
   98.87 +	unsigned long shub_itc_clocks_max;
   98.88 +	unsigned long shub_ptc_flushes_not_my_mm;
   98.89 +};
   98.90 +
   98.91 +#define sn2_ptctest	0
   98.92 +
   98.93 +static inline unsigned long wait_piowc(void)
   98.94 +{
   98.95 +	volatile unsigned long *piows;
   98.96 +	unsigned long zeroval, ws;
   98.97 +
   98.98 +	piows = pda->pio_write_status_addr;
   98.99 +	zeroval = pda->pio_write_status_val;
  98.100 +	do {
  98.101 +		cpu_relax();
  98.102 +	} while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval);
  98.103 +	return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
  98.104 +}
  98.105 +
  98.106 +#ifndef XEN  /* No idea if Xen will ever support this */
  98.107 +/**
  98.108 + * sn_migrate - SN-specific task migration actions
  98.109 + * @task: Task being migrated to new CPU
  98.110 + *
  98.111 + * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order.
  98.112 + * Context switching user threads which have memory-mapped MMIO may cause
  98.113 + * PIOs to issue from seperate CPUs, thus the PIO writes must be drained
  98.114 + * from the previous CPU's Shub before execution resumes on the new CPU.
  98.115 + */
  98.116 +void sn_migrate(struct task_struct *task)
  98.117 +{
  98.118 +	pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu);
  98.119 +	volatile unsigned long *adr = last_pda->pio_write_status_addr;
  98.120 +	unsigned long val = last_pda->pio_write_status_val;
  98.121 +
  98.122 +	/* Drain PIO writes from old CPU's Shub */
  98.123 +	while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK)
  98.124 +			!= val))
  98.125 +		cpu_relax();
  98.126 +}
  98.127 +
  98.128 +void sn_tlb_migrate_finish(struct mm_struct *mm)
  98.129 +{
  98.130 +	/* flush_tlb_mm is inefficient if more than 1 users of mm */
  98.131 +#ifndef XEN
  98.132 +	if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1)
  98.133 +#else
  98.134 +	if (mm == &current->arch.mm && mm && atomic_read(&mm->mm_users) == 1)
  98.135 +#endif
  98.136 +		flush_tlb_mm(mm);
  98.137 +}
  98.138 +#endif
  98.139 +
  98.140 +/**
  98.141 + * sn2_global_tlb_purge - globally purge translation cache of virtual address range
  98.142 + * @mm: mm_struct containing virtual address range
  98.143 + * @start: start of virtual address range
  98.144 + * @end: end of virtual address range
  98.145 + * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
  98.146 + *
  98.147 + * Purges the translation caches of all processors of the given virtual address
  98.148 + * range.
  98.149 + *
  98.150 + * Note:
  98.151 + * 	- cpu_vm_mask is a bit mask that indicates which cpus have loaded the context.
  98.152 + * 	- cpu_vm_mask is converted into a nodemask of the nodes containing the
  98.153 + * 	  cpus in cpu_vm_mask.
  98.154 + *	- if only one bit is set in cpu_vm_mask & it is the current cpu & the
  98.155 + *	  process is purging its own virtual address range, then only the
  98.156 + *	  local TLB needs to be flushed. This flushing can be done using
  98.157 + *	  ptc.l. This is the common case & avoids the global spinlock.
  98.158 + *	- if multiple cpus have loaded the context, then flushing has to be
  98.159 + *	  done with ptc.g/MMRs under protection of the global ptc_lock.
  98.160 + */
  98.161 +
  98.162 +#ifdef XEN  /* Xen is soooooooo stupid! */
  98.163 +// static cpumask_t mask_all = CPU_MASK_ALL;
  98.164 +#endif
  98.165 +
  98.166 +void
  98.167 +#ifndef XEN
  98.168 +sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
  98.169 +#else
  98.170 +sn2_global_tlb_purge(unsigned long start,
  98.171 +#endif
  98.172 +		     unsigned long end, unsigned long nbits)
  98.173 +{
  98.174 +	int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid;
  98.175 +#ifndef XEN
  98.176 +	int mymm = (mm == current->active_mm && mm == current->mm);
  98.177 +#else
  98.178 +	// struct mm_struct *mm;
  98.179 +	int mymm = 0;
  98.180 +#endif
  98.181 +	int use_cpu_ptcga;
  98.182 +	volatile unsigned long *ptc0, *ptc1;
  98.183 +	unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
  98.184 +	short nasids[MAX_NUMNODES], nix;
  98.185 +	nodemask_t nodes_flushed;
  98.186 +	int active, max_active, deadlock;
  98.187 +
  98.188 +	nodes_clear(nodes_flushed);
  98.189 +	i = 0;
  98.190 +
  98.191 +#ifndef XEN  /* One day Xen will grow up! */
  98.192 +	for_each_cpu_mask(cpu, mm->cpu_vm_mask) {
  98.193 +		cnode = cpu_to_node(cpu);
  98.194 +		node_set(cnode, nodes_flushed);
  98.195 +		lcpu = cpu;
  98.196 +		i++;
  98.197 +	}
  98.198 +#else
  98.199 +	for_each_cpu(cpu) {
  98.200 +		cnode = cpu_to_node(cpu);
  98.201 +		node_set(cnode, nodes_flushed);
  98.202 +		lcpu = cpu;
  98.203 +		i++;
  98.204 +	}
  98.205 +#endif
  98.206 +
  98.207 +	if (i == 0)
  98.208 +		return;
  98.209 +
  98.210 +	preempt_disable();
  98.211 +
  98.212 +	if (likely(i == 1 && lcpu == smp_processor_id() && mymm)) {
  98.213 +		do {
  98.214 +			ia64_ptcl(start, nbits << 2);
  98.215 +			start += (1UL << nbits);
  98.216 +		} while (start < end);
  98.217 +		ia64_srlz_i();
  98.218 +		__get_cpu_var(ptcstats).ptc_l++;
  98.219 +		preempt_enable();
  98.220 +		return;
  98.221 +	}
  98.222 +
  98.223 +#ifndef XEN
  98.224 +	if (atomic_read(&mm->mm_users) == 1 && mymm) {
  98.225 +#ifndef XEN  /* I hate Xen! */
  98.226 +		flush_tlb_mm(mm);
  98.227 +#else
  98.228 +		flush_tlb_mask(mask_all);
  98.229 +#endif
  98.230 +		__get_cpu_var(ptcstats).change_rid++;
  98.231 +		preempt_enable();
  98.232 +		return;
  98.233 +	}
  98.234 +#endif
  98.235 +
  98.236 +	itc = ia64_get_itc();
  98.237 +	nix = 0;
  98.238 +	for_each_node_mask(cnode, nodes_flushed)
  98.239 +		nasids[nix++] = cnodeid_to_nasid(cnode);
  98.240 +
  98.241 +#ifndef XEN
  98.242 +	rr_value = (mm->context << 3) | REGION_NUMBER(start);
  98.243 +#else
  98.244 +	rr_value = REGION_NUMBER(start);
  98.245 +#endif
  98.246 +
  98.247 +	shub1 = is_shub1();
  98.248 +	if (shub1) {
  98.249 +		data0 = (1UL << SH1_PTC_0_A_SHFT) |
  98.250 +		    	(nbits << SH1_PTC_0_PS_SHFT) |
  98.251 +			(rr_value << SH1_PTC_0_RID_SHFT) |
  98.252 +		    	(1UL << SH1_PTC_0_START_SHFT);
  98.253 +#ifndef XEN
  98.254 +		ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0);
  98.255 +		ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1);
  98.256 +#else
  98.257 +		ptc0 = (unsigned long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0);
  98.258 +		ptc1 = (unsigned long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1);
  98.259 +#endif
  98.260 +	} else {
  98.261 +		data0 = (1UL << SH2_PTC_A_SHFT) |
  98.262 +			(nbits << SH2_PTC_PS_SHFT) |
  98.263 +		    	(1UL << SH2_PTC_START_SHFT);
  98.264 +#ifndef XEN
  98.265 +		ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC + 
  98.266 +#else
  98.267 +		ptc0 = (unsigned long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC + 
  98.268 +#endif
  98.269 +			(rr_value << SH2_PTC_RID_SHFT));
  98.270 +		ptc1 = NULL;
  98.271 +	}
  98.272 +	
  98.273 +
  98.274 +	mynasid = get_nasid();
  98.275 +	use_cpu_ptcga = local_node_uses_ptc_ga(shub1);
  98.276 +	max_active = max_active_pio(shub1);
  98.277 +
  98.278 +	itc = ia64_get_itc();
  98.279 +	spin_lock_irqsave(PTC_LOCK(shub1), flags);
  98.280 +	itc2 = ia64_get_itc();
  98.281 +
  98.282 +	__get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc;
  98.283 +	__get_cpu_var(ptcstats).shub_ptc_flushes++;
  98.284 +	__get_cpu_var(ptcstats).nodes_flushed += nix;
  98.285 +	if (!mymm)
  98.286 +		 __get_cpu_var(ptcstats).shub_ptc_flushes_not_my_mm++;
  98.287 +
  98.288 +	if (use_cpu_ptcga && !mymm) {
  98.289 +		old_rr = ia64_get_rr(start);
  98.290 +		ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8));
  98.291 +		ia64_srlz_d();
  98.292 +	}
  98.293 +
  98.294 +	wait_piowc();
  98.295 +	do {
  98.296 +		if (shub1)
  98.297 +			data1 = start | (1UL << SH1_PTC_1_START_SHFT);
  98.298 +		else
  98.299 +			data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
  98.300 +		deadlock = 0;
  98.301 +		active = 0;
  98.302 +		for (ibegin = 0, i = 0; i < nix; i++) {
  98.303 +			nasid = nasids[i];
  98.304 +			if (use_cpu_ptcga && unlikely(nasid == mynasid)) {
  98.305 +				ia64_ptcga(start, nbits << 2);
  98.306 +				ia64_srlz_i();
  98.307 +			} else {
  98.308 +				ptc0 = CHANGE_NASID(nasid, ptc0);
  98.309 +				if (ptc1)
  98.310 +					ptc1 = CHANGE_NASID(nasid, ptc1);
  98.311 +				pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1);
  98.312 +				active++;
  98.313 +			}
  98.314 +			if (active >= max_active || i == (nix - 1)) {
  98.315 +				if ((deadlock = wait_piowc())) {
  98.316 +					sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
  98.317 +					if (reset_max_active_on_deadlock())
  98.318 +						max_active = 1;
  98.319 +				}
  98.320 +				active = 0;
  98.321 +				ibegin = i + 1;
  98.322 +			}
  98.323 +		}
  98.324 +		start += (1UL << nbits);
  98.325 +	} while (start < end);
  98.326 +
  98.327 +	itc2 = ia64_get_itc() - itc2;
  98.328 +	__get_cpu_var(ptcstats).shub_itc_clocks += itc2;
  98.329 +	if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
  98.330 +		__get_cpu_var(ptcstats).shub_itc_clocks_max = itc2;
  98.331 +
  98.332 +	if (old_rr) {
  98.333 +		ia64_set_rr(start, old_rr);
  98.334 +		ia64_srlz_d();
  98.335 +	}
  98.336 +
  98.337 +	spin_unlock_irqrestore(PTC_LOCK(shub1), flags);
  98.338 +
  98.339 +	preempt_enable();
  98.340 +}
  98.341 +
  98.342 +/*
  98.343 + * sn2_ptc_deadlock_recovery
  98.344 + *
  98.345 + * Recover from PTC deadlocks conditions. Recovery requires stepping thru each 
  98.346 + * TLB flush transaction.  The recovery sequence is somewhat tricky & is
  98.347 + * coded in assembly language.
  98.348 + */
  98.349 +
  98.350 +void
  98.351 +sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid,
  98.352 +			  volatile unsigned long *ptc0, unsigned long data0,
  98.353 +			  volatile unsigned long *ptc1, unsigned long data1)
  98.354 +{
  98.355 +	short nasid, i;
  98.356 +	unsigned long *piows, zeroval, n;
  98.357 +
  98.358 +	__get_cpu_var(ptcstats).deadlocks++;
  98.359 +
  98.360 +	piows = (unsigned long *) pda->pio_write_status_addr;
  98.361 +	zeroval = pda->pio_write_status_val;
  98.362 +
  98.363 +
  98.364 +	for (i=ib; i <= ie; i++) {
  98.365 +		nasid = nasids[i];
  98.366 +		if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid)
  98.367 +			continue;
  98.368 +		ptc0 = CHANGE_NASID(nasid, ptc0);
  98.369 +		if (ptc1)
  98.370 +			ptc1 = CHANGE_NASID(nasid, ptc1);
  98.371 +
  98.372 +		n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
  98.373 +		__get_cpu_var(ptcstats).deadlocks2 += n;
  98.374 +	}
  98.375 +
  98.376 +}
  98.377 +
  98.378 +/**
  98.379 + * sn_send_IPI_phys - send an IPI to a Nasid and slice
  98.380 + * @nasid: nasid to receive the interrupt (may be outside partition)
  98.381 + * @physid: physical cpuid to receive the interrupt.
  98.382 + * @vector: command to send
  98.383 + * @delivery_mode: delivery mechanism
  98.384 + *
  98.385 + * Sends an IPI (interprocessor interrupt) to the processor specified by
  98.386 + * @physid
  98.387 + *
  98.388 + * @delivery_mode can be one of the following
  98.389 + *
  98.390 + * %IA64_IPI_DM_INT - pend an interrupt
  98.391 + * %IA64_IPI_DM_PMI - pend a PMI
  98.392 + * %IA64_IPI_DM_NMI - pend an NMI
  98.393 + * %IA64_IPI_DM_INIT - pend an INIT interrupt
  98.394 + */
  98.395 +void sn_send_IPI_phys(int nasid, long physid, int vector, int delivery_mode)
  98.396 +{
  98.397 +	long val;
  98.398 +	unsigned long flags = 0;
  98.399 +	volatile long *p;
  98.400 +
  98.401 +	p = (long *)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT);
  98.402 +	val = (1UL << SH_IPI_INT_SEND_SHFT) |
  98.403 +	    (physid << SH_IPI_INT_PID_SHFT) |
  98.404 +	    ((long)delivery_mode << SH_IPI_INT_TYPE_SHFT) |
  98.405 +	    ((long)vector << SH_IPI_INT_IDX_SHFT) |
  98.406 +	    (0x000feeUL << SH_IPI_INT_BASE_SHFT);
  98.407 +
  98.408 +	mb();
  98.409 +	if (enable_shub_wars_1_1()) {
  98.410 +		spin_lock_irqsave(&sn2_global_ptc_lock, flags);
  98.411 +	}
  98.412 +	pio_phys_write_mmr(p, val);
  98.413 +	if (enable_shub_wars_1_1()) {
  98.414 +		wait_piowc();
  98.415 +		spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
  98.416 +	}
  98.417 +
  98.418 +}
  98.419 +
  98.420 +EXPORT_SYMBOL(sn_send_IPI_phys);
  98.421 +
  98.422 +/**
  98.423 + * sn2_send_IPI - send an IPI to a processor
  98.424 + * @cpuid: target of the IPI
  98.425 + * @vector: command to send
  98.426 + * @delivery_mode: delivery mechanism
  98.427 + * @redirect: redirect the IPI?
  98.428 + *
  98.429 + * Sends an IPI (InterProcessor Interrupt) to the processor specified by
  98.430 + * @cpuid.  @vector specifies the command to send, while @delivery_mode can 
  98.431 + * be one of the following
  98.432 + *
  98.433 + * %IA64_IPI_DM_INT - pend an interrupt
  98.434 + * %IA64_IPI_DM_PMI - pend a PMI
  98.435 + * %IA64_IPI_DM_NMI - pend an NMI
  98.436 + * %IA64_IPI_DM_INIT - pend an INIT interrupt
  98.437 + */
  98.438 +void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
  98.439 +{
  98.440 +	long physid;
  98.441 +	int nasid;
  98.442 +
  98.443 +	physid = cpu_physical_id(cpuid);
  98.444 +#ifdef XEN
  98.445 +	if (!sn_nodepda) {
  98.446 +		ia64_sn_get_sapic_info(physid, &nasid, NULL, NULL);
  98.447 +	} else
  98.448 +#endif
  98.449 +	nasid = cpuid_to_nasid(cpuid);
  98.450 +
  98.451 +	/* the following is used only when starting cpus at boot time */
  98.452 +	if (unlikely(nasid == -1))
  98.453 +		ia64_sn_get_sapic_info(physid, &nasid, NULL, NULL);
  98.454 +
  98.455 + 	sn_send_IPI_phys(nasid, physid, vector, delivery_mode);
  98.456 +}
  98.457 +
  98.458 +#ifdef CONFIG_PROC_FS
  98.459 +
  98.460 +#define PTC_BASENAME	"sgi_sn/ptc_statistics"
  98.461 +
  98.462 +static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset)
  98.463 +{
  98.464 +	if (*offset < NR_CPUS)
  98.465 +		return offset;
  98.466 +	return NULL;
  98.467 +}
  98.468 +
  98.469 +static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset)
  98.470 +{
  98.471 +	(*offset)++;
  98.472 +	if (*offset < NR_CPUS)
  98.473 +		return offset;
  98.474 +	return NULL;
  98.475 +}
  98.476 +
  98.477 +static void sn2_ptc_seq_stop(struct seq_file *file, void *data)
  98.478 +{
  98.479 +}
  98.480 +
  98.481 +static int sn2_ptc_seq_show(struct seq_file *file, void *data)
  98.482 +{
  98.483 +	struct ptc_stats *stat;
  98.484 +	int cpu;
  98.485 +
  98.486 +	cpu = *(loff_t *) data;
  98.487 +
  98.488 +	if (!cpu) {
  98.489 +		seq_printf(file,
  98.490 +			   "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n");
  98.491 +		seq_printf(file, "# ptctest %d\n", sn2_ptctest);
  98.492 +	}
  98.493 +
  98.494 +	if (cpu < NR_CPUS && cpu_online(cpu)) {
  98.495 +		stat = &per_cpu(ptcstats, cpu);
  98.496 +		seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
  98.497 +				stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
  98.498 +				stat->deadlocks,
  98.499 +				1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
  98.500 +				1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
  98.501 +				1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,
  98.502 +				stat->shub_ptc_flushes_not_my_mm,
  98.503 +				stat->deadlocks2);
  98.504 +	}
  98.505 +	return 0;
  98.506 +}
  98.507 +
  98.508 +static struct seq_operations sn2_ptc_seq_ops = {
  98.509 +	.start = sn2_ptc_seq_start,
  98.510 +	.next = sn2_ptc_seq_next,
  98.511 +	.stop = sn2_ptc_seq_stop,
  98.512 +	.show = sn2_ptc_seq_show
  98.513 +};
  98.514 +
  98.515 +static int sn2_ptc_proc_open(struct inode *inode, struct file *file)
  98.516 +{
  98.517 +	return seq_open(file, &sn2_ptc_seq_ops);
  98.518 +}
  98.519 +
  98.520 +static struct file_operations proc_sn2_ptc_operations = {
  98.521 +	.open = sn2_ptc_proc_open,
  98.522 +	.read = seq_read,
  98.523 +	.llseek = seq_lseek,
  98.524 +	.release = seq_release,
  98.525 +};
  98.526 +
  98.527 +static struct proc_dir_entry *proc_sn2_ptc;
  98.528 +
  98.529 +static int __init sn2_ptc_init(void)
  98.530 +{
  98.531 +	if (!ia64_platform_is("sn2"))
  98.532 +		return 0;
  98.533 +
  98.534 +	if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) {
  98.535 +		printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);
  98.536 +		return -EINVAL;
  98.537 +	}
  98.538 +	proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations;
  98.539 +	spin_lock_init(&sn2_global_ptc_lock);
  98.540 +	return 0;
  98.541 +}
  98.542 +
  98.543 +static void __exit sn2_ptc_exit(void)
  98.544 +{
  98.545 +	remove_proc_entry(PTC_BASENAME, NULL);
  98.546 +}
  98.547 +
  98.548 +module_init(sn2_ptc_init);
  98.549 +module_exit(sn2_ptc_exit);
  98.550 +#endif /* CONFIG_PROC_FS */
  98.551 +
    99.1 --- a/xen/arch/ia64/linux/Makefile	Thu Jan 18 15:18:07 2007 +0000
    99.2 +++ b/xen/arch/ia64/linux/Makefile	Fri Jan 19 14:48:57 2007 +0000
    99.3 @@ -1,6 +1,9 @@
    99.4 +subdir-y += dig
    99.5 +subdir-y += hp
    99.6 +subdir-y += sn
    99.7 +
    99.8  obj-y += bitop.o
    99.9  obj-y += clear_page.o
   99.10 -obj-y += cmdline.o
   99.11  obj-y += copy_page_mck.o
   99.12  obj-y += efi_stub.o
   99.13  obj-y += extable.o
   99.14 @@ -23,6 +26,7 @@ obj-y += __udivdi3.o
   99.15  obj-y += __moddi3.o
   99.16  obj-y += __umoddi3.o
   99.17  obj-y += carta_random.o
   99.18 +obj-y += io.o
   99.19  
   99.20  ## variants of divide/modulo
   99.21  ## see files in xen/arch/ia64/linux/lib (linux/arch/ia64/lib)
   100.1 --- a/xen/arch/ia64/linux/README.origin	Thu Jan 18 15:18:07 2007 +0000
   100.2 +++ b/xen/arch/ia64/linux/README.origin	Fri Jan 19 14:48:57 2007 +0000
   100.3 @@ -4,7 +4,6 @@ NOTE: DO NOT commit changes to these fil
   100.4  needs to be changed, move it to ../linux-xen and follow
   100.5  the instructions in the README there.
   100.6  
   100.7 -cmdline.c		-> linux/lib/cmdline.c
   100.8  efi_stub.S		-> linux/arch/ia64/kernel/efi_stub.S
   100.9  extable.c		-> linux/arch/ia64/mm/extable.c
  100.10  hpsim.S			-> linux/arch/ia64/hp/sim/hpsim.S
  100.11 @@ -27,3 +26,6 @@ strlen.S		-> linux/arch/ia64/lib/strlen.
  100.12  
  100.13  # The files below are from Linux-2.6.16.33
  100.14  carta_random.S		-> linux/arch/ia64/lib/carta_random.S
  100.15 +
  100.16 +# The files below are from Linux-2.6.19
  100.17 +io.c			-> linux/arch/ia64/lib/io.c
   101.1 --- a/xen/arch/ia64/linux/cmdline.c	Thu Jan 18 15:18:07 2007 +0000
   101.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.3 @@ -1,121 +0,0 @@
   101.4 -/*
   101.5 - * linux/lib/cmdline.c
   101.6 - * Helper functions generally used for parsing kernel command line
   101.7 - * and module options.
   101.8 - *
   101.9 - * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.
  101.10 - *
  101.11 - * This source code is licensed under the GNU General Public License,
  101.12 - * Version 2.  See the file COPYING for more details.
  101.13 - *
  101.14 - * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
  101.15 - *
  101.16 - */
  101.17 -
  101.18 -#include <linux/module.h>
  101.19 -#include <linux/kernel.h>
  101.20 -#include <linux/string.h>
  101.21 -#include <xen/lib.h>
  101.22 -
  101.23 -
  101.24 -/**
  101.25 - *	get_option - Parse integer from an option string
  101.26 - *	@str: option string
  101.27 - *	@pint: (output) integer value parsed from @str
  101.28 - *
  101.29 - *	Read an int from an option string; if available accept a subsequent
  101.30 - *	comma as well.
  101.31 - *
  101.32 - *	Return values:
  101.33 - *	0 : no int in string
  101.34 - *	1 : int found, no subsequent comma
  101.35 - *	2 : int found including a subsequent comma
  101.36 - */
  101.37 -
  101.38 -int get_option (char **str, int *pint)
  101.39 -{
  101.40 -	char *cur = *str;
  101.41 -
  101.42 -	if (!cur || !(*cur))
  101.43 -		return 0;
  101.44 -	*pint = simple_strtol (cur, str, 0);
  101.45 -	if (cur == *str)
  101.46 -		return 0;
  101.47 -	if (**str == ',') {
  101.48 -		(*str)++;
  101.49 -		return 2;
  101.50 -	}
  101.51 -
  101.52 -	return 1;
  101.53 -}
  101.54 -
  101.55 -/**
  101.56 - *	get_options - Parse a string into a list of integers
  101.57 - *	@str: String to be parsed
  101.58 - *	@nints: size of integer array
  101.59 - *	@ints: integer array
  101.60 - *
  101.61 - *	This function parses a string containing a comma-separated
  101.62 - *	list of integers.  The parse halts when the array is
  101.63 - *	full, or when no more numbers can be retrieved from the
  101.64 - *	string.
  101.65 - *
  101.66 - *	Return value is the character in the string which caused
  101.67 - *	the parse to end (typically a null terminator, if @str is
  101.68 - *	completely parseable).
  101.69 - */
  101.70 - 
  101.71 -char *get_options(const char *str, int nints, int *ints)
  101.72 -{
  101.73 -	int res, i = 1;
  101.74 -
  101.75 -	while (i < nints) {
  101.76 -		res = get_option ((char **)&str, ints + i);
  101.77 -		if (res == 0)
  101.78 -			break;
  101.79 -		i++;
  101.80 -		if (res == 1)
  101.81 -			break;
  101.82 -	}
  101.83 -	ints[0] = i - 1;
  101.84 -	return (char *)str;
  101.85 -}
  101.86 -
  101.87 -/**
  101.88 - *	memparse - parse a string with mem suffixes into a number
  101.89 - *	@ptr: Where parse begins
  101.90 - *	@retptr: (output) Pointer to next char after parse completes
  101.91 - *
  101.92 - *	Parses a string into a number.  The number stored at @ptr is
  101.93 - *	potentially suffixed with %K (for kilobytes, or 1024 bytes),
  101.94 - *	%M (for megabytes, or 1048576 bytes), or %G (for gigabytes, or
  101.95 - *	1073741824).  If the number is suffixed with K, M, or G, then
  101.96 - *	the return value is the number multiplied by one kilobyte, one
  101.97 - *	megabyte, or one gigabyte, respectively.
  101.98 - */
  101.99 -
 101.100 -unsigned long long memparse (char *ptr, char **retptr)
 101.101 -{
 101.102 -	unsigned long long ret = simple_strtoull (ptr, retptr, 0);
 101.103 -
 101.104 -	switch (**retptr) {
 101.105 -	case 'G':
 101.106 -	case 'g':
 101.107 -		ret <<= 10;
 101.108 -	case 'M':
 101.109 -	case 'm':
 101.110 -		ret <<= 10;
 101.111 -	case 'K':
 101.112 -	case 'k':
 101.113 -		ret <<= 10;
 101.114 -		(*retptr)++;
 101.115 -	default:
 101.116 -		break;
 101.117 -	}
 101.118 -	return ret;
 101.119 -}
 101.120 -
 101.121 -
 101.122 -EXPORT_SYMBOL(memparse);
 101.123 -EXPORT_SYMBOL(get_option);
 101.124 -EXPORT_SYMBOL(get_options);
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/xen/arch/ia64/linux/dig/Makefile	Fri Jan 19 14:48:57 2007 +0000
   102.3 @@ -0,0 +1,1 @@
   102.4 +obj-y += machvec.o
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/xen/arch/ia64/linux/dig/README.origin	Fri Jan 19 14:48:57 2007 +0000
   103.3 @@ -0,0 +1,7 @@
   103.4 +Source files in this directory are identical copies of linux-2.6.19 files:
   103.5 +
   103.6 +NOTE: DO NOT commit changes to these files!   If a file
   103.7 +needs to be changed, move it to ../linux-xen and follow
   103.8 +the instructions in the README there.
   103.9 +
  103.10 +machvec.c		-> linux/arch/ia64/dig/machvec.c
   104.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.2 +++ b/xen/arch/ia64/linux/dig/machvec.c	Fri Jan 19 14:48:57 2007 +0000
   104.3 @@ -0,0 +1,3 @@
   104.4 +#define MACHVEC_PLATFORM_NAME		dig
   104.5 +#define MACHVEC_PLATFORM_HEADER		<asm/machvec_dig.h>
   104.6 +#include <asm/machvec_init.h>
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/xen/arch/ia64/linux/hp/Makefile	Fri Jan 19 14:48:57 2007 +0000
   105.3 @@ -0,0 +1,1 @@
   105.4 +subdir-y += zx1
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/xen/arch/ia64/linux/hp/zx1/Makefile	Fri Jan 19 14:48:57 2007 +0000
   106.3 @@ -0,0 +1,1 @@
   106.4 +obj-y += hpzx1_machvec.o
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/xen/arch/ia64/linux/hp/zx1/README.origin	Fri Jan 19 14:48:57 2007 +0000
   107.3 @@ -0,0 +1,7 @@
   107.4 +Source files in this directory are identical copies of linux-2.6.19 files:
   107.5 +
   107.6 +NOTE: DO NOT commit changes to these files!   If a file
   107.7 +needs to be changed, move it to ../linux-xen and follow
   107.8 +the instructions in the README there.
   107.9 +
  107.10 +hpzx1_machvec.c		-> linux/arch/ia64/hp/zx1/hpzx1_machvec.c
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/xen/arch/ia64/linux/hp/zx1/hpzx1_machvec.c	Fri Jan 19 14:48:57 2007 +0000
   108.3 @@ -0,0 +1,3 @@
   108.4 +#define MACHVEC_PLATFORM_NAME		hpzx1
   108.5 +#define MACHVEC_PLATFORM_HEADER		<asm/machvec_hpzx1.h>
   108.6 +#include <asm/machvec_init.h>
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/xen/arch/ia64/linux/io.c	Fri Jan 19 14:48:57 2007 +0000
   109.3 @@ -0,0 +1,164 @@
   109.4 +#include <linux/module.h>
   109.5 +#include <linux/types.h>
   109.6 +
   109.7 +#include <asm/io.h>
   109.8 +
   109.9 +/*
  109.10 + * Copy data from IO memory space to "real" memory space.
  109.11 + * This needs to be optimized.
  109.12 + */
  109.13 +void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
  109.14 +{
  109.15 +	char *dst = to;
  109.16 +
  109.17 +	while (count) {
  109.18 +		count--;
  109.19 +		*dst++ = readb(from++);
  109.20 +	}
  109.21 +}
  109.22 +EXPORT_SYMBOL(memcpy_fromio);
  109.23 +
  109.24 +/*
  109.25 + * Copy data from "real" memory space to IO memory space.
  109.26 + * This needs to be optimized.
  109.27 + */
  109.28 +void memcpy_toio(volatile void __iomem *to, const void *from, long count)
  109.29 +{
  109.30 +	const char *src = from;
  109.31 +
  109.32 +	while (count) {
  109.33 +		count--;
  109.34 +		writeb(*src++, to++);
  109.35 +	}
  109.36 +}
  109.37 +EXPORT_SYMBOL(memcpy_toio);
  109.38 +
  109.39 +/*
  109.40 + * "memset" on IO memory space.
  109.41 + * This needs to be optimized.
  109.42 + */
  109.43 +void memset_io(volatile void __iomem *dst, int c, long count)
  109.44 +{
  109.45 +	unsigned char ch = (char)(c & 0xff);
  109.46 +
  109.47 +	while (count) {
  109.48 +		count--;
  109.49 +		writeb(ch, dst);
  109.50 +		dst++;
  109.51 +	}
  109.52 +}
  109.53 +EXPORT_SYMBOL(memset_io);
  109.54 +
  109.55 +#ifdef CONFIG_IA64_GENERIC
  109.56 +
  109.57 +#undef __ia64_inb
  109.58 +#undef __ia64_inw
  109.59 +#undef __ia64_inl
  109.60 +#undef __ia64_outb
  109.61 +#undef __ia64_outw
  109.62 +#undef __ia64_outl
  109.63 +#undef __ia64_readb
  109.64 +#undef __ia64_readw
  109.65 +#undef __ia64_readl
  109.66 +#undef __ia64_readq
  109.67 +#undef __ia64_readb_relaxed
  109.68 +#undef __ia64_readw_relaxed
  109.69 +#undef __ia64_readl_relaxed
  109.70 +#undef __ia64_readq_relaxed
  109.71 +#undef __ia64_writeb
  109.72 +#undef __ia64_writew
  109.73 +#undef __ia64_writel
  109.74 +#undef __ia64_writeq
  109.75 +#undef __ia64_mmiowb
  109.76 +
  109.77 +unsigned int
  109.78 +__ia64_inb (unsigned long port)
  109.79 +{
  109.80 +	return ___ia64_inb(port);
  109.81 +}
  109.82 +
  109.83 +unsigned int
  109.84 +__ia64_inw (unsigned long port)
  109.85 +{
  109.86 +	return ___ia64_inw(port);
  109.87 +}
  109.88 +
  109.89 +unsigned int
  109.90 +__ia64_inl (unsigned long port)
  109.91 +{
  109.92 +	return ___ia64_inl(port);
  109.93 +}
  109.94 +
  109.95 +void
  109.96 +__ia64_outb (unsigned char val, unsigned long port)
  109.97 +{
  109.98 +	___ia64_outb(val, port);
  109.99 +}
 109.100 +
 109.101 +void
 109.102 +__ia64_outw (unsigned short val, unsigned long port)
 109.103 +{
 109.104 +	___ia64_outw(val, port);
 109.105 +}
 109.106 +
 109.107 +void
 109.108 +__ia64_outl (unsigned int val, unsigned long port)
 109.109 +{
 109.110 +	___ia64_outl(val, port);
 109.111 +}
 109.112 +
 109.113 +unsigned char
 109.114 +__ia64_readb (void __iomem *addr)
 109.115 +{
 109.116 +	return ___ia64_readb (addr);
 109.117 +}
 109.118 +
 109.119 +unsigned short
 109.120 +__ia64_readw (void __iomem *addr)
 109.121 +{
 109.122 +	return ___ia64_readw (addr);
 109.123 +}
 109.124 +
 109.125 +unsigned int
 109.126 +__ia64_readl (void __iomem *addr)
 109.127 +{
 109.128 +	return ___ia64_readl (addr);
 109.129 +}
 109.130 +
 109.131 +unsigned long
 109.132 +__ia64_readq (void __iomem *addr)
 109.133 +{
 109.134 +	return ___ia64_readq (addr);
 109.135 +}
 109.136 +
 109.137 +unsigned char
 109.138 +__ia64_readb_relaxed (void __iomem *addr)
 109.139 +{
 109.140 +	return ___ia64_readb (addr);
 109.141 +}
 109.142 +
 109.143 +unsigned short
 109.144 +__ia64_readw_relaxed (void __iomem *addr)
 109.145 +{
 109.146 +	return ___ia64_readw (addr);
 109.147 +}
 109.148 +
 109.149 +unsigned int
 109.150 +__ia64_readl_relaxed (void __iomem *addr)
 109.151 +{
 109.152 +	return ___ia64_readl (addr);
 109.153 +}
 109.154 +
 109.155 +unsigned long
 109.156 +__ia64_readq_relaxed (void __iomem *addr)
 109.157 +{
 109.158 +	return ___ia64_readq (addr);
 109.159 +}
 109.160 +
 109.161 +void
 109.162 +__ia64_mmiowb(void)
 109.163 +{
 109.164 +	___ia64_mmiowb();
 109.165 +}
 109.166 +
 109.167 +#endif /* CONFIG_IA64_GENERIC */
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/xen/arch/ia64/linux/sn/Makefile	Fri Jan 19 14:48:57 2007 +0000
   110.3 @@ -0,0 +1,2 @@
   110.4 +subdir-y += kernel
   110.5 +subdir-y += pci
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/xen/arch/ia64/linux/sn/kernel/Makefile	Fri Jan 19 14:48:57 2007 +0000
   111.3 @@ -0,0 +1,3 @@
   111.4 +obj-y += machvec.o
   111.5 +obj-y += pio_phys.o
   111.6 +obj-y += ptc_deadlock.o
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/xen/arch/ia64/linux/sn/kernel/README.origin	Fri Jan 19 14:48:57 2007 +0000
   112.3 @@ -0,0 +1,9 @@
   112.4 +Source files in this directory are identical copies of linux-2.6.19 files:
   112.5 +
   112.6 +NOTE: DO NOT commit changes to these files!   If a file
   112.7 +needs to be changed, move it to ../linux-xen and follow
   112.8 +the instructions in the README there.
   112.9 +
  112.10 +machvec.c		-> linux/arch/ia64/sn/kernel/machvec.c
  112.11 +pio_phys.S		-> linux/arch/ia64/sn/kernel/pio_phys.S
  112.12 +ptc_deadlock.S		-> linux/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/xen/arch/ia64/linux/sn/kernel/machvec.c	Fri Jan 19 14:48:57 2007 +0000
   113.3 @@ -0,0 +1,11 @@
   113.4 +/*
   113.5 + * This file is subject to the terms and conditions of the GNU General Public
   113.6 + * License.  See the file "COPYING" in the main directory of this archive
   113.7 + * for more details.
   113.8 + *
   113.9 + * Copyright (c) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
  113.10 + */
  113.11 +
  113.12 +#define MACHVEC_PLATFORM_NAME	sn2
  113.13 +#define MACHVEC_PLATFORM_HEADER	<asm/machvec_sn2.h>
  113.14 +#include <asm/machvec_init.h>
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/xen/arch/ia64/linux/sn/kernel/pio_phys.S	Fri Jan 19 14:48:57 2007 +0000
   114.3 @@ -0,0 +1,71 @@
   114.4 +/*
   114.5 + * This file is subject to the terms and conditions of the GNU General Public
   114.6 + * License.  See the file "COPYING" in the main directory of this archive
   114.7 + * for more details.
   114.8 + *
   114.9 + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
  114.10 + *
  114.11 + * This file contains macros used to access MMR registers via
  114.12 + * uncached physical addresses.
  114.13 + *      pio_phys_read_mmr  - read an MMR
  114.14 + *      pio_phys_write_mmr - write an MMR
  114.15 + *      pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
  114.16 + *              Second MMR will be skipped if address is NULL
  114.17 + *
  114.18 + * Addresses passed to these routines should be uncached physical addresses
  114.19 + * 	ie., 0x80000....
  114.20 + */
  114.21 +
  114.22 +
  114.23 +
  114.24 +#include <asm/asmmacro.h>
  114.25 +#include <asm/page.h>
  114.26 +
  114.27 +GLOBAL_ENTRY(pio_phys_read_mmr)
  114.28 +	.prologue
  114.29 +	.regstk 1,0,0,0
  114.30 +	.body
  114.31 +	mov r2=psr
  114.32 +	rsm psr.i | psr.dt
  114.33 +	;;
  114.34 +	srlz.d
  114.35 +	ld8.acq r8=[r32]
  114.36 +	;;
  114.37 +	mov psr.l=r2;;
  114.38 +	srlz.d
  114.39 +	br.ret.sptk.many rp
  114.40 +END(pio_phys_read_mmr)
  114.41 +
  114.42 +GLOBAL_ENTRY(pio_phys_write_mmr)
  114.43 +	.prologue
  114.44 +	.regstk 2,0,0,0
  114.45 +	.body
  114.46 +	mov r2=psr
  114.47 +	rsm psr.i | psr.dt
  114.48 +	;;
  114.49 +	srlz.d
  114.50 +	st8.rel [r32]=r33
  114.51 +	;;
  114.52 +	mov psr.l=r2;;
  114.53 +	srlz.d
  114.54 +	br.ret.sptk.many rp
  114.55 +END(pio_phys_write_mmr)
  114.56 +
  114.57 +GLOBAL_ENTRY(pio_atomic_phys_write_mmrs)
  114.58 +	.prologue
  114.59 +	.regstk 4,0,0,0
  114.60 +	.body
  114.61 +	mov r2=psr
  114.62 +	cmp.ne p9,p0=r34,r0;
  114.63 +	rsm psr.i | psr.dt | psr.ic
  114.64 +	;;
  114.65 +	srlz.d
  114.66 +	st8.rel [r32]=r33
  114.67 +(p9)	st8.rel [r34]=r35
  114.68 +	;;
  114.69 +	mov psr.l=r2;;
  114.70 +	srlz.d
  114.71 +	br.ret.sptk.many rp
  114.72 +END(pio_atomic_phys_write_mmrs)
  114.73 +
  114.74 +
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/xen/arch/ia64/linux/sn/kernel/ptc_deadlock.S	Fri Jan 19 14:48:57 2007 +0000
   115.3 @@ -0,0 +1,92 @@
   115.4 +/* 
   115.5 + * This file is subject to the terms and conditions of the GNU General Public
   115.6 + * License.  See the file "COPYING" in the main directory of this archive
   115.7 + * for more details.
   115.8 + *
   115.9 + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
  115.10 + */
  115.11 +
  115.12 +#include <asm/types.h>
  115.13 +#include <asm/sn/shub_mmr.h>
  115.14 +
  115.15 +#define DEADLOCKBIT	SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT
  115.16 +#define WRITECOUNTMASK	SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK
  115.17 +#define ALIAS_OFFSET	8
  115.18 +
  115.19 +
  115.20 +	.global	sn2_ptc_deadlock_recovery_core
  115.21 +	.proc  	sn2_ptc_deadlock_recovery_core
  115.22 +
  115.23 +sn2_ptc_deadlock_recovery_core:
  115.24 +	.regstk 6,0,0,0
  115.25 +
  115.26 +	ptc0  	 = in0
  115.27 +	data0 	 = in1
  115.28 +	ptc1  	 = in2
  115.29 +	data1 	 = in3
  115.30 +	piowc 	 = in4
  115.31 +	zeroval  = in5
  115.32 +	piowcphy = r30
  115.33 +	psrsave  = r2
  115.34 +	scr1	 = r16
  115.35 +	scr2	 = r17
  115.36 +	mask	 = r18
  115.37 +
  115.38 +
  115.39 +	extr.u	piowcphy=piowc,0,61;;	// Convert piowc to uncached physical address
  115.40 +	dep	piowcphy=-1,piowcphy,63,1
  115.41 +	movl	mask=WRITECOUNTMASK
  115.42 +	mov	r8=r0
  115.43 +
  115.44 +1:
  115.45 +	cmp.ne  p8,p9=r0,ptc1		// Test for shub type (ptc1 non-null on shub1)
  115.46 +					// p8 = 1 if shub1, p9 = 1 if shub2
  115.47 +
  115.48 +	add	scr2=ALIAS_OFFSET,piowc	// Address of WRITE_STATUS alias register 
  115.49 +	mov	scr1=7;;		// Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR
  115.50 +(p8)	st8.rel	[scr2]=scr1;;
  115.51 +(p9)	ld8.acq	scr1=[scr2];;
  115.52 +
  115.53 +5:	ld8.acq	scr1=[piowc];;		// Wait for PIOs to complete.
  115.54 +	hint	@pause
  115.55 +	and	scr2=scr1,mask;;	// mask of writecount bits
  115.56 +	cmp.ne	p6,p0=zeroval,scr2
  115.57 +(p6)	br.cond.sptk 5b
  115.58 +	
  115.59 +
  115.60 +
  115.61 +	////////////// BEGIN PHYSICAL MODE ////////////////////
  115.62 +	mov psrsave=psr			// Disable IC (no PMIs)
  115.63 +	rsm psr.i | psr.dt | psr.ic;;
  115.64 +	srlz.i;;
  115.65 +
  115.66 +	st8.rel [ptc0]=data0		// Write PTC0 & wait for completion.
  115.67 +
  115.68 +5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
  115.69 +	hint	@pause
  115.70 +	and	scr2=scr1,mask;;	// mask of writecount bits
  115.71 +	cmp.ne	p6,p0=zeroval,scr2
  115.72 +(p6)	br.cond.sptk 5b;;
  115.73 +
  115.74 +	tbit.nz	p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK
  115.75 +(p7)	cmp.ne p7,p0=r0,ptc1;;		// Test for non-null ptc1
  115.76 +	
  115.77 +(p7)	st8.rel [ptc1]=data1;;		// Now write PTC1.
  115.78 +
  115.79 +5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
  115.80 +	hint	@pause
  115.81 +	and	scr2=scr1,mask;;	// mask of writecount bits
  115.82 +	cmp.ne	p6,p0=zeroval,scr2
  115.83 +(p6)	br.cond.sptk 5b
  115.84 +	
  115.85 +	tbit.nz	p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK
  115.86 +
  115.87 +	mov psr.l=psrsave;;		// Reenable IC
  115.88 +	srlz.i;;
  115.89 +	////////////// END   PHYSICAL MODE ////////////////////
  115.90 +
  115.91 +(p8)	add	r8=1,r8
  115.92 +(p8)	br.cond.spnt 1b;;		// Repeat if DEADLOCK occurred.
  115.93 +
  115.94 +	br.ret.sptk	rp
  115.95 +	.endp sn2_ptc_deadlock_recovery_core
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/xen/arch/ia64/linux/sn/pci/Makefile	Fri Jan 19 14:48:57 2007 +0000
   116.3 @@ -0,0 +1,1 @@
   116.4 +subdir-y += pcibr
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/xen/arch/ia64/linux/sn/pci/pcibr/Makefile	Fri Jan 19 14:48:57 2007 +0000
   117.3 @@ -0,0 +1,1 @@
   117.4 +obj-y += pcibr_reg.o
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/xen/arch/ia64/linux/sn/pci/pcibr/README.origin	Fri Jan 19 14:48:57 2007 +0000
   118.3 @@ -0,0 +1,7 @@
   118.4 +Source files in this directory are identical copies of linux-2.6.19 files:
   118.5 +
   118.6 +NOTE: DO NOT commit changes to these files!   If a file
   118.7 +needs to be changed, move it to ../linux-xen and follow
   118.8 +the instructions in the README there.
   118.9 +
  118.10 +pcibr_reg.c		-> linux/arch/ia64/sn/pci/pcibr/pcibr_reg.c
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/xen/arch/ia64/linux/sn/pci/pcibr/pcibr_reg.c	Fri Jan 19 14:48:57 2007 +0000
   119.3 @@ -0,0 +1,285 @@
   119.4 +/*
   119.5 + * This file is subject to the terms and conditions of the GNU General Public
   119.6 + * License.  See the file "COPYING" in the main directory of this archive
   119.7 + * for more details.
   119.8 + *
   119.9 + * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
  119.10 + */
  119.11 +
  119.12 +#include <linux/interrupt.h>
  119.13 +#include <linux/types.h>
  119.14 +#include <asm/sn/io.h>
  119.15 +#include <asm/sn/pcibr_provider.h>
  119.16 +#include <asm/sn/pcibus_provider_defs.h>
  119.17 +#include <asm/sn/pcidev.h>
  119.18 +#include <asm/sn/pic.h>
  119.19 +#include <asm/sn/tiocp.h>
  119.20 +
  119.21 +union br_ptr {
  119.22 +	struct tiocp tio;
  119.23 +	struct pic pic;
  119.24 +};
  119.25 +
  119.26 +/*
  119.27 + * Control Register Access -- Read/Write                            0000_0020
  119.28 + */
  119.29 +void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
  119.30 +{
  119.31 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
  119.32 +
  119.33 +	if (pcibus_info) {
  119.34 +		switch (pcibus_info->pbi_bridge_type) {
  119.35 +		case PCIBR_BRIDGETYPE_TIOCP:
  119.36 +			__sn_clrq_relaxed(&ptr->tio.cp_control, bits);
  119.37 +			break;
  119.38 +		case PCIBR_BRIDGETYPE_PIC:
  119.39 +			__sn_clrq_relaxed(&ptr->pic.p_wid_control, bits);
  119.40 +			break;
  119.41 +		default:
  119.42 +			panic
  119.43 +			    ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p",
  119.44 +			     ptr);
  119.45 +		}
  119.46 +	}
  119.47 +}
  119.48 +
  119.49 +void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits)
  119.50 +{
  119.51 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
  119.52 +
  119.53 +	if (pcibus_info) {
  119.54 +		switch (pcibus_info->pbi_bridge_type) {
  119.55 +		case PCIBR_BRIDGETYPE_TIOCP:
  119.56 +			__sn_setq_relaxed(&ptr->tio.cp_control, bits);
  119.57 +			break;
  119.58 +		case PCIBR_BRIDGETYPE_PIC:
  119.59 +			__sn_setq_relaxed(&ptr->pic.p_wid_control, bits);
  119.60 +			break;
  119.61 +		default:
  119.62 +			panic
  119.63 +			    ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p",
  119.64 +			     ptr);
  119.65 +		}
  119.66 +	}
  119.67 +}
  119.68 +
  119.69 +/*
  119.70 + * PCI/PCIX Target Flush Register Access -- Read Only		    0000_0050
  119.71 + */
  119.72 +u64 pcireg_tflush_get(struct pcibus_info *pcibus_info)
  119.73 +{
  119.74 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
  119.75 +	u64 ret = 0;
  119.76 +
  119.77 +	if (pcibus_info) {
  119.78 +		switch (pcibus_info->pbi_bridge_type) {
  119.79 +		case PCIBR_BRIDGETYPE_TIOCP:
  119.80 +			ret = __sn_readq_relaxed(&ptr->tio.cp_tflush);
  119.81 +			break;
  119.82 +		case PCIBR_BRIDGETYPE_PIC:
  119.83 +			ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush);
  119.84 +			break;
  119.85 +		default:
  119.86 +			panic
  119.87 +			    ("pcireg_tflush_get: unknown bridgetype bridge 0x%p",
  119.88 +			     ptr);
  119.89 +		}
  119.90 +	}
  119.91 +
  119.92 +	/* Read of the Target Flush should always return zero */
  119.93 +	if (ret != 0)
  119.94 +		panic("pcireg_tflush_get:Target Flush failed\n");
  119.95 +
  119.96 +	return ret;
  119.97 +}
  119.98 +
  119.99 +/*
 119.100 + * Interrupt Status Register Access -- Read Only		    0000_0100
 119.101 + */
 119.102 +u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info)
 119.103 +{
 119.104 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
 119.105 +	u64 ret = 0;
 119.106 +
 119.107 +	if (pcibus_info) {
 119.108 +		switch (pcibus_info->pbi_bridge_type) {
 119.109 +		case PCIBR_BRIDGETYPE_TIOCP:
 119.110 +			ret = __sn_readq_relaxed(&ptr->tio.cp_int_status);
 119.111 +			break;
 119.112 +		case PCIBR_BRIDGETYPE_PIC:
 119.113 +			ret = __sn_readq_relaxed(&ptr->pic.p_int_status);
 119.114 +			break;
 119.115 +		default:
 119.116 +			panic
 119.117 +			    ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p",
 119.118 +			     ptr);
 119.119 +		}
 119.120 +	}
 119.121 +	return ret;
 119.122 +}
 119.123 +
 119.124 +/*
 119.125 + * Interrupt Enable Register Access -- Read/Write                   0000_0108
 119.126 + */
 119.127 +void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
 119.128 +{
 119.129 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
 119.130 +
 119.131 +	if (pcibus_info) {
 119.132 +		switch (pcibus_info->pbi_bridge_type) {
 119.133 +		case PCIBR_BRIDGETYPE_TIOCP:
 119.134 +			__sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits);
 119.135 +			break;
 119.136 +		case PCIBR_BRIDGETYPE_PIC:
 119.137 +			__sn_clrq_relaxed(&ptr->pic.p_int_enable, bits);
 119.138 +			break;
 119.139 +		default:
 119.140 +			panic
 119.141 +			    ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p",
 119.142 +			     ptr);
 119.143 +		}
 119.144 +	}
 119.145 +}
 119.146 +
 119.147 +void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits)
 119.148 +{
 119.149 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
 119.150 +
 119.151 +	if (pcibus_info) {
 119.152 +		switch (pcibus_info->pbi_bridge_type) {
 119.153 +		case PCIBR_BRIDGETYPE_TIOCP:
 119.154 +			__sn_setq_relaxed(&ptr->tio.cp_int_enable, bits);
 119.155 +			break;
 119.156 +		case PCIBR_BRIDGETYPE_PIC:
 119.157 +			__sn_setq_relaxed(&ptr->pic.p_int_enable, bits);
 119.158 +			break;
 119.159 +		default:
 119.160 +			panic
 119.161 +			    ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p",
 119.162 +			     ptr);
 119.163 +		}
 119.164 +	}
 119.165 +}
 119.166 +
 119.167 +/*
 119.168 + * Intr Host Address Register (int_addr) -- Read/Write  0000_0130 - 0000_0168
 119.169 + */
 119.170 +void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
 119.171 +			       u64 addr)
 119.172 +{
 119.173 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
 119.174 +
 119.175 +	if (pcibus_info) {
 119.176 +		switch (pcibus_info->pbi_bridge_type) {
 119.177 +		case PCIBR_BRIDGETYPE_TIOCP:
 119.178 +			__sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n],
 119.179 +			    TIOCP_HOST_INTR_ADDR);
 119.180 +			__sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n],
 119.181 +			    (addr & TIOCP_HOST_INTR_ADDR));
 119.182 +			break;
 119.183 +		case PCIBR_BRIDGETYPE_PIC:
 119.184 +			__sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n],
 119.185 +			    PIC_HOST_INTR_ADDR);
 119.186 +			__sn_setq_relaxed(&ptr->pic.p_int_addr[int_n],
 119.187 +			    (addr & PIC_HOST_INTR_ADDR));
 119.188 +			break;
 119.189 +		default:
 119.190 +			panic
 119.191 +			    ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p",
 119.192 +			     ptr);
 119.193 +		}
 119.194 +	}
 119.195 +}
 119.196 +
 119.197 +/*
 119.198 + * Force Interrupt Register Access -- Write Only	0000_01C0 - 0000_01F8
 119.199 + */
 119.200 +void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
 119.201 +{
 119.202 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
 119.203 +
 119.204 +	if (pcibus_info) {
 119.205 +		switch (pcibus_info->pbi_bridge_type) {
 119.206 +		case PCIBR_BRIDGETYPE_TIOCP:
 119.207 +			writeq(1, &ptr->tio.cp_force_pin[int_n]);
 119.208 +			break;
 119.209 +		case PCIBR_BRIDGETYPE_PIC:
 119.210 +			writeq(1, &ptr->pic.p_force_pin[int_n]);
 119.211 +			break;
 119.212 +		default:
 119.213 +			panic
 119.214 +			    ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p",
 119.215 +			     ptr);
 119.216 +		}
 119.217 +	}
 119.218 +}
 119.219 +
 119.220 +/*
 119.221 + * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
 119.222 + */
 119.223 +u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
 119.224 +{
 119.225 +	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
 119.226 +	u64 ret = 0;
 119.227 +
 119.228 +	if (pcibus_info) {
 119.229 +		switch (pcibus_info->pbi_bridge_type) {
 119.230 +		case PCIBR_BRIDGETYPE_TIOCP:
 119.231 +			ret =
 119.232 +			    __sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]);
 119.233 +			break;
 119.234 +		case PCIBR_BRIDGETYPE_PIC:
 119.235 +			ret =
 119.236 +			    __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
 119.237 +			break;
 119.238 +		default:
 119.239 +		      panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr);
 119.240 +		}
 119.241 +
 119.242 +	}
 119.243 +	/* Read of the Write Buffer Flush should always return zero */
 119.244 +	return ret;
 119.245 +}