WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] merge with xen-unstable.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 31 Mar 2009 08:10:19 -0700
Delivery-date: Tue, 31 Mar 2009 08:11:22 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1238119631 -32400
# Node ID e54eeff2de547b173ee13557157e05ce3e3c3fe1
# Parent  5e4dd7079c484192e8621e64d817d58b995b4f75
# Parent  0b13d9787622d5e1d447a21657394805bb96d26f
merge with xen-unstable.hg
---
 tools/hotplug/Linux/blktap                                      |   93 
 Makefile                                                        |    2 
 config/NetBSD.mk                                                |    4 
 config/StdGNU.mk                                                |    3 
 docs/misc/vtd.txt                                               |   92 
 extras/mini-os/arch/ia64/mm.c                                   |    6 
 extras/mini-os/arch/x86/mm.c                                    |  142 +
 extras/mini-os/include/mm.h                                     |    1 
 extras/mini-os/include/x86/arch_mm.h                            |    3 
 stubdom/Makefile                                                |   22 
 tools/Makefile                                                  |    6 
 tools/blktap/drivers/blktapctrl.c                               |   78 
 tools/blktap/drivers/tapdisk.h                                  |   29 
 tools/blktap/lib/blktaplib.h                                    |   10 
 tools/blktap/lib/xenbus.c                                       |  150 +
 tools/console/client/main.c                                     |   50 
 tools/console/daemon/main.c                                     |    2 
 tools/examples/xend-config.sxp                                  |    1 
 tools/examples/xmexample.hvm                                    |    8 
 tools/firmware/Makefile                                         |    3 
 tools/firmware/hvmloader/acpi/dsdt.asl                          | 1218 
+++++++++
 tools/firmware/hvmloader/acpi/dsdt.c                            |  954 +++++++
 tools/firmware/hvmloader/config.h                               |    3 
 tools/firmware/hvmloader/hvmloader.c                            |   20 
 tools/firmware/rombios/32bit/pmm.c                              |    5 
 tools/firmware/rombios/rombios.c                                |   14 
 tools/fs-back/Makefile                                          |    2 
 tools/fs-back/fs-backend.c                                      |  402 +--
 tools/fs-back/fs-backend.h                                      |   10 
 tools/fs-back/fs-debug.h                                        |   12 
 tools/fs-back/fs-ops.c                                          |  175 -
 tools/fs-back/fs-xenbus.c                                       |   87 
 tools/fs-back/sys-queue.h                                       |  338 ++
 tools/hotplug/Linux/Makefile                                    |    3 
 tools/hotplug/Linux/xen-backend.rules                           |    1 
 tools/hotplug/Linux/xen-hotplug-cleanup                         |   10 
 tools/hotplug/Linux/xend.rules                                  |    3 
 tools/hotplug/NetBSD/Makefile                                   |    8 
 tools/libfsimage/zfs/fsys_zfs.c                                 |    3 
 tools/libfsimage/zfs/zfs-include/zfs.h                          |   12 
 tools/libxc/Makefile                                            |    2 
 tools/libxc/xc_core.c                                           |   10 
 tools/libxc/xc_dom_x86.c                                        |   14 
 tools/libxc/xc_domain_save.c                                    |    2 
 tools/libxc/xc_pm.c                                             |   56 
 tools/libxc/xc_ptrace_core.c                                    |    2 
 tools/libxc/xc_solaris.c                                        |    2 
 tools/libxc/xc_suspend.c                                        |  117 
 tools/libxc/xenctrl.h                                           |   22 
 tools/libxc/xenguest.h                                          |    6 
 tools/libxc/xg_private.c                                        |    2 
 tools/misc/xenpm.c                                              |  137 +
 tools/pygrub/src/pygrub                                         |   24 
 tools/python/setup.py                                           |    8 
 tools/python/xen/lowlevel/process/process.c                     |  164 +
 tools/python/xen/util/pci.py                                    |   57 
 tools/python/xen/util/vscsi_util.py                             |   13 
 tools/python/xen/web/SrvDir.py                                  |    4 
 tools/python/xen/web/connection.py                              |   37 
 tools/python/xen/web/unix.py                                    |   32 
 tools/python/xen/xend/XendAPIStore.py                           |   49 
 tools/python/xen/xend/XendCheckpoint.py                         |    2 
 tools/python/xen/xend/XendConfig.py                             |   40 
 tools/python/xen/xend/XendConstants.py                          |    5 
 tools/python/xen/xend/XendDomain.py                             |   28 
 tools/python/xen/xend/XendDomainInfo.py                         |   89 
 tools/python/xen/xend/XendNode.py                               |  108 
 tools/python/xen/xend/XendOptions.py                            |    7 
 tools/python/xen/xend/XendPPCI.py                               |   10 
 tools/python/xen/xend/image.py                                  |   59 
 tools/python/xen/xend/osdep.py                                  |   75 
 tools/python/xen/xend/server/BlktapController.py                |    3 
 tools/python/xen/xend/server/SrvDaemon.py                       |    2 
 tools/python/xen/xend/server/SrvDomain.py                       |    3 
 tools/python/xen/xend/server/netif.py                           |   22 
 tools/python/xen/xend/server/pciif.py                           |    4 
 tools/python/xen/xend/server/udevevent.py                       |   68 
 tools/python/xen/xm/create.dtd                                  |    1 
 tools/python/xen/xm/create.py                                   |   27 
 tools/python/xen/xm/main.py                                     |   53 
 tools/python/xen/xm/xenapi_create.py                            |    1 
 tools/xcutils/xc_save.c                                         |  127 -
 tools/xenstore/Makefile                                         |    4 
 tools/xenstore/xs.c                                             |   25 
 tools/xenstore/xs.h                                             |    1 
 tools/xentrace/formats                                          |    4 
 tools/xentrace/xentrace_format                                  |    6 
 unmodified_drivers/linux-2.6/compat-include/linux/scatterlist.h |   10 
 xen/arch/ia64/xen/hypercall.c                                   |   22 
 xen/arch/x86/acpi/cpu_idle.c                                    |   71 
 xen/arch/x86/acpi/cpufreq/cpufreq.c                             |  135 -
 xen/arch/x86/acpi/power.c                                       |   24 
 xen/arch/x86/acpi/suspend.c                                     |    8 
 xen/arch/x86/boot/build32.mk                                    |    3 
 xen/arch/x86/cpu/common.c                                       |    3 
 xen/arch/x86/cpu/mcheck/Makefile                                |    1 
 xen/arch/x86/cpu/mcheck/amd_f10.c                               |   43 
 xen/arch/x86/cpu/mcheck/amd_k8.c                                |  229 -
 xen/arch/x86/cpu/mcheck/amd_nonfatal.c                          |  150 -
 xen/arch/x86/cpu/mcheck/k7.c                                    |   11 
 xen/arch/x86/cpu/mcheck/mce.c                                   | 1257 
++++++----
 xen/arch/x86/cpu/mcheck/mce.h                                   |  115 
 xen/arch/x86/cpu/mcheck/mce_intel.c                             | 1016 +++++---
 xen/arch/x86/cpu/mcheck/mctelem.c                               |  443 +++
 xen/arch/x86/cpu/mcheck/mctelem.h                               |   71 
 xen/arch/x86/cpu/mcheck/non-fatal.c                             |   87 
 xen/arch/x86/cpu/mcheck/p5.c                                    |   15 
 xen/arch/x86/cpu/mcheck/winchip.c                               |    8 
 xen/arch/x86/cpu/mcheck/x86_mca.h                               |   60 
 xen/arch/x86/domain.c                                           |   11 
 xen/arch/x86/domctl.c                                           |    8 
 xen/arch/x86/hpet.c                                             |  403 +++
 xen/arch/x86/hvm/emulate.c                                      |    2 
 xen/arch/x86/hvm/hvm.c                                          |   14 
 xen/arch/x86/hvm/rtc.c                                          |    7 
 xen/arch/x86/hvm/svm/svm.c                                      |   12 
 xen/arch/x86/hvm/vmsi.c                                         |   56 
 xen/arch/x86/hvm/vmx/vpmu_core2.c                               |    6 
 xen/arch/x86/mm.c                                               |   83 
 xen/arch/x86/mm/shadow/multi.c                                  |   82 
 xen/arch/x86/msi.c                                              |    2 
 xen/arch/x86/oprofile/op_model_ppro.c                           |    2 
 xen/arch/x86/physdev.c                                          |   26 
 xen/arch/x86/setup.c                                            |    2 
 xen/arch/x86/smpboot.c                                          |    8 
 xen/arch/x86/sysctl.c                                           |   24 
 xen/arch/x86/time.c                                             |   11 
 xen/arch/x86/traps.c                                            |   48 
 xen/arch/x86/x86_32/entry.S                                     |    2 
 xen/arch/x86/x86_64/compat/entry.S                              |    2 
 xen/arch/x86/x86_64/entry.S                                     |    2 
 xen/arch/x86/x86_64/traps.c                                     |   47 
 xen/common/domain.c                                             |    2 
 xen/common/memory.c                                             |   11 
 xen/common/page_alloc.c                                         |  105 
 xen/common/sched_credit.c                                       |    9 
 xen/common/schedule.c                                           |   10 
 xen/common/sysctl.c                                             |   29 
 xen/drivers/acpi/pmstat.c                                       |   90 
 xen/drivers/cpufreq/cpufreq_misc_governors.c                    |   83 
 xen/drivers/cpufreq/cpufreq_ondemand.c                          |    4 
 xen/drivers/cpufreq/utility.c                                   |   28 
 xen/drivers/passthrough/io.c                                    |  141 -
 xen/drivers/passthrough/iommu.c                                 |   18 
 xen/drivers/passthrough/pci.c                                   |   41 
 xen/drivers/passthrough/vtd/dmar.c                              |   18 
 xen/drivers/passthrough/vtd/dmar.h                              |    2 
 xen/drivers/passthrough/vtd/extern.h                            |    6 
 xen/drivers/passthrough/vtd/intremap.c                          |   69 
 xen/drivers/passthrough/vtd/iommu.c                             |  139 -
 xen/drivers/passthrough/vtd/qinval.c                            |   29 
 xen/include/acpi/cpufreq/cpufreq.h                              |    9 
 xen/include/asm-ia64/linux-xen/asm/processor.h                  |    8 
 xen/include/asm-x86/desc.h                                      |    4 
 xen/include/asm-x86/domain.h                                    |   28 
 xen/include/asm-x86/hpet.h                                      |    5 
 xen/include/asm-x86/mm.h                                        |   31 
 xen/include/asm-x86/msr-index.h                                 |   24 
 xen/include/asm-x86/processor.h                                 |    3 
 xen/include/asm-x86/softirq.h                                   |    3 
 xen/include/asm-x86/traps.h                                     |    2 
 xen/include/asm-x86/x86_64/page.h                               |    2 
 xen/include/public/arch-x86/xen-mca.h                           |  133 -
 xen/include/public/domctl.h                                     |    2 
 xen/include/public/io/fsif.h                                    |    3 
 xen/include/public/io/usbif.h                                   |  121 
 xen/include/public/io/vscsiif.h                                 |  105 
 xen/include/public/physdev.h                                    |   16 
 xen/include/public/sysctl.h                                     |   35 
 xen/include/xen/hvm/irq.h                                       |    4 
 xen/include/xen/iommu.h                                         |    2 
 xen/include/xen/irq.h                                           |    2 
 xen/include/xen/lib.h                                           |    1 
 xen/include/xen/pci.h                                           |   11 
 xen/include/xen/sched.h                                         |    7 
 175 files changed, 9032 insertions(+), 2524 deletions(-)

diff -r 5e4dd7079c48 -r e54eeff2de54 Makefile
--- a/Makefile  Fri Mar 27 10:54:08 2009 +0900
+++ b/Makefile  Fri Mar 27 11:07:11 2009 +0900
@@ -203,6 +203,8 @@ uninstall:
        rm -rf $(D)/etc/hotplug/xen-backend.agent
        rm -f  $(D)/etc/udev/rules.d/xen-backend.rules
        rm -f  $(D)/etc/udev/xen-backend.rules
+       rm -f  $(D)/etc/udev/rules.d/xend.rules
+       rm -f  $(D)/etc/udev/xend.rules
        rm -f  $(D)/etc/sysconfig/xendomains
        rm -rf $(D)/var/run/xen* $(D)/var/lib/xen*
        rm -rf $(D)/boot/*xen*
diff -r 5e4dd7079c48 -r e54eeff2de54 config/NetBSD.mk
--- a/config/NetBSD.mk  Fri Mar 27 10:54:08 2009 +0900
+++ b/config/NetBSD.mk  Fri Mar 27 11:07:11 2009 +0900
@@ -2,3 +2,7 @@ include $(XEN_ROOT)/config/StdGNU.mk
 
 # Override settings for this OS
 CURSES_LIBS = -lcurses
+
+LIBLEAFDIR_x86_64 = lib
+LIBEXEC = $(PREFIX)/libexec
+PRIVATE_BINDIR = $(BINDIR)
diff -r 5e4dd7079c48 -r e54eeff2de54 config/StdGNU.mk
--- a/config/StdGNU.mk  Fri Mar 27 10:54:08 2009 +0900
+++ b/config/StdGNU.mk  Fri Mar 27 11:07:11 2009 +0900
@@ -25,9 +25,12 @@ BINDIR = $(PREFIX)/bin
 BINDIR = $(PREFIX)/bin
 INCLUDEDIR = $(PREFIX)/include
 LIBLEAFDIR = lib
+LIBLEAFDIR_x86_32 = lib
 LIBLEAFDIR_x86_64 = lib64
 LIBDIR = $(PREFIX)/$(LIBLEAFDIR)
+LIBDIR_x86_32 = $(PREFIX)/$(LIBLEAFDIR_x86_32)
 LIBDIR_x86_64 = $(PREFIX)/$(LIBLEAFDIR_x86_64)
+LIBEXEC = $(LIBDIR_x86_32)/xen/bin
 MANDIR = $(PREFIX)/share/man
 MAN1DIR = $(MANDIR)/man1
 MAN8DIR = $(MANDIR)/man8
diff -r 5e4dd7079c48 -r e54eeff2de54 docs/misc/vtd.txt
--- a/docs/misc/vtd.txt Fri Mar 27 10:54:08 2009 +0900
+++ b/docs/misc/vtd.txt Fri Mar 27 11:07:11 2009 +0900
@@ -26,7 +26,18 @@ title Xen-Fedora Core (2.6.18-xen)
         module /boot/vmlinuz-2.6.18.8-xen root=LABEL=/ ro xencons=ttyS 
console=tty0 console=ttyS0, pciback.hide=(01:00.0)(03:00.0)
         module /boot/initrd-2.6.18-xen.img
 
-12) reboot system
+    or use dynamic hiding via PCI backend sysfs interface:
+        a) check if the driver has binded to the device
+            ls -l /sys/bus/pci/devices/0000:01:00.0/driver
+            ... /sys/bus/pci/devices/0000:01:00.0/driver -> 
../../../../bus/pci/drivers/igb
+        b) if yes, then unload the driver first
+            echo -n 0000:01:00.0 >/sys/bus/pci/drivers/igb/unbind
+        c) add the device to the PCI backend
+            echo -n 0000:01:00.0 >/sys/bus/pci/drivers/pciback/new_slot
+        d) let the PCI backend bind to the device
+            echo -n 0000:01:00.0 >/sys/bus/pci/drivers/pciback/bind
+
+12) reboot system (not requires if you use the dynamic hiding method)
 13) add "pci" line in /etc/xen/hvm.conf for to assigned devices
         pci = [ '01:00.0', '03:00.0' ]
 15) start hvm guest and use "lspci" to see the passthru device and
@@ -160,3 +171,82 @@ buffer specified by driver.
 buffer specified by driver.
 
 Such devices assigned to HVM domain currently do not work.
+
+
+Using SR-IOV with VT-d
+--------------------------------
+
+The Single Root I/O Virtualization is a PCI Express feature supported by
+some devices such as Intel 82576 which allows you to create virtual PCI
+devices (Virtual Function) and assign them to the HVM guest.
+
+You can use latest lspci (v3.1 and above) to check if your PCIe device
+supports the SR-IOV capability or not.
+
+  $ lspci -s 01:00.0 -vvv
+
+  01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network 
Connection (rev 01)
+        Subsystem: Intel Corporation Gigabit ET Dual Port Server Adapter
+
+        ...
+
+        Capabilities: [160] Single Root I/O Virtualization (SR-IOV)
+                IOVCap: Migration-, Interrupt Message Number: 000
+                IOVCtl: Enable+ Migration- Interrupt- MSE+ ARIHierarchy+
+                IOVSta: Migration-
+                Initial VFs: 8, Total VFs: 8, Number of VFs: 7, Function 
Dependency Link: 00
+                VF offset: 128, stride: 2, Device ID: 10ca
+                Supported Page Size: 00000553, System Page Size: 00000001
+                VF Migration: offset: 00000000, BIR: 0
+        Kernel driver in use: igb
+
+
+The function that has the SR-IOV capability is also known as Physical
+Function. You need the Physical Function driver (runs in the Dom0 and
+controls the physical resources allocation) to enable the Virtual Function.
+Following is the Virtual Functions associated with above Physical Function.
+
+  $ lspci | grep -e 01:1[01].[0246]
+
+  01:10.0 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+  01:10.2 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+  01:10.4 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+  01:10.6 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+  01:11.0 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+  01:11.2 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+  01:11.4 Ethernet controller: Intel Corporation Device 10ca (rev 01)
+
+We can tell that Physical Function 01:00.0 has 7 Virtual Functions (01:10.0,
+01:10.2, 01:10.4, 01:10.6, 01:11.0, 01:11.2, 01:11.4). And the Virtual
+Function PCI Configuration Space looks just like normal PCI device.
+
+  $ lspci -s 01:10.0 -vvv
+
+  01:10.0 Ethernet controller: Intel Corporation 82576 Gigabit Virtual Function
+        Subsystem: Intel Corporation Gigabit Virtual Function
+        Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- 
Stepping- SERR- FastB2B- DisINTx-
+        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- 
<TAbort- <MAbort- >SERR- <PERR- INTx-
+        Region 0: [virtual] Memory at d2840000 (64-bit, non-prefetchable) 
[size=16K]
+        Region 3: [virtual] Memory at d2860000 (64-bit, non-prefetchable) 
[size=16K]
+        Capabilities: [70] MSI-X: Enable+ Mask- TabSize=3
+                Vector table: BAR=3 offset=00000000
+                PBA: BAR=3 offset=00002000
+        Capabilities: [a0] Express (v2) Endpoint, MSI 00
+
+        ...
+
+
+The Virtual Function only appears after the Physical Function driver
+is loaded. Once the Physical Function driver is unloaded. All Virtual
+Functions associated with this Physical Function disappear.
+
+The Virtual Function is essentially same as the normal PCI device when
+using it in VT-d environment. You need to hide the Virtual Function,
+use the Virtual Function bus, device and function number in the HVM
+guest configuration file and then boot the HVM guest. You also need the
+Virtual Function driver which is the normal PCI device driver in the
+HMV guest to drive the Virtual Function. The PCIe SR-IOV specification
+requires that the Virtual Function can only support MSI/MSI-x if it
+uses interrupt. This means you also need to enable Xen/MSI support.
+Since the Virtual Function is dynamically allocated by Physical Function
+driver, you might want to use the dynamic hiding method mentioned above.
diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c     Fri Mar 27 10:54:08 2009 +0900
+++ b/extras/mini-os/arch/ia64/mm.c     Fri Mar 27 11:07:11 2009 +0900
@@ -162,6 +162,12 @@ int unmap_frames(unsigned long virt_addr
     ASSERT(0);
 }
 
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
+{
+    /* TODO */
+    ASSERT(0);
+}
+
 void arch_init_p2m(unsigned long max_pfn)
 {
     printk("Warn: p2m map not implemented.\n");
diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/extras/mini-os/arch/x86/mm.c      Fri Mar 27 11:07:11 2009 +0900
@@ -702,6 +702,148 @@ int unmap_frames(unsigned long va, unsig
 }
 
 /*
+ * Allocate pages which are contiguous in machine memory.
+ * Returns a VA to where they are mapped or 0 on failure.
+ * 
+ * addr_bits indicates if the region has restrictions on where it is
+ * located. Typical values are 32 (if for example PCI devices can't access
+ * 64bit memory) or 0 for no restrictions.
+ *
+ * Allocated pages can be freed using the page allocators free_pages() 
+ * function.
+ *
+ * based on Linux function xen_create_contiguous_region()
+ */
+#define MAX_CONTIG_ORDER 9 /* 2MB */
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
+{
+    unsigned long in_va, va;
+    unsigned long in_frames[1UL << order], out_frames, mfn;
+    multicall_entry_t call[1UL << order];
+    unsigned int i, num_pages = 1UL << order;
+    int ret, exch_success;
+
+    /* pass in num_pages 'extends' of size 1 and
+     * request 1 extend of size 'order */
+    struct xen_memory_exchange exchange = {
+        .in = {
+            .nr_extents   = num_pages,
+            .extent_order = 0,
+            .domid        = DOMID_SELF
+        },
+        .out = {
+            .nr_extents   = 1,
+            .extent_order = order,
+            .address_bits = addr_bits,
+            .domid        = DOMID_SELF
+        },
+        .nr_exchanged = 0
+    };
+
+    if ( order > MAX_CONTIG_ORDER )
+    {
+        printk("alloc_contig_pages: order too large 0x%x > 0x%x\n",
+               order, MAX_CONTIG_ORDER);
+        return 0;
+    }
+
+    /* Allocate some potentially discontiguous pages */
+    in_va = alloc_pages(order);
+    if ( !in_va )
+    {
+        printk("alloc_contig_pages: could not get enough pages (order=0x%x\n",
+               order);
+        return 0;
+    }
+
+    /* set up arguments for exchange hyper call */
+    set_xen_guest_handle(exchange.in.extent_start, in_frames);
+    set_xen_guest_handle(exchange.out.extent_start, &out_frames);
+
+    /* unmap current frames, keep a list of MFNs */
+    for ( i = 0; i < num_pages; i++ )
+    {
+        int arg = 0;
+
+        va = in_va + (PAGE_SIZE * i);
+        in_frames[i] = virt_to_mfn(va);
+
+        /* update P2M mapping */
+        phys_to_machine_mapping[virt_to_pfn(va)] = INVALID_P2M_ENTRY;
+
+        /* build multi call */
+        call[i].op = __HYPERVISOR_update_va_mapping;
+        call[i].args[arg++] = va;
+        call[i].args[arg++] = 0;
+#ifdef __i386__
+        call[i].args[arg++] = 0;
+#endif  
+        call[i].args[arg++] = UVMF_INVLPG;
+    }
+
+    ret = HYPERVISOR_multicall(call, i);
+    if ( ret )
+    {
+        printk("Odd, update_va_mapping hypercall failed with rc=%d.\n", ret);
+        return 0;
+    }
+
+    /* try getting a contig range of MFNs */
+    out_frames = virt_to_pfn(in_va); /* PFNs to populate */
+    ret = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+    if ( ret ) {
+        printk("mem exchanged order=0x%x failed with rc=%d, 
nr_exchanged=%d\n", 
+               order, ret, exchange.nr_exchanged);
+        /* we still need to return the allocated pages above to the pool
+         * ie. map them back into the 1:1 mapping etc. so we continue but 
+         * in the end return the pages to the page allocator and return 0. */
+        exch_success = 0;
+    }
+    else
+        exch_success = 1;
+
+    /* map frames into 1:1 and update p2m */
+    for ( i = 0; i < num_pages; i++ )
+    {
+        int arg = 0;
+        pte_t pte;
+
+        va = in_va + (PAGE_SIZE * i);
+        mfn = i < exchange.nr_exchanged ? (out_frames + i) : in_frames[i];
+        pte = __pte(mfn << PAGE_SHIFT | L1_PROT);
+
+        /* update P2M mapping */
+        phys_to_machine_mapping[virt_to_pfn(va)] = mfn;
+
+        /* build multi call */
+        call[i].op = __HYPERVISOR_update_va_mapping;
+        call[i].args[arg++] = va;
+#ifdef __x86_64__
+        call[i].args[arg++] = (pgentry_t)pte.pte;
+#else
+        call[i].args[arg++] = pte.pte_low;
+        call[i].args[arg++] = pte.pte_high;
+#endif  
+        call[i].args[arg++] = UVMF_INVLPG;
+    }
+    ret = HYPERVISOR_multicall(call, i);
+    if ( ret )
+    {
+        printk("update_va_mapping hypercall no. 2 failed with rc=%d.\n", ret);
+        return 0;
+    }
+
+    if ( !exch_success )
+    {
+        /* since the exchanged failed we just free the pages as well */
+        free_pages((void *) in_va, order);
+        return 0;
+    }
+    
+    return in_va;
+}
+
+/*
  * Check if a given MFN refers to real memory
  */
 static long system_ram_end_mfn;
diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Fri Mar 27 10:54:08 2009 +0900
+++ b/extras/mini-os/include/mm.h       Fri Mar 27 11:07:11 2009 +0900
@@ -72,6 +72,7 @@ void do_map_frames(unsigned long addr,
         unsigned long *f, unsigned long n, unsigned long stride,
        unsigned long increment, domid_t id, int may_fail, unsigned long prot);
 int unmap_frames(unsigned long va, unsigned long num_frames);
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits);
 #ifdef HAVE_LIBC
 extern unsigned long heap, brk, heap_mapped, heap_end;
 #endif
diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h      Fri Mar 27 10:54:08 2009 +0900
+++ b/extras/mini-os/include/x86/arch_mm.h      Fri Mar 27 11:07:11 2009 +0900
@@ -137,6 +137,9 @@ typedef unsigned long pgentry_t;
 #define IO_PROT (L1_PROT)
 #define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
 
+/* for P2M */
+#define INVALID_P2M_ENTRY (~0UL)
+
 #include "arch_limits.h"
 #define PAGE_SIZE       __PAGE_SIZE
 #define PAGE_SHIFT      __PAGE_SHIFT
diff -r 5e4dd7079c48 -r e54eeff2de54 stubdom/Makefile
--- a/stubdom/Makefile  Fri Mar 27 10:54:08 2009 +0900
+++ b/stubdom/Makefile  Fri Mar 27 11:07:11 2009 +0900
@@ -6,8 +6,6 @@ export stubdom=y
 export stubdom=y
 export debug=y
 include $(XEN_ROOT)/Config.mk
-
-IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-vnc-tls 
--disable-brlapi --disable-kqemu
 
 #ZLIB_URL?=http://www.zlib.net
 ZLIB_URL=$(XEN_EXTFILES_URL)
@@ -237,8 +235,12 @@ ioemu: cross-zlib cross-libpci libxc
        [ -f ioemu/config-host.mak ] || \
          ( $(absolutify_xen_root); \
            cd ioemu ; \
-          CONFIG_STUBDOM=yes XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) 
CFLAGS="$(TARGET_CFLAGS)" sh ./xen-setup --cc=$(CC) --disable-gcc-check 
$(IOEMU_OPTIONS))
-       CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu 
LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) TOOLS= CONFIG_STUBDOM=yes
+           LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) \
+           TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" \
+           TARGET_CFLAGS="$(TARGET_CFLAGS)" \
+           TARGET_LDFLAGS="$(TARGET_LDFLAGS)" \
+           ./xen-setup-stubdom )
+       $(MAKE) -C ioemu
 
 ######
 # caml
@@ -312,14 +314,14 @@ install-readme:
        $(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.stubdom
 
 install-ioemu: ioemu-stubdom
-       $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/bin"
-       $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin"
-       $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot"
-       $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz 
"$(DESTDIR)/usr/lib/xen/boot/ioemu-stubdom.gz"
+       $(INSTALL_DIR) "$(DESTDIR)$(LIBEXEC)"
+       $(INSTALL_PROG) stubdom-dm "$(DESTDIR)$(LIBEXEC)"
+       $(INSTALL_DIR) "$(DESTDIR)$(LIBDIR_x86_32)/xen/boot"
+       $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz 
"$(DESTDIR)$(LIBDIR_x86_32)/xen/boot/ioemu-stubdom.gz"
 
 install-grub: pv-grub
-       $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot"
-       $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz 
"$(DESTDIR)/usr/lib/xen/boot/pv-grub-$(XEN_TARGET_ARCH).gz"
+       $(INSTALL_DIR) "$(DESTDIR)$(LIBDIR_x86_32)/xen/boot"
+       $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz 
"$(DESTDIR)$(LIBDIR_x86_32)/xen/boot/pv-grub-$(XEN_TARGET_ARCH).gz"
 
 #######
 # clean
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/Makefile
--- a/tools/Makefile    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/Makefile    Fri Mar 27 11:07:11 2009 +0900
@@ -19,11 +19,11 @@ SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
 SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
 SUBDIRS-$(VTPM_TOOLS) += vtpm
 SUBDIRS-y += xenstat
-SUBDIRS-y += libaio
-SUBDIRS-y += blktap
+SUBDIRS-$(CONFIG_Linux) += libaio
+SUBDIRS-$(CONFIG_Linux) += blktap
 SUBDIRS-y += libfsimage
 SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
-SUBDIRS-y += fs-back
+SUBDIRS-$(CONFIG_Linux) += fs-back
 SUBDIRS-$(CONFIG_IOEMU) += ioemu-dir
 SUBDIRS-y += xenpmd
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/drivers/blktapctrl.c
--- a/tools/blktap/drivers/blktapctrl.c Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/blktap/drivers/blktapctrl.c Fri Mar 27 11:07:11 2009 +0900
@@ -148,7 +148,8 @@ static int get_tapdisk_pid(blkif_t *blki
  *   return 0 on success, -1 on error.
  */
 
-static int test_path(char *path, char **dev, int *type, blkif_t **blkif)
+static int test_path(char *path, char **dev, int *type, blkif_t **blkif,
+       int* use_ioemu)
 {
        char *ptr, handle[10];
        int i, size, found = 0;
@@ -157,6 +158,17 @@ static int test_path(char *path, char **
        size = sizeof(dtypes)/sizeof(disk_info_t *);
        *type = MAX_DISK_TYPES + 1;
         *blkif = NULL;
+
+       if (!strncmp(path, "tapdisk:", strlen("tapdisk:"))) {
+               *use_ioemu = 0;
+               path += strlen("tapdisk:");
+       } else if (!strncmp(path, "ioemu:", strlen("ioemu:"))) {
+               *use_ioemu = 1;
+               path += strlen("ioemu:");
+       } else {
+               // Use the default for the image type
+               *use_ioemu = -1;
+       }
 
        if ( (ptr = strstr(path, ":"))!=NULL) {
                handle_len = (ptr - path);
@@ -174,6 +186,8 @@ static int test_path(char *path, char **
                         }
 
                        if (found) {
+                               if (*use_ioemu == -1)
+                                       *use_ioemu = dtypes[i]->use_ioemu;
                                *type = dtypes[i]->idnum;
                         
                         if (dtypes[i]->single_handler == 1) {
@@ -185,6 +199,7 @@ static int test_path(char *path, char **
                                         *blkif = active_disks[dtypes[i]
                                                              ->idnum]->blkif;
                         }
+
                         return 0;
                 }
             }
@@ -216,6 +231,24 @@ static void add_disktype(blkif_t *blkif,
        entry->pprev = pprev;
 }
 
+static int qemu_instance_has_disks(pid_t pid)
+{
+       int i;
+       int count = 0;
+       driver_list_entry_t *entry;
+
+       for (i = 0; i < MAX_DISK_TYPES; i++) {
+               entry = active_disks[i];
+               while (entry) {
+                       if ((entry->blkif->tappid == pid) && 
dtypes[i]->use_ioemu)
+                               count++;
+                       entry = entry->next;
+               }
+       }
+
+       return (count != 0);
+}
+
 static int del_disktype(blkif_t *blkif)
 {
        driver_list_entry_t *entry, **pprev;
@@ -239,6 +272,14 @@ static int del_disktype(blkif_t *blkif)
 
        DPRINTF("DEL_DISKTYPE: Freeing entry\n");
        free(entry);
+
+       /*
+        * When using ioemu, all disks of one VM are connected to the same
+        * qemu-dm instance. We may close the file handle only if there is
+        * no other disk left for this domain.
+        */
+       if (dtypes[type]->use_ioemu)
+               return !qemu_instance_has_disks(blkif->tappid);
 
        /* Caller should close() if no single controller, or list is empty. */
        return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
@@ -504,7 +545,8 @@ static int connect_qemu(blkif_t *blkif, 
        static int tapdisk_ioemu_pid = 0;
        static int dom0_readfd = 0;
        static int dom0_writefd = 0;
-       
+       int refresh_pid = 0;
+
        if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0)
                return -1;
 
@@ -523,15 +565,23 @@ static int connect_qemu(blkif_t *blkif, 
                if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) {
                        /* No device model and tapdisk-ioemu doesn't run yet */
                        DPRINTF("Launching tapdisk-ioemu\n");
-                       tapdisk_ioemu_pid = launch_tapdisk_ioemu();
+                       launch_tapdisk_ioemu();
                        
                        dom0_readfd = open_ctrl_socket(wrctldev);
                        dom0_writefd = open_ctrl_socket(rdctldev);
+
+                       refresh_pid = 1;
                }
 
                DPRINTF("Using tapdisk-ioemu connection\n");
                blkif->fds[READ] = dom0_readfd;
                blkif->fds[WRITE] = dom0_writefd;
+
+               if (refresh_pid) {
+                       get_tapdisk_pid(blkif);
+                       tapdisk_ioemu_pid = blkif->tappid;
+               }
+
        } else if (access(rdctldev, R_OK | W_OK) == 0) {
                /* Use existing pipe to the device model */
                DPRINTF("Using qemu-dm connection\n");
@@ -605,13 +655,11 @@ static int blktapctrl_new_blkif(blkif_t 
        image_t *image;
        blkif_t *exist = NULL;
        static uint16_t next_cookie = 0;
+       int use_ioemu;
 
        DPRINTF("Received a poll for a new vbd\n");
        if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
-               if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0)
-                       return -1;
-
-               if (test_path(blk->params, &ptr, &type, &exist) != 0) {
+               if (test_path(blk->params, &ptr, &type, &exist, &use_ioemu) != 
0) {
                         DPRINTF("Error in blktap device string(%s).\n",
                                 blk->params);
                         goto fail;
@@ -620,7 +668,7 @@ static int blktapctrl_new_blkif(blkif_t 
                blkif->cookie = next_cookie++;
 
                if (!exist) {
-                       if (type == DISK_TYPE_IOEMU) {
+                       if (use_ioemu) {
                                if (connect_qemu(blkif, blkif->domid))
                                        goto fail;
                        } else {
@@ -633,10 +681,6 @@ static int blktapctrl_new_blkif(blkif_t 
                        blkif->fds[READ] = exist->fds[READ];
                        blkif->fds[WRITE] = exist->fds[WRITE];
                }
-
-               add_disktype(blkif, type);
-               blkif->major = major;
-               blkif->minor = minor;
 
                image = (image_t *)malloc(sizeof(image_t));
                blkif->prv = (void *)image;
@@ -661,11 +705,18 @@ static int blktapctrl_new_blkif(blkif_t 
                        goto fail;
                }
 
+               if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0)
+                       return -1;
+
+               blkif->major = major;
+               blkif->minor = minor;
+
+               add_disktype(blkif, type);
+
        } else return -1;
 
        return 0;
 fail:
-       ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
        return -EINVAL;
 }
 
@@ -696,6 +747,7 @@ static int unmap_blktapctrl(blkif_t *blk
        }
 
        if (del_disktype(blkif)) {
+               DPRINTF("Closing communication pipe to pid %d\n", 
blkif->tappid);
                close(blkif->fds[WRITE]);
                close(blkif->fds[READ]);
        }
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/drivers/tapdisk.h
--- a/tools/blktap/drivers/tapdisk.h    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/blktap/drivers/tapdisk.h    Fri Mar 27 11:07:11 2009 +0900
@@ -145,6 +145,8 @@ typedef struct disk_info {
        char handle[10];     /* xend handle, e.g. 'ram' */
        int  single_handler; /* is there a single controller for all */
                             /* instances of disk type? */
+       int  use_ioemu;      /* backend provider: 0 = tapdisk; 1 = ioemu */
+
 #ifdef TAPDISK
        struct tap_disk *drv;   
 #endif
@@ -159,16 +161,6 @@ extern struct tap_disk tapdisk_qcow;
 extern struct tap_disk tapdisk_qcow;
 extern struct tap_disk tapdisk_qcow2;
 
-#define MAX_DISK_TYPES     20
-
-#define DISK_TYPE_AIO      0
-#define DISK_TYPE_SYNC     1
-#define DISK_TYPE_VMDK     2
-#define DISK_TYPE_RAM      3
-#define DISK_TYPE_QCOW     4
-#define DISK_TYPE_QCOW2    5
-#define DISK_TYPE_IOEMU    6
-
 
 /*Define Individual Disk Parameters here */
 static disk_info_t aio_disk = {
@@ -176,6 +168,7 @@ static disk_info_t aio_disk = {
        "raw image (aio)",
        "aio",
        0,
+       0,
 #ifdef TAPDISK
        &tapdisk_aio,
 #endif
@@ -185,6 +178,7 @@ static disk_info_t sync_disk = {
        DISK_TYPE_SYNC,
        "raw image (sync)",
        "sync",
+       0,
        0,
 #ifdef TAPDISK
        &tapdisk_sync,
@@ -196,6 +190,7 @@ static disk_info_t vmdk_disk = {
        "vmware image (vmdk)",
        "vmdk",
        1,
+       0,
 #ifdef TAPDISK
        &tapdisk_vmdk,
 #endif
@@ -206,6 +201,7 @@ static disk_info_t ram_disk = {
        "ramdisk image (ram)",
        "ram",
        1,
+       0,
 #ifdef TAPDISK
        &tapdisk_ram,
 #endif
@@ -216,6 +212,7 @@ static disk_info_t qcow_disk = {
        "qcow disk (qcow)",
        "qcow",
        0,
+       0,
 #ifdef TAPDISK
        &tapdisk_qcow,
 #endif
@@ -226,18 +223,9 @@ static disk_info_t qcow2_disk = {
        "qcow2 disk (qcow2)",
        "qcow2",
        0,
+       0,
 #ifdef TAPDISK
        &tapdisk_qcow2,
-#endif
-};
-
-static disk_info_t ioemu_disk = {
-       DISK_TYPE_IOEMU,
-       "ioemu disk",
-       "ioemu",
-       1,
-#ifdef TAPDISK
-       NULL
 #endif
 };
 
@@ -249,7 +237,6 @@ static disk_info_t *dtypes[] = {
        &ram_disk,
        &qcow_disk,
        &qcow2_disk,
-       &ioemu_disk,
 };
 
 typedef struct driver_list_entry {
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/lib/blktaplib.h
--- a/tools/blktap/lib/blktaplib.h      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/blktap/lib/blktaplib.h      Fri Mar 27 11:07:11 2009 +0900
@@ -210,6 +210,16 @@ typedef struct msg_pid {
 #define CTLMSG_PID         9
 #define CTLMSG_PID_RSP     10
 
+/* disk driver types */
+#define MAX_DISK_TYPES     20
+
+#define DISK_TYPE_AIO      0
+#define DISK_TYPE_SYNC     1
+#define DISK_TYPE_VMDK     2
+#define DISK_TYPE_RAM      3
+#define DISK_TYPE_QCOW     4
+#define DISK_TYPE_QCOW2    5
+
 /* xenstore/xenbus: */
 #define DOMNAME "Domain-0"
 int setup_probe_watch(struct xs_handle *h);
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/lib/xenbus.c
--- a/tools/blktap/lib/xenbus.c Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/blktap/lib/xenbus.c Fri Mar 27 11:07:11 2009 +0900
@@ -48,6 +48,7 @@
 #include <poll.h>
 #include <time.h>
 #include <sys/time.h>
+#include <unistd.h>
 #include "blktaplib.h"
 #include "list.h"
 #include "xs_api.h"
@@ -149,6 +150,137 @@ static int backend_remove(struct xs_hand
        return 0;
 }
 
+static int check_sharing(struct xs_handle *h, struct backend_info *be)
+{
+       char *dom_uuid;
+       char *cur_dom_uuid;
+       char *path;
+       char *mode;
+       char *params;
+       char **domains;
+       char **devices;
+       int i, j;
+       unsigned int num_dom, num_dev;
+       blkif_info_t *info;
+       int ret = 0;
+
+       /* If the mode contains '!' or doesn't contain 'w' don't check anything 
*/
+       xs_gather(h, be->backpath, "mode", NULL, &mode, NULL);
+       if (strchr(mode, '!'))
+               goto out;
+       if (strchr(mode, 'w') == NULL)
+               goto out;
+
+       /* Get the UUID of the domain we want to attach to */
+       if (asprintf(&path, "/local/domain/%ld", be->frontend_id) == -1)
+               goto fail;
+       xs_gather(h, path, "vm", NULL, &dom_uuid, NULL);
+       free(path);
+
+       /* Iterate through the devices of all VMs */
+       domains = xs_directory(h, XBT_NULL, "backend/tap", &num_dom);
+       if (domains == NULL)
+               num_dom = 0;
+
+       for (i = 0; !ret && (i < num_dom); i++) {
+
+               /* If it's the same VM, no action needed */
+               if (asprintf(&path, "/local/domain/%s", domains[i]) == -1) {
+                       ret = -1;
+                       break;
+               }
+               xs_gather(h, path, "vm", NULL, &cur_dom_uuid, NULL);
+               free(path);
+
+               if (!strcmp(cur_dom_uuid, dom_uuid)) {
+                       free(cur_dom_uuid);
+                       continue;
+               }
+
+               /* Check the devices */
+               if (asprintf(&path, "backend/tap/%s", domains[i]) == -1) {
+                       ret = -1;
+                       free(cur_dom_uuid);
+                       break;
+               }
+               devices = xs_directory(h, XBT_NULL, path, &num_dev);
+               if (devices == NULL)
+                       num_dev = 0;
+               free(path);
+
+               for (j = 0; !ret && (j < num_dev); j++) {
+                       if (asprintf(&path, "backend/tap/%s/%s", domains[i], 
devices[j]) == -1) {
+                               ret = -1;
+                               break;
+                       }
+                       xs_gather(h, path, "params", NULL, &params, NULL);
+                       free(path);
+
+                       info =  be->blkif->info;
+                       if (strcmp(params, info->params)) {
+                               ret = -1;
+                       }
+
+                       free(params);
+               }
+
+               free(cur_dom_uuid);
+               free(devices);
+       }
+       free(domains);
+       free(dom_uuid);
+       goto out;
+
+fail:
+       ret = -1;
+out:
+       free(mode);
+       return ret;
+}
+
+static int check_image(struct xs_handle *h, struct backend_info *be,
+       const char** errmsg)
+{
+       const char *tmp;
+       const char *path;
+       int mode;
+       blkif_t *blkif = be->blkif;
+       blkif_info_t *info = blkif->info;
+
+       /* Strip off the image type */
+       path = info->params;
+
+       if (!strncmp(path, "tapdisk:", strlen("tapdisk:"))) {
+               path += strlen("tapdisk:");
+       } else if (!strncmp(path, "ioemu:", strlen("ioemu:"))) {
+               path += strlen("ioemu:");
+       }
+
+       tmp = strchr(path, ':');
+       if (tmp != NULL)
+               path = tmp + 1;
+
+       /* Check if the image exists and access is permitted */
+       mode = R_OK;
+       if (!be->readonly)
+               mode |= W_OK;
+       if (access(path, mode)) {
+               if (errno == ENOENT)
+                       *errmsg = "File not found.";
+               else
+                       *errmsg = "Insufficient file permissions.";
+               return -1;
+       }
+
+       /* Check that the image is not attached to a different VM */
+       if (check_sharing(h, be)) {
+               *errmsg = "File already in use by other domain";
+               return -1;
+       }
+
+       return 0;
+}
+
 static void ueblktap_setup(struct xs_handle *h, char *bepath)
 {
        struct backend_info *be;
@@ -156,6 +288,7 @@ static void ueblktap_setup(struct xs_han
        int len, er, deverr;
        long int pdev = 0, handle;
        blkif_info_t *blk;
+       const char* errmsg = NULL;
        
        be = be_lookup_be(bepath);
        if (be == NULL)
@@ -211,6 +344,9 @@ static void ueblktap_setup(struct xs_han
                        be->pdev = pdev;
                }
 
+               if (check_image(h, be, &errmsg))
+                       goto fail;
+
                er = blkif_init(be->blkif, handle, be->pdev, be->readonly);
                if (er != 0) {
                        DPRINTF("Unable to open device %s\n",blk->params);
@@ -246,12 +382,21 @@ static void ueblktap_setup(struct xs_han
        }
 
        be->blkif->state = CONNECTED;
+       xs_printf(h, be->backpath, "hotplug-status", "connected");
+
        DPRINTF("[SETUP] Complete\n\n");
        goto close;
        
 fail:
-       if ( (be != NULL) && (be->blkif != NULL) ) 
+       if (be) {
+               if (errmsg == NULL)
+                       errmsg = "Setting up the backend failed. See the log "
+                               "files in /var/log/xen/ for details.";
+               xs_printf(h, be->backpath, "hotplug-error", errmsg);
+               xs_printf(h, be->backpath, "hotplug-status", "error");
+
                backend_remove(h, be);
+       }
 close:
        if (path)
                free(path);
@@ -286,7 +431,8 @@ static void ueblktap_probe(struct xs_han
        len = strsep_len(bepath, '/', 7);
        if (len < 0) 
                goto free_be;
-       bepath[len] = '\0';
+       if (bepath[len] != '\0')
+               goto free_be;
        
        be = malloc(sizeof(*be));
        if (!be) {
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/console/client/main.c
--- a/tools/console/client/main.c       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/console/client/main.c       Fri Mar 27 11:07:11 2009 +0900
@@ -35,6 +35,9 @@
 #include <err.h>
 #include <errno.h>
 #include <string.h>
+#ifdef __sun__
+#include <sys/stropts.h>
+#endif
 
 #include "xs.h"
 
@@ -71,6 +74,21 @@ static void usage(const char *program) {
               , program);
 }
 
+#ifdef __sun__
+void cfmakeraw(struct termios *termios_p)
+{
+       termios_p->c_iflag &=
+           ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+       termios_p->c_oflag &= ~OPOST;
+       termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+       termios_p->c_cflag &= ~(CSIZE|PARENB);
+       termios_p->c_cflag |= CS8;
+
+       termios_p->c_cc[VMIN] = 0;
+       termios_p->c_cc[VTIME] = 0;
+}
+#endif
+
 static int get_pty_fd(struct xs_handle *xs, char *path, int seconds)
 /* Check for a pty in xenstore, open it and return its fd.
  * Assumes there is already a watch set in the store for this path. */
@@ -80,7 +98,7 @@ static int get_pty_fd(struct xs_handle *
        int xs_fd = xs_fileno(xs), pty_fd = -1;
        int start, now;
        unsigned int len = 0;
-       char *pty_path, **watch_paths;;
+       char *pty_path, **watch_paths;
 
        start = now = time(NULL);
        do {
@@ -104,6 +122,29 @@ static int get_pty_fd(struct xs_handle *
                        }
                }
        } while (pty_fd == -1 && (now = time(NULL)) < start + seconds);
+
+#ifdef __sun__
+       if (pty_fd != -1) {
+               struct termios term;
+
+               /*
+                * The pty may come from either xend (with pygrub) or
+                * xenconsoled.  It may have tty semantics set up, or not.
+                * While it isn't strictly necessary to have those
+                * semantics here, it is good to have a consistent
+                * state that is the same as under Linux.
+                *
+                * If tcgetattr fails, they have not been set up,
+                * so go ahead and set them up now, by pushing the
+                * ptem and ldterm streams modules.
+                */
+               if (tcgetattr(pty_fd, &term) < 0) {
+                       ioctl(pty_fd, I_PUSH, "ptem");
+                       ioctl(pty_fd, I_PUSH, "ldterm");
+               }
+       }
+#endif
+
        return pty_fd;
 }
 
@@ -119,12 +160,12 @@ static void init_term(int fd, struct ter
        new_term = *old;
        cfmakeraw(&new_term);
 
-       tcsetattr(fd, TCSAFLUSH, &new_term);
+       tcsetattr(fd, TCSANOW, &new_term);
 }
 
 static void restore_term(int fd, struct termios *old)
 {
-       tcsetattr(fd, TCSAFLUSH, old);
+       tcsetattr(fd, TCSANOW, old);
 }
 
 static int console_loop(int fd, struct xs_handle *xs, char *pty_path)
@@ -152,7 +193,8 @@ static int console_loop(int fd, struct x
 
                if (FD_ISSET(xs_fileno(xs), &fds)) {
                        int newfd = get_pty_fd(xs, pty_path, 0);
-                       close(fd);
+                       if (fd != -1)
+                               close(fd);
                         if (newfd == -1) 
                                /* Console PTY has become invalid */
                                return 0;
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/console/daemon/main.c
--- a/tools/console/daemon/main.c       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/console/daemon/main.c       Fri Mar 27 11:07:11 2009 +0900
@@ -86,7 +86,9 @@ int main(int argc, char **argv)
                        version(argv[0]);
                        exit(0);
                case 'v':
+#ifndef __sun__
                        syslog_option |= LOG_PERROR;
+#endif
                        syslog_mask = LOG_DEBUG;
                        break;
                case 'i':
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/examples/xend-config.sxp
--- a/tools/examples/xend-config.sxp    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/examples/xend-config.sxp    Fri Mar 27 11:07:11 2009 +0900
@@ -64,6 +64,7 @@
 #(xend-relocation-server no)
 (xend-relocation-server yes)
 #(xend-relocation-ssl-server no)
+#(xend-udev-event-server no)
 
 #(xend-unix-path /var/lib/xend/xend-socket)
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/examples/xmexample.hvm
--- a/tools/examples/xmexample.hvm      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/examples/xmexample.hvm      Fri Mar 27 11:07:11 2009 +0900
@@ -223,6 +223,10 @@ serial='pty'
 #-----------------------------------------------------------------------------
 #   Set keyboard layout, default is en-us keyboard. 
 #keymap='ja'
+
+#-----------------------------------------------------------------------------
+#   Enable/disable xen platform PCI device, default=1 (enabled)
+#xen_platform_pci=1
 
 #-----------------------------------------------------------------------------
 #   Configure guest CPUID responses:
@@ -264,8 +268,8 @@ serial='pty'
 # Look like a generic 686 :
 # cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
 #           '1:eax=0x06b1,
-#              ecx=xxxxxxxxxx0000xx00xxx0000000xx0,
-#              edx=xx00000xxxxxxx0xxxxxxxxx0xxxxxx',
+#              ecx=xxxxxxxxxxx0000xx00xxx0000000xx0,
+#              edx=xxx00000xxxxxxx0xxxxxxxxx0xxxxxx',
 #           '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
 #  '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0']
 #  with the highest leaf
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/Makefile
--- a/tools/firmware/Makefile   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/Makefile   Fri Mar 27 11:07:11 2009 +0900
@@ -2,9 +2,8 @@ include $(XEN_ROOT)/tools/Rules.mk
 include $(XEN_ROOT)/tools/Rules.mk
 
 # hvmloader is a 32-bit protected mode binary.
-# It belongs in /usr/lib, not /usr/lib64.
 TARGET      := hvmloader/hvmloader
-INST_DIR := $(DESTDIR)/usr/lib/xen/boot
+INST_DIR := $(DESTDIR)$(LIBDIR_x86_32)/xen/boot
 
 SUBDIRS :=
 SUBDIRS += rombios
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/hvmloader/acpi/dsdt.asl
--- a/tools/firmware/hvmloader/acpi/dsdt.asl    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/hvmloader/acpi/dsdt.asl    Fri Mar 27 11:07:11 2009 +0900
@@ -981,60 +981,1027 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, 
              * handle the hotplug action and status, which is beyond the ACPI
              * scope.
              */
-
-            Device (S1F0)
+            Device(S00)
+            {
+                Name (_ADR, 0x00000000) /* Dev 0, Func 0 */
+                Name (_SUN, 0x00000000)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x00, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x00, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x00, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH00) /* eject php slot 0x00 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x00, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH00) /* IN status as the _STA */
+                }
+            }
+
+            Device(S01)
+            {
+                Name (_ADR, 0x00010000) /* Dev 1, Func 0 */
+                Name (_SUN, 0x00000001)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x01, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x01, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x01, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH01) /* eject php slot 0x01 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x01, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH01) /* IN status as the _STA */
+                }
+            }
+
+            Device(S02)
+            {
+                Name (_ADR, 0x00020000) /* Dev 2, Func 0 */
+                Name (_SUN, 0x00000002)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x02, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x02, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x02, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH02) /* eject php slot 0x02 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x02, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH02) /* IN status as the _STA */
+                }
+            }
+
+            Device(S03)
+            {
+                Name (_ADR, 0x00030000) /* Dev 3, Func 0 */
+                Name (_SUN, 0x00000003)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x03, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x03, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x03, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH03) /* eject php slot 0x03 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x03, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH03) /* IN status as the _STA */
+                }
+            }
+
+            Device(S04)
+            {
+                Name (_ADR, 0x00040000) /* Dev 4, Func 0 */
+                Name (_SUN, 0x00000004)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x04, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x04, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x04, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH04) /* eject php slot 0x04 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x04, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH04) /* IN status as the _STA */
+                }
+            }
+
+            Device(S05)
+            {
+                Name (_ADR, 0x00050000) /* Dev 5, Func 0 */
+                Name (_SUN, 0x00000005)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x05, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x05, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x05, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH05) /* eject php slot 0x05 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x05, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH05) /* IN status as the _STA */
+                }
+            }
+
+            Device(S06)
             {
                 Name (_ADR, 0x00060000) /* Dev 6, Func 0 */
-                Name (_SUN, 0x00000001)
-
-                Method (_PS0, 0)
-                {
-                    Store (0x80, \_GPE.DPT2)
-                }
-
-                Method (_PS3, 0)
-                {
-                    Store (0x83, \_GPE.DPT2)
-                }
-
-                Method (_EJ0, 1)
-                {
-                    Store (0x88, \_GPE.DPT2)
-                    Store (0x1, \_GPE.PHP1) /* eject php slot 1*/
-                }
-
-                Method (_STA, 0)
-                {
-                    Store (0x89, \_GPE.DPT2)
-                    Return ( \_GPE.PHP1 )   /* IN status as the _STA */
-                }
-            }
-
-            Device (S2F0)
+                Name (_SUN, 0x00000006)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x06, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x06, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x06, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH06) /* eject php slot 0x06 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x06, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH06) /* IN status as the _STA */
+                }
+            }
+
+            Device(S07)
             {
                 Name (_ADR, 0x00070000) /* Dev 7, Func 0 */
-                Name (_SUN, 0x00000002)
-
-                Method (_PS0, 0)
-                {
-                    Store (0x90, \_GPE.DPT2)
-                }
-
-                Method (_PS3, 0)
-                {
-                    Store (0x93, \_GPE.DPT2)
-                }
-
-                Method (_EJ0, 1)
-                {
-                    Store (0x98, \_GPE.DPT2)
-                    Store (0x1, \_GPE.PHP2) /* eject php slot 1*/
-                }
-
-                Method (_STA, 0)
-                {
-                    Store (0x99, \_GPE.DPT2)
-                    Return ( \_GPE.PHP2 )   /* IN status as the _STA */
+                Name (_SUN, 0x00000007)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x07, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x07, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x07, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH07) /* eject php slot 0x07 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x07, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH07) /* IN status as the _STA */
+                }
+            }
+
+            Device(S08)
+            {
+                Name (_ADR, 0x00080000) /* Dev 8, Func 0 */
+                Name (_SUN, 0x00000008)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x08, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x08, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x08, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH08) /* eject php slot 0x08 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x08, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH08) /* IN status as the _STA */
+                }
+            }
+
+            Device(S09)
+            {
+                Name (_ADR, 0x00090000) /* Dev 9, Func 0 */
+                Name (_SUN, 0x00000009)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x09, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x09, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x09, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH09) /* eject php slot 0x09 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x09, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH09) /* IN status as the _STA */
+                }
+            }
+
+            Device(S0A)
+            {
+                Name (_ADR, 0x000a0000) /* Dev 10, Func 0 */
+                Name (_SUN, 0x0000000a)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x0a, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x0a, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x0a, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH0A) /* eject php slot 0x0a */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x0a, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH0A) /* IN status as the _STA */
+                }
+            }
+
+            Device(S0B)
+            {
+                Name (_ADR, 0x000b0000) /* Dev 11, Func 0 */
+                Name (_SUN, 0x0000000b)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x0b, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x0b, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x0b, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH0B) /* eject php slot 0x0b */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x0b, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH0B) /* IN status as the _STA */
+                }
+            }
+
+            Device(S0C)
+            {
+                Name (_ADR, 0x000c0000) /* Dev 12, Func 0 */
+                Name (_SUN, 0x0000000c)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x0c, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x0c, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x0c, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH0C) /* eject php slot 0x0c */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x0c, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH0C) /* IN status as the _STA */
+                }
+            }
+
+            Device(S0D)
+            {
+                Name (_ADR, 0x000d0000) /* Dev 13, Func 0 */
+                Name (_SUN, 0x0000000d)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x0d, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x0d, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x0d, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH0D) /* eject php slot 0x0d */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x0d, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH0D) /* IN status as the _STA */
+                }
+            }
+
+            Device(S0E)
+            {
+                Name (_ADR, 0x000e0000) /* Dev 14, Func 0 */
+                Name (_SUN, 0x0000000e)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x0e, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x0e, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x0e, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH0E) /* eject php slot 0x0e */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x0e, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH0E) /* IN status as the _STA */
+                }
+            }
+
+            Device(S0F)
+            {
+                Name (_ADR, 0x000f0000) /* Dev 15, Func 0 */
+                Name (_SUN, 0x0000000f)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x0f, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x0f, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x0f, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH0F) /* eject php slot 0x0f */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x0f, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH0F) /* IN status as the _STA */
+                }
+            }
+
+            Device(S10)
+            {
+                Name (_ADR, 0x00100000) /* Dev 16, Func 0 */
+                Name (_SUN, 0x00000010)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x10, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x10, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x10, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH10) /* eject php slot 0x10 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x10, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH10) /* IN status as the _STA */
+                }
+            }
+
+            Device(S11)
+            {
+                Name (_ADR, 0x00110000) /* Dev 17, Func 0 */
+                Name (_SUN, 0x00000011)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x11, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x11, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x11, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH11) /* eject php slot 0x11 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x11, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH11) /* IN status as the _STA */
+                }
+            }
+
+            Device(S12)
+            {
+                Name (_ADR, 0x00120000) /* Dev 18, Func 0 */
+                Name (_SUN, 0x00000012)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x12, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x12, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x12, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH12) /* eject php slot 0x12 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x12, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH12) /* IN status as the _STA */
+                }
+            }
+
+            Device(S13)
+            {
+                Name (_ADR, 0x00130000) /* Dev 19, Func 0 */
+                Name (_SUN, 0x00000013)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x13, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x13, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x13, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH13) /* eject php slot 0x13 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x13, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH13) /* IN status as the _STA */
+                }
+            }
+
+            Device(S14)
+            {
+                Name (_ADR, 0x00140000) /* Dev 20, Func 0 */
+                Name (_SUN, 0x00000014)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x14, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x14, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x14, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH14) /* eject php slot 0x14 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x14, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH14) /* IN status as the _STA */
+                }
+            }
+
+            Device(S15)
+            {
+                Name (_ADR, 0x00150000) /* Dev 21, Func 0 */
+                Name (_SUN, 0x00000015)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x15, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x15, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x15, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH15) /* eject php slot 0x15 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x15, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH15) /* IN status as the _STA */
+                }
+            }
+
+            Device(S16)
+            {
+                Name (_ADR, 0x00160000) /* Dev 22, Func 0 */
+                Name (_SUN, 0x00000016)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x16, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x16, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x16, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH16) /* eject php slot 0x16 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x16, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH16) /* IN status as the _STA */
+                }
+            }
+
+            Device(S17)
+            {
+                Name (_ADR, 0x00170000) /* Dev 23, Func 0 */
+                Name (_SUN, 0x00000017)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x17, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x17, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x17, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH17) /* eject php slot 0x17 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x17, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH17) /* IN status as the _STA */
+                }
+            }
+
+            Device(S18)
+            {
+                Name (_ADR, 0x00180000) /* Dev 24, Func 0 */
+                Name (_SUN, 0x00000018)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x18, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x18, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x18, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH18) /* eject php slot 0x18 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x18, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH18) /* IN status as the _STA */
+                }
+            }
+
+            Device(S19)
+            {
+                Name (_ADR, 0x00190000) /* Dev 25, Func 0 */
+                Name (_SUN, 0x00000019)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x19, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x19, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x19, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH19) /* eject php slot 0x19 */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x19, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH19) /* IN status as the _STA */
+                }
+            }
+
+            Device(S1A)
+            {
+                Name (_ADR, 0x001a0000) /* Dev 26, Func 0 */
+                Name (_SUN, 0x0000001a)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x1a, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x1a, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x1a, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH1A) /* eject php slot 0x1a */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x1a, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH1A) /* IN status as the _STA */
+                }
+            }
+
+            Device(S1B)
+            {
+                Name (_ADR, 0x001b0000) /* Dev 27, Func 0 */
+                Name (_SUN, 0x0000001b)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x1b, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x1b, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x1b, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH1B) /* eject php slot 0x1b */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x1b, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH1B) /* IN status as the _STA */
+                }
+            }
+
+            Device(S1C)
+            {
+                Name (_ADR, 0x001c0000) /* Dev 28, Func 0 */
+                Name (_SUN, 0x0000001c)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x1c, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x1c, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x1c, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH1C) /* eject php slot 0x1c */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x1c, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH1C) /* IN status as the _STA */
+                }
+            }
+
+            Device(S1D)
+            {
+                Name (_ADR, 0x001d0000) /* Dev 29, Func 0 */
+                Name (_SUN, 0x0000001d)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x1d, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x1d, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x1d, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH1D) /* eject php slot 0x1d */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x1d, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH1D) /* IN status as the _STA */
+                }
+            }
+
+            Device(S1E)
+            {
+                Name (_ADR, 0x001e0000) /* Dev 30, Func 0 */
+                Name (_SUN, 0x0000001e)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x1e, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x1e, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x1e, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH1E) /* eject php slot 0x1e */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x1e, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH1E) /* IN status as the _STA */
+                }
+            }
+
+            Device(S1F)
+            {
+                Name (_ADR, 0x001f0000) /* Dev 31, Func 0 */
+                Name (_SUN, 0x0000001f)
+
+                Method (_PS0, 0)
+                {
+                    Store (0x1f, \_GPE.DPT1)
+                    Store (0x80, \_GPE.DPT2)
+                }
+
+                Method (_PS3, 0)
+                {
+                    Store (0x1f, \_GPE.DPT1)
+                    Store (0x83, \_GPE.DPT2)
+                }
+
+                Method (_EJ0, 1)
+                {
+                    Store (0x1f, \_GPE.DPT1)
+                    Store (0x88, \_GPE.DPT2)
+                    Store (0x1, \_GPE.PH1F) /* eject php slot 0x1f */
+                }
+
+                Method (_STA, 0)
+                {
+                    Store (0x1f, \_GPE.DPT1)
+                    Store (0x89, \_GPE.DPT2)
+                    Return (\_GPE.PH1F) /* IN status as the _STA */
                 }
             }
         }
@@ -1042,39 +2009,162 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, 
 
     Scope (\_GPE)
     {
-        OperationRegion (PHP, SystemIO, 0x10c0, 0x03)
+        OperationRegion (PHP, SystemIO, 0x10c0, 0x22)
         Field (PHP, ByteAcc, NoLock, Preserve)
         {
-            PSTA,   8, /* hotplug controller status reg */
-            PHP1,   8, /* hotplug slot 1 control reg */
-            PHP2,   8  /* hotplug slot 2 control reg */
-        }
+            PSTA,  8, /* hotplug controller event reg */
+            PSTB,  8, /* hotplug controller slot  reg */
+            PH00,  8, /* hotplug slot 0x00 control reg */
+            PH01,  8, /* hotplug slot 0x01 control reg */
+            PH02,  8, /* hotplug slot 0x02 control reg */
+            PH03,  8, /* hotplug slot 0x03 control reg */
+            PH04,  8, /* hotplug slot 0x04 control reg */
+            PH05,  8, /* hotplug slot 0x05 control reg */
+            PH06,  8, /* hotplug slot 0x06 control reg */
+            PH07,  8, /* hotplug slot 0x07 control reg */
+            PH08,  8, /* hotplug slot 0x08 control reg */
+            PH09,  8, /* hotplug slot 0x09 control reg */
+            PH0A,  8, /* hotplug slot 0x0a control reg */
+            PH0B,  8, /* hotplug slot 0x0b control reg */
+            PH0C,  8, /* hotplug slot 0x0c control reg */
+            PH0D,  8, /* hotplug slot 0x0d control reg */
+            PH0E,  8, /* hotplug slot 0x0e control reg */
+            PH0F,  8, /* hotplug slot 0x0f control reg */
+            PH10,  8, /* hotplug slot 0x10 control reg */
+            PH11,  8, /* hotplug slot 0x11 control reg */
+            PH12,  8, /* hotplug slot 0x12 control reg */
+            PH13,  8, /* hotplug slot 0x13 control reg */
+            PH14,  8, /* hotplug slot 0x14 control reg */
+            PH15,  8, /* hotplug slot 0x15 control reg */
+            PH16,  8, /* hotplug slot 0x16 control reg */
+            PH17,  8, /* hotplug slot 0x17 control reg */
+            PH18,  8, /* hotplug slot 0x18 control reg */
+            PH19,  8, /* hotplug slot 0x19 control reg */
+            PH1A,  8, /* hotplug slot 0x1a control reg */
+            PH1B,  8, /* hotplug slot 0x1b control reg */
+            PH1C,  8, /* hotplug slot 0x1c control reg */
+            PH1D,  8, /* hotplug slot 0x1d control reg */
+            PH1E,  8, /* hotplug slot 0x1e control reg */
+            PH1F,  8  /* hotplug slot 0x1f control reg */
+       }
         OperationRegion (DG1, SystemIO, 0xb044, 0x04)
         Field (DG1, ByteAcc, NoLock, Preserve)
         {
             DPT1,   8,
             DPT2,   8
         }
-        Method (_L03, 0, NotSerialized)
+        Method (_L03, 0, Serialized)
         {
             /* detect slot and event(remove/add) */
             Name (SLT, 0x0)
             Name (EVT, 0x0)
             Store (PSTA, Local1)
-            ShiftRight (Local1, 0x4, SLT)
             And (Local1, 0xf, EVT)
+            Store (PSTB, Local1)           /* XXX: Store (PSTB, SLT) ? */
+            And (Local1, 0xff, SLT)
 
             /* debug */
             Store (SLT, DPT1)
             Store (EVT, DPT2)
 
-            If ( LEqual(SLT, 0x1) )
-            {
-                Notify (\_SB.PCI0.S1F0, EVT)
-            }
-            ElseIf ( LEqual(SLT, 0x2) )
-            {
-                Notify (\_SB.PCI0.S2F0, EVT)
+            Switch (SLT)
+            {
+                Case (0x00) {
+                    Notify (\_SB.PCI0.S00, EVT)
+                }
+                Case (0x01) {
+                    Notify (\_SB.PCI0.S01, EVT)
+                }
+                Case (0x02) {
+                    Notify (\_SB.PCI0.S02, EVT)
+                }
+                Case (0x03) {
+                    Notify (\_SB.PCI0.S03, EVT)
+                }
+                Case (0x04) {
+                    Notify (\_SB.PCI0.S04, EVT)
+                }
+                Case (0x05) {
+                    Notify (\_SB.PCI0.S05, EVT)
+                }
+                Case (0x06) {
+                    Notify (\_SB.PCI0.S06, EVT)
+                }
+                Case (0x07) {
+                    Notify (\_SB.PCI0.S07, EVT)
+                }
+                Case (0x08) {
+                    Notify (\_SB.PCI0.S08, EVT)
+                }
+                Case (0x09) {
+                    Notify (\_SB.PCI0.S09, EVT)
+                }
+                Case (0x0a) {
+                    Notify (\_SB.PCI0.S0A, EVT)
+                }
+                Case (0x0b) {
+                    Notify (\_SB.PCI0.S0B, EVT)
+                }
+                Case (0x0c) {
+                    Notify (\_SB.PCI0.S0C, EVT)
+                }
+                Case (0x0d) {
+                    Notify (\_SB.PCI0.S0D, EVT)
+                }
+                Case (0x0e) {
+                    Notify (\_SB.PCI0.S0E, EVT)
+                }
+                Case (0x0f) {
+                    Notify (\_SB.PCI0.S0F, EVT)
+                }
+                Case (0x10) {
+                    Notify (\_SB.PCI0.S10, EVT)
+                }
+                Case (0x11) {
+                    Notify (\_SB.PCI0.S11, EVT)
+                }
+                Case (0x12) {
+                    Notify (\_SB.PCI0.S12, EVT)
+                }
+                Case (0x13) {
+                    Notify (\_SB.PCI0.S13, EVT)
+                }
+                Case (0x14) {
+                    Notify (\_SB.PCI0.S14, EVT)
+                }
+                Case (0x15) {
+                    Notify (\_SB.PCI0.S15, EVT)
+                }
+                Case (0x16) {
+                    Notify (\_SB.PCI0.S16, EVT)
+                }
+                Case (0x17) {
+                    Notify (\_SB.PCI0.S17, EVT)
+                }
+                Case (0x18) {
+                    Notify (\_SB.PCI0.S18, EVT)
+                }
+                Case (0x19) {
+                    Notify (\_SB.PCI0.S19, EVT)
+                }
+                Case (0x1a) {
+                    Notify (\_SB.PCI0.S1A, EVT)
+                }
+                Case (0x1b) {
+                    Notify (\_SB.PCI0.S1B, EVT)
+                }
+                Case (0x1c) {
+                    Notify (\_SB.PCI0.S1C, EVT)
+                }
+                Case (0x1d) {
+                    Notify (\_SB.PCI0.S1D, EVT)
+                }
+                Case (0x1e) {
+                    Notify (\_SB.PCI0.S1E, EVT)
+                }
+                Case (0x1f) {
+                    Notify (\_SB.PCI0.S1F, EVT)
+                }
             }
         }
     }
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/hvmloader/acpi/dsdt.c
--- a/tools/firmware/hvmloader/acpi/dsdt.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/hvmloader/acpi/dsdt.c      Fri Mar 27 11:07:11 2009 +0900
@@ -5,15 +5,15 @@
  * Copyright (C) 2000 - 2009 Intel Corporation
  * Supports ACPI Specification Revision 3.0a
  * 
- * Compilation of "dsdt.asl" - Mon Mar  9 09:11:00 2009
+ * Compilation of "dsdt.asl" - Tue Mar 17 10:44:21 2009
  * 
  * C source code output
  *
  */
 unsigned char AmlCode[] =
 {
-    0x44,0x53,0x44,0x54,0x20,0x18,0x00,0x00,  /* 00000000    "DSDT ..." */
-    0x02,0x5B,0x58,0x65,0x6E,0x00,0x00,0x00,  /* 00000008    ".[Xen..." */
+    0x44,0x53,0x44,0x54,0x02,0x32,0x00,0x00,  /* 00000000    "DSDT.2.." */
+    0x02,0xC6,0x58,0x65,0x6E,0x00,0x00,0x00,  /* 00000008    "..Xen..." */
     0x48,0x56,0x4D,0x00,0x00,0x00,0x00,0x00,  /* 00000010    "HVM....." */
     0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
     0x20,0x02,0x09,0x20,0x08,0x50,0x4D,0x42,  /* 00000020    " .. .PMB" */
@@ -56,7 +56,7 @@ unsigned char AmlCode[] =
     0x07,0x0A,0x07,0x00,0x00,0x08,0x50,0x49,  /* 00000148    "......PI" */
     0x43,0x44,0x00,0x14,0x0C,0x5F,0x50,0x49,  /* 00000150    "CD..._PI" */
     0x43,0x01,0x70,0x68,0x50,0x49,0x43,0x44,  /* 00000158    "C.phPICD" */
-    0x10,0x80,0x60,0x01,0x5F,0x53,0x42,0x5F,  /* 00000160    "..`._SB_" */
+    0x10,0x83,0xB7,0x02,0x5F,0x53,0x42,0x5F,  /* 00000160    "...._SB_" */
     0x5B,0x80,0x42,0x49,0x4F,0x53,0x00,0x0C,  /* 00000168    "[.BIOS.." */
     0x00,0xA0,0x0E,0x00,0x0A,0x10,0x5B,0x81,  /* 00000170    "......[." */
     0x21,0x42,0x49,0x4F,0x53,0x01,0x55,0x41,  /* 00000178    "!BIOS.UA" */
@@ -72,8 +72,8 @@ unsigned char AmlCode[] =
     0x00,0x00,0xFF,0xFF,0x09,0x00,0x00,0x00,  /* 000001C8    "........" */
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 000001D0    "........" */
     0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,  /* 000001D8    "........" */
-    0x00,0x00,0x79,0x00,0x5B,0x82,0x8B,0x57,  /* 000001E0    "..y.[..W" */
-    0x01,0x50,0x43,0x49,0x30,0x08,0x5F,0x48,  /* 000001E8    ".PCI0._H" */
+    0x00,0x00,0x79,0x00,0x5B,0x82,0x8E,0xAE,  /* 000001E0    "..y.[..." */
+    0x02,0x50,0x43,0x49,0x30,0x08,0x5F,0x48,  /* 000001E8    ".PCI0._H" */
     0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03,0x08,  /* 000001F0    "ID.A...." */
     0x5F,0x55,0x49,0x44,0x00,0x08,0x5F,0x41,  /* 000001F8    "_UID.._A" */
     0x44,0x52,0x00,0x08,0x5F,0x42,0x42,0x4E,  /* 00000200    "DR.._BBN" */
@@ -728,62 +728,890 @@ unsigned char AmlCode[] =
     0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,  /* 00001648    "....._CR" */
     0x53,0x11,0x10,0x0A,0x0D,0x47,0x01,0x78,  /* 00001650    "S....G.x" */
     0x03,0x78,0x03,0x08,0x08,0x22,0x80,0x00,  /* 00001658    ".x...".." */
-    0x79,0x00,0x5B,0x82,0x4D,0x07,0x53,0x31,  /* 00001660    "y.[.M.S1" */
-    0x46,0x30,0x08,0x5F,0x41,0x44,0x52,0x0C,  /* 00001668    "F0._ADR." */
-    0x00,0x00,0x06,0x00,0x08,0x5F,0x53,0x55,  /* 00001670    "....._SU" */
-    0x4E,0x01,0x14,0x13,0x5F,0x50,0x53,0x30,  /* 00001678    "N..._PS0" */
-    0x00,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001680    ".p..\._G" */
-    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x13,  /* 00001688    "PEDPT2.." */
-    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x83,  /* 00001690    "_PS3.p.." */
-    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001698    "\._GPEDP" */
-    0x54,0x32,0x14,0x1F,0x5F,0x45,0x4A,0x30,  /* 000016A0    "T2.._EJ0" */
-    0x01,0x70,0x0A,0x88,0x5C,0x2E,0x5F,0x47,  /* 000016A8    ".p..\._G" */
-    0x50,0x45,0x44,0x50,0x54,0x32,0x70,0x01,  /* 000016B0    "PEDPT2p." */
-    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x50,0x48,  /* 000016B8    "\._GPEPH" */
-    0x50,0x31,0x14,0x1E,0x5F,0x53,0x54,0x41,  /* 000016C0    "P1.._STA" */
-    0x00,0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,  /* 000016C8    ".p..\._G" */
-    0x50,0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,  /* 000016D0    "PEDPT2.\" */
-    0x2E,0x5F,0x47,0x50,0x45,0x50,0x48,0x50,  /* 000016D8    "._GPEPHP" */
-    0x31,0x5B,0x82,0x4E,0x07,0x53,0x32,0x46,  /* 000016E0    "1[.N.S2F" */
-    0x30,0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,  /* 000016E8    "0._ADR.." */
-    0x00,0x07,0x00,0x08,0x5F,0x53,0x55,0x4E,  /* 000016F0    "...._SUN" */
-    0x0A,0x02,0x14,0x13,0x5F,0x50,0x53,0x30,  /* 000016F8    "...._PS0" */
-    0x00,0x70,0x0A,0x90,0x5C,0x2E,0x5F,0x47,  /* 00001700    ".p..\._G" */
-    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x13,  /* 00001708    "PEDPT2.." */
-    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x93,  /* 00001710    "_PS3.p.." */
-    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001718    "\._GPEDP" */
-    0x54,0x32,0x14,0x1F,0x5F,0x45,0x4A,0x30,  /* 00001720    "T2.._EJ0" */
-    0x01,0x70,0x0A,0x98,0x5C,0x2E,0x5F,0x47,  /* 00001728    ".p..\._G" */
-    0x50,0x45,0x44,0x50,0x54,0x32,0x70,0x01,  /* 00001730    "PEDPT2p." */
-    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x50,0x48,  /* 00001738    "\._GPEPH" */
-    0x50,0x32,0x14,0x1E,0x5F,0x53,0x54,0x41,  /* 00001740    "P2.._STA" */
-    0x00,0x70,0x0A,0x99,0x5C,0x2E,0x5F,0x47,  /* 00001748    ".p..\._G" */
-    0x50,0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,  /* 00001750    "PEDPT2.\" */
-    0x2E,0x5F,0x47,0x50,0x45,0x50,0x48,0x50,  /* 00001758    "._GPEPHP" */
-    0x32,0x10,0x4E,0x0B,0x5F,0x47,0x50,0x45,  /* 00001760    "2.N._GPE" */
-    0x5B,0x80,0x50,0x48,0x50,0x5F,0x01,0x0B,  /* 00001768    "[.PHP_.." */
-    0xC0,0x10,0x0A,0x03,0x5B,0x81,0x15,0x50,  /* 00001770    "....[..P" */
-    0x48,0x50,0x5F,0x01,0x50,0x53,0x54,0x41,  /* 00001778    "HP_.PSTA" */
-    0x08,0x50,0x48,0x50,0x31,0x08,0x50,0x48,  /* 00001780    ".PHP1.PH" */
-    0x50,0x32,0x08,0x5B,0x80,0x44,0x47,0x31,  /* 00001788    "P2.[.DG1" */
-    0x5F,0x01,0x0B,0x44,0xB0,0x0A,0x04,0x5B,  /* 00001790    "_..D...[" */
-    0x81,0x10,0x44,0x47,0x31,0x5F,0x01,0x44,  /* 00001798    "..DG1_.D" */
-    0x50,0x54,0x31,0x08,0x44,0x50,0x54,0x32,  /* 000017A0    "PT1.DPT2" */
-    0x08,0x14,0x46,0x07,0x5F,0x4C,0x30,0x33,  /* 000017A8    "..F._L03" */
-    0x00,0x08,0x53,0x4C,0x54,0x5F,0x00,0x08,  /* 000017B0    "..SLT_.." */
-    0x45,0x56,0x54,0x5F,0x00,0x70,0x50,0x53,  /* 000017B8    "EVT_.pPS" */
-    0x54,0x41,0x61,0x7A,0x61,0x0A,0x04,0x53,  /* 000017C0    "TAaza..S" */
-    0x4C,0x54,0x5F,0x7B,0x61,0x0A,0x0F,0x45,  /* 000017C8    "LT_{a..E" */
-    0x56,0x54,0x5F,0x70,0x53,0x4C,0x54,0x5F,  /* 000017D0    "VT_pSLT_" */
-    0x44,0x50,0x54,0x31,0x70,0x45,0x56,0x54,  /* 000017D8    "DPT1pEVT" */
-    0x5F,0x44,0x50,0x54,0x32,0xA0,0x1B,0x93,  /* 000017E0    "_DPT2..." */
-    0x53,0x4C,0x54,0x5F,0x01,0x86,0x5C,0x2F,  /* 000017E8    "SLT_..\/" */
-    0x03,0x5F,0x53,0x42,0x5F,0x50,0x43,0x49,  /* 000017F0    "._SB_PCI" */
-    0x30,0x53,0x31,0x46,0x30,0x45,0x56,0x54,  /* 000017F8    "0S1F0EVT" */
-    0x5F,0xA1,0x1E,0xA0,0x1C,0x93,0x53,0x4C,  /* 00001800    "_.....SL" */
-    0x54,0x5F,0x0A,0x02,0x86,0x5C,0x2F,0x03,  /* 00001808    "T_...\/." */
-    0x5F,0x53,0x42,0x5F,0x50,0x43,0x49,0x30,  /* 00001810    "_SB_PCI0" */
-    0x53,0x32,0x46,0x30,0x45,0x56,0x54,0x5F,  /* 00001818    "S2F0EVT_" */
-
+    0x79,0x00,0x5B,0x82,0x49,0x0A,0x53,0x30,  /* 00001660    "y.[.I.S0" */
+    0x30,0x5F,0x08,0x5F,0x41,0x44,0x52,0x00,  /* 00001668    "0_._ADR." */
+    0x08,0x5F,0x53,0x55,0x4E,0x00,0x14,0x1F,  /* 00001670    "._SUN..." */
+    0x5F,0x50,0x53,0x30,0x00,0x70,0x00,0x5C,  /* 00001678    "_PS0.p.\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001680    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001688    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x1F,  /* 00001690    "PEDPT2.." */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x00,0x5C,  /* 00001698    "_PS3.p.\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000016A0    "._GPEDPT" */
+    0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,0x47,  /* 000016A8    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x2B,  /* 000016B0    "PEDPT2.+" */
+    0x5F,0x45,0x4A,0x30,0x01,0x70,0x00,0x5C,  /* 000016B8    "_EJ0.p.\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000016C0    "._GPEDPT" */
+    0x31,0x70,0x0A,0x88,0x5C,0x2E,0x5F,0x47,  /* 000016C8    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x70,0x01,  /* 000016D0    "PEDPT2p." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x50,0x48,  /* 000016D8    "\._GPEPH" */
+    0x30,0x30,0x14,0x2A,0x5F,0x53,0x54,0x41,  /* 000016E0    "00.*_STA" */
+    0x00,0x70,0x00,0x5C,0x2E,0x5F,0x47,0x50,  /* 000016E8    ".p.\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x89,  /* 000016F0    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000016F8    "\._GPEDP" */
+    0x54,0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001700    "T2.\._GP" */
+    0x45,0x50,0x48,0x30,0x30,0x5B,0x82,0x4D,  /* 00001708    "EPH00[.M" */
+    0x0A,0x53,0x30,0x31,0x5F,0x08,0x5F,0x41,  /* 00001710    ".S01_._A" */
+    0x44,0x52,0x0C,0x00,0x00,0x01,0x00,0x08,  /* 00001718    "DR......" */
+    0x5F,0x53,0x55,0x4E,0x01,0x14,0x1F,0x5F,  /* 00001720    "_SUN..._" */
+    0x50,0x53,0x30,0x00,0x70,0x01,0x5C,0x2E,  /* 00001728    "PS0.p.\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001730    "_GPEDPT1" */
+    0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001738    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0x14,0x1F,0x5F,  /* 00001740    "EDPT2.._" */
+    0x50,0x53,0x33,0x00,0x70,0x01,0x5C,0x2E,  /* 00001748    "PS3.p.\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001750    "_GPEDPT1" */
+    0x70,0x0A,0x83,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001758    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0x14,0x2B,0x5F,  /* 00001760    "EDPT2.+_" */
+    0x45,0x4A,0x30,0x01,0x70,0x01,0x5C,0x2E,  /* 00001768    "EJ0.p.\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001770    "_GPEDPT1" */
+    0x70,0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001778    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0x70,0x01,0x5C,  /* 00001780    "EDPT2p.\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x50,0x48,0x30,  /* 00001788    "._GPEPH0" */
+    0x31,0x14,0x2A,0x5F,0x53,0x54,0x41,0x00,  /* 00001790    "1.*_STA." */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001798    "p.\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 000017A0    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000017A8    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000017B0    "2.\._GPE" */
+    0x50,0x48,0x30,0x31,0x5B,0x82,0x42,0x0B,  /* 000017B8    "PH01[.B." */
+    0x53,0x30,0x32,0x5F,0x08,0x5F,0x41,0x44,  /* 000017C0    "S02_._AD" */
+    0x52,0x0C,0x00,0x00,0x02,0x00,0x08,0x5F,  /* 000017C8    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x02,0x14,0x20,0x5F,  /* 000017D0    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x02,0x5C,  /* 000017D8    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000017E0    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 000017E8    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 000017F0    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x02,  /* 000017F8    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001800    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00001808    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00001810    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00001818    ",_EJ0.p." */
+    0x02,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001820    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00001828    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00001830    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001838    "p.\._GPE" */
+    0x50,0x48,0x30,0x32,0x14,0x2B,0x5F,0x53,  /* 00001840    "PH02.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x02,0x5C,0x2E,  /* 00001848    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001850    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001858    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00001860    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x32,  /* 00001868    "_GPEPH02" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x33,0x5F,  /* 00001870    "[.B.S03_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00001878    "._ADR..." */
+    0x03,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00001880    "..._SUN." */
+    0x03,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00001888    ".. _PS0." */
+    0x70,0x0A,0x03,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001890    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00001898    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000018A0    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 000018A8    "T2. _PS3" */
+    0x00,0x70,0x0A,0x03,0x5C,0x2E,0x5F,0x47,  /* 000018B0    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 000018B8    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 000018C0    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 000018C8    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x03,0x5C,0x2E,0x5F,  /* 000018D0    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 000018D8    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000018E0    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 000018E8    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x33,  /* 000018F0    "_GPEPH03" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 000018F8    ".+_STA.p" */
+    0x0A,0x03,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001900    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00001908    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001910    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001918    "2.\._GPE" */
+    0x50,0x48,0x30,0x33,0x5B,0x82,0x42,0x0B,  /* 00001920    "PH03[.B." */
+    0x53,0x30,0x34,0x5F,0x08,0x5F,0x41,0x44,  /* 00001928    "S04_._AD" */
+    0x52,0x0C,0x00,0x00,0x04,0x00,0x08,0x5F,  /* 00001930    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x04,0x14,0x20,0x5F,  /* 00001938    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x04,0x5C,  /* 00001940    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001948    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001950    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00001958    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x04,  /* 00001960    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001968    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00001970    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00001978    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00001980    ",_EJ0.p." */
+    0x04,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001988    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00001990    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00001998    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000019A0    "p.\._GPE" */
+    0x50,0x48,0x30,0x34,0x14,0x2B,0x5F,0x53,  /* 000019A8    "PH04.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x04,0x5C,0x2E,  /* 000019B0    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 000019B8    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 000019C0    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 000019C8    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x34,  /* 000019D0    "_GPEPH04" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x35,0x5F,  /* 000019D8    "[.B.S05_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 000019E0    "._ADR..." */
+    0x05,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 000019E8    "..._SUN." */
+    0x05,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 000019F0    ".. _PS0." */
+    0x70,0x0A,0x05,0x5C,0x2E,0x5F,0x47,0x50,  /* 000019F8    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00001A00    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001A08    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00001A10    "T2. _PS3" */
+    0x00,0x70,0x0A,0x05,0x5C,0x2E,0x5F,0x47,  /* 00001A18    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00001A20    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001A28    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00001A30    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x05,0x5C,0x2E,0x5F,  /* 00001A38    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00001A40    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001A48    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00001A50    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x35,  /* 00001A58    "_GPEPH05" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00001A60    ".+_STA.p" */
+    0x0A,0x05,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001A68    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00001A70    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001A78    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001A80    "2.\._GPE" */
+    0x50,0x48,0x30,0x35,0x5B,0x82,0x42,0x0B,  /* 00001A88    "PH05[.B." */
+    0x53,0x30,0x36,0x5F,0x08,0x5F,0x41,0x44,  /* 00001A90    "S06_._AD" */
+    0x52,0x0C,0x00,0x00,0x06,0x00,0x08,0x5F,  /* 00001A98    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x06,0x14,0x20,0x5F,  /* 00001AA0    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x06,0x5C,  /* 00001AA8    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001AB0    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001AB8    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00001AC0    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x06,  /* 00001AC8    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001AD0    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00001AD8    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00001AE0    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00001AE8    ",_EJ0.p." */
+    0x06,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001AF0    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00001AF8    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00001B00    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001B08    "p.\._GPE" */
+    0x50,0x48,0x30,0x36,0x14,0x2B,0x5F,0x53,  /* 00001B10    "PH06.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x06,0x5C,0x2E,  /* 00001B18    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001B20    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001B28    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00001B30    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x36,  /* 00001B38    "_GPEPH06" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x37,0x5F,  /* 00001B40    "[.B.S07_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00001B48    "._ADR..." */
+    0x07,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00001B50    "..._SUN." */
+    0x07,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00001B58    ".. _PS0." */
+    0x70,0x0A,0x07,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001B60    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00001B68    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001B70    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00001B78    "T2. _PS3" */
+    0x00,0x70,0x0A,0x07,0x5C,0x2E,0x5F,0x47,  /* 00001B80    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00001B88    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001B90    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00001B98    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x07,0x5C,0x2E,0x5F,  /* 00001BA0    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00001BA8    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001BB0    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00001BB8    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x37,  /* 00001BC0    "_GPEPH07" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00001BC8    ".+_STA.p" */
+    0x0A,0x07,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001BD0    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00001BD8    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001BE0    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001BE8    "2.\._GPE" */
+    0x50,0x48,0x30,0x37,0x5B,0x82,0x42,0x0B,  /* 00001BF0    "PH07[.B." */
+    0x53,0x30,0x38,0x5F,0x08,0x5F,0x41,0x44,  /* 00001BF8    "S08_._AD" */
+    0x52,0x0C,0x00,0x00,0x08,0x00,0x08,0x5F,  /* 00001C00    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x08,0x14,0x20,0x5F,  /* 00001C08    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x08,0x5C,  /* 00001C10    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001C18    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001C20    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00001C28    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x08,  /* 00001C30    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001C38    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00001C40    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00001C48    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00001C50    ",_EJ0.p." */
+    0x08,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001C58    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00001C60    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00001C68    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001C70    "p.\._GPE" */
+    0x50,0x48,0x30,0x38,0x14,0x2B,0x5F,0x53,  /* 00001C78    "PH08.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x08,0x5C,0x2E,  /* 00001C80    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001C88    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001C90    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00001C98    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x38,  /* 00001CA0    "_GPEPH08" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x39,0x5F,  /* 00001CA8    "[.B.S09_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00001CB0    "._ADR..." */
+    0x09,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00001CB8    "..._SUN." */
+    0x09,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00001CC0    ".. _PS0." */
+    0x70,0x0A,0x09,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001CC8    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00001CD0    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001CD8    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00001CE0    "T2. _PS3" */
+    0x00,0x70,0x0A,0x09,0x5C,0x2E,0x5F,0x47,  /* 00001CE8    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00001CF0    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001CF8    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00001D00    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x09,0x5C,0x2E,0x5F,  /* 00001D08    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00001D10    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001D18    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00001D20    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x39,  /* 00001D28    "_GPEPH09" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00001D30    ".+_STA.p" */
+    0x0A,0x09,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001D38    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00001D40    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001D48    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001D50    "2.\._GPE" */
+    0x50,0x48,0x30,0x39,0x5B,0x82,0x42,0x0B,  /* 00001D58    "PH09[.B." */
+    0x53,0x30,0x41,0x5F,0x08,0x5F,0x41,0x44,  /* 00001D60    "S0A_._AD" */
+    0x52,0x0C,0x00,0x00,0x0A,0x00,0x08,0x5F,  /* 00001D68    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x0A,0x14,0x20,0x5F,  /* 00001D70    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x0A,0x5C,  /* 00001D78    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001D80    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001D88    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00001D90    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x0A,  /* 00001D98    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001DA0    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00001DA8    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00001DB0    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00001DB8    ",_EJ0.p." */
+    0x0A,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001DC0    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00001DC8    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00001DD0    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001DD8    "p.\._GPE" */
+    0x50,0x48,0x30,0x41,0x14,0x2B,0x5F,0x53,  /* 00001DE0    "PH0A.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x0A,0x5C,0x2E,  /* 00001DE8    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001DF0    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001DF8    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00001E00    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x41,  /* 00001E08    "_GPEPH0A" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x42,0x5F,  /* 00001E10    "[.B.S0B_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00001E18    "._ADR..." */
+    0x0B,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00001E20    "..._SUN." */
+    0x0B,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00001E28    ".. _PS0." */
+    0x70,0x0A,0x0B,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001E30    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00001E38    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001E40    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00001E48    "T2. _PS3" */
+    0x00,0x70,0x0A,0x0B,0x5C,0x2E,0x5F,0x47,  /* 00001E50    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00001E58    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001E60    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00001E68    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x0B,0x5C,0x2E,0x5F,  /* 00001E70    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00001E78    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001E80    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00001E88    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x42,  /* 00001E90    "_GPEPH0B" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00001E98    ".+_STA.p" */
+    0x0A,0x0B,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001EA0    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00001EA8    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001EB0    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001EB8    "2.\._GPE" */
+    0x50,0x48,0x30,0x42,0x5B,0x82,0x42,0x0B,  /* 00001EC0    "PH0B[.B." */
+    0x53,0x30,0x43,0x5F,0x08,0x5F,0x41,0x44,  /* 00001EC8    "S0C_._AD" */
+    0x52,0x0C,0x00,0x00,0x0C,0x00,0x08,0x5F,  /* 00001ED0    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x0C,0x14,0x20,0x5F,  /* 00001ED8    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x0C,0x5C,  /* 00001EE0    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00001EE8    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00001EF0    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00001EF8    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x0C,  /* 00001F00    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001F08    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00001F10    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00001F18    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00001F20    ",_EJ0.p." */
+    0x0C,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001F28    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00001F30    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00001F38    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001F40    "p.\._GPE" */
+    0x50,0x48,0x30,0x43,0x14,0x2B,0x5F,0x53,  /* 00001F48    "PH0C.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x0C,0x5C,0x2E,  /* 00001F50    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00001F58    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001F60    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00001F68    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x43,  /* 00001F70    "_GPEPH0C" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x44,0x5F,  /* 00001F78    "[.B.S0D_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00001F80    "._ADR..." */
+    0x0D,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00001F88    "..._SUN." */
+    0x0D,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00001F90    ".. _PS0." */
+    0x70,0x0A,0x0D,0x5C,0x2E,0x5F,0x47,0x50,  /* 00001F98    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00001FA0    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00001FA8    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00001FB0    "T2. _PS3" */
+    0x00,0x70,0x0A,0x0D,0x5C,0x2E,0x5F,0x47,  /* 00001FB8    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00001FC0    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00001FC8    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00001FD0    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x0D,0x5C,0x2E,0x5F,  /* 00001FD8    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00001FE0    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00001FE8    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00001FF0    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x44,  /* 00001FF8    "_GPEPH0D" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002000    ".+_STA.p" */
+    0x0A,0x0D,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002008    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002010    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002018    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002020    "2.\._GPE" */
+    0x50,0x48,0x30,0x44,0x5B,0x82,0x42,0x0B,  /* 00002028    "PH0D[.B." */
+    0x53,0x30,0x45,0x5F,0x08,0x5F,0x41,0x44,  /* 00002030    "S0E_._AD" */
+    0x52,0x0C,0x00,0x00,0x0E,0x00,0x08,0x5F,  /* 00002038    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x0E,0x14,0x20,0x5F,  /* 00002040    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x0E,0x5C,  /* 00002048    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002050    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00002058    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002060    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x0E,  /* 00002068    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002070    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00002078    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00002080    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00002088    ",_EJ0.p." */
+    0x0E,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002090    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002098    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 000020A0    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000020A8    "p.\._GPE" */
+    0x50,0x48,0x30,0x45,0x14,0x2B,0x5F,0x53,  /* 000020B0    "PH0E.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x0E,0x5C,0x2E,  /* 000020B8    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 000020C0    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 000020C8    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 000020D0    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x45,  /* 000020D8    "_GPEPH0E" */
+    0x5B,0x82,0x42,0x0B,0x53,0x30,0x46,0x5F,  /* 000020E0    "[.B.S0F_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 000020E8    "._ADR..." */
+    0x0F,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 000020F0    "..._SUN." */
+    0x0F,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 000020F8    ".. _PS0." */
+    0x70,0x0A,0x0F,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002100    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002108    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002110    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002118    "T2. _PS3" */
+    0x00,0x70,0x0A,0x0F,0x5C,0x2E,0x5F,0x47,  /* 00002120    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002128    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002130    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00002138    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x0F,0x5C,0x2E,0x5F,  /* 00002140    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00002148    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002150    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00002158    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x30,0x46,  /* 00002160    "_GPEPH0F" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002168    ".+_STA.p" */
+    0x0A,0x0F,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002170    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002178    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002180    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002188    "2.\._GPE" */
+    0x50,0x48,0x30,0x46,0x5B,0x82,0x42,0x0B,  /* 00002190    "PH0F[.B." */
+    0x53,0x31,0x30,0x5F,0x08,0x5F,0x41,0x44,  /* 00002198    "S10_._AD" */
+    0x52,0x0C,0x00,0x00,0x10,0x00,0x08,0x5F,  /* 000021A0    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x10,0x14,0x20,0x5F,  /* 000021A8    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x10,0x5C,  /* 000021B0    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000021B8    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 000021C0    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 000021C8    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x10,  /* 000021D0    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000021D8    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 000021E0    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 000021E8    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 000021F0    ",_EJ0.p." */
+    0x10,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 000021F8    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002200    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00002208    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002210    "p.\._GPE" */
+    0x50,0x48,0x31,0x30,0x14,0x2B,0x5F,0x53,  /* 00002218    "PH10.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x10,0x5C,0x2E,  /* 00002220    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00002228    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002230    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00002238    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x30,  /* 00002240    "_GPEPH10" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x31,0x5F,  /* 00002248    "[.B.S11_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00002250    "._ADR..." */
+    0x11,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00002258    "..._SUN." */
+    0x11,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002260    ".. _PS0." */
+    0x70,0x0A,0x11,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002268    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002270    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002278    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002280    "T2. _PS3" */
+    0x00,0x70,0x0A,0x11,0x5C,0x2E,0x5F,0x47,  /* 00002288    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002290    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002298    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 000022A0    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x11,0x5C,0x2E,0x5F,  /* 000022A8    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 000022B0    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000022B8    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 000022C0    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x31,  /* 000022C8    "_GPEPH11" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 000022D0    ".+_STA.p" */
+    0x0A,0x11,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000022D8    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 000022E0    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000022E8    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000022F0    "2.\._GPE" */
+    0x50,0x48,0x31,0x31,0x5B,0x82,0x42,0x0B,  /* 000022F8    "PH11[.B." */
+    0x53,0x31,0x32,0x5F,0x08,0x5F,0x41,0x44,  /* 00002300    "S12_._AD" */
+    0x52,0x0C,0x00,0x00,0x12,0x00,0x08,0x5F,  /* 00002308    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x12,0x14,0x20,0x5F,  /* 00002310    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x12,0x5C,  /* 00002318    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002320    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00002328    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002330    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x12,  /* 00002338    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002340    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00002348    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00002350    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00002358    ",_EJ0.p." */
+    0x12,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002360    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002368    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00002370    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002378    "p.\._GPE" */
+    0x50,0x48,0x31,0x32,0x14,0x2B,0x5F,0x53,  /* 00002380    "PH12.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x12,0x5C,0x2E,  /* 00002388    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00002390    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002398    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 000023A0    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x32,  /* 000023A8    "_GPEPH12" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x33,0x5F,  /* 000023B0    "[.B.S13_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 000023B8    "._ADR..." */
+    0x13,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 000023C0    "..._SUN." */
+    0x13,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 000023C8    ".. _PS0." */
+    0x70,0x0A,0x13,0x5C,0x2E,0x5F,0x47,0x50,  /* 000023D0    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 000023D8    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000023E0    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 000023E8    "T2. _PS3" */
+    0x00,0x70,0x0A,0x13,0x5C,0x2E,0x5F,0x47,  /* 000023F0    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 000023F8    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002400    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00002408    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x13,0x5C,0x2E,0x5F,  /* 00002410    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00002418    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002420    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00002428    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x33,  /* 00002430    "_GPEPH13" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002438    ".+_STA.p" */
+    0x0A,0x13,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002440    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002448    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002450    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002458    "2.\._GPE" */
+    0x50,0x48,0x31,0x33,0x5B,0x82,0x42,0x0B,  /* 00002460    "PH13[.B." */
+    0x53,0x31,0x34,0x5F,0x08,0x5F,0x41,0x44,  /* 00002468    "S14_._AD" */
+    0x52,0x0C,0x00,0x00,0x14,0x00,0x08,0x5F,  /* 00002470    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x14,0x14,0x20,0x5F,  /* 00002478    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x14,0x5C,  /* 00002480    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002488    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00002490    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002498    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x14,  /* 000024A0    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000024A8    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 000024B0    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 000024B8    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 000024C0    ",_EJ0.p." */
+    0x14,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 000024C8    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 000024D0    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 000024D8    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000024E0    "p.\._GPE" */
+    0x50,0x48,0x31,0x34,0x14,0x2B,0x5F,0x53,  /* 000024E8    "PH14.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x14,0x5C,0x2E,  /* 000024F0    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 000024F8    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002500    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00002508    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x34,  /* 00002510    "_GPEPH14" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x35,0x5F,  /* 00002518    "[.B.S15_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00002520    "._ADR..." */
+    0x15,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00002528    "..._SUN." */
+    0x15,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002530    ".. _PS0." */
+    0x70,0x0A,0x15,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002538    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002540    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002548    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002550    "T2. _PS3" */
+    0x00,0x70,0x0A,0x15,0x5C,0x2E,0x5F,0x47,  /* 00002558    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002560    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002568    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00002570    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x15,0x5C,0x2E,0x5F,  /* 00002578    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00002580    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002588    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00002590    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x35,  /* 00002598    "_GPEPH15" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 000025A0    ".+_STA.p" */
+    0x0A,0x15,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000025A8    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 000025B0    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000025B8    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000025C0    "2.\._GPE" */
+    0x50,0x48,0x31,0x35,0x5B,0x82,0x42,0x0B,  /* 000025C8    "PH15[.B." */
+    0x53,0x31,0x36,0x5F,0x08,0x5F,0x41,0x44,  /* 000025D0    "S16_._AD" */
+    0x52,0x0C,0x00,0x00,0x16,0x00,0x08,0x5F,  /* 000025D8    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x16,0x14,0x20,0x5F,  /* 000025E0    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x16,0x5C,  /* 000025E8    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000025F0    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 000025F8    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002600    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x16,  /* 00002608    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002610    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00002618    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00002620    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00002628    ",_EJ0.p." */
+    0x16,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002630    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002638    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00002640    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002648    "p.\._GPE" */
+    0x50,0x48,0x31,0x36,0x14,0x2B,0x5F,0x53,  /* 00002650    "PH16.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x16,0x5C,0x2E,  /* 00002658    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00002660    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002668    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00002670    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x36,  /* 00002678    "_GPEPH16" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x37,0x5F,  /* 00002680    "[.B.S17_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00002688    "._ADR..." */
+    0x17,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00002690    "..._SUN." */
+    0x17,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002698    ".. _PS0." */
+    0x70,0x0A,0x17,0x5C,0x2E,0x5F,0x47,0x50,  /* 000026A0    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 000026A8    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000026B0    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 000026B8    "T2. _PS3" */
+    0x00,0x70,0x0A,0x17,0x5C,0x2E,0x5F,0x47,  /* 000026C0    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 000026C8    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 000026D0    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 000026D8    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x17,0x5C,0x2E,0x5F,  /* 000026E0    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 000026E8    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000026F0    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 000026F8    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x37,  /* 00002700    "_GPEPH17" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002708    ".+_STA.p" */
+    0x0A,0x17,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002710    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002718    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002720    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002728    "2.\._GPE" */
+    0x50,0x48,0x31,0x37,0x5B,0x82,0x42,0x0B,  /* 00002730    "PH17[.B." */
+    0x53,0x31,0x38,0x5F,0x08,0x5F,0x41,0x44,  /* 00002738    "S18_._AD" */
+    0x52,0x0C,0x00,0x00,0x18,0x00,0x08,0x5F,  /* 00002740    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x18,0x14,0x20,0x5F,  /* 00002748    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x18,0x5C,  /* 00002750    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002758    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00002760    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002768    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x18,  /* 00002770    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002778    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00002780    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00002788    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00002790    ",_EJ0.p." */
+    0x18,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002798    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 000027A0    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 000027A8    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000027B0    "p.\._GPE" */
+    0x50,0x48,0x31,0x38,0x14,0x2B,0x5F,0x53,  /* 000027B8    "PH18.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x18,0x5C,0x2E,  /* 000027C0    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 000027C8    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 000027D0    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 000027D8    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x38,  /* 000027E0    "_GPEPH18" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x39,0x5F,  /* 000027E8    "[.B.S19_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 000027F0    "._ADR..." */
+    0x19,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 000027F8    "..._SUN." */
+    0x19,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002800    ".. _PS0." */
+    0x70,0x0A,0x19,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002808    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002810    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002818    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002820    "T2. _PS3" */
+    0x00,0x70,0x0A,0x19,0x5C,0x2E,0x5F,0x47,  /* 00002828    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002830    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002838    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00002840    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x19,0x5C,0x2E,0x5F,  /* 00002848    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00002850    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002858    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00002860    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x39,  /* 00002868    "_GPEPH19" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002870    ".+_STA.p" */
+    0x0A,0x19,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002878    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002880    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002888    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002890    "2.\._GPE" */
+    0x50,0x48,0x31,0x39,0x5B,0x82,0x42,0x0B,  /* 00002898    "PH19[.B." */
+    0x53,0x31,0x41,0x5F,0x08,0x5F,0x41,0x44,  /* 000028A0    "S1A_._AD" */
+    0x52,0x0C,0x00,0x00,0x1A,0x00,0x08,0x5F,  /* 000028A8    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x1A,0x14,0x20,0x5F,  /* 000028B0    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x1A,0x5C,  /* 000028B8    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000028C0    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 000028C8    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 000028D0    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x1A,  /* 000028D8    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 000028E0    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 000028E8    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 000028F0    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 000028F8    ",_EJ0.p." */
+    0x1A,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002900    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002908    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00002910    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002918    "p.\._GPE" */
+    0x50,0x48,0x31,0x41,0x14,0x2B,0x5F,0x53,  /* 00002920    "PH1A.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x1A,0x5C,0x2E,  /* 00002928    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00002930    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002938    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00002940    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x41,  /* 00002948    "_GPEPH1A" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x42,0x5F,  /* 00002950    "[.B.S1B_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00002958    "._ADR..." */
+    0x1B,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00002960    "..._SUN." */
+    0x1B,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002968    ".. _PS0." */
+    0x70,0x0A,0x1B,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002970    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002978    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002980    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002988    "T2. _PS3" */
+    0x00,0x70,0x0A,0x1B,0x5C,0x2E,0x5F,0x47,  /* 00002990    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002998    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 000029A0    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 000029A8    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x1B,0x5C,0x2E,0x5F,  /* 000029B0    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 000029B8    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000029C0    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 000029C8    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x42,  /* 000029D0    "_GPEPH1B" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 000029D8    ".+_STA.p" */
+    0x0A,0x1B,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000029E0    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 000029E8    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 000029F0    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 000029F8    "2.\._GPE" */
+    0x50,0x48,0x31,0x42,0x5B,0x82,0x42,0x0B,  /* 00002A00    "PH1B[.B." */
+    0x53,0x31,0x43,0x5F,0x08,0x5F,0x41,0x44,  /* 00002A08    "S1C_._AD" */
+    0x52,0x0C,0x00,0x00,0x1C,0x00,0x08,0x5F,  /* 00002A10    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x1C,0x14,0x20,0x5F,  /* 00002A18    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x1C,0x5C,  /* 00002A20    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002A28    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00002A30    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002A38    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x1C,  /* 00002A40    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002A48    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00002A50    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00002A58    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00002A60    ",_EJ0.p." */
+    0x1C,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002A68    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002A70    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00002A78    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002A80    "p.\._GPE" */
+    0x50,0x48,0x31,0x43,0x14,0x2B,0x5F,0x53,  /* 00002A88    "PH1C.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x1C,0x5C,0x2E,  /* 00002A90    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00002A98    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002AA0    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00002AA8    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x43,  /* 00002AB0    "_GPEPH1C" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x44,0x5F,  /* 00002AB8    "[.B.S1D_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00002AC0    "._ADR..." */
+    0x1D,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00002AC8    "..._SUN." */
+    0x1D,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002AD0    ".. _PS0." */
+    0x70,0x0A,0x1D,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002AD8    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002AE0    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002AE8    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002AF0    "T2. _PS3" */
+    0x00,0x70,0x0A,0x1D,0x5C,0x2E,0x5F,0x47,  /* 00002AF8    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002B00    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002B08    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00002B10    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x1D,0x5C,0x2E,0x5F,  /* 00002B18    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00002B20    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002B28    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00002B30    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x44,  /* 00002B38    "_GPEPH1D" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002B40    ".+_STA.p" */
+    0x0A,0x1D,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002B48    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002B50    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002B58    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002B60    "2.\._GPE" */
+    0x50,0x48,0x31,0x44,0x5B,0x82,0x42,0x0B,  /* 00002B68    "PH1D[.B." */
+    0x53,0x31,0x45,0x5F,0x08,0x5F,0x41,0x44,  /* 00002B70    "S1E_._AD" */
+    0x52,0x0C,0x00,0x00,0x1E,0x00,0x08,0x5F,  /* 00002B78    "R......_" */
+    0x53,0x55,0x4E,0x0A,0x1E,0x14,0x20,0x5F,  /* 00002B80    "SUN... _" */
+    0x50,0x53,0x30,0x00,0x70,0x0A,0x1E,0x5C,  /* 00002B88    "PS0.p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002B90    "._GPEDPT" */
+    0x31,0x70,0x0A,0x80,0x5C,0x2E,0x5F,0x47,  /* 00002B98    "1p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x32,0x14,0x20,  /* 00002BA0    "PEDPT2. " */
+    0x5F,0x50,0x53,0x33,0x00,0x70,0x0A,0x1E,  /* 00002BA8    "_PS3.p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002BB0    "\._GPEDP" */
+    0x54,0x31,0x70,0x0A,0x83,0x5C,0x2E,0x5F,  /* 00002BB8    "T1p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x32,0x14,  /* 00002BC0    "GPEDPT2." */
+    0x2C,0x5F,0x45,0x4A,0x30,0x01,0x70,0x0A,  /* 00002BC8    ",_EJ0.p." */
+    0x1E,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002BD0    ".\._GPED" */
+    0x50,0x54,0x31,0x70,0x0A,0x88,0x5C,0x2E,  /* 00002BD8    "PT1p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x32,  /* 00002BE0    "_GPEDPT2" */
+    0x70,0x01,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002BE8    "p.\._GPE" */
+    0x50,0x48,0x31,0x45,0x14,0x2B,0x5F,0x53,  /* 00002BF0    "PH1E.+_S" */
+    0x54,0x41,0x00,0x70,0x0A,0x1E,0x5C,0x2E,  /* 00002BF8    "TA.p..\." */
+    0x5F,0x47,0x50,0x45,0x44,0x50,0x54,0x31,  /* 00002C00    "_GPEDPT1" */
+    0x70,0x0A,0x89,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002C08    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x32,0xA4,0x5C,0x2E,  /* 00002C10    "EDPT2.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x45,  /* 00002C18    "_GPEPH1E" */
+    0x5B,0x82,0x42,0x0B,0x53,0x31,0x46,0x5F,  /* 00002C20    "[.B.S1F_" */
+    0x08,0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,  /* 00002C28    "._ADR..." */
+    0x1F,0x00,0x08,0x5F,0x53,0x55,0x4E,0x0A,  /* 00002C30    "..._SUN." */
+    0x1F,0x14,0x20,0x5F,0x50,0x53,0x30,0x00,  /* 00002C38    ".. _PS0." */
+    0x70,0x0A,0x1F,0x5C,0x2E,0x5F,0x47,0x50,  /* 00002C40    "p..\._GP" */
+    0x45,0x44,0x50,0x54,0x31,0x70,0x0A,0x80,  /* 00002C48    "EDPT1p.." */
+    0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,  /* 00002C50    "\._GPEDP" */
+    0x54,0x32,0x14,0x20,0x5F,0x50,0x53,0x33,  /* 00002C58    "T2. _PS3" */
+    0x00,0x70,0x0A,0x1F,0x5C,0x2E,0x5F,0x47,  /* 00002C60    ".p..\._G" */
+    0x50,0x45,0x44,0x50,0x54,0x31,0x70,0x0A,  /* 00002C68    "PEDPT1p." */
+    0x83,0x5C,0x2E,0x5F,0x47,0x50,0x45,0x44,  /* 00002C70    ".\._GPED" */
+    0x50,0x54,0x32,0x14,0x2C,0x5F,0x45,0x4A,  /* 00002C78    "PT2.,_EJ" */
+    0x30,0x01,0x70,0x0A,0x1F,0x5C,0x2E,0x5F,  /* 00002C80    "0.p..\._" */
+    0x47,0x50,0x45,0x44,0x50,0x54,0x31,0x70,  /* 00002C88    "GPEDPT1p" */
+    0x0A,0x88,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002C90    "..\._GPE" */
+    0x44,0x50,0x54,0x32,0x70,0x01,0x5C,0x2E,  /* 00002C98    "DPT2p.\." */
+    0x5F,0x47,0x50,0x45,0x50,0x48,0x31,0x46,  /* 00002CA0    "_GPEPH1F" */
+    0x14,0x2B,0x5F,0x53,0x54,0x41,0x00,0x70,  /* 00002CA8    ".+_STA.p" */
+    0x0A,0x1F,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002CB0    "..\._GPE" */
+    0x44,0x50,0x54,0x31,0x70,0x0A,0x89,0x5C,  /* 00002CB8    "DPT1p..\" */
+    0x2E,0x5F,0x47,0x50,0x45,0x44,0x50,0x54,  /* 00002CC0    "._GPEDPT" */
+    0x32,0xA4,0x5C,0x2E,0x5F,0x47,0x50,0x45,  /* 00002CC8    "2.\._GPE" */
+    0x50,0x48,0x31,0x46,0x10,0x4D,0x52,0x5F,  /* 00002CD0    "PH1F.MR_" */
+    0x47,0x50,0x45,0x5B,0x80,0x50,0x48,0x50,  /* 00002CD8    "GPE[.PHP" */
+    0x5F,0x01,0x0B,0xC0,0x10,0x0A,0x22,0x5B,  /* 00002CE0    "_....."[" */
+    0x81,0x41,0x0B,0x50,0x48,0x50,0x5F,0x01,  /* 00002CE8    ".A.PHP_." */
+    0x50,0x53,0x54,0x41,0x08,0x50,0x53,0x54,  /* 00002CF0    "PSTA.PST" */
+    0x42,0x08,0x50,0x48,0x30,0x30,0x08,0x50,  /* 00002CF8    "B.PH00.P" */
+    0x48,0x30,0x31,0x08,0x50,0x48,0x30,0x32,  /* 00002D00    "H01.PH02" */
+    0x08,0x50,0x48,0x30,0x33,0x08,0x50,0x48,  /* 00002D08    ".PH03.PH" */
+    0x30,0x34,0x08,0x50,0x48,0x30,0x35,0x08,  /* 00002D10    "04.PH05." */
+    0x50,0x48,0x30,0x36,0x08,0x50,0x48,0x30,  /* 00002D18    "PH06.PH0" */
+    0x37,0x08,0x50,0x48,0x30,0x38,0x08,0x50,  /* 00002D20    "7.PH08.P" */
+    0x48,0x30,0x39,0x08,0x50,0x48,0x30,0x41,  /* 00002D28    "H09.PH0A" */
+    0x08,0x50,0x48,0x30,0x42,0x08,0x50,0x48,  /* 00002D30    ".PH0B.PH" */
+    0x30,0x43,0x08,0x50,0x48,0x30,0x44,0x08,  /* 00002D38    "0C.PH0D." */
+    0x50,0x48,0x30,0x45,0x08,0x50,0x48,0x30,  /* 00002D40    "PH0E.PH0" */
+    0x46,0x08,0x50,0x48,0x31,0x30,0x08,0x50,  /* 00002D48    "F.PH10.P" */
+    0x48,0x31,0x31,0x08,0x50,0x48,0x31,0x32,  /* 00002D50    "H11.PH12" */
+    0x08,0x50,0x48,0x31,0x33,0x08,0x50,0x48,  /* 00002D58    ".PH13.PH" */
+    0x31,0x34,0x08,0x50,0x48,0x31,0x35,0x08,  /* 00002D60    "14.PH15." */
+    0x50,0x48,0x31,0x36,0x08,0x50,0x48,0x31,  /* 00002D68    "PH16.PH1" */
+    0x37,0x08,0x50,0x48,0x31,0x38,0x08,0x50,  /* 00002D70    "7.PH18.P" */
+    0x48,0x31,0x39,0x08,0x50,0x48,0x31,0x41,  /* 00002D78    "H19.PH1A" */
+    0x08,0x50,0x48,0x31,0x42,0x08,0x50,0x48,  /* 00002D80    ".PH1B.PH" */
+    0x31,0x43,0x08,0x50,0x48,0x31,0x44,0x08,  /* 00002D88    "1C.PH1D." */
+    0x50,0x48,0x31,0x45,0x08,0x50,0x48,0x31,  /* 00002D90    "PH1E.PH1" */
+    0x46,0x08,0x5B,0x80,0x44,0x47,0x31,0x5F,  /* 00002D98    "F.[.DG1_" */
+    0x01,0x0B,0x44,0xB0,0x0A,0x04,0x5B,0x81,  /* 00002DA0    "..D...[." */
+    0x10,0x44,0x47,0x31,0x5F,0x01,0x44,0x50,  /* 00002DA8    ".DG1_.DP" */
+    0x54,0x31,0x08,0x44,0x50,0x54,0x32,0x08,  /* 00002DB0    "T1.DPT2." */
+    0x14,0x49,0x44,0x5F,0x4C,0x30,0x33,0x08,  /* 00002DB8    ".ID_L03." */
+    0x08,0x5F,0x54,0x5F,0x30,0x00,0x08,0x53,  /* 00002DC0    "._T_0..S" */
+    0x4C,0x54,0x5F,0x00,0x08,0x45,0x56,0x54,  /* 00002DC8    "LT_..EVT" */
+    0x5F,0x00,0x70,0x50,0x53,0x54,0x41,0x61,  /* 00002DD0    "_.pPSTAa" */
+    0x7B,0x61,0x0A,0x0F,0x45,0x56,0x54,0x5F,  /* 00002DD8    "{a..EVT_" */
+    0x70,0x50,0x53,0x54,0x42,0x61,0x7B,0x61,  /* 00002DE0    "pPSTBa{a" */
+    0x0A,0xFF,0x53,0x4C,0x54,0x5F,0x70,0x53,  /* 00002DE8    "..SLT_pS" */
+    0x4C,0x54,0x5F,0x44,0x50,0x54,0x31,0x70,  /* 00002DF0    "LT_DPT1p" */
+    0x45,0x56,0x54,0x5F,0x44,0x50,0x54,0x32,  /* 00002DF8    "EVT_DPT2" */
+    0x70,0x53,0x4C,0x54,0x5F,0x5F,0x54,0x5F,  /* 00002E00    "pSLT__T_" */
+    0x30,0xA0,0x1B,0x93,0x5F,0x54,0x5F,0x30,  /* 00002E08    "0..._T_0" */
+    0x00,0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,  /* 00002E10    "..\/._SB" */
+    0x5F,0x50,0x43,0x49,0x30,0x53,0x30,0x30,  /* 00002E18    "_PCI0S00" */
+    0x5F,0x45,0x56,0x54,0x5F,0xA1,0x4C,0x3D,  /* 00002E20    "_EVT_.L=" */
+    0xA0,0x1B,0x93,0x5F,0x54,0x5F,0x30,0x01,  /* 00002E28    "..._T_0." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002E30    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x31,0x5F,  /* 00002E38    "PCI0S01_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x3B,0xA0,  /* 00002E40    "EVT_.M;." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x02,  /* 00002E48    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002E50    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x32,0x5F,  /* 00002E58    "PCI0S02_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x39,0xA0,  /* 00002E60    "EVT_.M9." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x03,  /* 00002E68    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002E70    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x33,0x5F,  /* 00002E78    "PCI0S03_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x37,0xA0,  /* 00002E80    "EVT_.M7." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x04,  /* 00002E88    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002E90    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x34,0x5F,  /* 00002E98    "PCI0S04_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x35,0xA0,  /* 00002EA0    "EVT_.M5." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x05,  /* 00002EA8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002EB0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x35,0x5F,  /* 00002EB8    "PCI0S05_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x33,0xA0,  /* 00002EC0    "EVT_.M3." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x06,  /* 00002EC8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002ED0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x36,0x5F,  /* 00002ED8    "PCI0S06_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x31,0xA0,  /* 00002EE0    "EVT_.M1." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x07,  /* 00002EE8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002EF0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x37,0x5F,  /* 00002EF8    "PCI0S07_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x2F,0xA0,  /* 00002F00    "EVT_.M/." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x08,  /* 00002F08    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002F10    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x38,0x5F,  /* 00002F18    "PCI0S08_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x2D,0xA0,  /* 00002F20    "EVT_.M-." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x09,  /* 00002F28    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002F30    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x39,0x5F,  /* 00002F38    "PCI0S09_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x2B,0xA0,  /* 00002F40    "EVT_.M+." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x0A,  /* 00002F48    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002F50    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x41,0x5F,  /* 00002F58    "PCI0S0A_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x29,0xA0,  /* 00002F60    "EVT_.M)." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x0B,  /* 00002F68    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002F70    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x42,0x5F,  /* 00002F78    "PCI0S0B_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x27,0xA0,  /* 00002F80    "EVT_.M'." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x0C,  /* 00002F88    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002F90    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x43,0x5F,  /* 00002F98    "PCI0S0C_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x25,0xA0,  /* 00002FA0    "EVT_.M%." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x0D,  /* 00002FA8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002FB0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x44,0x5F,  /* 00002FB8    "PCI0S0D_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x23,0xA0,  /* 00002FC0    "EVT_.M#." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x0E,  /* 00002FC8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002FD0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x45,0x5F,  /* 00002FD8    "PCI0S0E_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x21,0xA0,  /* 00002FE0    "EVT_.M!." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x0F,  /* 00002FE8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00002FF0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x30,0x46,0x5F,  /* 00002FF8    "PCI0S0F_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x1F,0xA0,  /* 00003000    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x10,  /* 00003008    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003010    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x30,0x5F,  /* 00003018    "PCI0S10_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x1D,0xA0,  /* 00003020    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x11,  /* 00003028    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003030    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x31,0x5F,  /* 00003038    "PCI0S11_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x1B,0xA0,  /* 00003040    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x12,  /* 00003048    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003050    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x32,0x5F,  /* 00003058    "PCI0S12_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x19,0xA0,  /* 00003060    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x13,  /* 00003068    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003070    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x33,0x5F,  /* 00003078    "PCI0S13_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x17,0xA0,  /* 00003080    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x14,  /* 00003088    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003090    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x34,0x5F,  /* 00003098    "PCI0S14_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x15,0xA0,  /* 000030A0    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x15,  /* 000030A8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 000030B0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x35,0x5F,  /* 000030B8    "PCI0S15_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x13,0xA0,  /* 000030C0    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x16,  /* 000030C8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 000030D0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x36,0x5F,  /* 000030D8    "PCI0S16_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x11,0xA0,  /* 000030E0    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x17,  /* 000030E8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 000030F0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x37,0x5F,  /* 000030F8    "PCI0S17_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x0F,0xA0,  /* 00003100    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x18,  /* 00003108    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003110    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x38,0x5F,  /* 00003118    "PCI0S18_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x0D,0xA0,  /* 00003120    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x19,  /* 00003128    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003130    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x39,0x5F,  /* 00003138    "PCI0S19_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x0B,0xA0,  /* 00003140    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x1A,  /* 00003148    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003150    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x41,0x5F,  /* 00003158    "PCI0S1A_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x09,0xA0,  /* 00003160    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x1B,  /* 00003168    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003170    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x42,0x5F,  /* 00003178    "PCI0S1B_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x07,0xA0,  /* 00003180    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x1C,  /* 00003188    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00003190    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x43,0x5F,  /* 00003198    "PCI0S1C_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x4D,0x05,0xA0,  /* 000031A0    "EVT_.M.." */
+    0x1C,0x93,0x5F,0x54,0x5F,0x30,0x0A,0x1D,  /* 000031A8    ".._T_0.." */
+    0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 000031B0    ".\/._SB_" */
+    0x50,0x43,0x49,0x30,0x53,0x31,0x44,0x5F,  /* 000031B8    "PCI0S1D_" */
+    0x45,0x56,0x54,0x5F,0xA1,0x3D,0xA0,0x1C,  /* 000031C0    "EVT_.=.." */
+    0x93,0x5F,0x54,0x5F,0x30,0x0A,0x1E,0x86,  /* 000031C8    "._T_0..." */
+    0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,0x50,  /* 000031D0    "\/._SB_P" */
+    0x43,0x49,0x30,0x53,0x31,0x45,0x5F,0x45,  /* 000031D8    "CI0S1E_E" */
+    0x56,0x54,0x5F,0xA1,0x1E,0xA0,0x1C,0x93,  /* 000031E0    "VT_....." */
+    0x5F,0x54,0x5F,0x30,0x0A,0x1F,0x86,0x5C,  /* 000031E8    "_T_0...\" */
+    0x2F,0x03,0x5F,0x53,0x42,0x5F,0x50,0x43,  /* 000031F0    "/._SB_PC" */
+    0x49,0x30,0x53,0x31,0x46,0x5F,0x45,0x56,  /* 000031F8    "I0S1F_EV" */
+    0x54,0x5F,
 };
 int DsdtLen=sizeof(AmlCode);
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/hvmloader/config.h Fri Mar 27 11:07:11 2009 +0900
@@ -47,6 +47,7 @@ extern unsigned long pci_mem_start, pci_
 #define E820_OFFSET                   0x8
 
 /* Xen Platform Device */
+#define XEN_PF_IOBASE   0x10
 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
 
 /* Located at BIOS_INFO_PHYSICAL_ADDRESS. */
@@ -56,9 +57,7 @@ struct bios_info {
     uint8_t  hpet_present:1;    /* 0[2] - System has HPET? */
     uint32_t pci_min, pci_len;  /* 4, 8 - PCI I/O hole boundaries */
     uint32_t bios32_entry;      /* 12   - Entry point for 32-bit BIOS */
-    uint16_t xen_pfiob;         /* 16   - Xen platform device I/O ports */
 };
 #define BIOSINFO_OFF_bios32_entry 12
-#define BIOSINFO_OFF_xen_pfiob    16
 
 #endif /* __HVMLOADER_CONFIG_H__ */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/hvmloader/hvmloader.c      Fri Mar 27 11:07:11 2009 +0900
@@ -539,25 +539,6 @@ static void cmos_write_memory_size(void)
     cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
 }
 
-static uint16_t xen_platform_io_base(void)
-{
-    uint32_t devfn, bar_data;
-    uint16_t vendor_id, device_id;
-
-    for ( devfn = 0; devfn < 128; devfn++ )
-    {
-        vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
-        device_id = pci_readw(devfn, PCI_DEVICE_ID);
-        if ( (vendor_id == 0x5853) && (device_id == 0x0001) )
-        {
-            bar_data = pci_readl(devfn, PCI_BASE_ADDRESS_0);
-            return bar_data & PCI_BASE_ADDRESS_IO_MASK;
-        }
-    }
-
-    return 0;
-}
-
 /*
  * Set up an empty TSS area for virtual 8086 mode to use. 
  * The only important thing is that it musn't have any bits set 
@@ -744,7 +725,6 @@ int main(void)
     bios_info->pci_min = pci_mem_start;
     bios_info->pci_len = pci_mem_end - pci_mem_start;
     bios_info->bios32_entry = bios32_addr;
-    bios_info->xen_pfiob = xen_platform_io_base();
 
     printf("Invoking ROMBIOS ...\n");
     return 0;
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/rombios/32bit/pmm.c
--- a/tools/firmware/rombios/32bit/pmm.c        Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/rombios/32bit/pmm.c        Fri Mar 27 11:07:11 2009 +0900
@@ -71,10 +71,13 @@
 
 #define DEBUG_PMM 0
 
+#define __stringify(a) #a
+#define stringify(a) __stringify(a)
+
 #define ASSERT(_expr, _action)                                  \
     if (!(_expr)) {                                             \
         printf("ASSERTION FAIL: %s %s:%d %s()\n",               \
-               __STRING(_expr), __FILE__, __LINE__, __func__);  \
+               stringify(_expr), __FILE__, __LINE__, __func__); \
         _action;                                                \
     } else
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/firmware/rombios/rombios.c  Fri Mar 27 11:07:11 2009 +0900
@@ -1418,24 +1418,14 @@ fixup_base_mem_in_k()
   write_word(0x40, 0x13, base_mem >> 10);
 }
 
-ASM_START
-_rom_write_access_control:
-    push ds
-    mov ax,#(BIOS_INFO_PHYSICAL_ADDRESS >> 4)
-    mov ds,ax
-    mov ax,[BIOSINFO_OFF_xen_pfiob]
-    pop ds
-    ret
-ASM_END
-
 void enable_rom_write_access()
 {
-    outb(rom_write_access_control(), 0);
+    outb(XEN_PF_IOBASE, 0);
 }
 
 void disable_rom_write_access()
 {
-    outb(rom_write_access_control(), PFFLAG_ROM_LOCK);
+    outb(XEN_PF_IOBASE, PFFLAG_ROM_LOCK);
 }
     
 #endif /* HVMASSIST */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/Makefile
--- a/tools/fs-back/Makefile    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/fs-back/Makefile    Fri Mar 27 11:07:11 2009 +0900
@@ -16,7 +16,7 @@ LIBS      := -L. -L.. -L../lib
 LIBS      := -L. -L.. -L../lib
 LIBS      += $(LDFLAGS_libxenctrl)
 LIBS      += $(LDFLAGS_libxenstore)
-LIBS      += -lpthread -lrt 
+LIBS      += -lrt 
 
 OBJS     := fs-xenbus.o fs-ops.o
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/fs-backend.c
--- a/tools/fs-back/fs-backend.c        Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/fs-back/fs-backend.c        Fri Mar 27 11:07:11 2009 +0900
@@ -1,107 +1,75 @@
 #undef NDEBUG
+#include <unistd.h>
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
 #include <malloc.h>
-#include <pthread.h>
 #include <xenctrl.h>
 #include <aio.h>
 #include <sys/mman.h>
 #include <sys/select.h>
+#include <sys/socket.h>
 #include <xen/io/ring.h>
+#include <xc_private.h>
+#include <err.h>
+#include "sys-queue.h"
 #include "fs-backend.h"
+#include "fs-debug.h"
 
 struct xs_handle *xsh = NULL;
 static struct fs_export *fs_exports = NULL;
 static int export_id = 0;
 static int mount_id = 0;
-
-static void dispatch_response(struct fs_mount *mount, int priv_req_id)
+static int pipefds[2];
+static LIST_HEAD(mount_requests_head, fs_mount) mount_requests_head;
+
+static void free_mount_request(struct fs_mount *mount);
+
+static void dispatch_response(struct fs_request *request)
 {
     int i;
     struct fs_op *op;
-    struct fs_request *req = &mount->requests[priv_req_id];
 
     for(i=0;;i++)
     {
         op = fsops[i];
         /* We should dispatch a response before reaching the end of the array 
*/
         assert(op != NULL);
-        if(op->type == req->req_shadow.type)
+        if(op->type == request->req_shadow.type)
         {
-            printf("Found op for type=%d\n", op->type);
+            FS_DEBUG("Found op for type=%d\n", op->type);
             /* There needs to be a response handler */
             assert(op->response_handler != NULL);
-            op->response_handler(mount, req);
+            op->response_handler(request->mount, request);
             break;
         }
     }
 
-    req->active = 0;
-    add_id_to_freelist(priv_req_id, mount->freelist);
-}
-
-static void handle_aio_events(struct fs_mount *mount)
-{
-    int fd, ret, count, i, notify;
-    evtchn_port_t port;
-    /* AIO control block for the evtchn file destriptor */
-    struct aiocb evtchn_cb;
-    const struct aiocb * cb_list[mount->nr_entries];
-    int request_ids[mount->nr_entries];
-
-    /* Prepare the AIO control block for evtchn */ 
-    fd = xc_evtchn_fd(mount->evth); 
-    bzero(&evtchn_cb, sizeof(struct aiocb));
-    evtchn_cb.aio_fildes = fd;
-    evtchn_cb.aio_nbytes = sizeof(port);
-    evtchn_cb.aio_buf = &port;
-    assert(aio_read(&evtchn_cb) == 0);
-
-wait_again:   
-    /* Create list of active AIO requests */
-    count = 0;
-    for(i=0; i<mount->nr_entries; i++)
-        if(mount->requests[i].active)
-        {
-            cb_list[count] = &mount->requests[i].aiocb;
-            request_ids[count] = i;
-            count++;
-        }
-    /* Add the event channel at the end of the list. Event channel needs to be
-     * handled last as it exits this function. */
-    cb_list[count] = &evtchn_cb;
-    request_ids[count] = -1;
-    count++;
-
-    /* Block till an AIO requset finishes, or we get an event */ 
-    while(1) {
-       int ret = aio_suspend(cb_list, count, NULL);
-       if (!ret)
-           break;
-       assert(errno == EINTR);
-    }
-    for(i=0; i<count; i++)
-        if(aio_error(cb_list[i]) != EINPROGRESS)
-        {
-            if(request_ids[i] >= 0)
-                dispatch_response(mount, request_ids[i]);
-            else
-                goto read_event_channel;
-        }
- 
-    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
-    printf("Pushed responces and notify=%d\n", notify);
+    request->active = 0;
+    add_id_to_freelist(request->id, request->mount->freelist);
+}
+
+static void handle_aio_event(struct fs_request *request)
+{
+    int ret, notify;
+
+    FS_DEBUG("handle_aio_event: mount %s request %d\n", 
request->mount->frontend, request->id);
+    if (request->active < 0) {
+        request->mount->nr_entries++;
+        if (!request->mount->nr_entries)
+            free_mount_request(request->mount);
+        return;
+    }
+
+    ret = aio_error(&request->aiocb);
+    if(ret != EINPROGRESS && ret != ECANCELED)
+        dispatch_response(request);
+
+    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&request->mount->ring, notify);
+    FS_DEBUG("Pushed responces and notify=%d\n", notify);
     if(notify)
-        xc_evtchn_notify(mount->evth, mount->local_evtchn);
-    
-    goto wait_again;
-
-read_event_channel:    
-    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
-    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
-}
-
+        xc_evtchn_notify(request->mount->evth, request->mount->local_evtchn);
+}
 
 static void allocate_request_array(struct fs_mount *mount)
 {
@@ -116,6 +84,7 @@ static void allocate_request_array(struc
     for(i=0; i< nr_entries; i++)
     {
         requests[i].active = 0; 
+        requests[i].mount = mount; 
         add_id_to_freelist(i, freelist);
     }
     mount->requests = requests;
@@ -123,86 +92,102 @@ static void allocate_request_array(struc
 }
 
 
-static void *handle_mount(void *data)
+static void handle_mount(struct fs_mount *mount)
 {
     int more, notify;
-    struct fs_mount *mount = (struct fs_mount *)data;
-    
-    printf("Starting a thread for mount: %d\n", mount->mount_id);
-    allocate_request_array(mount);
-
-    for(;;)
-    {
-        int nr_consumed=0;
-        RING_IDX cons, rp;
-        struct fsif_request *req;
-
-        handle_aio_events(mount);
+    int nr_consumed=0;
+    RING_IDX cons, rp;
+    struct fsif_request *req;
+
 moretodo:
-        rp = mount->ring.sring->req_prod;
-        xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
-
-        while ((cons = mount->ring.req_cons) != rp)
+    rp = mount->ring.sring->req_prod;
+    xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+    while ((cons = mount->ring.req_cons) != rp)
+    {
+        int i;
+        struct fs_op *op;
+
+        FS_DEBUG("Got a request at %d (of %d)\n", 
+                cons, RING_SIZE(&mount->ring));
+        req = RING_GET_REQUEST(&mount->ring, cons);
+        FS_DEBUG("Request type=%d\n", req->type); 
+        for(i=0;;i++)
         {
-            int i;
-            struct fs_op *op;
-
-            printf("Got a request at %d (of %d)\n", 
-                    cons, RING_SIZE(&mount->ring));
-            req = RING_GET_REQUEST(&mount->ring, cons);
-            printf("Request type=%d\n", req->type); 
-            for(i=0;;i++)
+            op = fsops[i];
+            if(op == NULL)
             {
-                op = fsops[i];
-                if(op == NULL)
-                {
-                    /* We've reached the end of the array, no appropirate
-                     * handler found. Warn, ignore and continue. */
-                    printf("WARN: Unknown request type: %d\n", req->type);
-                    mount->ring.req_cons++; 
-                    break;
-                }
-                if(op->type == req->type)
-                {
-                    /* There needs to be a dispatch handler */
-                    assert(op->dispatch_handler != NULL);
-                    op->dispatch_handler(mount, req);
-                    break;
-                }
-             }
-
-            nr_consumed++;
-        }
-        printf("Backend consumed: %d requests\n", nr_consumed);
-        RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
-        if(more) goto moretodo;
-
-        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
-        printf("Pushed responces and notify=%d\n", notify);
-        if(notify)
-            xc_evtchn_notify(mount->evth, mount->local_evtchn);
-    }
- 
-    printf("Destroying thread for mount: %d\n", mount->mount_id);
-    xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
+                /* We've reached the end of the array, no appropirate
+                 * handler found. Warn, ignore and continue. */
+                FS_DEBUG("WARN: Unknown request type: %d\n", req->type);
+                mount->ring.req_cons++; 
+                break;
+            }
+            if(op->type == req->type)
+            {
+                /* There needs to be a dispatch handler */
+                assert(op->dispatch_handler != NULL);
+                op->dispatch_handler(mount, req);
+                break;
+            }
+        }
+
+        nr_consumed++;
+    }
+    FS_DEBUG("Backend consumed: %d requests\n", nr_consumed);
+    RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
+    if(more) goto moretodo;
+
+    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
+    FS_DEBUG("Pushed responces and notify=%d\n", notify);
+    if(notify)
+        xc_evtchn_notify(mount->evth, mount->local_evtchn);
+}
+
+static void terminate_mount_request(struct fs_mount *mount) {
+    int count = 0, i;
+
+    FS_DEBUG("terminate_mount_request %s\n", mount->frontend);
+    xenbus_write_backend_state(mount, STATE_CLOSING);
+
+    for(i=0; i<mount->nr_entries; i++)
+        if(mount->requests[i].active) {
+            mount->requests[i].active = -1;
+            aio_cancel(mount->requests[i].aiocb.aio_fildes, 
&mount->requests[i].aiocb);
+            count--;
+        }
+    mount->nr_entries = count;
+
+    while (!xenbus_frontend_state_changed(mount, STATE_CLOSING));
+    xenbus_write_backend_state(mount, STATE_CLOSED);
+
+    xc_gnttab_munmap(mount->gnth, mount->ring.sring, mount->shared_ring_size);
     xc_gnttab_close(mount->gnth);
     xc_evtchn_unbind(mount->evth, mount->local_evtchn);
     xc_evtchn_close(mount->evth);
+
+    if (!count)
+        free_mount_request(mount);
+}
+
+static void free_mount_request(struct fs_mount *mount) {
+    FS_DEBUG("free_mount_request %s\n", mount->frontend);
     free(mount->frontend);
-    pthread_exit(NULL);
+    free(mount->requests);
+    free(mount->freelist);
+    LIST_REMOVE (mount, entries);
+    free(mount);
 }
 
 static void handle_connection(int frontend_dom_id, int export_id, char 
*frontend)
 {
     struct fs_mount *mount;
     struct fs_export *export;
-    int evt_port;
-    pthread_t handling_thread;
     struct fsif_sring *sring;
     uint32_t dom_ids[MAX_RING_SIZE];
     int i;
 
-    printf("Handling connection from dom=%d, for export=%d\n", 
+    FS_DEBUG("Handling connection from dom=%d, for export=%d\n", 
             frontend_dom_id, export_id);
     /* Try to find the export on the list */
     export = fs_exports;
@@ -214,7 +199,7 @@ static void handle_connection(int fronte
     }
     if(!export)
     {
-        printf("Could not find the export (the id is unknown).\n");
+        FS_DEBUG("Could not find the export (the id is unknown).\n");
         return;
     }
 
@@ -223,7 +208,7 @@ static void handle_connection(int fronte
     mount->export = export;
     mount->mount_id = mount_id++;
     xenbus_read_mount_request(mount, frontend);
-    printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
+    FS_DEBUG("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
             mount->frontend, mount->grefs[0], mount->remote_evtchn);
     xenbus_write_backend_node(mount);
     mount->evth = -1;
@@ -249,18 +234,24 @@ static void handle_connection(int fronte
     mount->nr_entries = mount->ring.nr_ents; 
     for (i = 0; i < MAX_FDS; i++)
         mount->fds[i] = -1;
-    xenbus_write_backend_ready(mount);
-
-    pthread_create(&handling_thread, NULL, &handle_mount, mount);
+
+    LIST_INSERT_HEAD(&mount_requests_head, mount, entries);
+    xenbus_watch_frontend_state(mount);
+    xenbus_write_backend_state(mount, STATE_READY);
+    
+    allocate_request_array(mount);
 }
 
 static void await_connections(void)
 {
-    int fd, ret, dom_id, export_id; 
+    int fd, max_fd, ret, dom_id, export_id; 
     fd_set fds;
     char **watch_paths;
     unsigned int len;
     char d;
+    struct fs_mount *pointer;
+
+    LIST_INIT (&mount_requests_head);
 
     assert(xsh != NULL);
     fd = xenbus_get_watch_fd(); 
@@ -268,28 +259,97 @@ static void await_connections(void)
     do {
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
-        ret = select(fd+1, &fds, NULL, NULL, NULL);
-        assert(ret == 1);
-        watch_paths = xs_read_watch(xsh, &len);
-        assert(len == 2);
-        assert(strcmp(watch_paths[1], "conn-watch") == 0);
-        dom_id = -1;
-        export_id = -1;
-       d = 0;
-        printf("Path changed %s\n", watch_paths[0]);
-        sscanf(watch_paths[0], WATCH_NODE"/%d/%d/fronten%c", 
-                &dom_id, &export_id, &d);
-        if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
-           char *frontend = xs_read(xsh, XBT_NULL, watch_paths[0], NULL);
-           if (frontend) {
-               handle_connection(dom_id, export_id, frontend);
-               xs_rm(xsh, XBT_NULL, watch_paths[0]);
-           }
-       }
-next_select:        
-        printf("Awaiting next connection.\n");
-        /* TODO - we need to figure out what to free */
-       free(watch_paths);
+       FD_SET(pipefds[0], &fds);
+        max_fd = fd > pipefds[0] ? fd : pipefds[0];
+        LIST_FOREACH(pointer, &mount_requests_head, entries) {
+            int tfd = xc_evtchn_fd(pointer->evth);
+            FD_SET(tfd, &fds);
+            if (tfd > max_fd) max_fd = tfd;
+        }
+        ret = select(max_fd+1, &fds, NULL, NULL, NULL);
+        if (ret < 0) {
+            if (errno == EINTR) continue;
+            /* try to recover */
+            else if (errno == EBADF) {
+                struct timeval timeout;
+                memset(&timeout, 0x00, sizeof(timeout));
+                FD_ZERO(&fds);
+                FD_SET(fd, &fds);
+                FD_SET(pipefds[0], &fds);
+                max_fd = fd > pipefds[0] ? fd : pipefds[0];
+                ret = select(max_fd + 1, &fds, NULL, NULL, &timeout);
+                if (ret < 0)
+                    err(1, "select: unrecoverable error occurred: %d\n", 
errno);
+
+                /* trying to find the bogus fd among the open event channels */
+                LIST_FOREACH(pointer, &mount_requests_head, entries) {
+                    int tfd = xc_evtchn_fd(pointer->evth);
+                    memset(&timeout, 0x00, sizeof(timeout));
+                    FD_ZERO(&fds);
+                    FD_SET(tfd, &fds);
+                    ret = select(tfd + 1, &fds, NULL, NULL, &timeout);
+                    if (ret < 0) {
+                        FS_DEBUG("fd %d is bogus, closing the related 
connection\n", tfd);
+                        pointer->evth = fd;
+                        terminate_mount_request(pointer);
+                        continue;
+                    }
+                }
+                continue;
+            } else
+                err(1, "select: unrecoverable error occurred: %d\n", errno);
+        }
+        if (FD_ISSET(fd, &fds)) {
+            watch_paths = xs_read_watch(xsh, &len);
+            if (!strcmp(watch_paths[XS_WATCH_TOKEN], "conn-watch")) {
+                dom_id = -1;
+                export_id = -1;
+                d = 0;
+                FS_DEBUG("Path changed %s\n", watch_paths[0]);
+                sscanf(watch_paths[XS_WATCH_PATH], 
WATCH_NODE"/%d/%d/fronten%c", 
+                        &dom_id, &export_id, &d);
+                if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
+                    char *frontend = xs_read(xsh, XBT_NULL, 
watch_paths[XS_WATCH_PATH], NULL);
+                    if (frontend) {
+                        handle_connection(dom_id, export_id, frontend);
+                        xs_rm(xsh, XBT_NULL, watch_paths[XS_WATCH_PATH]);
+                    }
+                }
+            } else if (!strcmp(watch_paths[XS_WATCH_TOKEN], "frontend-state")) 
{
+                LIST_FOREACH(pointer, &mount_requests_head, entries) {
+                    if (!strncmp(pointer->frontend, 
watch_paths[XS_WATCH_PATH], strlen(pointer->frontend))) {
+                        char *state = xenbus_read_frontend_state(pointer);
+                        if (!state || strcmp(state, STATE_READY)) {
+                            xenbus_unwatch_frontend_state(pointer);
+                            terminate_mount_request(pointer);
+                        }
+                        free(state);
+                        break;
+                    }
+                }
+            } else {
+                FS_DEBUG("xenstore watch event unrecognized\n");
+            }
+            FS_DEBUG("Awaiting next connection.\n");
+            /* TODO - we need to figure out what to free */
+            free(watch_paths);
+        }
+        if (FD_ISSET(pipefds[0], &fds)) {
+            struct fs_request *request;
+            if (read_exact(pipefds[0], &request, sizeof(struct fs_request *)) 
< 0)
+                err(1, "read request failed\n");
+            handle_aio_event(request); 
+        }
+        LIST_FOREACH(pointer, &mount_requests_head, entries) {
+            if (FD_ISSET(xc_evtchn_fd(pointer->evth), &fds)) {
+                evtchn_port_t port;
+                port = xc_evtchn_pending(pointer->evth);
+                if (port != -1) {
+                    handle_mount(pointer);
+                    xc_evtchn_unmask(pointer->evth, port);
+                }
+            }
+        }
     } while (1);
 }
 
@@ -312,10 +372,29 @@ static struct fs_export* create_export(c
     return curr_export;
 }
 
+static void aio_signal_handler(int signo, siginfo_t *info, void *context)
+{
+    struct fs_request *request = (struct fs_request*) info->si_value.sival_ptr;
+    int saved_errno = errno;
+    if (write_exact(pipefds[1], &request, sizeof(struct fs_request *)) < 0)
+        err(1, "write request filed\n");
+    errno = saved_errno;
+}
 
 int main(void)
 {
     struct fs_export *export;
+    struct sigaction act;
+    sigset_t enable;
+
+    sigemptyset(&enable);
+    sigaddset(&enable, SIGUSR2);
+    pthread_sigmask(SIG_UNBLOCK, &enable, NULL);
+
+    sigfillset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO; /* do not restart syscalls to interrupt 
select(); use sa_sigaction */
+    act.sa_sigaction = aio_signal_handler;
+    sigaction(SIGUSR2, &act, NULL);
 
     /* Open the connection to XenStore first */
     xsh = xs_domain_open();
@@ -327,6 +406,9 @@ int main(void)
     /* Create & register the default export */
     export = create_export("default", "/exports");
     xenbus_register_export(export);
+
+    if (socketpair(PF_UNIX,SOCK_STREAM, 0, pipefds) == -1)
+        err(1, "failed to create pipe\n");
 
     await_connections();
     /* Close the connection to XenStore when we are finished with everything */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/fs-backend.h
--- a/tools/fs-back/fs-backend.h        Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/fs-back/fs-backend.h        Fri Mar 27 11:07:11 2009 +0900
@@ -7,6 +7,7 @@
 #include <xen/event_channel.h>
 #include <xen/io/ring.h>
 #include <xen/io/fsif.h>
+#include "sys-queue.h"
 
 #define ROOT_NODE           "backend/vfs"
 #define EXPORTS_SUBNODE     "exports"
@@ -25,6 +26,8 @@ struct fs_export
 
 struct fs_request
 {
+    struct fs_mount *mount;
+    int id;
     int active;
     void *page;                         /* Pointer to mapped grant */
     int count;
@@ -50,6 +53,7 @@ struct fs_mount
     struct fs_request *requests;
     unsigned short *freelist;
     int fds[MAX_FDS];
+    LIST_ENTRY(fs_mount) entries;
 };
 
 
@@ -61,7 +65,11 @@ int xenbus_get_watch_fd(void);
 int xenbus_get_watch_fd(void);
 void xenbus_read_mount_request(struct fs_mount *mount, char *frontend);
 void xenbus_write_backend_node(struct fs_mount *mount);
-void xenbus_write_backend_ready(struct fs_mount *mount);
+void xenbus_write_backend_state(struct fs_mount *mount, const char *state);
+int xenbus_frontend_state_changed(struct fs_mount *mount, const char 
*oldstate);
+void xenbus_watch_frontend_state(struct fs_mount *mount);
+void xenbus_unwatch_frontend_state(struct fs_mount *mount);
+char* xenbus_read_frontend_state(struct fs_mount *mount);
 
 /* File operations, implemented in fs-ops.c */
 struct fs_op
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/fs-debug.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/fs-debug.h  Fri Mar 27 11:07:11 2009 +0900
@@ -0,0 +1,12 @@
+#ifndef __FS_DEBUG__
+#define __FS_DEBUG__
+
+// #define DEBUG 1
+
+#ifdef DEBUG
+#define FS_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while 
(0)
+#else
+#define FS_DEBUG(fmt, ...) do { } while (0)
+#endif
+
+#endif /*__FS_DEBUG__*/
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/fs-ops.c
--- a/tools/fs-back/fs-ops.c    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/fs-back/fs-ops.c    Fri Mar 27 11:07:11 2009 +0900
@@ -14,6 +14,7 @@
 #include <sys/mount.h>
 #include <unistd.h>
 #include "fs-backend.h"
+#include "fs-debug.h"
 
 /* For debugging only */
 #include <sys/time.h>
@@ -22,12 +23,11 @@
 
 #define BUFFER_SIZE 1024
 
-
 static unsigned short get_request(struct fs_mount *mount, struct fsif_request 
*req)
 {
     unsigned short id = get_id_from_freelist(mount->freelist); 
 
-    printf("Private Request id: %d\n", id);
+    FS_DEBUG("Private Request id: %d\n", id);
     memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
     mount->requests[id].active = 1;
 
@@ -49,12 +49,11 @@ static void dispatch_file_open(struct fs
 {
     char *file_name, full_path[BUFFER_SIZE];
     int fd;
-    struct timeval tv1, tv2;
-    RING_IDX rsp_idx;
-    fsif_response_t *rsp;
-    uint16_t req_id;
-
-    printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
+    RING_IDX rsp_idx;
+    fsif_response_t *rsp;
+    uint16_t req_id;
+
+    FS_DEBUG("Dispatching file open operation (gref=%d).\n", 
req->u.fopen.gref);
     /* Read the request, and open file */
     file_name = xc_gnttab_map_grant_ref(mount->gnth,
                                         mount->dom_id,
@@ -62,13 +61,13 @@ static void dispatch_file_open(struct fs
                                         PROT_READ);
    
     req_id = req->id;
-    printf("File open issued for %s\n", file_name); 
+    FS_DEBUG("File open issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
            mount->export->export_path, file_name);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    printf("Issuing open for %s\n", full_path);
+    FS_DEBUG("Issuing open for %s\n", full_path);
     fd = get_fd(mount);
     if (fd >= 0) {
         int real_fd = open(full_path, O_RDWR);
@@ -77,7 +76,7 @@ static void dispatch_file_open(struct fs
         else
         {
             mount->fds[fd] = real_fd;
-            printf("Got FD: %d for real %d\n", fd, real_fd);
+            FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd);
         }
     }
     /* We can advance the request consumer index, from here on, the request
@@ -87,7 +86,7 @@ static void dispatch_file_open(struct fs
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)fd;
@@ -100,7 +99,7 @@ static void dispatch_file_close(struct f
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
+    FS_DEBUG("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
    
     req_id = req->id;
     if (req->u.fclose.fd < MAX_FDS) {
@@ -109,15 +108,15 @@ static void dispatch_file_close(struct f
         mount->fds[req->u.fclose.fd] = -1;
     } else
         ret = -1;
-    printf("Got ret: %d\n", ret);
-    /* We can advance the request consumer index, from here on, the request
-     * should not be used (it may be overrinden by a response) */
-    mount->ring.req_cons++;
-
-
-    /* Get a response from the ring */
-    rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Got ret: %d\n", ret);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -127,7 +126,7 @@ static void dispatch_file_read(struct fs
 static void dispatch_file_read(struct fs_mount *mount, struct fsif_request 
*req)
 {
     void *buf;
-    int fd, i, count;
+    int fd, count;
     uint16_t req_id;
     unsigned short priv_id;
     struct fs_request *priv_req;
@@ -143,7 +142,7 @@ static void dispatch_file_read(struct fs
                                           PROT_WRITE);
    
     req_id = req->id;
-    printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
+    FS_DEBUG("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
             req->u.fread.fd, req->u.fread.len, req->u.fread.offset); 
 
     if (req->u.fread.fd < MAX_FDS)
@@ -152,10 +151,11 @@ static void dispatch_file_read(struct fs
         fd = -1;
 
     priv_id = get_request(mount, req);
-    printf("Private id is: %d\n", priv_id);
+    FS_DEBUG("Private id is: %d\n", priv_id);
     priv_req = &mount->requests[priv_id];
     priv_req->page = buf;
     priv_req->count = count;
+    priv_req->id = priv_id;
 
     /* Dispatch AIO read request */
     bzero(&priv_req->aiocb, sizeof(struct aiocb));
@@ -163,9 +163,11 @@ static void dispatch_file_read(struct fs
     priv_req->aiocb.aio_nbytes = req->u.fread.len;
     priv_req->aiocb.aio_offset = req->u.fread.offset;
     priv_req->aiocb.aio_buf = buf;
+    priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+    priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
+    priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
     assert(aio_read(&priv_req->aiocb) >= 0);
 
-out: 
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
     mount->ring.req_cons++;
@@ -185,7 +187,7 @@ static void end_file_read(struct fs_moun
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
     req_id = priv_req->req_shadow.id; 
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
@@ -194,7 +196,7 @@ static void dispatch_file_write(struct f
 static void dispatch_file_write(struct fs_mount *mount, struct fsif_request 
*req)
 {
     void *buf;
-    int fd, count, i;
+    int fd, count;
     uint16_t req_id;
     unsigned short priv_id;
     struct fs_request *priv_req;
@@ -210,7 +212,7 @@ static void dispatch_file_write(struct f
                                           PROT_READ);
    
     req_id = req->id;
-    printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
+    FS_DEBUG("File write issued for FD=%d (len=%"PRIu64", 
offest=%"PRIu64")\n", 
             req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset); 
    
     if (req->u.fwrite.fd < MAX_FDS)
@@ -219,10 +221,11 @@ static void dispatch_file_write(struct f
         fd = -1;
 
     priv_id = get_request(mount, req);
-    printf("Private id is: %d\n", priv_id);
+    FS_DEBUG("Private id is: %d\n", priv_id);
     priv_req = &mount->requests[priv_id];
     priv_req->page = buf;
     priv_req->count = count;
+    priv_req->id = priv_id;
 
     /* Dispatch AIO write request */
     bzero(&priv_req->aiocb, sizeof(struct aiocb));
@@ -230,6 +233,9 @@ static void dispatch_file_write(struct f
     priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
     priv_req->aiocb.aio_offset = req->u.fwrite.offset;
     priv_req->aiocb.aio_buf = buf;
+    priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+    priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
+    priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
     assert(aio_write(&priv_req->aiocb) >= 0);
 
      
@@ -252,7 +258,7 @@ static void end_file_write(struct fs_mou
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
     req_id = priv_req->req_shadow.id; 
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
@@ -260,7 +266,6 @@ static void end_file_write(struct fs_mou
 
 static void dispatch_stat(struct fs_mount *mount, struct fsif_request *req)
 {
-    struct fsif_stat_response *buf;
     struct stat stat;
     int fd, ret;
     uint16_t req_id;
@@ -273,7 +278,7 @@ static void dispatch_stat(struct fs_moun
     else
         fd = -1;
 
-    printf("File stat issued for FD=%d\n", req->u.fstat.fd); 
+    FS_DEBUG("File stat issued for FD=%d\n", req->u.fstat.fd); 
    
     /* We can advance the request consumer index, from here on, the request
      * should not be used (it may be overrinden by a response) */
@@ -281,12 +286,12 @@ static void dispatch_stat(struct fs_moun
    
     /* Stat, and create the response */ 
     ret = fstat(fd, &stat);
-    printf("Mode=%o, uid=%d, a_time=%ld\n",
+    FS_DEBUG("Mode=%o, uid=%d, a_time=%ld\n",
             stat.st_mode, stat.st_uid, (long)stat.st_atime);
     
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->fstat.stat_ret = (uint32_t)ret;
@@ -320,7 +325,7 @@ static void dispatch_truncate(struct fs_
 
     req_id = req->id;
     length = req->u.ftruncate.length;
-    printf("File truncate issued for FD=%d, length=%"PRId64"\n", 
req->u.ftruncate.fd, length); 
+    FS_DEBUG("File truncate issued for FD=%d, length=%"PRId64"\n", 
req->u.ftruncate.fd, length); 
    
     if (req->u.ftruncate.fd < MAX_FDS)
         fd = mount->fds[req->u.ftruncate.fd];
@@ -336,7 +341,7 @@ static void dispatch_truncate(struct fs_
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -350,7 +355,7 @@ static void dispatch_remove(struct fs_mo
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
+    FS_DEBUG("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
     /* Read the request, and open file */
     file_name = xc_gnttab_map_grant_ref(mount->gnth,
                                         mount->dom_id,
@@ -358,23 +363,23 @@ static void dispatch_remove(struct fs_mo
                                         PROT_READ);
    
     req_id = req->id;
-    printf("File remove issued for %s\n", file_name); 
+    FS_DEBUG("File remove issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
            mount->export->export_path, file_name);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    printf("Issuing remove for %s\n", full_path);
+    FS_DEBUG("Issuing remove for %s\n", full_path);
     ret = remove(full_path);
-    printf("Got ret: %d\n", ret);
-    /* We can advance the request consumer index, from here on, the request
-     * should not be used (it may be overrinden by a response) */
-    mount->ring.req_cons++;
-
-
-    /* Get a response from the ring */
-    rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Got ret: %d\n", ret);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -390,7 +395,7 @@ static void dispatch_rename(struct fs_mo
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
+    FS_DEBUG("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
     /* Read the request, and open file */
     buf = xc_gnttab_map_grant_ref(mount->gnth,
                                   mount->dom_id,
@@ -400,7 +405,7 @@ static void dispatch_rename(struct fs_mo
     req_id = req->id;
     old_file_name = buf + req->u.frename.old_name_offset;
     new_file_name = buf + req->u.frename.new_name_offset;
-    printf("File rename issued for %s -> %s (buf=%s)\n", 
+    FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n", 
             old_file_name, new_file_name, buf); 
     assert(BUFFER_SIZE > 
            strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
@@ -411,17 +416,17 @@ static void dispatch_rename(struct fs_mo
     snprintf(new_full_path, sizeof(new_full_path), "%s/%s",
            mount->export->export_path, new_file_name);
     assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
-    printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
+    FS_DEBUG("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
     ret = rename(old_full_path, new_full_path);
-    printf("Got ret: %d\n", ret);
-    /* We can advance the request consumer index, from here on, the request
-     * should not be used (it may be overrinden by a response) */
-    mount->ring.req_cons++;
-
-
-    /* Get a response from the ring */
-    rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Got ret: %d\n", ret);
+    /* We can advance the request consumer index, from here on, the request
+     * should not be used (it may be overrinden by a response) */
+    mount->ring.req_cons++;
+
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -438,7 +443,7 @@ static void dispatch_create(struct fs_mo
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching file create operation (gref=%d).\n", 
req->u.fcreate.gref);
+    FS_DEBUG("Dispatching file create operation (gref=%d).\n", 
req->u.fcreate.gref);
     /* Read the request, and create file/directory */
     mode = req->u.fcreate.mode;
     directory = req->u.fcreate.directory;
@@ -448,7 +453,7 @@ static void dispatch_create(struct fs_mo
                                         PROT_READ);
    
     req_id = req->id;
-    printf("File create issued for %s\n", file_name); 
+    FS_DEBUG("File create issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
@@ -460,12 +465,12 @@ static void dispatch_create(struct fs_mo
 
     if(directory)
     {
-        printf("Issuing create for directory: %s\n", full_path);
+        FS_DEBUG("Issuing create for directory: %s\n", full_path);
         ret = mkdir(full_path, mode);
     }
     else
     {
-        printf("Issuing create for file: %s\n", full_path);
+        FS_DEBUG("Issuing create for file: %s\n", full_path);
         ret = get_fd(mount);
         if (ret >= 0) {
             int real_fd = creat(full_path, mode); 
@@ -474,15 +479,15 @@ static void dispatch_create(struct fs_mo
             else
             {
                 mount->fds[ret] = real_fd;
-                printf("Got FD: %d for real %d\n", ret, real_fd);
+                FS_DEBUG("Got FD: %d for real %d\n", ret, real_fd);
             }
         }
     }
-    printf("Got ret %d (errno=%d)\n", ret, errno);
-
-    /* Get a response from the ring */
-    rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno);
+
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -499,7 +504,7 @@ static void dispatch_list(struct fs_moun
     DIR *dir;
     struct dirent *dirent = NULL;
 
-    printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
+    FS_DEBUG("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
     /* Read the request, and list directory */
     offset = req->u.flist.offset;
     buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
@@ -508,7 +513,7 @@ static void dispatch_list(struct fs_moun
                                         PROT_READ | PROT_WRITE);
    
     req_id = req->id;
-    printf("Dir list issued for %s\n", file_name); 
+    FS_DEBUG("Dir list issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
@@ -552,7 +557,7 @@ error_out:
     
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = ret_val;
@@ -566,7 +571,7 @@ static void dispatch_chmod(struct fs_mou
     uint16_t req_id;
     int32_t mode;
 
-    printf("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
+    FS_DEBUG("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
             req->u.fchmod.fd, req->u.fchmod.mode);
     req_id = req->id;
     if (req->u.fchmod.fd < MAX_FDS)
@@ -583,7 +588,7 @@ static void dispatch_chmod(struct fs_mou
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -598,7 +603,7 @@ static void dispatch_fs_space(struct fs_
     struct statvfs stat;
     int64_t ret;
 
-    printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
+    FS_DEBUG("Dispatching fs space operation (gref=%d).\n", 
req->u.fspace.gref);
     /* Read the request, and open file */
     file_name = xc_gnttab_map_grant_ref(mount->gnth,
                                         mount->dom_id,
@@ -606,13 +611,13 @@ static void dispatch_fs_space(struct fs_
                                         PROT_READ);
    
     req_id = req->id;
-    printf("Fs space issued for %s\n", file_name); 
+    FS_DEBUG("Fs space issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
            mount->export->export_path, file_name);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    printf("Issuing fs space for %s\n", full_path);
+    FS_DEBUG("Issuing fs space for %s\n", full_path);
     ret = statvfs(full_path, &stat);
     if(ret >= 0)
         ret = stat.f_bsize * stat.f_bfree;
@@ -624,7 +629,7 @@ static void dispatch_fs_space(struct fs_
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)ret;
@@ -643,15 +648,19 @@ static void dispatch_file_sync(struct fs
     else
         fd = -1;
 
-    printf("File sync issued for FD=%d\n", req->u.fsync.fd); 
+    FS_DEBUG("File sync issued for FD=%d\n", req->u.fsync.fd); 
    
     priv_id = get_request(mount, req);
-    printf("Private id is: %d\n", priv_id);
+    FS_DEBUG("Private id is: %d\n", priv_id);
     priv_req = &mount->requests[priv_id];
+    priv_req->id = priv_id;
 
     /* Dispatch AIO read request */
     bzero(&priv_req->aiocb, sizeof(struct aiocb));
     priv_req->aiocb.aio_fildes = fd;
+    priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+    priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
+    priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
     assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
 
      
@@ -669,7 +678,7 @@ static void end_file_sync(struct fs_moun
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
     req_id = priv_req->req_shadow.id; 
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
     rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
     rsp->id = req_id; 
     rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/fs-xenbus.c
--- a/tools/fs-back/fs-xenbus.c Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/fs-back/fs-xenbus.c Fri Mar 27 11:07:11 2009 +0900
@@ -4,10 +4,12 @@
 #include <stdarg.h>
 #include <string.h>
 #include <assert.h>
+#include <sys/select.h>
 #include <xenctrl.h>
 #include <xs.h>
 #include <xen/io/fsif.h>
 #include "fs-backend.h"
+#include "fs-debug.h"
 
 
 static bool xenbus_printf(struct xs_handle *xsh,
@@ -25,7 +27,7 @@ static bool xenbus_printf(struct xs_hand
     snprintf(fullpath, sizeof(fullpath), "%s/%s", node, path);
     vsnprintf(val, sizeof(val), fmt, args);
     va_end(args);
-    printf("xenbus_printf (%s) <= %s.\n", fullpath, val);    
+    FS_DEBUG("xenbus_printf (%s) <= %s.\n", fullpath, val);    
 
     return xs_write(xsh, xbt, fullpath, val, strlen(val));
 }
@@ -57,19 +59,19 @@ int xenbus_register_export(struct fs_exp
     assert(xsh != NULL);
     if(xsh == NULL)
     {
-        printf("Could not open connection to xenbus deamon.\n");
-        goto error_exit;
-    }
-    printf("Connection to the xenbus deamon opened successfully.\n");
+        FS_DEBUG("Could not open connection to xenbus deamon.\n");
+        goto error_exit;
+    }
+    FS_DEBUG("Connection to the xenbus deamon opened successfully.\n");
 
     /* Start transaction */
     xst = xs_transaction_start(xsh);
     if(xst == 0)
     {
-        printf("Could not start a transaction.\n");
-        goto error_exit;
-    }
-    printf("XS transaction is %d\n", xst); 
+        FS_DEBUG("Could not start a transaction.\n");
+        goto error_exit;
+    }
+    FS_DEBUG("XS transaction is %d\n", xst); 
  
     /* Create node string */
     snprintf(node, sizeof(node), "%s/%d", EXPORTS_NODE, export->export_id); 
@@ -78,7 +80,7 @@ int xenbus_register_export(struct fs_exp
 
     if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
     {
-        printf("Could not write the export node.\n");
+        FS_DEBUG("Could not write the export node.\n");
         goto error_exit;
     }
 
@@ -87,7 +89,7 @@ int xenbus_register_export(struct fs_exp
     perms.perms = XS_PERM_READ;
     if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
     {
-        printf("Could not set permissions on the export node.\n");
+        FS_DEBUG("Could not set permissions on the export node.\n");
         goto error_exit;
     }
 
@@ -166,7 +168,7 @@ void xenbus_write_backend_node(struct fs
 
     assert(xsh != NULL);
     self_id = get_self_id();
-    printf("Our own dom_id=%d\n", self_id);
+    FS_DEBUG("Our own dom_id=%d\n", self_id);
     snprintf(node, sizeof(node), "%s/backend", mount->frontend);
     snprintf(backend_node, sizeof(backend_node), 
"/local/domain/%d/"ROOT_NODE"/%d",
                                 self_id, mount->mount_id);
@@ -176,7 +178,7 @@ void xenbus_write_backend_node(struct fs
     xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, 
strlen(STATE_INITIALISED));
 }
 
-void xenbus_write_backend_ready(struct fs_mount *mount)
+void xenbus_write_backend_state(struct fs_mount *mount, const char *state)
 {
     char node[1024];
     int self_id;
@@ -184,6 +186,59 @@ void xenbus_write_backend_ready(struct f
     assert(xsh != NULL);
     self_id = get_self_id();
     snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
-    xs_write(xsh, XBT_NULL, node, STATE_READY, strlen(STATE_READY));
-}
-
+    xs_write(xsh, XBT_NULL, node, state, strlen(state));
+}
+
+void xenbus_watch_frontend_state(struct fs_mount *mount)
+{
+    int res;
+    char statepath[1024];
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    res = xs_watch(xsh, statepath, "frontend-state");
+    assert(res);
+}
+
+void xenbus_unwatch_frontend_state(struct fs_mount *mount)
+{
+    int res;
+    char statepath[1024];
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    res = xs_unwatch(xsh, statepath, "frontend-state");
+    assert(res);
+}
+
+int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate)
+{
+    unsigned int len;
+    char statepath[1024];
+    char *state = NULL;
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    state = xs_read(xsh, XBT_NULL, statepath, &len);
+    if (state && len > 0) {
+        if (strcmp(state, oldstate)) {
+            free(state);
+            return 1;
+        } else {
+            free(state);
+            return 0;
+        }
+    } else
+        return 1;
+}
+
+char* xenbus_read_frontend_state(struct fs_mount *mount)
+{
+    unsigned int len;
+    char statepath[1024];
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    return xs_read(xsh, XBT_NULL, statepath, &len);
+}
+
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/fs-back/sys-queue.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/sys-queue.h Fri Mar 27 11:07:11 2009 +0900
@@ -0,0 +1,338 @@
+/*      $NetBSD: queue.h,v 1.45.14.1 2007/07/18 20:13:24 liamjfoy Exp $ */
+
+/*
+ * Qemu version: Copy from netbsd, removed debug code, removed some of
+ * the implementations.  Left in lists, tail queues and circular queues.
+ */
+
+/*
+ * Copyright (c) 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)queue.h     8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines three types of data structures:
+ * lists, tail queues, and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)                                           \
+struct name {                                                           \
+        struct type *lh_first;  /* first element */                     \
+}
+
+#define LIST_HEAD_INITIALIZER(head)                                     \
+        { NULL }
+
+#define LIST_ENTRY(type)                                                \
+struct {                                                                \
+        struct type *le_next;   /* next element */                      \
+        struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do {                                            \
+        (head)->lh_first = NULL;                                        \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do {                     \
+        if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
+                (listelm)->field.le_next->field.le_prev =               \
+                    &(elm)->field.le_next;                              \
+        (listelm)->field.le_next = (elm);                               \
+        (elm)->field.le_prev = &(listelm)->field.le_next;               \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
+        (elm)->field.le_prev = (listelm)->field.le_prev;                \
+        (elm)->field.le_next = (listelm);                               \
+        *(listelm)->field.le_prev = (elm);                              \
+        (listelm)->field.le_prev = &(elm)->field.le_next;               \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do {                         \
+        if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
+                (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+        (head)->lh_first = (elm);                                       \
+        (elm)->field.le_prev = &(head)->lh_first;                       \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do {                                    \
+        if ((elm)->field.le_next != NULL)                               \
+                (elm)->field.le_next->field.le_prev =                   \
+                    (elm)->field.le_prev;                               \
+        *(elm)->field.le_prev = (elm)->field.le_next;                   \
+} while (/*CONSTCOND*/0)
+
+#define LIST_FOREACH(var, head, field)                                  \
+        for ((var) = ((head)->lh_first);                                \
+                (var);                                                  \
+                (var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define LIST_EMPTY(head)                ((head)->lh_first == NULL)
+#define LIST_FIRST(head)                ((head)->lh_first)
+#define LIST_NEXT(elm, field)           ((elm)->field.le_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual)                                   \
+struct name {                                                           \
+        qual type *tqh_first;           /* first element */             \
+        qual type *qual *tqh_last;      /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type)  _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head)                                    \
+        { NULL, &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual)                                        \
+struct {                                                                \
+        qual type *tqe_next;            /* next element */              \
+        qual type *qual *tqe_prev;      /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type)       _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do {                                           \
+        (head)->tqh_first = NULL;                                       \
+        (head)->tqh_last = &(head)->tqh_first;                          \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do {                        \
+        if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
+                (head)->tqh_first->field.tqe_prev =                     \
+                    &(elm)->field.tqe_next;                             \
+        else                                                            \
+                (head)->tqh_last = &(elm)->field.tqe_next;              \
+        (head)->tqh_first = (elm);                                      \
+        (elm)->field.tqe_prev = &(head)->tqh_first;                     \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do {                        \
+        (elm)->field.tqe_next = NULL;                                   \
+        (elm)->field.tqe_prev = (head)->tqh_last;                       \
+        *(head)->tqh_last = (elm);                                      \
+        (head)->tqh_last = &(elm)->field.tqe_next;                      \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
+        if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+                (elm)->field.tqe_next->field.tqe_prev =                 \
+                    &(elm)->field.tqe_next;                             \
+        else                                                            \
+                (head)->tqh_last = &(elm)->field.tqe_next;              \
+        (listelm)->field.tqe_next = (elm);                              \
+        (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+        (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+        (elm)->field.tqe_next = (listelm);                              \
+        *(listelm)->field.tqe_prev = (elm);                             \
+        (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do {                             \
+        if (((elm)->field.tqe_next) != NULL)                            \
+                (elm)->field.tqe_next->field.tqe_prev =                 \
+                    (elm)->field.tqe_prev;                              \
+        else                                                            \
+                (head)->tqh_last = (elm)->field.tqe_prev;               \
+        *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_FOREACH(var, head, field)                                 \
+        for ((var) = ((head)->tqh_first);                               \
+                (var);                                                  \
+                (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
+        for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));   
 \
+                (var);                                                  \
+                (var) = (*(((struct headname 
*)((var)->field.tqe_prev))->tqh_last)))
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_EMPTY(head)               ((head)->tqh_first == NULL)
+#define TAILQ_FIRST(head)               ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
+
+#define TAILQ_LAST(head, headname) \
+        (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)                                        \
+struct name {                                                           \
+        struct type *cqh_first;         /* first element */             \
+        struct type *cqh_last;          /* last element */              \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head)                                  \
+        { (void *)&head, (void *)&head }
+
+#define CIRCLEQ_ENTRY(type)                                             \
+struct {                                                                \
+        struct type *cqe_next;          /* next element */              \
+        struct type *cqe_prev;          /* previous element */          \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do {                                         \
+        (head)->cqh_first = (void *)(head);                             \
+        (head)->cqh_last = (void *)(head);                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {            \
+        (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
+        (elm)->field.cqe_prev = (listelm);                              \
+        if ((listelm)->field.cqe_next == (void *)(head))                \
+                (head)->cqh_last = (elm);                               \
+        else                                                            \
+                (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
+        (listelm)->field.cqe_next = (elm);                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {           \
+        (elm)->field.cqe_next = (listelm);                              \
+        (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
+        if ((listelm)->field.cqe_prev == (void *)(head))                \
+                (head)->cqh_first = (elm);                              \
+        else                                                            \
+                (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
+        (listelm)->field.cqe_prev = (elm);                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {                      \
+        (elm)->field.cqe_next = (head)->cqh_first;                      \
+        (elm)->field.cqe_prev = (void *)(head);                         \
+        if ((head)->cqh_last == (void *)(head))                         \
+                (head)->cqh_last = (elm);                               \
+        else                                                            \
+                (head)->cqh_first->field.cqe_prev = (elm);              \
+        (head)->cqh_first = (elm);                                      \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {                      \
+        (elm)->field.cqe_next = (void *)(head);                         \
+        (elm)->field.cqe_prev = (head)->cqh_last;                       \
+        if ((head)->cqh_first == (void *)(head))                        \
+                (head)->cqh_first = (elm);                              \
+        else                                                            \
+                (head)->cqh_last->field.cqe_next = (elm);               \
+        (head)->cqh_last = (elm);                                       \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do {                           \
+        if ((elm)->field.cqe_next == (void *)(head))                    \
+                (head)->cqh_last = (elm)->field.cqe_prev;               \
+        else                                                            \
+                (elm)->field.cqe_next->field.cqe_prev =                 \
+                    (elm)->field.cqe_prev;                              \
+        if ((elm)->field.cqe_prev == (void *)(head))                    \
+                (head)->cqh_first = (elm)->field.cqe_next;              \
+        else                                                            \
+                (elm)->field.cqe_prev->field.cqe_next =                 \
+                    (elm)->field.cqe_next;                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field)                               \
+        for ((var) = ((head)->cqh_first);                               \
+                (var) != (const void *)(head);                          \
+                (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field)                       \
+        for ((var) = ((head)->cqh_last);                                \
+                (var) != (const void *)(head);                          \
+                (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_EMPTY(head)             ((head)->cqh_first == (void *)(head))
+#define CIRCLEQ_FIRST(head)             ((head)->cqh_first)
+#define CIRCLEQ_LAST(head)              ((head)->cqh_last)
+#define CIRCLEQ_NEXT(elm, field)        ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field)        ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field)                             \
+        (((elm)->field.cqe_next == (void *)(head))                      \
+            ? ((head)->cqh_first)                                       \
+            : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field)                             \
+        (((elm)->field.cqe_prev == (void *)(head))                      \
+            ? ((head)->cqh_last)                                        \
+            : (elm->field.cqe_prev))
+
+#endif  /* !_SYS_QUEUE_H_ */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/hotplug/Linux/Makefile
--- a/tools/hotplug/Linux/Makefile      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/hotplug/Linux/Makefile      Fri Mar 27 11:07:11 2009 +0900
@@ -16,7 +16,6 @@ XEN_SCRIPTS += network-nat vif-nat
 XEN_SCRIPTS += network-nat vif-nat
 XEN_SCRIPTS += block
 XEN_SCRIPTS += block-enbd block-nbd
-XEN_SCRIPTS += blktap
 XEN_SCRIPTS += vtpm vtpm-delete
 XEN_SCRIPTS += xen-hotplug-cleanup
 XEN_SCRIPTS += external-device-migrate
@@ -30,7 +29,7 @@ XEN_HOTPLUG_SCRIPTS = xen-backend.agent
 XEN_HOTPLUG_SCRIPTS = xen-backend.agent
 
 UDEV_RULES_DIR = /etc/udev
-UDEV_RULES = xen-backend.rules
+UDEV_RULES = xen-backend.rules xend.rules
 
 DI = $(if $(DISTDIR),$(shell readlink -f $(DISTDIR)),)
 DE = $(if $(DESTDIR),$(shell readlink -f $(DESTDIR)),)
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/hotplug/Linux/blktap
--- a/tools/hotplug/Linux/blktap        Fri Mar 27 10:54:08 2009 +0900
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2005, XenSource Ltd.
-
-dir=$(dirname "$0")
-. "$dir/xen-hotplug-common.sh"
-. "$dir/block-common.sh"
-
-findCommand "$@"
-
-##
-# check_blktap_sharing file mode
-#
-# Perform the sharing check for the given blktap and mode.
-#
-check_blktap_sharing()
-{
-    local file="$1"
-    local mode="$2"
-
-    local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE"
-    for dom in $(xenstore-list "$base_path")
-    do
-        for dev in $(xenstore-list "$base_path/$dom")
-        do
-            params=$(xenstore_read "$base_path/$dom/$dev/params" | cut -d: -f2)
-            if [ "$file" = "$params" ]
-            then
-
-                if [ "$mode" = 'w' ]
-                then
-                    if ! same_vm "$dom" 
-                    then
-                        echo 'guest'
-                        return
-                    fi
-                else 
-                    local m=$(xenstore_read "$base_path/$dom/$dev/mode")
-                    m=$(canonicalise_mode "$m")
-
-                    if [ "$m" = 'w' ] 
-                    then
-                        if ! same_vm "$dom"
-                        then
-                            echo 'guest'
-                            return
-                        fi
-                    fi
-                fi
-            fi
-        done
-    done
-
-    echo 'ok'
-}
-
-
-t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
-if [ -n "$t" ]
-then
-    p=$(xenstore_read "$XENBUS_PATH/params")
-    # if we have a ':', chew from head including :
-    if echo $p | grep -q \:
-    then
-        p=${p#*:}
-    fi
-fi
-# some versions of readlink cannot be passed a regular file
-if [ -L "$p" ]; then
-    file=$(readlink -f "$p") || fatal "$p link does not exist."
-else
-    file="$p"
-fi
-
-if [ "$command" = 'add' ]
-then
-    [ -e "$file" ] || { fatal $file does not exist; }
-
-    FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id")
-    FRONTEND_UUID=$(xenstore_read "/local/domain/$FRONTEND_ID/vm")
-    mode=$(xenstore_read "$XENBUS_PATH/mode")
-    mode=$(canonicalise_mode "$mode")
-
-    if [ "$mode" != '!' ] 
-    then
-        result=$(check_blktap_sharing "$file" "$mode")
-        [ "$result" = 'ok' ] || ebusy "$file already in use by other domain"
-    fi
-
-    success
-fi
-
-exit 0
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/hotplug/Linux/xen-backend.rules
--- a/tools/hotplug/Linux/xen-backend.rules     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/hotplug/Linux/xen-backend.rules     Fri Mar 27 11:07:11 2009 +0900
@@ -1,4 +1,3 @@ SUBSYSTEM=="xen-backend", KERNEL=="tap*"
-SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} 
online"
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/hotplug/Linux/xen-hotplug-cleanup
--- a/tools/hotplug/Linux/xen-hotplug-cleanup   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/hotplug/Linux/xen-hotplug-cleanup   Fri Mar 27 11:07:11 2009 +0900
@@ -14,9 +14,13 @@ claim_lock "block"
 # split backend/DEVCLASS/VMID/DEVID on slashes
 path_array=( ${XENBUS_PATH//\// } )
 # get /vm/UUID path
-vm=$(xenstore-read "/local/domain/${path_array[2]}/vm")
+vm=$(xenstore_read_default "/local/domain/${path_array[2]}/vm" "")
 # construct /vm/UUID/device/DEVCLASS/DEVID
-vm_dev="$vm/device/${path_array[1]}/${path_array[3]}"
+if [ "$vm" != "" ]; then
+  vm_dev="$vm/device/${path_array[1]}/${path_array[3]}"
+else
+  vm_dev=
+fi
 
 # remove device frontend store entries
 xenstore-rm -t \
@@ -27,6 +31,6 @@ xenstore-rm -t "error/$XENBUS_PATH"  2>/
 xenstore-rm -t "error/$XENBUS_PATH"  2>/dev/null || true
 
 # remove device path from /vm/UUID
-xenstore-rm -t "$vm_dev" 2>/dev/null || true
+[ "$vm_dev" != "" ] && xenstore-rm -t "$vm_dev" 2>/dev/null || true
 
 release_lock "block"
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/hotplug/Linux/xend.rules
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/hotplug/Linux/xend.rules    Fri Mar 27 11:07:11 2009 +0900
@@ -0,0 +1,3 @@
+SUBSYSTEM=="pci", RUN+="socket:/org/xen/xend/udev_event"
+#SUBSYSTEM=="scsi", RUN+="socket:/org/xen/xend/udev_event"
+#SUBSYSTEM=="net", KERNEL!="vif[0-9]*.[0-9]*|tap[0-9]*.[0-9]*", 
RUN+="socket:/org/xen/xend/udev_event"
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/hotplug/NetBSD/Makefile
--- a/tools/hotplug/NetBSD/Makefile     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/hotplug/NetBSD/Makefile     Fri Mar 27 11:07:11 2009 +0900
@@ -2,14 +2,12 @@ include $(XEN_ROOT)/tools/Rules.mk
 include $(XEN_ROOT)/tools/Rules.mk
 
 # Xen configuration dir and configs to go there.
-XEN_CONFIG_DIR = $(PREFIX)/etc/xen
+XEN_CONFIG_DIR = /etc/xen
 
 # Xen script dir and scripts to go there.
-XEN_SCRIPT_DIR = $(PREFIX)/etc/xen/scripts
+XEN_SCRIPT_DIR = $(XEN_CONFIG_DIR)/scripts
 XEN_SCRIPTS =
 XEN_SCRIPTS += block-nbsd
-XEN_SCRIPTS += hvm-nbsd
-XEN_SCRIPTS += netbsd1-nbsd
 XEN_SCRIPTS += qemu-ifup-nbsd
 XEN_SCRIPTS += vif-bridge-nbsd
 XEN_SCRIPTS += vif-ip-nbsd
@@ -27,7 +25,7 @@ install: all install-scripts
 
 .PHONY: install-scripts
 install-scripts:
-       $(INSTALL_DATA_DIR) $(DESTDIR)$(XEN_SCRIPT_DIR)
+       $(INSTALL_DIR) $(DESTDIR)$(XEN_SCRIPT_DIR)
        set -e; for i in $(XEN_SCRIPTS); \
           do \
           $(INSTALL_DATA) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libfsimage/zfs/fsys_zfs.c
--- a/tools/libfsimage/zfs/fsys_zfs.c   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libfsimage/zfs/fsys_zfs.c   Fri Mar 27 11:07:11 2009 +0900
@@ -298,8 +298,7 @@ uberblock_verify(uberblock_phys_t *ub, i
                return (-1);
 
        if (uber->ub_magic == UBERBLOCK_MAGIC &&
-           uber->ub_version >= SPA_VERSION_1 &&
-           uber->ub_version <= SPA_VERSION)
+           uber->ub_version > 0 && uber->ub_version <= SPA_VERSION)
                return (0);
 
        return (-1);
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libfsimage/zfs/zfs-include/zfs.h
--- a/tools/libfsimage/zfs/zfs-include/zfs.h    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libfsimage/zfs/zfs-include/zfs.h    Fri Mar 27 11:07:11 2009 +0900
@@ -28,17 +28,7 @@
 /*
  * On-disk version number.
  */
-#define        SPA_VERSION_1                   1ULL
-#define        SPA_VERSION_2                   2ULL
-#define        SPA_VERSION_3                   3ULL
-#define        SPA_VERSION_4                   4ULL
-#define        SPA_VERSION_5                   5ULL
-#define        SPA_VERSION_6                   6ULL
-#define        SPA_VERSION_7                   7ULL
-#define        SPA_VERSION_8                   8ULL
-#define        SPA_VERSION_9                   9ULL
-#define        SPA_VERSION_10                  10ULL
-#define        SPA_VERSION                     SPA_VERSION_10
+#define        SPA_VERSION                     14ULL
 
 /*
  * The following are configuration names used in the nvlist describing a pool's
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/Makefile
--- a/tools/libxc/Makefile      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/Makefile      Fri Mar 27 11:07:11 2009 +0900
@@ -29,7 +29,7 @@ CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.
 CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
 
 GUEST_SRCS-y :=
-GUEST_SRCS-y += xg_private.c
+GUEST_SRCS-y += xg_private.c xc_suspend.c
 GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c
 GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xc_core.c     Fri Mar 27 11:07:11 2009 +0900
@@ -518,7 +518,17 @@ xc_domain_dumpcore_via_callback(int xc_h
     if ( sts != 0 )
         goto out;
 
+    /*
+     * Note: this is the *current* number of pages and may change under
+     * a live dump-core.  We'll just take this value, and if more pages
+     * exist, we'll skip them.  If there's less, then we'll just not use
+     * all the array...
+     *
+     * We don't want to use the total potential size of the memory map
+     * since that is usually much higher than info.nr_pages.
+     */
     nr_pages = info.nr_pages;
+
     if ( !auto_translated_physmap )
     {
         /* obtain p2m table */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_dom_x86.c
--- a/tools/libxc/xc_dom_x86.c  Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xc_dom_x86.c  Fri Mar 27 11:07:11 2009 +0900
@@ -694,7 +694,7 @@ int arch_setup_meminit(struct xc_dom_ima
 int arch_setup_meminit(struct xc_dom_image *dom)
 {
     int rc;
-    xen_pfn_t pfn;
+    xen_pfn_t pfn, allocsz, i;
 
     rc = x86_compat(dom->guest_xc, dom->guest_domid, dom->guest_type);
     if ( rc )
@@ -713,9 +713,15 @@ int arch_setup_meminit(struct xc_dom_ima
         dom->p2m_host[pfn] = pfn;
 
     /* allocate guest memory */
-    rc = xc_domain_memory_populate_physmap(dom->guest_xc, dom->guest_domid,
-                                           dom->total_pages, 0, 0,
-                                           dom->p2m_host);
+    for ( i = rc = allocsz = 0; (i < dom->total_pages) && !rc; i += allocsz )
+    {
+        allocsz = dom->total_pages - i;
+        if ( allocsz > 1024*1024 )
+            allocsz = 1024*1024;
+        rc = xc_domain_memory_populate_physmap(
+            dom->guest_xc, dom->guest_domid, allocsz, 0, 0, &dom->p2m_host[i]);
+    }
+
     return rc;
 }
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xc_domain_save.c      Fri Mar 27 11:07:11 2009 +0900
@@ -743,8 +743,6 @@ static xen_pfn_t *map_and_save_p2m_table
 
     return success ? p2m : NULL;
 }
-
-
 
 int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
                    uint32_t max_factor, uint32_t flags, int (*suspend)(void),
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_pm.c
--- a/tools/libxc/xc_pm.c       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xc_pm.c       Fri Mar 27 11:07:11 2009 +0900
@@ -306,3 +306,59 @@ int xc_set_cpufreq_para(int xc_handle, i
 
     return xc_sysctl(xc_handle, &sysctl);
 }
+
+int xc_get_cpufreq_avgfreq(int xc_handle, int cpuid, int *avg_freq)
+{
+    int ret = 0;
+    DECLARE_SYSCTL;
+
+    if ( (xc_handle < 0) || (!avg_freq) )
+        return -EINVAL;
+
+    sysctl.cmd = XEN_SYSCTL_pm_op;
+    sysctl.u.pm_op.cmd = GET_CPUFREQ_AVGFREQ;
+    sysctl.u.pm_op.cpuid = cpuid;
+    ret = xc_sysctl(xc_handle, &sysctl);
+
+    *avg_freq = sysctl.u.pm_op.get_avgfreq;
+
+    return ret;
+}
+
+int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info)
+{
+    int rc;
+    DECLARE_SYSCTL;
+
+    sysctl.cmd = XEN_SYSCTL_pm_op;
+    sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_get_cputopo;
+    sysctl.u.pm_op.cpuid = 0;
+    set_xen_guest_handle( sysctl.u.pm_op.get_topo.cpu_to_core,
+                         info->cpu_to_core );
+    set_xen_guest_handle( sysctl.u.pm_op.get_topo.cpu_to_socket,
+                         info->cpu_to_socket );
+    sysctl.u.pm_op.get_topo.max_cpus = info->max_cpus;
+
+    rc = do_sysctl(xc_handle, &sysctl);
+    info->nr_cpus = sysctl.u.pm_op.get_topo.nr_cpus;
+
+    return rc;
+}
+
+/* value:   0 - disable sched_smt_power_savings 
+            1 - enable sched_smt_power_savings
+ */
+int xc_set_sched_opt_smt(int xc_handle, uint32_t value)
+{
+   int rc;
+   DECLARE_SYSCTL;
+
+   sysctl.cmd = XEN_SYSCTL_pm_op;
+   sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_set_sched_opt_smt;
+   sysctl.u.pm_op.cpuid = 0;
+   sysctl.u.pm_op.set_sched_opt_smt = value;
+   rc = do_sysctl(xc_handle, &sysctl);
+
+   return rc;
+}
+
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_ptrace_core.c
--- a/tools/libxc/xc_ptrace_core.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xc_ptrace_core.c      Fri Mar 27 11:07:11 2009 +0900
@@ -154,7 +154,7 @@ xc_waitdomain_core_compat(
             IPRINTF("Could not allocate m2p array\n");
             return -1;
         }
-        bzero(m2p_array_compat, sizeof(unsigned long)* 1 << 20);
+        memset(m2p_array_compat, 0, sizeof(unsigned long)* 1 << 20);
 
         for (i = 0; i < nr_pages_compat; i++)
             m2p_array_compat[p2m_array_compat[i]] = i;
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_solaris.c
--- a/tools/libxc/xc_solaris.c  Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xc_solaris.c  Fri Mar 27 11:07:11 2009 +0900
@@ -134,6 +134,8 @@ void *xc_map_foreign_ranges(int xc_handl
     if (rc)
         goto ioctl_failed;
 
+    return addr;
+
 ioctl_failed:
     rc = munmap(addr, size);
     if (rc == -1)
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xc_suspend.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_suspend.c  Fri Mar 27 11:07:11 2009 +0900
@@ -0,0 +1,117 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+
+#include "xc_private.h"
+#include "xenguest.h"
+
+#define SUSPEND_LOCK_FILE "/var/lib/xen/suspend_evtchn_lock.d"
+static int lock_suspend_event(void)
+{
+    int fd, rc;
+    mode_t mask;
+    char buf[128];
+
+    mask = umask(022);
+    fd = open(SUSPEND_LOCK_FILE, O_CREAT | O_EXCL | O_RDWR, 0666);
+    if (fd < 0)
+    {
+        ERROR("Can't create lock file for suspend event channel\n");
+        return -EINVAL;
+    }
+    umask(mask);
+    snprintf(buf, sizeof(buf), "%10ld", (long)getpid());
+
+    rc = write_exact(fd, buf, strlen(buf));
+    close(fd);
+
+    return rc;
+}
+
+static int unlock_suspend_event(void)
+{
+    int fd, pid, n;
+    char buf[128];
+
+    fd = open(SUSPEND_LOCK_FILE, O_RDWR);
+
+    if (fd < 0)
+        return -EINVAL;
+
+    n = read(fd, buf, 127);
+
+    close(fd);
+
+    if (n > 0)
+    {
+        sscanf(buf, "%d", &pid);
+        /* We are the owner, so we can simply delete the file */
+        if (pid == getpid())
+        {
+            unlink(SUSPEND_LOCK_FILE);
+            return 0;
+        }
+    }
+
+    return -EPERM;
+}
+
+int xc_await_suspend(int xce, int suspend_evtchn)
+{
+    int rc;
+
+    do {
+        rc = xc_evtchn_pending(xce);
+        if (rc < 0) {
+            ERROR("error polling suspend notification channel: %d", rc);
+            return -1;
+        }
+    } while (rc != suspend_evtchn);
+
+    /* harmless for one-off suspend */
+    if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
+        ERROR("failed to unmask suspend notification channel: %d", rc);
+
+    return 0;
+}
+
+int xc_suspend_evtchn_release(int xce, int suspend_evtchn)
+{
+    if (suspend_evtchn >= 0)
+        xc_evtchn_unbind(xce, suspend_evtchn);
+
+    return unlock_suspend_event();
+}
+
+int xc_suspend_evtchn_init(int xc, int xce, int domid, int port)
+{
+    int rc, suspend_evtchn = -1;
+
+    if (lock_suspend_event())
+        return -EINVAL;
+
+    suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
+    if (suspend_evtchn < 0) {
+        ERROR("failed to bind suspend event channel: %d", suspend_evtchn);
+        goto cleanup;
+    }
+
+    rc = xc_domain_subscribe_for_suspend(xc, domid, port);
+    if (rc < 0) {
+        ERROR("failed to subscribe to domain: %d", rc);
+        goto cleanup;
+    }
+
+    /* event channel is pending immediately after binding */
+    xc_await_suspend(xce, suspend_evtchn);
+
+    return suspend_evtchn;
+
+cleanup:
+    if (suspend_evtchn > 0)
+        xc_suspend_evtchn_release(xce, suspend_evtchn);
+
+    return -1;
+}
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xenctrl.h     Fri Mar 27 11:07:11 2009 +0900
@@ -158,7 +158,7 @@ typedef struct xc_dominfo {
                   paused:1, blocked:1, running:1,
                   hvm:1, debugged:1;
     unsigned int  shutdown_reason; /* only meaningful if shutdown==1 */
-    unsigned long nr_pages;
+    unsigned long nr_pages; /* current number, not maximum */
     unsigned long shared_info_frame;
     uint64_t      cpu_time;
     unsigned long max_memkb;
@@ -1242,4 +1242,24 @@ int xc_set_cpufreq_gov(int xc_handle, in
 int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname);
 int xc_set_cpufreq_para(int xc_handle, int cpuid,
                         int ctrl_type, int ctrl_value);
+int xc_get_cpufreq_avgfreq(int xc_handle, int cpuid, int *avg_freq);
+
+struct xc_get_cputopo {
+     /* IN: maximum addressable entry in
+      * the caller-provided cpu_to_core/socket.
+      */
+    uint32_t max_cpus;
+    uint32_t *cpu_to_core;
+    uint32_t *cpu_to_socket;
+
+    /* OUT: number of cpus returned
+     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
+     */
+    uint32_t nr_cpus;
+};
+
+int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info);
+
+int xc_set_sched_opt_smt(int xc_handle, uint32_t value);
+
 #endif /* XENCTRL_H */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xenguest.h    Fri Mar 27 11:07:11 2009 +0900
@@ -142,4 +142,10 @@ int xc_hvm_build_mem(int xc_handle,
                      const char *image_buffer,
                      unsigned long image_size);
 
+int xc_suspend_evtchn_release(int xce, int suspend_evtchn);
+
+int xc_suspend_evtchn_init(int xc, int xce, int domid, int port);
+
+int xc_await_suspend(int xce, int suspend_evtchn);
+
 #endif /* XENGUEST_H */
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/libxc/xg_private.c  Fri Mar 27 11:07:11 2009 +0900
@@ -108,7 +108,7 @@ char *xc_inflate_buffer(const char *in_b
                 (256 * ((unsigned char)in_buf[in_size-2] +
                         (256 * (unsigned char)in_buf[in_size-1])))));
 
-    bzero(&zStream, sizeof(zStream));
+    memset(&zStream, 0, sizeof(zStream));
     out_buf = malloc(out_len + 16);        /* Leave a little extra space */
     if ( out_buf == NULL )
     {
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/misc/xenpm.c
--- a/tools/misc/xenpm.c        Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/misc/xenpm.c        Fri Mar 27 11:07:11 2009 +0900
@@ -15,9 +15,6 @@
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
-
-/* to eliminate warning on `strndup' */
-#define _GNU_SOURCE
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -58,8 +55,10 @@ void show_help(void)
             "                                     it is used in ondemand 
governor.\n"
             " set-up-threshold      [cpuid] <num> set up threshold on CPU 
<cpuid> or all\n"
             "                                     it is used in ondemand 
governor.\n"
-            " start                               start collect Cx/Px 
statistics,\n"
-            "                                     output after CTRL-C or 
SIGINT.\n"
+            " get-cpu-topology                    get thread/core/socket 
topology info\n"
+            " set-sched-smt           enable|disable enable/disable scheduler 
smt power saving\n"
+            " start [seconds]                     start collect Cx/Px 
statistics,\n"
+            "                                     output after CTRL-C or 
SIGINT or several seconds.\n"
             );
 }
 /* wrapper function */
@@ -224,6 +223,20 @@ static int get_pxstat_by_cpuid(int xc_fd
     return 0;
 }
 
+/* show cpu actual average freq information on CPU cpuid */
+static int get_avgfreq_by_cpuid(int xc_fd, int cpuid, int *avgfreq)
+{
+    int ret = 0;
+
+    ret = xc_get_cpufreq_avgfreq(xc_fd, cpuid, avgfreq);
+    if ( ret )
+    {
+        return errno;
+    }
+
+    return 0;
+}
+
 static int show_pxstat_by_cpuid(int xc_fd, int cpuid)
 {
     int ret = 0;
@@ -265,6 +278,7 @@ static uint64_t usec_start, usec_end;
 static uint64_t usec_start, usec_end;
 static struct xc_cx_stat *cxstat, *cxstat_start, *cxstat_end;
 static struct xc_px_stat *pxstat, *pxstat_start, *pxstat_end;
+static int *avgfreq;
 static uint64_t *sum, *sum_cx, *sum_px;
 
 static void signal_int_handler(int signo)
@@ -299,6 +313,9 @@ static void signal_int_handler(int signo
                     sum_px[i] += pxstat_end[i].pt[j].residency -
                                  pxstat_start[i].pt[j].residency;
     }
+
+    for ( i = 0; i < max_cpu_nr; i++ )
+        get_avgfreq_by_cpuid(xc_fd, i, &avgfreq[i]);
 
     printf("Elapsed time (ms): %"PRIu64"\n", (usec_end - usec_start) / 1000UL);
     for ( i = 0; i < max_cpu_nr; i++ )
@@ -331,6 +348,7 @@ static void signal_int_handler(int signo
                         res / 1000000UL, 100UL * res / (double)sum_px[i]);
             }
         }
+        printf("  Avg freq\t%d\tKHz\n", avgfreq[i]);
     }
 
     /* some clean up and then exits */
@@ -344,6 +362,7 @@ static void signal_int_handler(int signo
     free(cxstat);
     free(pxstat);
     free(sum);
+    free(avgfreq);
     xc_interface_close(xc_fd);
     exit(0);
 }
@@ -352,6 +371,16 @@ void start_gather_func(int argc, char *a
 {
     int i;
     struct timeval tv;
+    int timeout = 0;
+
+    if ( argc == 1 )
+    {
+        sscanf(argv[0], "%d", &timeout);
+        if ( timeout <= 0 )
+            fprintf(stderr, "failed to set timeout seconds, falling 
back...\n");
+        else
+            printf("Timeout set to %d seconds\n", timeout);
+    }
 
     if ( gettimeofday(&tv, NULL) == -1 )
     {
@@ -374,11 +403,20 @@ void start_gather_func(int argc, char *a
     {
         free(sum);
         free(cxstat);
+        return ;
+    }
+    avgfreq = malloc(sizeof(int) * max_cpu_nr);
+    if ( avgfreq == NULL )
+    {
+        free(sum);
+        free(cxstat);
+        free(pxstat);
         return ;
     }
     memset(sum, 0, sizeof(uint64_t) * 2 * max_cpu_nr);
     memset(cxstat, 0, sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
     memset(pxstat, 0, sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
+    memset(avgfreq, 0, sizeof(int) * max_cpu_nr);
     sum_cx = sum;
     sum_px = sum + max_cpu_nr;
     cxstat_start = cxstat;
@@ -397,6 +435,7 @@ void start_gather_func(int argc, char *a
     {
         get_cxstat_by_cpuid(xc_fd, i, &cxstat_start[i]);
         get_pxstat_by_cpuid(xc_fd, i, &pxstat_start[i]);
+        get_avgfreq_by_cpuid(xc_fd, i, &avgfreq[i]);
     }
 
     if (signal(SIGINT, signal_int_handler) == SIG_ERR)
@@ -405,9 +444,25 @@ void start_gather_func(int argc, char *a
         free(sum);
         free(pxstat);
         free(cxstat);
-        return ;
-    }
-    printf("Start sampling, waiting for CTRL-C or SIGINT signal ...\n");
+        free(avgfreq);
+        return ;
+    }
+
+    if ( timeout > 0 )
+    {
+        if ( signal(SIGALRM, signal_int_handler) == SIG_ERR )
+        {
+            fprintf(stderr, "failed to set signal alarm handler\n");
+            free(sum);
+            free(pxstat);
+            free(cxstat);
+            free(avgfreq);
+            return ;
+        }
+        alarm(timeout);
+    }
+
+    printf("Start sampling, waiting for CTRL-C or SIGINT or SIGALARM signal 
...\n");
 
     pause();
 }
@@ -750,6 +805,70 @@ out:
     fprintf(stderr, "failed to set governor name\n");
 }
 
+#define MAX_NR_CPU 512
+
+void cpu_topology_func(int argc, char *argv[])
+{
+    uint32_t cpu_to_core[MAX_NR_CPU];
+    uint32_t cpu_to_socket[MAX_NR_CPU];
+    struct xc_get_cputopo info;
+    int i, ret;
+
+    info.cpu_to_core = cpu_to_core;
+    info.cpu_to_socket = cpu_to_socket;
+    info.max_cpus = MAX_NR_CPU;
+    ret = xc_get_cputopo(xc_fd, &info);
+    if (!ret)
+    {
+        printf("CPU\tcore\tsocket\n");
+        for (i=0; i<info.nr_cpus; i++)
+        {
+            if ( info.cpu_to_core[i] != INVALID_TOPOLOGY_ID &&
+                    info.cpu_to_socket[i] != INVALID_TOPOLOGY_ID )
+            {
+            printf("CPU%d\t %d\t %d\n", i, info.cpu_to_core[i],
+                    info.cpu_to_socket[i]);
+            }
+        }
+    }
+    else
+    {
+        printf("Can not get Xen CPU topology!\n");
+    }
+
+    return ;
+}
+
+void set_sched_smt_func(int argc, char *argv[])
+{
+    int value, rc;
+
+    if (argc != 1){
+        show_help();
+        exit(-1);
+    }
+
+    if ( !strncmp(argv[0], "disable", sizeof("disable")) )
+    {
+        value = 0;
+    }
+    else if ( !strncmp(argv[0], "enable", sizeof("enable")) )
+    {
+        value = 1;
+    }
+    else
+    {
+        show_help();
+        exit(-1);
+    }
+
+    rc = xc_set_sched_opt_smt(xc_fd, value);
+    printf("%s sched_smt_power_savings %s\n", argv[0],
+                    rc? "failed":"successeed" );
+
+    return;
+}
+
 struct {
     const char *name;
     void (*function)(int argc, char *argv[]);
@@ -765,6 +884,8 @@ struct {
     { "set-scaling-speed", scaling_speed_func },
     { "set-sampling-rate", scaling_sampling_rate_func },
     { "set-up-threshold", scaling_up_threshold_func },
+    { "get-cpu-topology", cpu_topology_func},
+    { "set-sched-smt", set_sched_smt_func},
 };
 
 int main(int argc, char *argv[])
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/pygrub/src/pygrub   Fri Mar 27 11:07:11 2009 +0900
@@ -441,7 +441,11 @@ class Grub:
                 # Timed out waiting for a keypress
                 if mytime != -1:
                     mytime += 1
-                    if mytime >= int(timeout):
+                    # curses.timeout() does not work properly on Solaris
+                    # So we may come here even after a key has been pressed.
+                    # Check both timeout and mytime to avoid exiting
+                    # when we shouldn't.
+                    if timeout != -1 and mytime >= int(timeout):
                         self.isdone = True
                         break
             else:
@@ -526,7 +530,11 @@ def run_grub(file, entry, fs, arg):
         print "No kernel image selected!"
         sys.exit(1)
 
-    img = g.cf.images[sel]
+    try:
+        img = g.cf.images[sel]
+    except:
+        log.debug("PyGrub: Default selection is not valid, using first boot 
configuration...")
+        img = g.cf.images[0]
 
     grubcfg = { "kernel": None, "ramdisk": None, "args": None }
 
@@ -579,6 +587,15 @@ def sniff_solaris(fs, cfg):
 
     return cfg
  
+def sniff_netware(fs, cfg):
+    if not fs.file_exists("/nwserver/xnloader.sys"):
+        return cfg
+
+    if not cfg["kernel"]:
+        cfg["kernel"] = "/nwserver/xnloader.sys"
+
+    return cfg
+
 if __name__ == "__main__":
     sel = None
     
@@ -659,6 +676,9 @@ if __name__ == "__main__":
     chosencfg = sniff_solaris(fs, incfg)
 
     if not chosencfg["kernel"]:
+        chosencfg = sniff_netware(fs, incfg)
+
+    if not chosencfg["kernel"]:
         chosencfg = run_grub(file, entry, fs, incfg["args"])
 
     data = fs.open_file(chosencfg["kernel"]).read()
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/setup.py
--- a/tools/python/setup.py     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/setup.py     Fri Mar 27 11:07:11 2009 +0900
@@ -38,6 +38,13 @@ scf = Extension("scf",
                libraries          = libraries,
                sources            = [ "xen/lowlevel/scf/scf.c" ])
              
+process = Extension("process",
+               extra_compile_args = extra_compile_args,
+               include_dirs       = include_dirs + [ "xen/lowlevel/process" ],
+               library_dirs       = library_dirs,
+               libraries          = libraries + [ "contract" ],
+               sources            = [ "xen/lowlevel/process/process.c" ])
+
 acm = Extension("acm",
                extra_compile_args = extra_compile_args,
                include_dirs       = include_dirs + [ "xen/lowlevel/acm" ],
@@ -63,6 +70,7 @@ modules = [ xc, xs, ptsname, acm, flask 
 modules = [ xc, xs, ptsname, acm, flask ]
 if os.uname()[0] == 'SunOS':
     modules.append(scf)
+    modules.append(process)
 
 setup(name            = 'xen',
       version         = '3.0',
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/lowlevel/process/process.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/lowlevel/process/process.c       Fri Mar 27 11:07:11 
2009 +0900
@@ -0,0 +1,164 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <Python.h>
+
+#include <libcontract.h>
+#include <sys/contract/process.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+/*
+ * On Solaris, xend runs under a contract as an smf(5) service.  As a
+ * result, when spawning long-running children such as a domain's
+ * qemu-dm instantiation, we have to make sure it's in a separate
+ * contract. Before we fork, we must activate a separate process
+ * contract template to place the child processes in a new contract.
+ */
+
+static PyObject *
+pyprocess_activate(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+       static char *kwlist[] = { "name", NULL };
+       char *name = NULL;
+       int flags;
+       int cfd;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name))
+               return (NULL);
+
+       cfd = open64("/system/contract/process/template", O_RDWR);
+
+       if (cfd == -1)
+               goto err;
+
+       if ((flags = fcntl(cfd, F_GETFD, 0)) == -1)
+               goto err;
+       
+       if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1)
+               goto err;
+
+       if (name != NULL)
+               ct_pr_tmpl_set_svc_aux(cfd, name);
+
+       if (ct_tmpl_activate(cfd))
+               goto err;
+
+       return (PyInt_FromLong((long)cfd));
+
+err:
+       if (cfd != -1)
+               close(cfd);
+       PyErr_SetFromErrno(PyExc_OSError);
+       return (NULL);
+}
+
+static PyObject *
+pyprocess_clear(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+       static char *kwlist[] = { "contract", NULL };
+       int cfd;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &cfd))
+               return (NULL);
+
+       if (ct_tmpl_clear(cfd) != 0) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return (NULL);
+       }
+
+       close(cfd);
+
+       Py_INCREF(Py_None);
+       return (Py_None);
+}
+
+static PyObject *
+pyprocess_abandon_latest(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+       static char *kwlist[] = { NULL };
+       static char path[PATH_MAX];
+       ct_stathdl_t st;
+       ctid_t latest;
+       int cfd;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
+               return (NULL);
+
+       cfd = open64("/system/contract/process/latest", O_RDONLY);
+       if (cfd == -1)
+               goto err;
+
+       ct_status_read(cfd, CTD_COMMON, &st);
+       latest = ct_status_get_id(st);
+       ct_status_free(st);
+       close(cfd);
+
+       snprintf(path, PATH_MAX, "/system/contract/process/%ld/ctl",
+           (long)latest);
+
+       if ((cfd = open64(path, O_WRONLY)) < 0) 
+               goto err;
+       if (ct_ctl_abandon(cfd))
+               goto err;
+       close(cfd);
+
+       Py_INCREF(Py_None);
+       return (Py_None);
+err:
+       PyErr_SetFromErrno(PyExc_OSError);
+       return (NULL);
+}
+
+PyDoc_STRVAR(pyprocess_activate__doc__,
+    "activate(name)\n"
+    "\n"
+    "Activate a new process contract template. If name is given,\n"
+    "it is used as the template's auxiliary value.\n"
+    "Returns the new contract template.\n");
+ 
+PyDoc_STRVAR(pyprocess_clear__doc__,
+    "clear(contract)\n"
+    "\n"
+    "Clear and close the given contract template.\n");
+
+PyDoc_STRVAR(pyprocess_abandon_latest__doc__,
+    "abandon_latest()\n"
+    "\n"
+    "Abandon the latest contract created by this thread.\n");
+
+static struct PyMethodDef pyprocess_module_methods[] = {
+    { "activate", (PyCFunction) pyprocess_activate,
+      METH_VARARGS|METH_KEYWORDS, pyprocess_activate__doc__ },
+    { "clear", (PyCFunction) pyprocess_clear,
+      METH_VARARGS|METH_KEYWORDS, pyprocess_clear__doc__ },
+    { "abandon_latest", (PyCFunction) pyprocess_abandon_latest,
+      METH_VARARGS|METH_KEYWORDS, pyprocess_abandon_latest__doc__ },
+    { NULL, NULL, 0, NULL }    
+};
+
+PyMODINIT_FUNC
+initprocess(void)
+{
+       Py_InitModule("process", pyprocess_module_methods);
+}
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/util/pci.py      Fri Mar 27 11:07:11 2009 +0900
@@ -12,6 +12,7 @@ import types
 import types
 import struct
 import time
+import threading
 from xen.util import utils
 
 PROC_PCI_PATH = '/proc/bus/pci/devices'
@@ -97,6 +98,7 @@ MSIX_SIZE_MASK = 0x7ff
 
 # Global variable to store information from lspci
 lspci_info = None
+lspci_info_lock = threading.RLock()
 
 #Calculate PAGE_SHIFT: number of bits to shift an address to get the page 
number
 PAGE_SIZE = resource.getpagesize()
@@ -174,12 +176,16 @@ def get_all_pci_devices():
 
     return pci_devs
 
-def create_lspci_info():
+def _create_lspci_info():
+    """Execute 'lspci' command and parse the result.
+    If the command does not exist, lspci_info will be kept blank ({}).
+
+    Expects to be protected by lspci_info_lock.
+    """
     global lspci_info
+    
     lspci_info = {}
 
-    # Execute 'lspci' command and parse the result.
-    # If the command does not exist, lspci_info will be kept blank ({}).
     for paragraph in os.popen(LSPCI_CMD + ' -vmm').read().split('\n\n'):
         device_name = None
         device_info = {}
@@ -194,6 +200,14 @@ def create_lspci_info():
                 pass
         if device_name is not None:
             lspci_info[device_name] = device_info
+
+def create_lspci_info():
+    global lspci_info_lock
+    lspci_info_lock.acquire()
+    try:
+        _create_lspci_info()
+    finally:
+        lspci_info_lock.release()
 
 def save_pci_conf_space(devs_string):
     pci_list = []
@@ -911,22 +925,27 @@ class PciDevice:
         Since we cannot obtain these data from sysfs, use 'lspci' command.
         """
         global lspci_info
-
-        if lspci_info is None:
-            create_lspci_info()
-
-        try:
-            device_info = lspci_info[self.name]
-            self.revision = int(device_info['Rev'], 16)
-            self.vendorname = device_info['Vendor']
-            self.devicename = device_info['Device']
-            self.classname = device_info['Class']
-            self.subvendorname = device_info['SVendor']
-            self.subdevicename = device_info['SDevice']
-        except KeyError:
-            pass
-
-        return True
+        global lspci_info_lock
+
+        lspci_info_lock.acquire()
+        try:
+            if lspci_info is None:
+                _create_lspci_info()
+
+            try:
+                device_info = lspci_info[self.name]
+                self.revision = int(device_info['Rev'], 16)
+                self.vendorname = device_info['Vendor']
+                self.devicename = device_info['Device']
+                self.classname = device_info['Class']
+                self.subvendorname = device_info['SVendor']
+                self.subdevicename = device_info['SDevice']
+            except KeyError:
+                pass
+
+            return True
+        finally:
+            lspci_info_lock.release()
 
     def __str__(self):
         str = "PCI Device %s\n" % (self.name)
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/util/vscsi_util.py
--- a/tools/python/xen/util/vscsi_util.py       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/util/vscsi_util.py       Fri Mar 27 11:07:11 2009 +0900
@@ -90,7 +90,7 @@ def _vscsi_get_scsidevices_by_lsscsi(opt
 
     devices = []
 
-    for scsiinfo in os.popen('lsscsi -g %s' % option).readlines():
+    for scsiinfo in os.popen('{ lsscsi -g %s; } 2>/dev/null' % 
option).readlines():
         s = scsiinfo.split()
         hctl = s[0][1:-1]
         try:
@@ -112,7 +112,10 @@ def _vscsi_get_scsidevices_by_sysfs():
     """ get all scsi devices information by sysfs """
 
     devices = []
-    sysfs_mnt = utils.find_sysfs_mount() 
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+    except:
+        return devices
 
     for dirpath, dirnames, files in os.walk(sysfs_mnt + SYSFS_SCSI_PATH):
         for hctl in dirnames:
@@ -152,7 +155,9 @@ def vscsi_get_hctl_and_devname_by(target
         elif target.startswith('/dev/'): 
             scsi_devices = _vscsi_get_scsidevices_by_lsscsi("| grep %s" % 
target)
         else:
-            scsi_devices = vscsi_get_scsidevices()
+            scsi_devices = _vscsi_get_scsidevices_by_lsscsi("")
+        if not scsi_devices:
+            scsi_devices = _vscsi_get_scsidevices_by_sysfs()
 
     if len(target.split(':')) == 4:
         return _vscsi_get_devname_by(target, scsi_devices)
@@ -248,7 +253,7 @@ def get_all_scsi_devices():
             get_scsi_scsilevel(scsi_dev['physical_HCTL'])
 
         try:
-            lsscsi_info = os.popen('lsscsi ' + 
scsi_dev['physical_HCTL']).read().split()
+            lsscsi_info = os.popen('lsscsi %s 2>/dev/null' % 
scsi_dev['physical_HCTL']).read().split()
             scsi_dev['type'] = lsscsi_info[1]
         except:
             scsi_dev['type'] = None
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/web/SrvDir.py
--- a/tools/python/xen/web/SrvDir.py    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/web/SrvDir.py    Fri Mar 27 11:07:11 2009 +0900
@@ -20,7 +20,7 @@ from xen.xend import sxp
 from xen.xend import sxp
 from xen.xend import PrettyPrint
 from xen.xend.Args import ArgError
-from xen.xend.XendError import XendError
+from xen.xend.XendError import XendError, XendInvalidDomain
 #from xen.xend.XendLogging import log
 
 import resource
@@ -70,6 +70,8 @@ class SrvDir(SrvBase):
         try:
             val = self.get(x)
         except XendError, ex:
+            return self.noChild(str(ex))
+        except XendInvalidDomain, ex:
             return self.noChild(str(ex))
         if val is None:
             return self.noChild('Not found: ' + str(x))
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/web/connection.py
--- a/tools/python/xen/web/connection.py        Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/web/connection.py        Fri Mar 27 11:07:11 2009 +0900
@@ -292,3 +292,40 @@ def hostAllowed(addrport, hosts_allowed)
                 return True
         log.warn("Rejected connection from %s (%s).", addrport[0], fqdn)
         return False
+
+
+class SocketDgramListener:
+    """A connectionless server socket, running listen in a thread.
+    """
+
+    def __init__(self, protocol_class):
+        self.protocol = protocol_class()
+        self.sock = self.createSocket()
+        threading.Thread(target=self.main).start()
+
+
+    def close(self):
+        try:
+            self.sock.close()
+        except:
+            pass
+
+
+    def createSocket(self):
+        raise NotImplementedError()
+
+
+    def main(self):
+        try:
+            while True:
+                try:
+                    data = self.sock.recv(BUFFER_SIZE)
+                    self.protocol.dataReceived(data)
+                except socket.error, ex:
+                    if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR):
+                        break
+        finally:
+            try:
+                self.close()
+            except:
+                pass
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/web/unix.py
--- a/tools/python/xen/web/unix.py      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/web/unix.py      Fri Mar 27 11:07:11 2009 +0900
@@ -27,16 +27,19 @@ import connection
 import connection
 
 
-def bind(path):
-    """Create a Unix socket, and bind it to the given path.  The socket is
-created such that only the current user may access it."""
+def bind(path, type = socket.SOCK_STREAM):
+    """Create a Unix socket, and bind it to the given path.
+    The socket is created such that only the current user may access it."""
 
-    parent = os.path.dirname(path)
-    mkdir.parents(parent, stat.S_IRWXU, True)
-    if os.path.exists(path):
-        os.unlink(path)
+    if path[0] == '\0': # Abstract namespace is used for the path
+        pass
+    else:
+        parent = os.path.dirname(path)
+        mkdir.parents(parent, stat.S_IRWXU, True)
+        if os.path.exists(path):
+            os.unlink(path)
 
-    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    sock = socket.socket(socket.AF_UNIX, type)
     sock.bind(path)
     return sock
 
@@ -48,8 +51,19 @@ class UnixListener(connection.SocketList
 
 
     def createSocket(self):
-        return bind(self.path)
+        return bind(self.path, socket.SOCK_STREAM)
 
 
     def acceptConnection(self, sock, _):
         connection.SocketServerConnection(sock, self.protocol_class)
+
+
+class UnixDgramListener(connection.SocketDgramListener):
+    def __init__(self, path, protocol_class):
+        self.path = path
+        connection.SocketDgramListener.__init__(self, protocol_class)
+
+
+    def createSocket(self):
+        return bind(self.path, socket.SOCK_DGRAM)
+
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendAPIStore.py
--- a/tools/python/xen/xend/XendAPIStore.py     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendAPIStore.py     Fri Mar 27 11:07:11 2009 +0900
@@ -25,36 +25,59 @@ by type, to ensure safety
 by type, to ensure safety
 """
 
+import threading
+
 __classes = {}
+__classes_lock = threading.RLock()
 
 def register(uuid, type, inst):
-    __classes[(uuid, type)] = inst
-    return inst
+    __classes_lock.acquire()
+    try:
+        __classes[(uuid, type)] = inst
+        return inst
+    finally:
+        __classes_lock.release()
 
 def deregister(uuid, type):
-    old = get(uuid, type)
-    if old is not None:
-        del __classes[(uuid, type)]
-    return old
+    __classes_lock.acquire()
+    try:
+        old = get(uuid, type)
+        if old is not None:
+            del __classes[(uuid, type)]
+        return old
+    finally:
+        __classes_lock.release()
 
 def get(uuid, type):
     """
     Get the instances by uuid and type
     """
-    return __classes.get((uuid, type), None)
+    __classes_lock.acquire()
+    try:
+        return __classes.get((uuid, type), None)
+    finally:
+        __classes_lock.release()
 
 def get_all(all_type):
     """
     Get all instances by type
     """
-    return [inst
-            for ((uuid, t), inst) in __classes.items()
-            if t == all_type]        
+    __classes_lock.acquire()
+    try:
+        return [inst
+                for ((uuid, t), inst) in __classes.items()
+                if t == all_type]        
+    finally:
+        __classes_lock.release()
 
 def get_all_uuid(all_type):
     """
     Get all uuids by type
     """
-    return [uuid
-            for (uuid, t) in __classes.keys()
-            if t == all_type]
+    __classes_lock.acquire()
+    try:
+        return [uuid
+                for (uuid, t) in __classes.keys()
+                if t == all_type]
+    finally:
+        __classes_lock.release()
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendCheckpoint.py   Fri Mar 27 11:07:11 2009 +0900
@@ -114,7 +114,7 @@ def save(fd, dominfo, network, live, dst
             if line == "suspend":
                 log.debug("Suspending %d ...", dominfo.getDomid())
                 dominfo.shutdown('suspend')
-                dominfo.waitForShutdown()
+                dominfo.waitForSuspend()
             if line in ('suspend', 'suspended'):
                 dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP2,
                                        domain_name)
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendConfig.py       Fri Mar 27 11:07:11 2009 +0900
@@ -170,6 +170,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
     'xen_extended_power_mgmt': int,
     'pci_msitranslate': int,
     'pci_power_mgmt': int,
+    'xen_platform_pci': int,
 }
 
 # Xen API console 'other_config' keys.
@@ -464,6 +465,8 @@ class XendConfig(dict):
                 self['platform']['rtc_timeoffset'] = 0
             if 'hpet' not in self['platform']:
                 self['platform']['hpet'] = 0
+            if 'xen_platform_pci' not in self['platform']:
+                self['platform']['xen_platform_pci'] = 1
             if 'vpt_align' not in self['platform']:
                 self['platform']['vpt_align'] = 1
             if 'loader' not in self['platform']:
@@ -1155,7 +1158,7 @@ class XendConfig(dict):
                     return None
         return devid
     
-    def device_duplicate_check(self, dev_type, dev_info, defined_config):
+    def device_duplicate_check(self, dev_type, dev_info, defined_config, 
config):
         defined_devices_sxpr = self.all_devices_sxpr(target = defined_config)
         
         if dev_type == 'vbd' or dev_type == 'tap':
@@ -1174,9 +1177,34 @@ class XendConfig(dict):
                         if blkdev_file == o_blkdev_file:
                             raise XendConfigError('The file "%s" is already 
used' %
                                                   blkdev_file)
+                    if dev_uname == o_dev_uname:
+                        raise XendConfigError('The uname "%s" is already 
defined' %
+                                             dev_uname)
                     o_blkdev_name = sxp.child_value(o_dev_info, 'dev')
                     o_devid = self._blkdev_name_to_number(o_blkdev_name)
                     if o_devid != None and devid == o_devid:
+                        name_array = blkdev_name.split(':', 2)
+                        if len(name_array) == 2 and name_array[1] == 'cdrom':
+                            #
+                            # Since the device is a cdrom, we are most likely
+                            # inserting, changing, or removing a cd.  We can
+                            # update the old device instead of creating a new
+                            # one.
+                            #
+                            if o_dev_uname != None and dev_uname == None:
+                                #
+                                # We are removing a cd.  We can simply update
+                                # the uname on the existing device.
+                                #
+                                merge_sxp = sxp.from_string("('vbd' ('uname' 
''))")
+                            else:
+                                merge_sxp = config
+
+                            dev_uuid = sxp.child_value(o_dev_info, 'uuid')
+                            if dev_uuid != None and \
+                               self.device_update(dev_uuid, cfg_sxp = 
merge_sxp):
+                                return dev_uuid
+
                         raise XendConfigError('The device "%s" is already 
defined' %
                                               blkdev_name)
                     
@@ -1188,6 +1216,7 @@ class XendConfig(dict):
                     if dev_mac.lower() == sxp.child_value(o_dev_info, 
'mac').lower():
                         raise XendConfigError('The mac "%s" is already 
defined' %
                                               dev_mac)
+        return None
     
     def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None,
                    target = None):
@@ -1326,7 +1355,9 @@ class XendConfig(dict):
                 if not dev_info.get('mac'):
                     dev_info['mac'] = randomMAC()
 
-            self.device_duplicate_check(dev_type, dev_info, target)
+            ret_uuid = self.device_duplicate_check(dev_type, dev_info, target, 
config)
+            if ret_uuid != None:
+                return ret_uuid
 
             if dev_type == 'vif':
                 if dev_info.get('policy') and dev_info.get('label'):
@@ -1820,8 +1851,11 @@ class XendConfig(dict):
                 vscsi_be = vscsi_dict.get('backend', None)
 
                 # destroy existing XenAPI DSCSI objects
+                vscsi_devid = int(dev_info['devs'][0]['devid'])
                 for dscsi_uuid in XendDSCSI.get_by_VM(self['uuid']):
-                    XendAPIStore.deregister(dscsi_uuid, "DSCSI")
+                    dscsi_inst = XendAPIStore.get(dscsi_uuid, 'DSCSI')
+                    if vscsi_devid == dscsi_inst.get_virtual_host():
+                        XendAPIStore.deregister(dscsi_uuid, "DSCSI")
 
                 # create XenAPI DSCSI objects.
                 for vscsi_dev in vscsi_devs:
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendConstants.py
--- a/tools/python/xen/xend/XendConstants.py    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendConstants.py    Fri Mar 27 11:07:11 2009 +0900
@@ -96,7 +96,7 @@ ZOMBIE_PREFIX = 'Zombie-'
 ZOMBIE_PREFIX = 'Zombie-'
 
 """Minimum time between domain restarts in seconds."""
-MINIMUM_RESTART_TIME = 20
+MINIMUM_RESTART_TIME = 60
 
 RESTART_IN_PROGRESS = 'xend/restart_in_progress'
 DUMPCORE_IN_PROGRESS = 'xend/dumpcore_in_progress'
@@ -135,3 +135,6 @@ VTPM_DELETE_SCRIPT = '/etc/xen/scripts/v
 
 XS_VMROOT = "/vm/"
 
+NR_PCI_DEV = 32
+AUTO_PHP_SLOT = NR_PCI_DEV
+AUTO_PHP_SLOT_STR = "%02x" % NR_PCI_DEV
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendDomain.py       Fri Mar 27 11:07:11 2009 +0900
@@ -1223,7 +1223,7 @@ class XendDomain:
             log.exception("domain_pause")
             raise XendError(str(ex))
 
-    def domain_dump(self, domid, filename, live, crash):
+    def domain_dump(self, domid, filename=None, live=False, crash=False, 
reset=False):
         """Dump domain core."""
 
         dominfo = self.domain_lookup_nr(domid)
@@ -1237,13 +1237,25 @@ class XendDomain:
                              POWER_STATE_NAMES[DOM_STATE_PAUSED],
                              POWER_STATE_NAMES[dominfo._stateGet()])
 
-        try:
-            log.info("Domain core dump requested for domain %s (%d) "
-                     "live=%d crash=%d.",
-                     dominfo.getName(), dominfo.getDomid(), live, crash)
-            return dominfo.dumpCore(filename)
-        except Exception, ex:
-            raise XendError(str(ex))
+        dopause = (not live and dominfo._stateGet() == DOM_STATE_RUNNING)
+        if dopause:
+            dominfo.pause()
+
+        try:
+            try:
+                log.info("Domain core dump requested for domain %s (%d) "
+                         "live=%d crash=%d reset=%d.",
+                         dominfo.getName(), dominfo.getDomid(), live, crash, 
reset)
+                dominfo.dumpCore(filename)
+                if crash:
+                    self.domain_destroy(domid)
+                elif reset:
+                    self.domain_reset(domid)
+            except Exception, ex:
+                raise XendError(str(ex))
+        finally:
+            if dopause and not crash and not reset:
+                dominfo.unpause()
 
     def domain_destroy(self, domid):
         """Terminate domain immediately.
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Mar 27 11:07:11 2009 +0900
@@ -793,7 +793,7 @@ class XendDomainInfo:
                 existing_dev_uuid = sxp.child_value(existing_dev_info, 'uuid')
                 existing_pci_conf = self.info['devices'][existing_dev_uuid][1]
                 existing_pci_devs = existing_pci_conf['devs']
-                vslt = '0x0'
+                vslt = AUTO_PHP_SLOT_STR
                 for x in existing_pci_devs:
                     if ( int(x['domain'], 16) == int(dev['domain'], 16) and
                          int(x['bus'], 16) == int(dev['bus'], 16) and
@@ -801,7 +801,7 @@ class XendDomainInfo:
                          int(x['func'], 16) == int(dev['func'], 16) ):
                         vslt = x['vslt']
                         break
-                if vslt == '0x0':
+                if vslt == AUTO_PHP_SLOT_STR:
                     raise VmError("Device %04x:%02x:%02x.%01x is not connected"
                                   % (int(dev['domain'],16), int(dev['bus'],16),
                                      int(dev['slot'],16), int(dev['func'],16)))
@@ -1410,7 +1410,8 @@ class XendDomainInfo:
             for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
                 if dev_type == 'vfb':
                     old_location = dev_info.get('location')
-                    listen_host = dev_info.get('vnclisten', 'localhost')
+                    listen_host = dev_info.get('vnclisten', \
+                                XendOptions.instance().get_vnclisten_address())
                     new_location = '%s:%s' % (listen_host, str(vnc_port))
                     if old_location == new_location:
                         break
@@ -1495,7 +1496,8 @@ class XendDomainInfo:
         t.mkdir()
         t.set_permissions({'dom' : self.domid, 'read' : True})
         t.write('vm', self.vmpath)
-        for i in [ 'device', 'control', 'error', 'memory' ]:
+        # NB. Solaris guests use guest/ and hvmpv/ xenstore directories
+        for i in [ 'device', 'control', 'error', 'memory', 'guest', 'hvmpv' ]:
             t.mkdir(i)
             t.set_permissions(i, {'dom' : self.domid})
 
@@ -2027,26 +2029,31 @@ class XendDomainInfo:
         @raise: XendError if core dumping failed.
         """
         
+        if not corefile:
+            this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime())
+            corefile = "/var/xen/dump/%s-%s.%s.core" % (this_time,
+                              self.info['name_label'], self.domid)
+                
+        if os.path.isdir(corefile):
+            raise XendError("Cannot dump core in a directory: %s" %
+                            corefile)
+
         try:
-            if not corefile:
-                this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime())
-                corefile = "/var/xen/dump/%s-%s.%s.core" % (this_time,
-                                  self.info['name_label'], self.domid)
-                
-            if os.path.isdir(corefile):
-                raise XendError("Cannot dump core in a directory: %s" %
-                                corefile)
-            
-            self._writeVm(DUMPCORE_IN_PROGRESS, 'True')
-            xc.domain_dumpcore(self.domid, corefile)
+            try:
+                self._writeVm(DUMPCORE_IN_PROGRESS, 'True')
+                xc.domain_dumpcore(self.domid, corefile)
+            except RuntimeError, ex:
+                corefile_incomp = corefile+'-incomplete'
+                try:
+                    os.rename(corefile, corefile_incomp)
+                except:
+                    pass
+
+                log.error("core dump failed: id = %s name = %s: %s",
+                          self.domid, self.info['name_label'], str(ex))
+                raise XendError("Failed to dump core: %s" %  str(ex))
+        finally:
             self._removeVm(DUMPCORE_IN_PROGRESS)
-        except RuntimeError, ex:
-            corefile_incomp = corefile+'-incomplete'
-            os.rename(corefile, corefile_incomp)
-            self._removeVm(DUMPCORE_IN_PROGRESS)
-            log.exception("XendDomainInfo.dumpCore failed: id = %s name = %s",
-                          self.domid, self.info['name_label'])
-            raise XendError("Failed to dump core: %s" %  str(ex))
 
     #
     # Device creation/deletion functions
@@ -2544,6 +2551,31 @@ class XendDomainInfo:
         finally:
             self.state_updated.release()
 
+    def waitForSuspend(self):
+        """Wait for the guest to respond to a suspend request by
+        shutting down.  If the guest hasn't re-written control/shutdown
+        after a certain amount of time, it's obviously not listening and
+        won't suspend, so we give up.  HVM guests with no PV drivers
+        should already be shutdown.
+        """
+        state = "suspend"
+        nr_tries = 60
+
+        self.state_updated.acquire()
+        try:
+            while self._stateGet() in (DOM_STATE_RUNNING,DOM_STATE_PAUSED):
+                self.state_updated.wait(1.0)
+                if state == "suspend":
+                    if nr_tries == 0:
+                        msg = ('Timeout waiting for domain %s to suspend'
+                            % self.domid)
+                        self._writeDom('control/shutdown', '')
+                        raise XendError(msg)
+                    state = self.readDom('control/shutdown')
+                    nr_tries -= 1
+        finally:
+            self.state_updated.release()
+
     #
     # TODO: recategorise - called from XendCheckpoint
     # 
@@ -2888,7 +2920,9 @@ class XendDomainInfo:
         while True:
             test = 0
             diff = time.time() - start
-            for i in self.getDeviceController('vbd').deviceIDs():
+            vbds = self.getDeviceController('vbd').deviceIDs()
+            taps = self.getDeviceController('tap').deviceIDs()
+            for i in vbds + taps:
                 test = 1
                 log.info("Dev %s still active, looping...", i)
                 time.sleep(0.1)
@@ -3669,7 +3703,8 @@ class XendDomainInfo:
                     ['v-dev', xenapi_dscsi.get('virtual_HCTL')],
                     ['state', xenbusState['Initialising']],
                     ['uuid', dscsi_uuid]
-                ]
+                ],
+                ['feature-host', 0]
             ]
 
         if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
@@ -3682,7 +3717,7 @@ class XendDomainInfo:
                     raise XendError('Failed to create device')
 
             else:
-                new_vscsi_sxp = ['vscsi']
+                new_vscsi_sxp = ['vscsi', ['feature-host', 0]]
                 for existing_dev in sxp.children(cur_vscsi_sxp, 'dev'):
                     new_vscsi_sxp.append(existing_dev)
                 new_vscsi_sxp.append(sxp.child0(target_vscsi_sxp, 'dev'))
@@ -3776,7 +3811,7 @@ class XendDomainInfo:
         dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid')
 
         target_dev = None
-        new_vscsi_sxp = ['vscsi']
+        new_vscsi_sxp = ['vscsi', ['feature-host', 0]]
         for dev in sxp.children(cur_vscsi_sxp, 'dev'):
             if vHCTL == sxp.child_value(dev, 'v-dev'):
                 target_dev = dev
@@ -3787,7 +3822,7 @@ class XendDomainInfo:
             raise XendError('Failed to destroy device')
 
         target_dev.append(['state', xenbusState['Closing']])
-        target_vscsi_sxp = ['vscsi', target_dev]
+        target_vscsi_sxp = ['vscsi', target_dev, ['feature-host', 0]]
 
         if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendNode.py Fri Mar 27 11:07:11 2009 +0900
@@ -18,6 +18,7 @@
 
 import os
 import socket
+import time
 import xen.lowlevel.xc
 
 from xen.util import Brctl
@@ -145,6 +146,18 @@ class XendNode:
 
         self.srs = {}
 
+        self._init_networks()
+        self._init_PIFs()
+
+        self._init_SRs()
+        self._init_PBDs()
+
+        self._init_PPCIs()
+
+        self._init_PSCSIs()
+
+
+    def _init_networks(self):
         # Initialise networks
         # First configure ones off disk
         saved_networks = self.state_store.load_state('network')
@@ -157,7 +170,16 @@ class XendNode:
                 
         # Next discover any existing bridges and check
         # they are not already configured
-        bridges = Brctl.get_state().keys()
+
+        # 'tmpbridge' is a temporary bridge created by network-bridge script.
+        # Wait a couple of seconds for it to be renamed.
+        for i in xrange(20):
+            bridges = Brctl.get_state().keys()
+            if 'tmpbridge' in bridges:
+                time.sleep(0.1)
+            else:
+                break
+            
         configured_bridges = [XendAPIStore.get(
                                   network_uuid, "network")
                                       .get_name_label()
@@ -166,8 +188,10 @@ class XendNode:
                                 for bridge in bridges
                                 if bridge not in configured_bridges]
         for unconfigured_bridge in unconfigured_bridges:
-            XendNetwork.create_phy(unconfigured_bridge)
-
+            if unconfigured_bridge != 'tmpbridge':
+                XendNetwork.create_phy(unconfigured_bridge)
+
+    def _init_PIFs(self):
         # Initialise PIFs
         # First configure ones off disk
         saved_pifs = self.state_store.load_state('pif')
@@ -210,7 +234,8 @@ class XendNode:
                     log.debug("Cannot find network for bridge %s "
                               "when configuring PIF %s",
                               (bridge_name, name))     
-        
+
+    def _init_SRs(self):
         # initialise storage
         saved_srs = self.state_store.load_state('sr')
         if saved_srs:
@@ -229,6 +254,7 @@ class XendNode:
             qcow_sr_uuid = uuid.createString()
             self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
 
+    def _init_PBDs(self):
         saved_pbds = self.state_store.load_state('pbd')
         if saved_pbds:
             for pbd_uuid, pbd_cfg in saved_pbds.items():
@@ -237,8 +263,7 @@ class XendNode:
                 except CreateUnspecifiedAttributeError:
                     log.warn("Error recreating PBD %s", pbd_uuid) 
 
-
-        # Initialise PPCIs
+    def _init_PPCIs(self):
         saved_ppcis = self.state_store.load_state('ppci')
         saved_ppci_table = {}
         if saved_ppcis:
@@ -271,7 +296,7 @@ class XendNode:
             ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
             XendPPCI(ppci_uuid, ppci_record)
 
-
+    def _init_PSCSIs(self):
         # Initialise PSCSIs
         saved_pscsis = self.state_store.load_state('pscsi')
         saved_pscsi_table = {}
@@ -288,6 +313,75 @@ class XendNode:
                 pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'],
                                                    uuid.createString())
                 XendPSCSI(pscsi_uuid, pscsi_record)
+
+
+    def add_network(self, interface):
+        # TODO
+        log.debug("add_network(): Not implemented.")
+
+
+    def remove_network(self, interface):
+        # TODO
+        log.debug("remove_network(): Not implemented.")
+
+
+    def add_PPCI(self, pci_name):
+        # Update lspci info
+        PciUtil.create_lspci_info()
+
+        # Initialise the PPCI
+        saved_ppcis = self.state_store.load_state('ppci')
+        saved_ppci_table = {}
+        if saved_ppcis:
+            for ppci_uuid, ppci_record in saved_ppcis.items():
+                try:
+                    saved_ppci_table[ppci_record['name']] = ppci_uuid
+                except KeyError:
+                    pass
+
+        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
+        pci_dev = PciUtil.PciDevice(domain, bus, slot, func)
+        ppci_record = {
+            'domain':                   pci_dev.domain,
+            'bus':                      pci_dev.bus,
+            'slot':                     pci_dev.slot,
+            'func':                     pci_dev.func,
+            'vendor_id':                pci_dev.vendor,
+            'vendor_name':              pci_dev.vendorname,
+            'device_id':                pci_dev.device,
+            'device_name':              pci_dev.devicename,
+            'revision_id':              pci_dev.revision,
+            'class_code':               pci_dev.classcode,
+            'class_name':               pci_dev.classname,
+            'subsystem_vendor_id':      pci_dev.subvendor,
+            'subsystem_vendor_name':    pci_dev.subvendorname,
+            'subsystem_id':             pci_dev.subdevice,
+            'subsystem_name':           pci_dev.subdevicename,
+            'driver':                   pci_dev.driver
+            }
+        # If saved uuid exists, use it. Otherwise create one.
+        ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
+        XendPPCI(ppci_uuid, ppci_record)
+
+
+    def remove_PPCI(self, pci_name):
+        # Update lspci info
+        PciUtil.create_lspci_info()
+
+        # Remove the PPCI
+        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
+        ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
+        XendAPIStore.get(ppci_ref, "PPCI").destroy()
+
+
+    def add_PSCSI(self):
+        # TODO
+        log.debug("add_network(): Not implemented.")
+
+
+    def remove_PSCSI(self):
+        # TODO
+        log.debug("add_network(): Not implemented.")
 
 
 ##    def network_destroy(self, net_uuid):
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendOptions.py
--- a/tools/python/xen/xend/XendOptions.py      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendOptions.py      Fri Mar 27 11:07:11 2009 +0900
@@ -75,6 +75,9 @@ class XendOptions:
     """Default for the flag indicating whether xend should run a ssl 
relocation server."""
     xend_relocation_ssl_server_default = 'no'
 
+    """Default for the flag indicating whether xend should run a udev event 
server."""
+    xend_udev_event_server_default = 'no'
+
     """Default interface address the xend relocation server listens at. """
     xend_relocation_address_default = ''
 
@@ -215,6 +218,10 @@ class XendOptions:
 
     def get_xend_relocation_server_ssl_cert_file(self):
         return self.get_config_string("xend-relocation-server-ssl-cert-file")
+
+    def get_xend_udev_event_server(self):
+        return self.get_config_bool("xend-udev-event-server",
+                                    self.xend_udev_event_server_default)
 
     def get_xend_port(self):
         """Get the port xend listens at for its HTTP interface.
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/XendPPCI.py
--- a/tools/python/xen/xend/XendPPCI.py Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/XendPPCI.py Fri Mar 27 11:07:11 2009 +0900
@@ -19,6 +19,8 @@ from xen.xend.XendBase import XendBase
 from xen.xend.XendBase import XendBase
 from xen.xend.XendBase import XendAPIStore
 from xen.xend import uuid as genuuid
+
+from xen.util.pci import parse_hex
 
 class XendPPCI(XendBase):
     """Representation of a physical PCI device."""
@@ -72,10 +74,10 @@ class XendPPCI(XendBase):
  
     def get_by_sbdf(self, domain, bus, slot, func):
         for ppci in XendAPIStore.get_all("PPCI"):
-            if ppci.get_domain() == int(domain, 16) and \
-               ppci.get_bus() == int(bus, 16) and \
-               ppci.get_slot() == int(slot, 16) and \
-               ppci.get_func() == int(func, 16):
+            if ppci.get_domain() == parse_hex(domain) and \
+               ppci.get_bus() == parse_hex(bus) and \
+               ppci.get_slot() == parse_hex(slot) and \
+               ppci.get_func() == parse_hex(func):
                 return ppci.get_uuid()
         return None
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/image.py    Fri Mar 27 11:07:11 2009 +0900
@@ -28,6 +28,7 @@ import errno
 import errno
 import glob
 import traceback
+import platform
 
 import xen.lowlevel.xc
 from xen.xend.XendConstants import *
@@ -40,6 +41,7 @@ from xen.xend import XendOptions
 from xen.xend import XendOptions
 from xen.util import oshelp
 from xen.util import utils
+from xen.xend import osdep
 
 xc = xen.lowlevel.xc.xc()
 
@@ -226,23 +228,23 @@ class ImageHandler:
         if self.device_model is None:
             return
 
-        # If we use a device model, the pipes for communication between
-        # blktapctrl and ioemu must be present before the devices are 
-        # created (blktapctrl must access them for new block devices)
-
-        # mkdir throws an exception if the path already exists
-        try:
-            os.mkdir('/var/run/tap', 0755)
-        except:
-            pass
-
-        try:
-            os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600)
-            os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600)
-        except OSError, e:
-            log.warn('Could not create blktap pipes for domain %d' % domid)
-            log.exception(e)
-            pass
+        if platform.system() != 'SunOS':
+            # If we use a device model, the pipes for communication between
+            # blktapctrl and ioemu must be present before the devices are 
+            # created (blktapctrl must access them for new block devices)
+
+            try:
+                os.makedirs('/var/run/tap', 0755)
+            except:
+                pass
+
+            try:
+                os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600)
+                os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600)
+            except OSError, e:
+                log.warn('Could not create blktap pipes for domain %d' % domid)
+                log.exception(e)
+                pass
 
 
     # Return a list of cmd line args to the device models based on the
@@ -407,9 +409,12 @@ class ImageHandler:
         logfd = os.open(self.logfile, logfile_mode)
         
         sys.stderr.flush()
+        contract = osdep.prefork("%s:%d" %
+                                 (self.vm.getName(), self.vm.getDomid()))
         pid = os.fork()
         if pid == 0: #child
             try:
+                osdep.postfork(contract)
                 os.dup2(null, 0)
                 os.dup2(logfd, 1)
                 os.dup2(logfd, 2)
@@ -426,6 +431,7 @@ class ImageHandler:
             except:
                 os._exit(127)
         else:
+            osdep.postfork(contract, abandon=True)
             self.pid = pid
             os.close(null)
             os.close(logfd)
@@ -482,11 +488,7 @@ class ImageHandler:
 
     def _dmfailed(self, message):
         log.warning("domain %s: %s", self.vm.getName(), message)
-        # ideally we would like to forcibly crash the domain with
-        # something like
-        #    xc.domain_shutdown(self.vm.getDomid(), DOMAIN_CRASH)
-        # but this can easily lead to very rapid restart loops against
-        # which we currently have no protection
+        xc.domain_shutdown(self.vm.getDomid(), DOMAIN_CRASH)
 
     def recreate(self):
         if self.device_model is None:
@@ -714,6 +716,7 @@ class HVMImageHandler(ImageHandler):
         if 'hvm' not in info['xen_caps']:
             raise HVMRequired()
 
+        xen_platform_pci = int(vmConfig['platform'].get('xen_platform_pci',1))
         rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
 
         if not self.display :
@@ -722,13 +725,23 @@ class HVMImageHandler(ImageHandler):
                         ("image/device-model", self.device_model),
                         ("image/display", self.display))
         self.vm.permissionsVm("image/dmargs", { 'dom': self.vm.getDomid(), 
'read': True } )
+
+        if xen_platform_pci == 0:
+            disable_pf = 1
+            log.info("No need to create platform device.[domid:%d]", 
self.vm.getDomid())
+        else:
+            disable_pf = 0
+            log.info("Need to create platform device.[domid:%d]", 
self.vm.getDomid())
+
+        xstransact.Store("/local/domain/0/device-model/%i"%self.vm.getDomid(),
+                                      ('disable_pf', disable_pf))
         self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
         self.vm.permissionsVm("rtc/timeoffset", { 'dom': self.vm.getDomid(), 
'read': True } )
 
         self.apic = int(vmConfig['platform'].get('apic', 0))
         self.acpi = int(vmConfig['platform'].get('acpi', 0))
         self.guest_os_type = vmConfig['platform'].get('guest_os_type')
-           
+
 
     # Return a list of cmd line args to the device models based on the
     # xm config file
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/osdep.py
--- a/tools/python/xen/xend/osdep.py    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/osdep.py    Fri Mar 27 11:07:11 2009 +0900
@@ -18,6 +18,7 @@
 # Use is subject to license terms.
 
 import os
+import commands
 
 _scripts_dir = {
     "Linux": "/etc/xen/scripts",
@@ -142,7 +143,79 @@ def _linux_get_cpuinfo():
     finally:
         f.close()
 
+def _solaris_get_cpuinfo():
+    cpuinfo = {}
+
+    # call kstat to extrace specific cpu_info output
+    cmd = "/usr/bin/kstat -p -c misc -m cpu_info"
+    kstatoutput = commands.getoutput (cmd)
+
+    # walk each line
+    for kstatline in kstatoutput.split('\n'):
+
+        # split the line on 
+        # module:cpu #:module#:name value
+        (module, cpunum, combo, namevalue) = kstatline.split (":")
+
+        # check to see if this cpunum is already a key.  If not,
+        # initialize an empty hash table
+        if not cpuinfo.has_key (int(cpunum)):
+            cpuinfo[int(cpunum)] = {}
+
+        # split the namevalue output on whitespace
+        data = namevalue.split()
+
+        # the key will be data[0]
+        key = data[0]
+
+        # check the length of the data list.  If it's larger than
+        # 2, join the rest of the list together with a space.
+        # Otherwise, value is just data[1]
+        if len (data) > 2:
+            value = ' '.join (data[1:])
+        else:
+            value = data[1]
+
+        # add this key/value pair to the cpuhash
+        cpuinfo[int(cpunum)][key] = value
+    
+    # Translate Solaris tokens into what Xend expects
+    for key in cpuinfo.keys():
+        cpuinfo[key]["flags"] = ""
+        cpuinfo[key]["model name"] = cpuinfo[key]["brand"]
+        cpuinfo[key]["cpu MHz"] = cpuinfo[key]["clock_MHz"]
+
+    # return the hash table
+    return cpuinfo
+
 _get_cpuinfo = {
+    "SunOS": _solaris_get_cpuinfo
+}
+
+def _default_prefork(name):
+    pass
+
+def _default_postfork(ct, abandon=False):
+    pass
+
+# call this for long-running processes that should survive a xend
+# restart
+def _solaris_prefork(name):
+    from xen.lowlevel import process
+    return process.activate(name)
+
+def _solaris_postfork(ct, abandon=False):
+    from xen.lowlevel import process
+    process.clear(ct)
+    if abandon:
+        process.abandon_latest()
+
+_get_prefork = {
+    "SunOS": _solaris_prefork
+}
+
+_get_postfork = {
+    "SunOS": _solaris_postfork
 }
 
 def _get(var, default=None):
@@ -154,3 +227,5 @@ vif_script = _get(_vif_script, "vif-brid
 vif_script = _get(_vif_script, "vif-bridge")
 lookup_balloon_stat = _get(_balloon_stat, _linux_balloon_stat)
 get_cpuinfo = _get(_get_cpuinfo, _linux_get_cpuinfo)
+prefork = _get(_get_prefork, _default_prefork)
+postfork = _get(_get_postfork, _default_postfork)
diff -r 5e4dd7079c48 -r e54eeff2de54 
tools/python/xen/xend/server/BlktapController.py
--- a/tools/python/xen/xend/server/BlktapController.py  Fri Mar 27 10:54:08 
2009 +0900
+++ b/tools/python/xen/xend/server/BlktapController.py  Fri Mar 27 11:07:11 
2009 +0900
@@ -15,7 +15,8 @@ blktap_disk_types = [
     'qcow',
     'qcow2',
 
-    'ioemu'
+    'ioemu',
+    'tapdisk',
     ]
 
 class BlktapController(BlkifController):
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/server/SrvDaemon.py
--- a/tools/python/xen/xend/server/SrvDaemon.py Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/server/SrvDaemon.py Fri Mar 27 11:07:11 2009 +0900
@@ -24,6 +24,7 @@ from xen.util import mkdir
 from xen.util import mkdir
 
 import relocate
+import udevevent
 import SrvServer
 from params import *
 
@@ -336,6 +337,7 @@ class Daemon:
             del xc
 
             relocate.listenRelocation()
+            udevevent.listenUdevEvent()
             servers = SrvServer.create()
             servers.start(status)
             del servers
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/server/SrvDomain.py Fri Mar 27 11:07:11 2009 +0900
@@ -104,7 +104,8 @@ class SrvDomain(SrvDir):
                     [['dom',         'int'],
                      ['file',        'str'],
                      ['live',        'int'],
-                     ['crash',       'int']])
+                     ['crash',       'int'],
+                     ['reset',       'int']])
         return fn(req.args, {'dom': self.dom.domid})
 
     def op_migrate(self, op, req):
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/server/netif.py     Fri Mar 27 11:07:11 2009 +0900
@@ -24,7 +24,7 @@ import random
 import random
 import re
 
-from xen.xend import XendOptions
+from xen.xend import XendOptions, sxp
 from xen.xend.server.DevController import DevController
 from xen.xend.XendError import VmError
 from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
@@ -196,3 +196,23 @@ class NetifController(DevController):
                 result[x] = y
 
         return result
+
+    # match a VIF ID from xenstore, or a MAC address stored in the domain 
config
+    def convertToDeviceNumber(self, devid):
+        try:
+            return int(devid)
+        except ValueError:
+            if type(devid) is not str:
+                raise VmError("devid %s is wrong type" % str(devid))
+            try:
+                dev = devid.split('/')[-1]
+                return (int(dev))
+            except ValueError:
+                devs = [d for d in self.vm.info.all_devices_sxpr()
+                    if d[0] == 'vif']
+                for nr in range(len(devs)):
+                    dev_type, dev_info = devs[nr]
+                    if (sxp.child_value(dev_info, 'mac').lower() ==
+                        devid.lower()):
+                        return nr
+                raise VmError("unknown devid %s" % str(devid))
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xend/server/pciif.py     Fri Mar 27 11:07:11 2009 +0900
@@ -24,6 +24,7 @@ from xen.xend import arch
 from xen.xend import arch
 from xen.xend.XendError import VmError
 from xen.xend.XendLogging import log
+from xen.xend.XendConstants import *
 
 from xen.xend.server.DevController import DevController
 from xen.xend.server.DevConstants import xenbusState
@@ -74,6 +75,7 @@ class PciController(DevController):
             bus = parse_hex(pci_config.get('bus', 0))
             slot = parse_hex(pci_config.get('slot', 0))
             func = parse_hex(pci_config.get('func', 0))            
+            vslot = parse_hex(pci_config.get('vslot', 0))
 
             opts = pci_config.get('opts', '')
             if len(opts) > 0:
@@ -218,7 +220,7 @@ class PciController(DevController):
                     try:
                         dev_dict['vslt'] = slot_list[i]
                     except IndexError:
-                        dev_dict['vslt'] = '0x0'
+                        dev_dict['vslt'] = AUTO_PHP_SLOT_STR
 
                 pci_devs.append(dev_dict)
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xend/server/udevevent.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/server/udevevent.py Fri Mar 27 11:07:11 2009 +0900
@@ -0,0 +1,68 @@
+import socket
+
+from xen.web import protocol, unix
+
+from xen.xend.XendLogging import log
+from xen.xend import XendNode
+from xen.xend import XendOptions
+
+UDEV_EVENT_PATH = '\0/org/xen/xend/udev_event'
+
+class UdevEventProtocol(protocol.Protocol):
+
+    def __init__(self):
+        protocol.Protocol.__init__(self)
+
+    def dataReceived(self, data):
+        udev_event = {}
+        for entry in data.split('\0'):
+            try:
+                opt, val = entry.split("=")
+                udev_event[opt] = val
+            except (TypeError, ValueError):
+                pass
+        if udev_event.get('ACTION', None) is None:
+            log.warn("Invalid udev event received")
+            return
+
+        log.debug("udev event received: %s", udev_event)
+
+        self._process_event(udev_event)
+
+    def _process_event(self, udev_event):
+        try:
+            if (udev_event.get('SUBSYSTEM', None) == 'pci'):
+                pci_name = udev_event.get('PCI_SLOT_NAME', None)
+                if (udev_event['ACTION'] == 'add'):
+                    log.info("Adding pci device %s", pci_name)
+                    XendNode.instance().add_PPCI(pci_name)
+                elif (udev_event['ACTION'] == 'remove'):
+                    log.info("Removing pci device %s", pci_name)
+                    XendNode.instance().remove_PPCI(pci_name)
+
+            elif (udev_event.get('SUBSYSTEMS', None) == 'scsi'):
+                if (udev_event['ACTION'] == 'add'):
+                    log.info("Adding scsi device")
+                    XendNode.instance().add_PSCSI()
+                elif (udev_event['ACTION'] == 'remove'):
+                    log.info("Removing scci device")
+                    XendNode.instance().remove_PSCSI()
+
+            elif (udev_event.get('SUBSYSTEM', None) == 'net'):
+                interface = udev_event.get('INTERFACE', None)
+                if (udev_event['ACTION'] == 'add'):
+                    log.info("Adding net device %s", interface)
+                    XendNode.instance().add_network(interface)
+                elif (udev_event['ACTION'] == 'remove'):
+                    log.info("Removing net device %s", interface)
+                    XendNode.instance().remove_network(interface)
+
+        except Exception, e:
+            log.warn("error while processing udev event(): %s" % str(e))
+
+
+def listenUdevEvent():
+    xoptions = XendOptions.instance()
+    if xoptions.get_xend_udev_event_server():
+        unix.UnixDgramListener(UDEV_EVENT_PATH, UdevEventProtocol)
+
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xm/create.dtd
--- a/tools/python/xen/xm/create.dtd    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xm/create.dtd    Fri Mar 27 11:07:11 2009 +0900
@@ -47,6 +47,7 @@
                  other_config*)> 
 <!ATTLIST vm     is_a_template          CDATA #REQUIRED
                  auto_power_on          CDATA #REQUIRED
+                 s3_integrity           CDATA #REQUIRED
                  vcpus_max              CDATA #REQUIRED
                  vcpus_at_startup       CDATA #REQUIRED
                  actions_after_shutdown %NORMAL_EXIT; #REQUIRED 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xm/create.py     Fri Mar 27 11:07:11 2009 +0900
@@ -1,4 +1,4 @@
-#============================================================================
+#============================================================================UTO
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of version 2.1 of the GNU Lesser General Public
 # License as published by the Free Software Foundation.
@@ -32,6 +32,7 @@ from xen.xend import osdep
 from xen.xend import osdep
 import xen.xend.XendClient
 from xen.xend.XendBootloader import bootloader
+from xen.xend.XendConstants import *
 from xen.xend.server.DevConstants import xenbusState
 from xen.util import blkif
 from xen.util import vscsi_util
@@ -322,10 +323,12 @@ gopts.var('disk', val='phy:DEV,VDEV,MODE
           backend driver domain to use for the disk.
           The option may be repeated to add more than one disk.""")
 
-gopts.var('pci', val='BUS:DEV.FUNC[,msitranslate=0|1][,power_mgmt=0|1]',
+gopts.var('pci', 
val='BUS:DEV.FUNC[@VSLOT][,msitranslate=0|1][,power_mgmt=0|1]',
           fn=append_value, default=[],
           use="""Add a PCI device to a domain, using given params (in hex).
           For example 'pci=c0:02.1'.
+          If VSLOT is supplied the device will be inserted into that
+          virtual slot in the guest, else a free slot is selected.
           If msitranslate is set, MSI-INTx translation is enabled if possible.
           Guest that doesn't support MSI will get IO-APIC type IRQs
           translated from physical MSI, HVM only. Default is 1.
@@ -610,6 +613,10 @@ gopts.var('pci_power_mgmt', val='POWERMG
 gopts.var('pci_power_mgmt', val='POWERMGMT',
           fn=set_int, default=0,
           use="""Global PCI Power Management flag (0=disable;1=enable).""")
+
+gopts.var('xen_platform_pci', val='0|1',
+           fn=set_int, default=1,
+           use="Is xen_platform_pci used?")
 
 def err(msg):
     """Print an error to stderr and exit.
@@ -692,7 +699,7 @@ def configure_pci(config_devs, vals):
     """Create the config for pci devices.
     """
     config_pci = []
-    for (domain, bus, slot, func, opts) in vals.pci:
+    for (domain, bus, slot, func, vslot, opts) in vals.pci:
         config_pci_opts = []
         d = comma_sep_kv_to_dict(opts)
 
@@ -703,7 +710,7 @@ def configure_pci(config_devs, vals):
             config_pci_opts.append([k, d[k]])
 
         config_pci_bdf = ['dev', ['domain', domain], ['bus', bus], \
-                          ['slot', slot], ['func', func]]
+                          ['slot', slot], ['func', func], ['vslot', vslot]]
         map(f, d.keys())
         if len(config_pci_opts)>0:
             config_pci_bdf.append(['opts', config_pci_opts])
@@ -738,6 +745,9 @@ def configure_vscsis(config_devs, vals):
 
         feature_host = 0
         if v_dev == 'host':
+            if serverType == SERVER_XEN_API:
+                # TODO
+                raise ValueError("SCSI devices assignment by HBA is not 
implemeted")
             feature_host = 1
             scsi_info = []
             devid = get_devid(p_hctl)
@@ -921,7 +931,7 @@ def configure_hvm(config_image, vals):
              'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
              'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
              'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
-             'vpt_align', 'pci_power_mgmt' ]
+             'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
 
     for a in args:
         if a in vals.__dict__ and vals.__dict__[a] is not None:
@@ -1047,16 +1057,21 @@ def preprocess_pci(vals):
                 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
                 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
                 r"(?P<func>[0-7])" + \
-                r"(,(?P<opts>.*))?$", pci_dev_str)
+                r"(@(?P<vslot>[0-9a-fA-F]))?" + \
+                r"(,(?P<opts>.*))?$", \
+                pci_dev_str)
         if pci_match!=None:
             pci_dev_info = pci_match.groupdict('')
             if pci_dev_info['domain']=='':
                 pci_dev_info['domain']='0'
+            if pci_dev_info['vslot']=='':
+                pci_dev_info['vslot']="%02x" % AUTO_PHP_SLOT
             try:
                 pci.append( ('0x'+pci_dev_info['domain'], \
                         '0x'+pci_dev_info['bus'], \
                         '0x'+pci_dev_info['slot'], \
                         '0x'+pci_dev_info['func'], \
+                        '0x'+pci_dev_info['vslot'], \
                         pci_dev_info['opts']))
             except IndexError:
                 err('Error in PCI slot syntax "%s"'%(pci_dev_str))
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xm/main.py       Fri Mar 27 11:07:11 2009 +0900
@@ -1351,22 +1351,8 @@ def xm_dump_core(args):
     else:
         filename = None
 
-    if not live:
-        ds = server.xend.domain.pause(dom, True)
-
-    try:
-        print "Dumping core of domain: %s ..." % str(dom)
-        server.xend.domain.dump(dom, filename, live, crash)
-
-        if crash:
-            print "Destroying domain: %s ..." % str(dom)
-            server.xend.domain.destroy(dom)
-        elif reset:
-            print "Resetting domain: %s ..." % str(dom)
-            server.xend.domain.reset(dom)
-    finally:
-        if not live and not crash and not reset and ds == DOM_STATE_RUNNING:
-            server.xend.domain.unpause(dom)
+    print "Dumping core of domain: %s ..." % str(dom)
+    server.xend.domain.dump(dom, filename, live, crash, reset)
 
 def xm_rename(args):
     arg_check(args, "rename", 2)
@@ -2231,6 +2217,33 @@ def xm_pci_list_assignable_devices(args)
             print d.name,
         print
 
+def vscsi_sort(devs):
+    def sort_hctl(ds, l):
+        s = []
+        for d1 in ds:
+            for d2 in d1:
+                v_dev = sxp.child_value(d2, 'v-dev')
+                n = int(v_dev.split(':')[l])
+                try:
+                    j = s[n]
+                except IndexError:
+                    j = []
+                    s.extend([ [] for _ in range(len(s), n+1) ])
+                j.append(d2)
+                s[n] = j
+        return s
+
+    for i in range(len(devs)):
+        ds1 = [ devs[i][1][0][1] ]
+        ds1 = sort_hctl(ds1, 3)
+        ds1 = sort_hctl(ds1, 2)
+        ds1 = sort_hctl(ds1, 1)
+        ds2 = []
+        for d in ds1:
+            ds2.extend(d)
+        devs[i][1][0][1] = ds2
+    return devs
+
 def vscsi_convert_sxp_to_dict(dev_sxp):
     dev_dict = {}
     for opt_val in dev_sxp[1:]:
@@ -2270,6 +2283,9 @@ def xm_scsi_list(args):
 
     else:
         devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
+
+    # Sort devs by virtual HCTL.
+    devs = vscsi_sort(devs)
 
     if use_long:
         map(PrettyPrint.prettyprint, devs)
@@ -2440,7 +2456,7 @@ def parse_pci_configuration(args, state,
     if len(args) == 3:
         vslt = args[2]
     else:
-        vslt = '0x0' #chose a free virtual PCI slot
+        vslt = AUTO_PHP_SLOT_STR
     pci=['pci']
     pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
             r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
@@ -2523,6 +2539,9 @@ def parse_scsi_configuration(p_scsi, v_h
     if p_scsi is not None:
         # xm scsi-attach
         if v_hctl == "host":
+            if serverType == SERVER_XEN_API:
+                # TODO
+                raise OptionError("SCSI devices assignment by HBA is not 
implemeted")
             host_mode = 1
             scsi_devices = vscsi_util.vscsi_get_scsidevices()
         elif len(v_hctl.split(':')) != 4:
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py      Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/python/xen/xm/xenapi_create.py      Fri Mar 27 11:07:11 2009 +0900
@@ -1048,6 +1048,7 @@ class sxp2xml:
             'hap',
             'pci_msitranslate',
             'pci_power_mgmt',
+            'xen_platform_pci',
         ]
 
         platform_configs = []
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/xcutils/xc_save.c   Fri Mar 27 11:07:11 2009 +0900
@@ -46,97 +46,6 @@ static int compat_suspend(void)
             !strncmp(ans, "done\n", 5));
 }
 
-static int suspend_evtchn_release(void)
-{
-    if (si.suspend_evtchn >= 0) {
-        xc_evtchn_unbind(si.xce, si.suspend_evtchn);
-        si.suspend_evtchn = -1;
-    }
-    if (si.xce >= 0) {
-        xc_evtchn_close(si.xce);
-        si.xce = -1;
-    }
-
-    return 0;
-}
-
-static int await_suspend(void)
-{
-    int rc;
-
-    do {
-        rc = xc_evtchn_pending(si.xce);
-        if (rc < 0) {
-            warnx("error polling suspend notification channel: %d", rc);
-            return -1;
-        }
-    } while (rc != si.suspend_evtchn);
-
-    /* harmless for one-off suspend */
-    if (xc_evtchn_unmask(si.xce, si.suspend_evtchn) < 0)
-        warnx("failed to unmask suspend notification channel: %d", rc);
-
-    return 0;
-}
-
-static int suspend_evtchn_init(int xc, int domid)
-{
-    struct xs_handle *xs;
-    char path[128];
-    char *portstr;
-    unsigned int plen;
-    int port;
-    int rc;
-
-    si.xce = -1;
-    si.suspend_evtchn = -1;
-
-    xs = xs_daemon_open();
-    if (!xs) {
-        warnx("failed to get xenstore handle");
-        return -1;
-    }
-    sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid);
-    portstr = xs_read(xs, XBT_NULL, path, &plen);
-    xs_daemon_close(xs);
-
-    if (!portstr || !plen) {
-        warnx("could not read suspend event channel");
-        return -1;
-    }
-
-    port = atoi(portstr);
-    free(portstr);
-
-    si.xce = xc_evtchn_open();
-    if (si.xce < 0) {
-        warnx("failed to open event channel handle");
-        goto cleanup;
-    }
-
-    si.suspend_evtchn = xc_evtchn_bind_interdomain(si.xce, domid, port);
-    if (si.suspend_evtchn < 0) {
-        warnx("failed to bind suspend event channel: %d", si.suspend_evtchn);
-        goto cleanup;
-    }
-
-    rc = xc_domain_subscribe_for_suspend(xc, domid, port);
-    if (rc < 0) {
-        warnx("failed to subscribe to domain: %d", rc);
-        goto cleanup;
-    }
-
-    /* event channel is pending immediately after binding */
-    await_suspend();
-
-    return 0;
-
-  cleanup:
-    suspend_evtchn_release();
-
-    return -1;
-}
-
 /**
  * Issue a suspend request to a dedicated event channel in the guest, and
  * receive the acknowledgement from the subscribe event channel. */
@@ -150,7 +59,7 @@ static int evtchn_suspend(void)
         return 0;
     }
 
-    if (await_suspend() < 0) {
+    if (xc_await_suspend(si.xce, si.suspend_evtchn) < 0) {
         warnx("suspend failed");
         return 0;
     }
@@ -303,12 +212,11 @@ static void *init_qemu_maps(int domid, u
     return seg;
 }
 
-
 int
 main(int argc, char **argv)
 {
     unsigned int maxit, max_f;
-    int io_fd, ret;
+    int io_fd, ret, port;
 
     if (argc != 6)
         errx(1, "usage: %s iofd domid maxit maxf flags", argv[0]);
@@ -323,14 +231,37 @@ main(int argc, char **argv)
     max_f = atoi(argv[4]);
     si.flags = atoi(argv[5]);
 
-    if (suspend_evtchn_init(si.xc_fd, si.domid) < 0)
-        warnx("suspend event channel initialization failed, using slow path");
-
+    si.suspend_evtchn = si.xce = -1;
+
+    si.xce = xc_evtchn_open();
+    if (si.xce < 0)
+        warnx("failed to open event channel handle");
+
+    if (si.xce > 0)
+    {
+        port = xs_suspend_evtchn_port(si.domid);
+
+        if (port < 0)
+            warnx("faield to get the suspend evtchn port\n");
+        else
+        {
+            si.suspend_evtchn =
+              xc_suspend_evtchn_init(si.xc_fd, si.xce, si.domid, port);
+
+            if (si.suspend_evtchn < 0)
+                warnx("suspend event channel initialization failed"
+                       "using slow path");
+        }
+    }
     ret = xc_domain_save(si.xc_fd, io_fd, si.domid, maxit, max_f, si.flags, 
                          &suspend, !!(si.flags & XCFLAGS_HVM),
                          &init_qemu_maps, &qemu_flip_buffer);
 
-    suspend_evtchn_release();
+    if (si.suspend_evtchn > 0)
+        xc_suspend_evtchn_release(si.xce, si.suspend_evtchn);
+
+    if (si.xce > 0)
+        xc_evtchn_close(si.xce);
 
     xc_interface_close(si.xc_fd);
 
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile   Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/xenstore/Makefile   Fri Mar 27 11:07:11 2009 +0900
@@ -97,9 +97,9 @@ install: all
        $(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR)
        $(INSTALL_PROG) xenstored $(DESTDIR)$(SBINDIR)
        $(INSTALL_PROG) xenstore-control $(DESTDIR)$(BINDIR)
-       $(INSTALL_PROG) xenstore $(DESTDIR)/usr/bin
+       $(INSTALL_PROG) xenstore $(DESTDIR)$(BINDIR)
        set -e ; for c in $(CLIENTS) ; do \
-               ln -f $(DESTDIR)/usr/bin/xenstore $(DESTDIR)/usr/bin/$${c} ; \
+               ln -f $(DESTDIR)$(BINDIR)/xenstore $(DESTDIR)$(BINDIR)/$${c} ; \
        done
        $(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
        $(INSTALL_PROG) libxenstore.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/xenstore/xs.c       Fri Mar 27 11:07:11 2009 +0900
@@ -802,6 +802,31 @@ bool xs_is_domain_introduced(struct xs_h
        return rc;
 }
 
+int xs_suspend_evtchn_port(int domid)
+{
+    char path[128];
+    char *portstr;
+    int port;
+    unsigned int plen;
+    struct xs_handle *xs;
+
+    xs = xs_daemon_open();
+    if (!xs)
+        return -1;
+
+    sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid);
+    portstr = xs_read(xs, XBT_NULL, path, &plen);
+    xs_daemon_close(xs);
+
+    if (!portstr || !plen)
+        return -1;
+
+    port = atoi(portstr);
+    free(portstr);
+
+    return port;
+}
+
 /* Only useful for DEBUG versions */
 char *xs_debug_command(struct xs_handle *h, const char *cmd,
                       void *data, unsigned int len)
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h       Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/xenstore/xs.h       Fri Mar 27 11:07:11 2009 +0900
@@ -163,6 +163,7 @@ char *xs_debug_command(struct xs_handle 
 char *xs_debug_command(struct xs_handle *h, const char *cmd,
                       void *data, unsigned int len);
 
+int xs_suspend_evtchn_port(int domid);
 #endif /* _XS_H */
 
 /*
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/xentrace/formats
--- a/tools/xentrace/formats    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/xentrace/formats    Fri Mar 27 11:07:11 2009 +0900
@@ -118,5 +118,5 @@ 0x0040f10f  CPU%(cpu)d  %(tsc)d (+%(relt
 0x0040f10f  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  shadow_emulate_resync_only     
   [ gfn = 0x%(1)16x ]
 
 0x00801001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_freq_change [ %(1)dMHz -> 
%(2)dMHz ]
-0x00802001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_entry  [ C0 -> C%(1)d 
]
-0x00802002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_exit   [ C%(1)d -> C0 
]
+0x00802001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_entry  [ C0 -> 
C%(1)d, acpi_pm_tick = %(2)d ]
+0x00802002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_idle_exit   [ C%(1)d -> 
C0, acpi_pm_tick = %(2)d ]
diff -r 5e4dd7079c48 -r e54eeff2de54 tools/xentrace/xentrace_format
--- a/tools/xentrace/xentrace_format    Fri Mar 27 10:54:08 2009 +0900
+++ b/tools/xentrace/xentrace_format    Fri Mar 27 11:07:11 2009 +0900
@@ -81,7 +81,11 @@ signal.signal(signal.SIGINT,  sighand)
 
 interrupted = 0
 
-defs = read_defs(arg[0])
+try:
+    defs = read_defs(arg[0])
+except IOError, exn:
+    print exn
+    sys.exit(1)
 
 # structure of trace record (as output by xentrace):
 # HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I) D6(I) D7(I)
diff -r 5e4dd7079c48 -r e54eeff2de54 
unmodified_drivers/linux-2.6/compat-include/linux/scatterlist.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/unmodified_drivers/linux-2.6/compat-include/linux/scatterlist.h   Fri Mar 
27 11:07:11 2009 +0900
@@ -0,0 +1,10 @@
+#ifndef _LINUX_SCATTERLIST_H
+#define _LINUX_SCATTERLIST_H
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
+#error "This version of Linux should not need compat linux/scatterlist.h"
+#endif
+
+#include <asm/scatterlist.h>
+
+#endif /* _LINUX_SCATTERLIST_H */
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c     Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/ia64/xen/hypercall.c     Fri Mar 27 11:07:11 2009 +0900
@@ -674,6 +674,28 @@ long do_physdev_op(int cmd, XEN_GUEST_HA
             break;
     }
 
+    case PHYSDEVOP_manage_pci_add_ext: {
+        struct physdev_manage_pci_ext manage_pci_ext;
+        struct pci_dev_info pdev_info;
+
+        ret = -EPERM;
+        if ( !IS_PRIV(current->domain) )
+            break;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&manage_pci_ext, arg, 1) != 0 )
+            break;
+
+        pdev_info.is_extfn = manage_pci_ext.is_extfn;
+        pdev_info.is_virtfn = manage_pci_ext.is_virtfn;
+        pdev_info.physfn.bus = manage_pci_ext.physfn.bus;
+        pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn;
+        ret = pci_add_device_ext(manage_pci_ext.bus,
+                                 manage_pci_ext.devfn,
+                                 &pdev_info);
+            break;
+    }
+
     default:
         ret = -ENOSYS;
         printk("not implemented do_physdev_op: %d\n", cmd);
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/acpi/cpu_idle.c      Fri Mar 27 11:07:11 2009 +0900
@@ -167,25 +167,6 @@ static void acpi_idle_do_entry(struct ac
     }
 }
 
-static inline void acpi_idle_update_bm_rld(struct acpi_processor_power *power,
-                                           struct acpi_processor_cx *target)
-{
-    if ( !power->flags.bm_check )
-        return;
-
-    if ( power->flags.bm_rld_set && target->type != ACPI_STATE_C3 )
-    {
-        acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-        power->flags.bm_rld_set = 0;
-    }
-
-    if ( !power->flags.bm_rld_set && target->type == ACPI_STATE_C3 )
-    {
-        acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
-        power->flags.bm_rld_set = 1;
-    }
-}
-
 static int acpi_idle_bm_check(void)
 {
     u32 bm_status = 0;
@@ -239,15 +220,9 @@ static void acpi_processor_idle(void)
     if ( !cx )
     {
         if ( pm_idle_save )
-        {
-            printk(XENLOG_DEBUG "call pm_idle_save()\n");
             pm_idle_save();
-        }
         else
-        {
-            printk(XENLOG_DEBUG "call acpi_safe_halt()\n");
             acpi_safe_halt();
-        }
         return;
     }
 
@@ -258,24 +233,22 @@ static void acpi_processor_idle(void)
      * ------
      * Invoke the current Cx state to put the processor to sleep.
      */
-    acpi_idle_update_bm_rld(power, cx);
-
     switch ( cx->type )
     {
     case ACPI_STATE_C1:
     case ACPI_STATE_C2:
         if ( cx->type == ACPI_STATE_C1 || local_apic_timer_c2_ok )
         {
-            /* Trace cpu idle entry */
-            TRACE_1D(TRC_PM_IDLE_ENTRY, cx->idx);
             /* Get start time (ticks) */
             t1 = inl(pmtmr_ioport);
+            /* Trace cpu idle entry */
+            TRACE_2D(TRC_PM_IDLE_ENTRY, cx->idx, t1);
             /* Invoke C2 */
             acpi_idle_do_entry(cx);
             /* Get end time (ticks) */
             t2 = inl(pmtmr_ioport);
             /* Trace cpu idle exit */
-            TRACE_1D(TRC_PM_IDLE_EXIT, cx->idx);
+            TRACE_2D(TRC_PM_IDLE_EXIT, cx->idx, t2);
 
             /* Re-enable interrupts */
             local_irq_enable();
@@ -314,8 +287,6 @@ static void acpi_processor_idle(void)
             ACPI_FLUSH_CPU_CACHE();
         }
 
-        /* Trace cpu idle entry */
-        TRACE_1D(TRC_PM_IDLE_ENTRY, cx->idx);
         /*
          * Before invoking C3, be aware that TSC/APIC timer may be 
          * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
@@ -326,6 +297,8 @@ static void acpi_processor_idle(void)
 
         /* Get start time (ticks) */
         t1 = inl(pmtmr_ioport);
+        /* Trace cpu idle entry */
+        TRACE_2D(TRC_PM_IDLE_ENTRY, cx->idx, t1);
         /* Invoke C3 */
         acpi_idle_do_entry(cx);
         /* Get end time (ticks) */
@@ -334,7 +307,7 @@ static void acpi_processor_idle(void)
         /* recovering TSC */
         cstate_restore_tsc();
         /* Trace cpu idle exit */
-        TRACE_1D(TRC_PM_IDLE_EXIT, cx->idx);
+        TRACE_2D(TRC_PM_IDLE_EXIT, cx->idx, t2);
 
         if ( power->flags.bm_check && power->flags.bm_control )
         {
@@ -491,12 +464,22 @@ static void acpi_processor_power_init_bm
     else if ( c->x86_vendor == X86_VENDOR_INTEL )
     {
         /*
-         * Today all CPUs that support C3 share cache.
-         * TBD: This needs to look at cache shared map, once
-         * multi-core detection patch makes to the base.
+         * Today all MP CPUs that support C3 share cache.
+         * And caches should not be flushed by software while
+         * entering C3 type state.
          */
         flags->bm_check = 1;
     }
+
+    /*
+     * On all recent platforms, ARB_DISABLE is a nop.
+     * So, set bm_control to zero to indicate that ARB_DISABLE
+     * is not required while entering C3 type state on
+     * P4, Core and beyond CPUs
+     */
+    if ( c->x86_vendor == X86_VENDOR_INTEL &&
+        (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 14)) )
+            flags->bm_control = 0;
 }
 
 #define VENDOR_INTEL                   (1)
@@ -504,7 +487,8 @@ static void acpi_processor_power_init_bm
 
 static int check_cx(struct acpi_processor_power *power, xen_processor_cx_t *cx)
 {
-    static int bm_check_flag;
+    static int bm_check_flag = -1;
+    static int bm_control_flag = -1;
 
     switch ( cx->reg.space_id )
     {
@@ -550,15 +534,17 @@ static int check_cx(struct acpi_processo
         }
 
         /* All the logic here assumes flags.bm_check is same across all CPUs */
-        if ( !bm_check_flag )
+        if ( bm_check_flag == -1 )
         {
             /* Determine whether bm_check is needed based on CPU  */
             acpi_processor_power_init_bm_check(&(power->flags));
             bm_check_flag = power->flags.bm_check;
+            bm_control_flag = power->flags.bm_control;
         }
         else
         {
             power->flags.bm_check = bm_check_flag;
+            power->flags.bm_control = bm_control_flag;
         }
 
         if ( power->flags.bm_check )
@@ -579,6 +565,15 @@ static int check_cx(struct acpi_processo
                         "C3 support without BM control\n"));
                 }
             }
+            /*
+             * On older chipsets, BM_RLD needs to be set
+             * in order for Bus Master activity to wake the
+             * system from C3.  Newer chipsets handle DMA
+             * during C3 automatically and BM_RLD is a NOP.
+             * In either case, the proper way to
+             * handle BM_RLD is to set it and leave it set.
+             */
+            acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
         }
         else
         {
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/acpi/cpufreq/cpufreq.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c       Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c       Fri Mar 27 11:07:11 2009 +0900
@@ -232,6 +232,26 @@ static u32 get_cur_val(cpumask_t mask)
     return cmd.val;
 }
 
+struct perf_pair {
+    union {
+        struct {
+            uint32_t lo;
+            uint32_t hi;
+        } split;
+        uint64_t whole;
+    } aperf, mperf;
+};
+static DEFINE_PER_CPU(struct perf_pair, gov_perf_pair);
+static DEFINE_PER_CPU(struct perf_pair, usr_perf_pair);
+
+static void read_measured_perf_ctrs(void *_readin)
+{
+    struct perf_pair *readin = _readin;
+
+    rdmsr(MSR_IA32_APERF, readin->aperf.split.lo, readin->aperf.split.hi);
+    rdmsr(MSR_IA32_MPERF, readin->mperf.split.lo, readin->mperf.split.hi);
+}
+
 /*
  * Return the measured active (C0) frequency on this CPU since last call
  * to this function.
@@ -245,40 +265,13 @@ static u32 get_cur_val(cpumask_t mask)
  * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
  * no meaning should be associated with absolute values of these MSRs.
  */
-static void  __get_measured_perf(void *perf_percent)
-{
-    unsigned int *ratio = perf_percent;
-    union {
-        struct {
-            uint32_t lo;
-            uint32_t hi;
-        } split;
-        uint64_t whole;
-    } aperf_cur, mperf_cur;
-
-    rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
-    rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
-
-    wrmsr(MSR_IA32_APERF, 0,0);
-    wrmsr(MSR_IA32_MPERF, 0,0);
-
-    if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
-        int shift_count = 7;
-        aperf_cur.whole >>= shift_count;
-        mperf_cur.whole >>= shift_count;
-    }
-
-    if (aperf_cur.whole && mperf_cur.whole)
-        *ratio = (aperf_cur.whole * 100) / mperf_cur.whole;
-    else
-        *ratio = 0;
-}
-
-static unsigned int get_measured_perf(unsigned int cpu)
-{
-    struct cpufreq_policy *policy;
+static unsigned int get_measured_perf(unsigned int cpu, unsigned int flag)
+{
+    struct cpufreq_policy *policy;    
+    struct perf_pair readin, cur, *saved;
     unsigned int perf_percent;
     cpumask_t cpumask;
+    unsigned int retval;
 
     if (!cpu_online(cpu))
         return 0;
@@ -287,16 +280,80 @@ static unsigned int get_measured_perf(un
     if (!policy)
         return 0;
 
-    /* Usually we take the short path (no IPI) for the sake of performance. */
+    switch (flag)
+    {
+    case GOV_GETAVG:
+    {
+        saved = &per_cpu(gov_perf_pair, cpu);
+        break;
+    }
+    case USR_GETAVG:
+    {
+        saved = &per_cpu(usr_perf_pair, cpu);
+        break;
+    }
+    default:
+        return 0;
+    }
+
     if (cpu == smp_processor_id()) {
-        __get_measured_perf((void *)&perf_percent);
+        read_measured_perf_ctrs((void *)&readin);
     } else {
         cpumask = cpumask_of_cpu(cpu);
-        on_selected_cpus(cpumask, __get_measured_perf, 
-                        (void *)&perf_percent,0,1);
-    }
-
-    return drv_data[cpu]->max_freq * perf_percent / 100;
+        on_selected_cpus(cpumask, read_measured_perf_ctrs, 
+                        (void *)&readin, 0, 1);
+    }
+
+    cur.aperf.whole = readin.aperf.whole - saved->aperf.whole;
+    cur.mperf.whole = readin.mperf.whole - saved->mperf.whole;
+    saved->aperf.whole = readin.aperf.whole;
+    saved->mperf.whole = readin.mperf.whole;
+
+#ifdef __i386__
+    /*
+     * We dont want to do 64 bit divide with 32 bit kernel
+     * Get an approximate value. Return failure in case we cannot get
+     * an approximate value.
+     */
+    if (unlikely(cur.aperf.split.hi || cur.mperf.split.hi)) {
+        int shift_count;
+        uint32_t h;
+
+        h = max_t(uint32_t, cur.aperf.split.hi, cur.mperf.split.hi);
+        shift_count = fls(h);
+
+        cur.aperf.whole >>= shift_count;
+        cur.mperf.whole >>= shift_count;
+    }
+
+    if (((unsigned long)(-1) / 100) < cur.aperf.split.lo) {
+        int shift_count = 7;
+        cur.aperf.split.lo >>= shift_count;
+        cur.mperf.split.lo >>= shift_count;
+    }
+
+    if (cur.aperf.split.lo && cur.mperf.split.lo)
+        perf_percent = (cur.aperf.split.lo * 100) / cur.mperf.split.lo;
+    else
+        perf_percent = 0;
+
+#else
+    if (unlikely(((unsigned long)(-1) / 100) < cur.aperf.whole)) {
+        int shift_count = 7;
+        cur.aperf.whole >>= shift_count;
+        cur.mperf.whole >>= shift_count;
+    }
+
+    if (cur.aperf.whole && cur.mperf.whole)
+        perf_percent = (cur.aperf.whole * 100) / cur.mperf.whole;
+    else
+        perf_percent = 0;
+
+#endif
+
+    retval = drv_data[policy->cpu]->max_freq * perf_percent / 100;
+
+    return retval;
 }
 
 static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/acpi/power.c Fri Mar 27 11:07:11 2009 +0900
@@ -44,16 +44,16 @@ void do_suspend_lowlevel(void);
 
 static int device_power_down(void)
 {
+    console_suspend();
+
+    time_suspend();
+
+    i8259A_suspend();
+
+    ioapic_suspend();
+
     iommu_suspend();
 
-    console_suspend();
-
-    time_suspend();
-
-    i8259A_suspend();
-    
-    ioapic_suspend();
-    
     lapic_suspend();
 
     return 0;
@@ -62,16 +62,16 @@ static void device_power_up(void)
 static void device_power_up(void)
 {
     lapic_resume();
-    
+
+    iommu_resume();
+
     ioapic_resume();
 
     i8259A_resume();
-    
+
     time_resume();
 
     console_resume();
-
-    iommu_resume();
 }
 
 static void freeze_domains(void)
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/acpi/suspend.c
--- a/xen/arch/x86/acpi/suspend.c       Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/acpi/suspend.c       Fri Mar 27 11:07:11 2009 +0900
@@ -31,13 +31,9 @@ void save_rest_processor_state(void)
 
 void restore_rest_processor_state(void)
 {
-    int cpu = smp_processor_id();
-    struct tss_struct *t = &init_tss[cpu];
     struct vcpu *v = current;
 
-    /* Rewriting the TSS desc is necessary to clear the Busy flag. */
-    set_tss_desc(cpu, t);
-    load_TR(cpu);
+    load_TR();
 
 #if defined(CONFIG_X86_64)
     /* Recover syscall MSRs */
@@ -47,7 +43,7 @@ void restore_rest_processor_state(void)
     wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);    
 #else /* !defined(CONFIG_X86_64) */
     if ( supervisor_mode_kernel && cpu_has_sep )
-        wrmsr(MSR_IA32_SYSENTER_ESP, &t->esp1, 0);
+        wrmsr(MSR_IA32_SYSENTER_ESP, &init_tss[smp_processor_id()].esp1, 0);
 #endif
 
     /* Maybe load the debug registers. */
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/boot/build32.mk
--- a/xen/arch/x86/boot/build32.mk      Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/boot/build32.mk      Fri Mar 27 11:07:11 2009 +0900
@@ -10,8 +10,9 @@ include $(XEN_ROOT)/Config.mk
 
 CFLAGS += -Werror -fno-builtin -msoft-float
 
+# NB. awk invocation is a portable alternative to 'head -n -1'
 %.S: %.bin
-       (od -v -t x $< | head -n -1 | \
+       (od -v -t x $< | awk 'NR > 1 {print s} {s=$$0}' | \
        sed 's/ /,0x/g' | sed 's/^[0-9]*,/ .long /') >$@
 
 %.bin: %.lnk
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/common.c
--- a/xen/arch/x86/cpu/common.c Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/common.c Fri Mar 27 11:07:11 2009 +0900
@@ -614,8 +614,7 @@ void __cpuinit cpu_init(void)
        BUG_ON((get_stack_bottom() & 15) != 0);
        t->rsp0 = get_stack_bottom();
 #endif
-       set_tss_desc(cpu,t);
-       load_TR(cpu);
+       load_TR();
        asm volatile ( "lldt %%ax" : : "a" (0) );
 
        /* Clear all 6 debug registers: */
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/mcheck/Makefile
--- a/xen/arch/x86/cpu/mcheck/Makefile  Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/mcheck/Makefile  Fri Mar 27 11:07:11 2009 +0900
@@ -2,6 +2,7 @@ obj-y += k7.o
 obj-y += k7.o
 obj-y += amd_k8.o
 obj-y += amd_f10.o
+obj-y += mctelem.o
 obj-y += mce.o
 obj-y += mce_intel.o
 obj-y += non-fatal.o
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/mcheck/amd_f10.c
--- a/xen/arch/x86/cpu/mcheck/amd_f10.c Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/mcheck/amd_f10.c Fri Mar 27 11:07:11 2009 +0900
@@ -49,20 +49,21 @@
 #include "x86_mca.h"
 
 
-static int amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status)
+static enum mca_extinfo
+amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status)
 {
        struct mcinfo_extended mc_ext;
 
        /* Family 0x10 introduced additional MSR that belong to the
         * northbridge bank (4). */
-       if (bank != 4)
-               return 0;
+       if (mi == NULL || bank != 4)
+               return MCA_EXTINFO_IGNORED;
 
        if (!(status & MCi_STATUS_VAL))
-               return 0;
+               return MCA_EXTINFO_IGNORED;
 
        if (!(status & MCi_STATUS_MISCV))
-               return 0;
+               return MCA_EXTINFO_IGNORED;
 
        memset(&mc_ext, 0, sizeof(mc_ext));
        mc_ext.common.type = MC_TYPE_EXTENDED;
@@ -73,28 +74,30 @@ static int amd_f10_handler(struct mc_inf
        mc_ext.mc_msr[1].reg = MSR_F10_MC4_MISC2;
        mc_ext.mc_msr[2].reg = MSR_F10_MC4_MISC3;
 
-       rdmsrl(MSR_F10_MC4_MISC1, mc_ext.mc_msr[0].value);
-       rdmsrl(MSR_F10_MC4_MISC2, mc_ext.mc_msr[1].value);
-       rdmsrl(MSR_F10_MC4_MISC3, mc_ext.mc_msr[2].value);
+       mca_rdmsrl(MSR_F10_MC4_MISC1, mc_ext.mc_msr[0].value);
+       mca_rdmsrl(MSR_F10_MC4_MISC2, mc_ext.mc_msr[1].value);
+       mca_rdmsrl(MSR_F10_MC4_MISC3, mc_ext.mc_msr[2].value);
        
        x86_mcinfo_add(mi, &mc_ext);
-       return 1;
+       return MCA_EXTINFO_LOCAL;
 }
 
 
 extern void k8_machine_check(struct cpu_user_regs *regs, long error_code);
 
 /* AMD Family10 machine check */
-void amd_f10_mcheck_init(struct cpuinfo_x86 *c) 
+int amd_f10_mcheck_init(struct cpuinfo_x86 *c) 
 { 
        uint64_t value;
        uint32_t i;
        int cpu_nr;
 
-       machine_check_vector = k8_machine_check;
-       mc_callback_bank_extended = amd_f10_handler;
+       if (!cpu_has(c, X86_FEATURE_MCA))
+               return 0;
+
+       x86_mce_vector_register(k8_machine_check);
+       x86_mce_callback_register(amd_f10_handler);
        cpu_nr = smp_processor_id();
-       wmb();
 
        rdmsrl(MSR_IA32_MCG_CAP, value);
        if (value & MCG_CTL_P)  /* Control register present ? */
@@ -104,18 +107,9 @@ void amd_f10_mcheck_init(struct cpuinfo_
        for (i = 0; i < nr_mce_banks; i++) {
                switch (i) {
                case 4: /* Northbridge */
-                       /* Enable error reporting of all errors,
-                        * enable error checking and
-                        * disable sync flooding */
-                       wrmsrl(MSR_IA32_MC4_CTL, 0x02c3c008ffffffffULL);
+                       /* Enable error reporting of all errors */
+                       wrmsrl(MSR_IA32_MC4_CTL, 0xffffffffffffffffULL);
                        wrmsrl(MSR_IA32_MC4_STATUS, 0x0ULL);
-
-                       /* XXX: We should write the value 0x1087821UL into
-                        * to register F3x180 here, which sits in
-                        * the PCI extended configuration space.
-                        * Since this is not possible here, we can only hope,
-                        * Dom0 is doing that.
-                        */
                        break;
 
                default:
@@ -128,4 +122,5 @@ void amd_f10_mcheck_init(struct cpuinfo_
 
        set_in_cr4(X86_CR4_MCE);
        printk("CPU%i: AMD Family10h machine check reporting enabled.\n", 
cpu_nr);
+       return 1;
 }
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/mcheck/amd_k8.c
--- a/xen/arch/x86/cpu/mcheck/amd_k8.c  Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/mcheck/amd_k8.c  Fri Mar 27 11:07:11 2009 +0900
@@ -67,234 +67,27 @@
 #include <asm/msr.h>
 
 #include "mce.h"
-#include "x86_mca.h"
 
 
 /* Machine Check Handler for AMD K8 family series */
 void k8_machine_check(struct cpu_user_regs *regs, long error_code)
 {
-       struct vcpu *vcpu = current;
-       struct domain *curdom;
-       struct mc_info *mc_data;
-       struct mcinfo_global mc_global;
-       struct mcinfo_bank mc_info;
-       uint64_t status, addrv, miscv, uc;
-       uint32_t i;
-       unsigned int cpu_nr;
-       uint32_t xen_impacted = 0;
-#define DOM_NORMAL     0
-#define DOM0_TRAP      1
-#define DOMU_TRAP      2
-#define DOMU_KILLED    4
-       uint32_t dom_state = DOM_NORMAL;
-
-       /* This handler runs as interrupt gate. So IPIs from the
-        * polling service routine are defered until we finished.
-        */
-
-        /* Disable interrupts for the _vcpu_. It may not re-scheduled to
-        * an other physical CPU or the impacted process in the guest
-        * continues running with corrupted data, otherwise. */
-        vcpu_schedule_lock_irq(vcpu);
-
-       mc_data = x86_mcinfo_getptr();
-       cpu_nr = smp_processor_id();
-       BUG_ON(cpu_nr != vcpu->processor);
-
-       curdom = vcpu->domain;
-
-       memset(&mc_global, 0, sizeof(mc_global));
-       mc_global.common.type = MC_TYPE_GLOBAL;
-       mc_global.common.size = sizeof(mc_global);
-
-       mc_global.mc_domid = curdom->domain_id; /* impacted domain */
-
-       x86_mc_get_cpu_info(cpu_nr, &mc_global.mc_socketid,
-           &mc_global.mc_coreid, &mc_global.mc_core_threadid,
-           &mc_global.mc_apicid, NULL, NULL, NULL);
-
-       mc_global.mc_vcpuid = vcpu->vcpu_id; /* impacted vcpu */
-       mc_global.mc_flags |= MC_FLAG_UNCORRECTABLE;
-       rdmsrl(MSR_IA32_MCG_STATUS, mc_global.mc_gstatus);
-
-       /* Quick check, who is impacted */
-       xen_impacted = is_idle_domain(curdom);
-
-       /* Dom0 */
-       x86_mcinfo_clear(mc_data);
-       x86_mcinfo_add(mc_data, &mc_global);
-
-       for (i = 0; i < nr_mce_banks; i++) {
-               struct domain *d;
-
-               rdmsrl(MSR_IA32_MC0_STATUS + 4 * i, status);
-
-               if (!(status & MCi_STATUS_VAL))
-                       continue;
-
-               /* An error happened in this bank.
-                * This is expected to be an uncorrectable error,
-                * since correctable errors get polled.
-                */
-               uc = status & MCi_STATUS_UC;
-
-               memset(&mc_info, 0, sizeof(mc_info));
-               mc_info.common.type = MC_TYPE_BANK;
-               mc_info.common.size = sizeof(mc_info);
-               mc_info.mc_bank = i;
-               mc_info.mc_status = status;
-
-               addrv = 0;
-               if (status & MCi_STATUS_ADDRV) {
-                       rdmsrl(MSR_IA32_MC0_ADDR + 4 * i, addrv);
-                       
-                       d = maddr_get_owner(addrv);
-                       if (d != NULL)
-                               mc_info.mc_domid = d->domain_id;
-               }
-
-               miscv = 0;
-               if (status & MCi_STATUS_MISCV)
-                       rdmsrl(MSR_IA32_MC0_MISC + 4 * i, miscv);
-
-               mc_info.mc_addr = addrv;
-               mc_info.mc_misc = miscv;
-
-               x86_mcinfo_add(mc_data, &mc_info); /* Dom0 */
-
-               if (mc_callback_bank_extended)
-                       mc_callback_bank_extended(mc_data, i, status);
-
-               /* clear status */
-               wrmsrl(MSR_IA32_MC0_STATUS + 4 * i, 0x0ULL);
-               wmb();
-               add_taint(TAINT_MACHINE_CHECK);
-       }
-
-       status = mc_global.mc_gstatus;
-
-       /* clear MCIP or cpu enters shutdown state
-        * in case another MCE occurs. */
-       status &= ~MCG_STATUS_MCIP;
-       wrmsrl(MSR_IA32_MCG_STATUS, status);
-       wmb();
-
-       /* For the details see the discussion "MCE/MCA concept" on xen-devel.
-        * The thread started here:
-        * 
http://lists.xensource.com/archives/html/xen-devel/2007-05/msg01015.html
-        */
-
-       /* MCG_STATUS_RIPV: 
-        * When this bit is not set, then the instruction pointer onto the stack
-        * to resume at is not valid. If xen is interrupted, then we panic 
anyway
-        * right below. Otherwise it is up to the guest to figure out if 
-        * guest kernel or guest userland is affected and should kill either
-        * itself or the affected process.
-        */
-
-       /* MCG_STATUS_EIPV:
-        * Evaluation of EIPV is the job of the guest.
-        */
-
-       if (xen_impacted) {
-               /* Now we are going to panic anyway. Allow interrupts, so that
-                * printk on serial console can work. */
-               vcpu_schedule_unlock_irq(vcpu);
-
-               /* Uh, that means, machine check exception
-                * inside Xen occured. */
-               printk("Machine check exception occured in Xen.\n");
-
-               /* if MCG_STATUS_EIPV indicates, the IP on the stack is related
-                * to the error then it makes sense to print a stack trace.
-                * That can be useful for more detailed error analysis and/or
-                * error case studies to figure out, if we can clear
-                * xen_impacted and kill a DomU instead
-                * (i.e. if a guest only control structure is affected, but then
-                * we must ensure the bad pages are not re-used again).
-                */
-               if (status & MCG_STATUS_EIPV) {
-                       printk("MCE: Instruction Pointer is related to the 
error. "
-                               "Therefore, print the execution state.\n");
-                       show_execution_state(regs);
-               }
-               x86_mcinfo_dump(mc_data);
-               mc_panic("End of MCE. Use mcelog to decode above error 
codes.\n");
-       }
-
-       /* If Dom0 registered a machine check handler, which is only possible
-        * with a PV MCA driver, then ... */
-       if ( guest_has_trap_callback(dom0, 0, TRAP_machine_check) ) {
-               dom_state = DOM0_TRAP;
-
-               /* ... deliver machine check trap to Dom0. */
-               send_guest_trap(dom0, 0, TRAP_machine_check);
-
-               /* Xen may tell Dom0 now to notify the DomU.
-                * But this will happen through a hypercall. */
-       } else
-               /* Dom0 did not register a machine check handler, but if DomU
-                * did so, then... */
-                if ( guest_has_trap_callback(curdom, vcpu->vcpu_id, 
TRAP_machine_check) ) {
-                       dom_state = DOMU_TRAP;
-
-                       /* ... deliver machine check trap to DomU */
-                       send_guest_trap(curdom, vcpu->vcpu_id, 
TRAP_machine_check);
-       } else {
-               /* hmm... noone feels responsible to handle the error.
-                * So, do a quick check if a DomU is impacted or not.
-                */
-               if (curdom == dom0) {
-                       /* Dom0 is impacted. Since noone can't handle
-                        * this error, panic! */
-                       x86_mcinfo_dump(mc_data);
-                       mc_panic("MCE occured in Dom0, which it can't 
handle\n");
-
-                       /* UNREACHED */
-               } else {
-                       dom_state = DOMU_KILLED;
-
-                       /* Enable interrupts. This basically results in
-                        * calling sti on the *physical* cpu. But after
-                        * domain_crash() the vcpu pointer is invalid.
-                        * Therefore, we must unlock the irqs before killing
-                        * it. */
-                       vcpu_schedule_unlock_irq(vcpu);
-
-                       /* DomU is impacted. Kill it and continue. */
-                       domain_crash(curdom);
-               }
-       }
-
-
-       switch (dom_state) {
-       case DOM0_TRAP:
-       case DOMU_TRAP:
-               /* Enable interrupts. */
-               vcpu_schedule_unlock_irq(vcpu);
-
-               /* guest softirqs and event callbacks are scheduled
-                * immediately after this handler exits. */
-               break;
-       case DOMU_KILLED:
-               /* Nothing to do here. */
-               break;
-       default:
-               BUG();
-       }
+       mcheck_cmn_handler(regs, error_code, mca_allbanks);
 }
 
-
 /* AMD K8 machine check */
-void amd_k8_mcheck_init(struct cpuinfo_x86 *c)
+int amd_k8_mcheck_init(struct cpuinfo_x86 *c)
 {
        uint64_t value;
        uint32_t i;
        int cpu_nr;
 
-       machine_check_vector = k8_machine_check;
+       /* Check for PPro style MCA; our caller has confirmed MCE support. */
+       if (!cpu_has(c, X86_FEATURE_MCA))
+               return 0;
+
+       x86_mce_vector_register(k8_machine_check);
        cpu_nr = smp_processor_id();
-       wmb();
 
        rdmsrl(MSR_IA32_MCG_CAP, value);
        if (value & MCG_CTL_P)  /* Control register present ? */
@@ -304,10 +97,8 @@ void amd_k8_mcheck_init(struct cpuinfo_x
        for (i = 0; i < nr_mce_banks; i++) {
                switch (i) {
                case 4: /* Northbridge */
-                       /* Enable error reporting of all errors,
-                        * enable error checking and
-                        * disable sync flooding */
-                       wrmsrl(MSR_IA32_MC4_CTL, 0x02c3c008ffffffffULL);
+                       /* Enable error reporting of all errors */
+                       wrmsrl(MSR_IA32_MC4_CTL, 0xffffffffffffffffULL);
                        wrmsrl(MSR_IA32_MC4_STATUS, 0x0ULL);
                        break;
 
@@ -321,4 +112,6 @@ void amd_k8_mcheck_init(struct cpuinfo_x
 
        set_in_cr4(X86_CR4_MCE);
        printk("CPU%i: AMD K8 machine check reporting enabled.\n", cpu_nr);
+
+       return 1;
 }
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/mcheck/amd_nonfatal.c
--- a/xen/arch/x86/cpu/mcheck/amd_nonfatal.c    Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/mcheck/amd_nonfatal.c    Fri Mar 27 11:07:11 2009 +0900
@@ -58,22 +58,23 @@
 #include <xen/smp.h>
 #include <xen/timer.h>
 #include <xen/event.h>
-#include <asm/processor.h> 
+
+#include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/msr.h>
 
 #include "mce.h"
-#include "x86_mca.h"
 
 static struct timer mce_timer;
 
-#define MCE_PERIOD MILLISECS(15000)
+#define MCE_PERIOD MILLISECS(10000)
 #define MCE_MIN    MILLISECS(2000)
 #define MCE_MAX    MILLISECS(30000)
 
 static s_time_t period = MCE_PERIOD;
 static int hw_threshold = 0;
 static int adjust = 0;
+static int variable_period = 1;
 
 /* The polling service routine:
  * Collects information of correctable errors and notifies
@@ -81,99 +82,46 @@ static int adjust = 0;
  */
 void mce_amd_checkregs(void *info)
 {
-       struct vcpu *vcpu = current;
-       struct mc_info *mc_data;
-       struct mcinfo_global mc_global;
-       struct mcinfo_bank mc_info;
-       uint64_t status, addrv, miscv;
-       unsigned int i;
+       mctelem_cookie_t mctc;
+       struct mca_summary bs;
        unsigned int event_enabled;
-       unsigned int cpu_nr;
-       int error_found;
-
-       /* We don't need a slot yet. Only allocate one on error. */
-       mc_data = NULL;
-
-       cpu_nr = smp_processor_id();
-       BUG_ON(cpu_nr != vcpu->processor);
+
+       mctc = mcheck_mca_logout(MCA_POLLER, mca_allbanks, &bs);
+
        event_enabled = guest_enabled_event(dom0->vcpu[0], VIRQ_MCA);
-       error_found = 0;
-
-       memset(&mc_global, 0, sizeof(mc_global));
-       mc_global.common.type = MC_TYPE_GLOBAL;
-       mc_global.common.size = sizeof(mc_global);
-
-       mc_global.mc_domid = vcpu->domain->domain_id; /* impacted domain */
-       mc_global.mc_vcpuid = vcpu->vcpu_id; /* impacted vcpu */
-
-       x86_mc_get_cpu_info(cpu_nr, &mc_global.mc_socketid,
-           &mc_global.mc_coreid, &mc_global.mc_core_threadid,
-           &mc_global.mc_apicid, NULL, NULL, NULL);
-
-       mc_global.mc_flags |= MC_FLAG_CORRECTABLE;
-       rdmsrl(MSR_IA32_MCG_STATUS, mc_global.mc_gstatus);
-
-       for (i = 0; i < nr_mce_banks; i++) {
-               struct domain *d;
-
-               rdmsrl(MSR_IA32_MC0_STATUS + i * 4, status);
-
-               if (!(status & MCi_STATUS_VAL))
-                       continue;
-
-               if (mc_data == NULL) {
-                       /* Now we need a slot to fill in error telemetry. */
-                       mc_data = x86_mcinfo_getptr();
-                       BUG_ON(mc_data == NULL);
-                       x86_mcinfo_clear(mc_data);
-                       x86_mcinfo_add(mc_data, &mc_global);
-               }
-
-               memset(&mc_info, 0, sizeof(mc_info));
-               mc_info.common.type = MC_TYPE_BANK;
-               mc_info.common.size = sizeof(mc_info);
-               mc_info.mc_bank = i;
-               mc_info.mc_status = status;
-
-               /* Increase polling frequency */
-               error_found = 1;
-
-               addrv = 0;
-               if (status & MCi_STATUS_ADDRV) {
-                       rdmsrl(MSR_IA32_MC0_ADDR + i * 4, addrv);
-
-                       d = maddr_get_owner(addrv);
-                       if (d != NULL)
-                               mc_info.mc_domid = d->domain_id;
-               }
-
-               miscv = 0;
-               if (status & MCi_STATUS_MISCV)
-                       rdmsrl(MSR_IA32_MC0_MISC + i * 4, miscv);
-
-               mc_info.mc_addr = addrv;
-               mc_info.mc_misc = miscv;
-               x86_mcinfo_add(mc_data, &mc_info);
-
-               if (mc_callback_bank_extended)
-                       mc_callback_bank_extended(mc_data, i, status);
-
-               /* clear status */
-               wrmsrl(MSR_IA32_MC0_STATUS + i * 4, 0x0ULL);
-               wmb();
-       }
-
-       if (error_found > 0) {
-               /* If Dom0 enabled the VIRQ_MCA event, then ... */
-               if (event_enabled)
-                       /* ... notify it. */
+
+       if (bs.errcnt && mctc != NULL) {
+               static uint64_t dumpcount = 0;
+
+               /* If Dom0 enabled the VIRQ_MCA event, then notify it.
+                * Otherwise, if dom0 has had plenty of time to register
+                * the virq handler but still hasn't then dump telemetry
+                * to the Xen console.  The call count may be incremented
+                * on multiple cpus at once and is indicative only - just
+                * a simple-minded attempt to avoid spamming the console
+                * for corrected errors in early startup. */
+
+               if (event_enabled) {
+                       mctelem_commit(mctc);
                        send_guest_global_virq(dom0, VIRQ_MCA);
-               else
-                       /* ... or dump it */
-                       x86_mcinfo_dump(mc_data);
-       }
-
-       adjust += error_found;
+               } else if (++dumpcount >= 10) {
+                       x86_mcinfo_dump((struct mc_info 
*)mctelem_dataptr(mctc));
+                       mctelem_dismiss(mctc);
+               } else {
+                       mctelem_dismiss(mctc);
+               }
+               
+       } else if (mctc != NULL) {
+               mctelem_dismiss(mctc);
+       }
+
+       /* adjust is global and all cpus may attempt to increment it without
+        * synchronisation, so they race and the final adjust count
+        * (number of cpus seeing any error) is approximate.  We can
+        * guarantee that if any cpu observes an error that the
+        * adjust count is at least 1. */
+       if (bs.errcnt)
+               adjust++;
 }
 
 /* polling service routine invoker:
@@ -188,7 +136,7 @@ static void mce_amd_work_fn(void *data)
        on_each_cpu(mce_amd_checkregs, data, 1, 1);
 
        if (adjust > 0) {
-               if ( !guest_enabled_event(dom0->vcpu[0], VIRQ_MCA) ) {
+               if (!guest_enabled_event(dom0->vcpu[0], VIRQ_MCA) ) {
                        /* Dom0 did not enable VIRQ_MCA, so Xen is reporting. */
                        printk("MCE: polling routine found correctable error. "
                                " Use mcelog to parse above error output.\n");
@@ -199,7 +147,7 @@ static void mce_amd_work_fn(void *data)
                uint64_t value;
                uint32_t counter;
 
-               rdmsrl(MSR_IA32_MC4_MISC, value);
+               mca_rdmsrl(MSR_IA32_MC4_MISC, value);
                /* Only the error counter field is of interest
                 * Bit field is described in AMD K8 BKDG chapter 6.4.5.5
                 */
@@ -224,24 +172,24 @@ static void mce_amd_work_fn(void *data)
                        value &= ~(0x60FFF00000000ULL);
                        /* Counter enable */
                        value |= (1ULL << 51);
-                       wrmsrl(MSR_IA32_MC4_MISC, value);
+                       mca_wrmsrl(MSR_IA32_MC4_MISC, value);
                        wmb();
                }
        }
 
-       if (adjust > 0) {
+       if (variable_period && adjust > 0) {
                /* Increase polling frequency */
                adjust++; /* adjust == 1 must have an effect */
                period /= adjust;
-       } else {
+       } else if (variable_period) {
                /* Decrease polling frequency */
                period *= 2;
        }
-       if (period > MCE_MAX) {
+       if (variable_period && period > MCE_MAX) {
                /* limit: Poll at least every 30s */
                period = MCE_MAX;
        }
-       if (period < MCE_MIN) {
+       if (variable_period && period < MCE_MIN) {
                /* limit: Poll every 2s.
                 * When this is reached an uncorrectable error
                 * is expected to happen, if Dom0 does nothing.
@@ -262,7 +210,7 @@ void amd_nonfatal_mcheck_init(struct cpu
 
        /* The threshold bitfields in MSR_IA32_MC4_MISC has
         * been introduced along with the SVME feature bit. */
-       if (cpu_has(c, X86_FEATURE_SVME)) {
+       if (variable_period && cpu_has(c, X86_FEATURE_SVME)) {
                uint64_t value;
 
                /* hw threshold registers present */
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/mcheck/k7.c
--- a/xen/arch/x86/cpu/mcheck/k7.c      Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/mcheck/k7.c      Fri Mar 27 11:07:11 2009 +0900
@@ -68,13 +68,16 @@ static fastcall void k7_machine_check(st
 
 
 /* AMD K7 machine check */
-void amd_k7_mcheck_init(struct cpuinfo_x86 *c)
+int amd_k7_mcheck_init(struct cpuinfo_x86 *c)
 {
        u32 l, h;
        int i;
 
-       machine_check_vector = k7_machine_check;
-       wmb();
+       /* Check for PPro style MCA; our caller has confirmed MCE support. */
+       if (!cpu_has(c, X86_FEATURE_MCA))
+               return 0;
+
+       x86_mce_vector_register(k7_machine_check);
 
        rdmsr (MSR_IA32_MCG_CAP, l, h);
        if (l & (1<<8)) /* Control register present ? */
@@ -92,4 +95,6 @@ void amd_k7_mcheck_init(struct cpuinfo_x
        set_in_cr4 (X86_CR4_MCE);
        printk (KERN_INFO "CPU%d: AMD K7 machine check reporting enabled.\n",
                smp_processor_id());
+
+       return 1;
 }
diff -r 5e4dd7079c48 -r e54eeff2de54 xen/arch/x86/cpu/mcheck/mce.c
--- a/xen/arch/x86/cpu/mcheck/mce.c     Fri Mar 27 10:54:08 2009 +0900
+++ b/xen/arch/x86/cpu/mcheck/mce.c     Fri Mar 27 11:07:11 2009 +0900
@@ -10,104 +10,492 @@
 #include <xen/smp.h>
 #include <xen/errno.h>
 #include <xen/console.h>
-
-#include <asm/processor.h> 
+#include <xen/sched.h>
+#include <xen/sched-if.h>
+#include <xen/cpumask.h>
+#include <xen/event.h>
+#include <xen/guest_access.h>
+
+#include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/msr.h>
 
 #include "mce.h"
-#include "x86_mca.h"
 
 int mce_disabled = 0;
 unsigned int nr_mce_banks;
 
 EXPORT_SYMBOL_GPL(nr_mce_banks);       /* non-fatal.o */
 
-/* XXX For now a fixed array is used. Later this should be changed
- * to a dynamic allocated array with the size calculated in relation
- * to physical cpus present in the machine.
- * The more physical cpus are available, the more entries you need.
- */
-#define MAX_MCINFO     20
-
-struct mc_machine_notify {
-       struct mc_info mc;
-       uint32_t fetch_idx;
-       uint32_t valid;
-};
-
-struct mc_machine {
-
-       /* Array structure used for collecting machine check error telemetry. */
-       struct mc_info mc[MAX_MCINFO];
-
-       /* We handle multiple machine check reports lockless by
-        * iterating through the array using the producer/consumer concept.
-        */
-       /* Producer array index to fill with machine check error data.
-        * Index must be increased atomically. */
-       uint32_t error_idx;
-
-       /* Consumer array index to fetch machine check error data from.
-        * Index must be increased atomically. */
-       uint32_t fetch_idx;
-
-       /* Integer array holding the indeces of the mc array that allows
-         * a Dom0 to notify a DomU to re-fetch the same machine check error
-         * data. The notification and refetch also uses its own 
-        * producer/consumer mechanism, because Dom0 may decide to not report
-        * every error to the impacted DomU.
-        */
-       struct mc_machine_notify notify[MAX_MCINFO];
-
-       /* Array index to get fetch_idx from.
-        * Index must be increased atomically. */
-       uint32_t notifyproducer_idx;
-       uint32_t notifyconsumer_idx;
-};
-
-/* Global variable with machine check information. */
-struct mc_machine mc_data;
+static void intpose_init(void);
+static void mcinfo_clear(struct mc_info *);
+
+#define        SEG_PL(segsel)                  ((segsel) & 0x3)
+#define _MC_MSRINJ_F_REQ_HWCR_WREN     (1 << 16)
+
+#if 1  /* XXFM switch to 0 for putback */
+
+#define        x86_mcerr(str, err) _x86_mcerr(str, err)
+
+static int _x86_mcerr(const char *msg, int err)
+{
+       printk("x86_mcerr: %s, returning %d\n",
+           msg != NULL ? msg : "", err);
+       return err;
+}
+#else
+#define x86_mcerr(str,err)
+#endif
+
+cpu_banks_t mca_allbanks;
 
 /* Handle unconfigured int18 (should never happen) */
 static void unexpected_machine_check(struct cpu_user_regs *regs, long 
error_code)
-{      
+{
        printk(XENLOG_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
                smp_processor_id());
 }
 
 
+static x86_mce_vector_t _machine_check_vector = unexpected_machine_check;
+
+void x86_mce_vector_register(x86_mce_vector_t hdlr)
+{
+       _machine_check_vector = hdlr;
+       wmb();
+}
+
 /* Call the installed machine check handler for this CPU setup. */
-void (*machine_check_vector)(struct cpu_user_regs *regs, long error_code) = 
unexpected_machine_check;
+
+void machine_check_vector(struct cpu_user_regs *regs, long error_code)
+{
+       _machine_check_vector(regs, error_code);
+}
 
 /* Init machine check callback handler
  * It is used to collect additional information provided by newer
  * CPU families/models without the need to duplicate the whole handler.
  * This avoids having many handlers doing almost nearly the same and each
  * with its own tweaks ands bugs. */
-int (*mc_callback_bank_extended)(struct mc_info *, uint16_t, uint64_t) = NULL;
-
-
-static void amd_mcheck_init(struct cpuinfo_x86 *ci)
-{
+static x86_mce_callback_t mc_callback_bank_extended = NULL;
+
+void x86_mce_callback_register(x86_mce_callback_t cbfunc)
+{
+       mc_callback_bank_extended = cbfunc;
+}
+
+/* Utility function to perform MCA bank telemetry readout and to push that
+ * telemetry towards an interested dom0 for logging and diagnosis.
+ * The caller - #MC handler or MCA poll function - must arrange that we
+ * do not migrate cpus. */
+
+/* XXFM Could add overflow counting? */
+mctelem_cookie_t mcheck_mca_logout(enum mca_source who, cpu_banks_t bankmask,
+    struct mca_summary *sp)
+{
+       struct vcpu *v = current;
+       struct domain *d;
+       uint64_t gstatus, status, addr, misc;
+       struct mcinfo_global mcg;       /* on stack */
+       struct mcinfo_common *mic;
+       struct mcinfo_global *mig;      /* on stack */
+       mctelem_cookie_t mctc = NULL;
+       uint32_t uc = 0, pcc = 0;
+       struct mc_info *mci = NULL;
+       mctelem_class_t which = MC_URGENT;      /* XXXgcc */
+       unsigned int cpu_nr;
+       int errcnt = 0;
+       int i;
+       enum mca_extinfo cbret = MCA_EXTINFO_IGNORED;
+
+       cpu_nr = smp_processor_id();
+       BUG_ON(cpu_nr != v->processor);
+
+       mca_rdmsrl(MSR_IA32_MCG_STATUS, gstatus);
+
+       memset(&mcg, 0, sizeof (mcg));
+       mcg.common.type = MC_TYPE_GLOBAL;
+       mcg.common.size = sizeof (mcg);
+       if (v != NULL && ((d = v->domain) != NULL)) {
+               mcg.mc_domid = d->domain_id;
+               mcg.mc_vcpuid = v->vcpu_id;
+       } else {
+               mcg.mc_domid = -1;
+               mcg.mc_vcpuid = -1;
+       }
+       mcg.mc_gstatus = gstatus;       /* MCG_STATUS */
+
+       switch (who) {
+       case MCA_MCE_HANDLER:
+               mcg.mc_flags = MC_FLAG_MCE;
+               which = MC_URGENT;
+               break;
+
+       case MCA_POLLER:
+       case MCA_RESET:
+               mcg.mc_flags = MC_FLAG_POLLED;
+               which = MC_NONURGENT;
+               break;
+
+       case MCA_CMCI_HANDLER:
+               mcg.mc_flags = MC_FLAG_CMCI;
+               which = MC_NONURGENT;
+               break;
+
+       default:
+               BUG();
+       }
+
+       /* Retrieve detector information */
+       x86_mc_get_cpu_info(cpu_nr, &mcg.mc_socketid,
+           &mcg.mc_coreid, &mcg.mc_core_threadid,
+           &mcg.mc_apicid, NULL, NULL, NULL);
+
+       for (i = 0; i < 32 && i < nr_mce_banks; i++) {
+               struct mcinfo_bank mcb;         /* on stack */
+
+               /* Skip bank if corresponding bit in bankmask is clear */
+               if (!test_bit(i, bankmask))
+                       continue;
+
+               mca_rdmsrl(MSR_IA32_MC0_STATUS + i * 4, status);
+               if (!(status & MCi_STATUS_VAL))
+                       continue;       /* this bank has no valid telemetry */
+
+               /* If this is the first bank with valid MCA DATA, then
+                * try to reserve an entry from the urgent/nonurgent queue
+                * depending on whethere we are called from an exception or
+                * a poller;  this can fail (for example dom0 may not
+                * yet have consumed past telemetry). */
+               if (errcnt == 0) {
+                       if ((mctc = mctelem_reserve(which)) != NULL) {
+                               mci = mctelem_dataptr(mctc);
+                               mcinfo_clear(mci);
+                       }
+               }
+
+               memset(&mcb, 0, sizeof (mcb));
+               mcb.common.type = MC_TYPE_BANK;
+               mcb.common.size = sizeof (mcb);
+               mcb.mc_bank = i;
+               mcb.mc_status = status;
+
+               /* form a mask of which banks have logged uncorrected errors */
+               if ((status & MCi_STATUS_UC) != 0)
+                       uc |= (1 << i);
+
+               /* likewise for those with processor context corrupt */
+               if ((status & MCi_STATUS_PCC) != 0)
+                       pcc |= (1 << i);
+
+               addr = misc = 0;
+
+               if (status & MCi_STATUS_ADDRV) {
+                       mca_rdmsrl(MSR_IA32_MC0_ADDR + 4 * i, addr);
+                       d = maddr_get_owner(addr);
+                       if (d != NULL && (who == MCA_POLLER ||
+                           who == MCA_CMCI_HANDLER))
+                               mcb.mc_domid = d->domain_id;
+               }
+
+               if (status & MCi_STATUS_MISCV)
+                       mca_rdmsrl(MSR_IA32_MC0_MISC + 4 * i, misc);
+
+               mcb.mc_addr = addr;
+               mcb.mc_misc = misc;
+
+               if (who == MCA_CMCI_HANDLER) {
+                       mca_rdmsrl(MSR_IA32_MC0_CTL2 + i, mcb.mc_ctrl2);
+                       rdtscll(mcb.mc_tsc);
+               }
+
+               /* Increment the error count;  if this is the first bank
+                * with a valid error then add the global info to the mcinfo. */
+               if (errcnt++ == 0 && mci != NULL)
+                       x86_mcinfo_add(mci, &mcg);
+
+               /* Add the bank data */
+               if (mci != NULL)
+                       x86_mcinfo_add(mci, &mcb);
+
+               if (mc_callback_bank_extended && cbret != MCA_EXTINFO_GLOBAL) {
+                       cbret = mc_callback_bank_extended(mci, i, status);
+               }
+
+               /* Clear status */
+               mca_wrmsrl(MSR_IA32_MC0_STATUS + 4 * i, 0x0ULL);
+               wmb();
+       }
+
+       if (mci != NULL && errcnt > 0) {
+               x86_mcinfo_lookup(mic, mci, MC_TYPE_GLOBAL);
+               mig = (struct mcinfo_global *)mic;
+               if (pcc)
+                       mcg.mc_flags |= MC_FLAG_UNCORRECTABLE;
+               else if (uc)
+                       mcg.mc_flags |= MC_FLAG_RECOVERABLE;
+               else
+                       mcg.mc_flags |= MC_FLAG_CORRECTABLE;
+       }
+
+
+       if (sp) {
+               sp->errcnt = errcnt;
+               sp->ripv = (gstatus & MCG_STATUS_RIPV) != 0;
+               sp->eipv = (gstatus & MCG_STATUS_EIPV) != 0;
+               sp->uc = uc;
+               sp->pcc = pcc;
+       }
+
+       return mci != NULL ? mctc : NULL;       /* may be NULL */
+}
+
+#define DOM_NORMAL     0
+#define DOM0_TRAP      1
+#define DOMU_TRAP      2
+#define DOMU_KILLED    4
+
+/* Shared #MC handler. */
+void mcheck_cmn_handler(struct cpu_user_regs *regs, long error_code,
+    cpu_banks_t bankmask)
+{
+       int xen_state_lost, dom0_state_lost, domU_state_lost;
+       struct vcpu *v = current;
+       struct domain *curdom = v->domain;
+       domid_t domid = curdom->domain_id;
+       int ctx_xen, ctx_dom0, ctx_domU;
+       uint32_t dom_state = DOM_NORMAL;
+       mctelem_cookie_t mctc = NULL;
+       struct mca_summary bs;
+       struct mc_info *mci = NULL;
+       int irqlocked = 0;
+       uint64_t gstatus;
+       int ripv;
+
+       /* This handler runs as interrupt gate. So IPIs from the
+        * polling service routine are defered until we're finished.
+        */
+
+       /* Disable interrupts for the _vcpu_. It may not re-scheduled to
+        * another physical CPU. */
+       vcpu_schedule_lock_irq(v);
+       irqlocked = 1;
+
+       /* Read global status;  if it does not indicate machine check
+        * in progress then bail as long as we have a valid ip to return to. */
+       mca_rdmsrl(MSR_IA32_MCG_STATUS, gstatus);
+       ripv = ((gstatus & MCG_STATUS_RIPV) != 0);
+       if (!(gstatus & MCG_STATUS_MCIP) && ripv) {
+               add_taint(TAINT_MACHINE_CHECK); /* questionable */
+               vcpu_schedule_unlock_irq(v);
+               irqlocked = 0;
+               goto cmn_handler_done;
+       }
+
+       /* Go and grab error telemetry.  We must choose whether to commit
+        * for logging or dismiss the cookie that is returned, and must not
+        * reference the cookie after that action.
+        */
+       mctc = mcheck_mca_logout(MCA_MCE_HANDLER, bankmask, &bs);
+       if (mctc != NULL)
+               mci = (struct mc_info *)mctelem_dataptr(mctc);
+
+       /* Clear MCIP or another #MC will enter shutdown state */
+       gstatus &= ~MCG_STATUS_MCIP;
+       mca_wrmsrl(MSR_IA32_MCG_STATUS, gstatus);
+       wmb();
+
+       /* If no valid errors and our stack is intact, we're done */
+       if (ripv && bs.errcnt == 0) {
+               vcpu_schedule_unlock_irq(v);
+               irqlocked = 0;
+               goto cmn_handler_done;
+       }
+
+       if (bs.uc || bs.pcc)
+               add_taint(TAINT_MACHINE_CHECK);
+
+       /* Machine check exceptions will usually be for UC and/or PCC errors,
+        * but it is possible to configure machine check for some classes
+        * of corrected error.
+        *
+        * UC errors could compromise any domain or the hypervisor
+        * itself - for example a cache writeback of modified data that
+        * turned out to be bad could be for data belonging to anyone, not
+        * just the current domain.  In the absence of known data poisoning
+        * to prevent consumption of such bad data in the system we regard
+        * all UC errors as terminal.  It may be possible to attempt some
+        * heuristics based on the address affected, which guests have
+        * mappings to that mfn etc.
+        *
+        * PCC errors apply to the current context.
+        *
+        * If MCG_STATUS indicates !RIPV then even a #MC that is not UC
+        * and not PCC is terminal - the return instruction pointer
+        * pushed onto the stack is bogus.  If the interrupt context is
+        * the hypervisor or dom0 the game is over, otherwise we can
+        * limit the impact to a single domU but only if we trampoline
+        * somewhere safely - we can't return and unwind the stack.
+        * Since there is no trampoline in place we will treat !RIPV
+        * as terminal for any context.
+        */
+       ctx_xen = SEG_PL(regs->cs) == 0;
+       ctx_dom0 = !ctx_xen && (domid == dom0->domain_id);
+       ctx_domU = !ctx_xen && !ctx_dom0;
+
+       xen_state_lost = bs.uc != 0 || (ctx_xen && (bs.pcc || !ripv)) ||
+           !ripv;
+       dom0_state_lost = bs.uc != 0 || (ctx_dom0 && (bs.pcc || !ripv));
+       domU_state_lost = bs.uc != 0 || (ctx_domU && (bs.pcc || !ripv));
+
+       if (xen_state_lost) {
+               /* Now we are going to panic anyway. Allow interrupts, so that
+                * printk on serial console can work. */
+               vcpu_schedule_unlock_irq(v);
+               irqlocked = 0;
+
+               printk("Terminal machine check exception occured in "
+                   "hypervisor context.\n");
+
+               /* If MCG_STATUS_EIPV indicates, the IP on the stack is related
+                * to the error then it makes sense to print a stack trace.
+                * That can be useful for more detailed error analysis and/or
+                * error case studies to figure out, if we can clear
+                * xen_impacted and kill a DomU instead
+                * (i.e. if a guest only control structure is affected, but then
+                * we must ensure the bad pages are not re-used again).
+                */
+               if (bs.eipv & MCG_STATUS_EIPV) {
+                       printk("MCE: Instruction Pointer is related to the "
+                           "error, therefore print the execution state.\n");
+                       show_execution_state(regs);
+               }
+
+               /* Commit the telemetry so that panic flow can find it. */
+               if (mctc != NULL) {
+                       x86_mcinfo_dump(mci);
+                       mctelem_commit(mctc);
+               }
+               mc_panic("Hypervisor state lost due to machine check "
+                   "exception.\n");
+               /*NOTREACHED*/
+       }
+
+       /*
+        * Xen hypervisor state is intact.  If dom0 state is lost then
+        * give it a chance to decide what to do if it has registered
+        * a handler for this event, otherwise panic.
+        *
+        * XXFM Could add some Solaris dom0 contract kill here?
+        */
+       if (dom0_state_lost) {
+               if (guest_has_trap_callback(dom0, 0, TRAP_machine_check)) {
+                       dom_state = DOM0_TRAP;
+                       send_guest_trap(dom0, 0, TRAP_machine_check);
+                       /* XXFM case of return with !ripv ??? */
+               } else {
+                       /* Commit telemetry for panic flow. */
+                       if (mctc != NULL) {
+                               x86_mcinfo_dump(mci);
+                               mctelem_commit(mctc);
+                       }
+                       mc_panic("Dom0 state lost due to machine check "
+                           "exception\n");
+                       /*NOTREACHED*/
+               }
+       }
+
+       /*
+        * If a domU has lost state then send it a trap if it has registered
+        * a handler, otherwise crash the domain.
+        * XXFM Revisit this functionality.
+        */
+       if (domU_state_lost) {
+               if (guest_has_trap_callback(v->domain, v->vcpu_id,
+                   TRAP_machine_check)) {
+                       dom_state = DOMU_TRAP;
+                       send_guest_trap(curdom, v->vcpu_id,
+                           TRAP_machine_check);
+               } else {
+                       dom_state = DOMU_KILLED;
+                       /* Enable interrupts. This basically results in
+                        * calling sti on the *physical* cpu. But after
+                        * domain_crash() the vcpu pointer is invalid.
+                        * Therefore, we must unlock the irqs before killing
+                        * it. */
+                       vcpu_schedule_unlock_irq(v);
+                       irqlocked = 0;
+
+                       /* DomU is impacted. Kill it and continue. */
+                       domain_crash(curdom);
+               }
+       }
+
+       switch (dom_state) {
+       case DOM0_TRAP:
+       case DOMU_TRAP:
+               /* Enable interrupts. */
+               vcpu_schedule_unlock_irq(v);
+               irqlocked = 0;
+
+               /* guest softirqs and event callbacks are scheduled
+                * immediately after this handler exits. */
+               break;
+       case DOMU_KILLED:
+               /* Nothing to do here. */
+               break;
+
+       case DOM_NORMAL:
+               vcpu_schedule_unlock_irq(v);
+               irqlocked = 0;
+               break;
+       }
+
+cmn_handler_done:
+       BUG_ON(irqlocked);
+       BUG_ON(!ripv);
+
+       if (bs.errcnt) {
+               /* Not panicing, so forward telemetry to dom0 now if it
+                * is interested. */
+               if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
+                       if (mctc != NULL)
+                               mctelem_commit(mctc);
+                       send_guest_global_virq(dom0, VIRQ_MCA);
+               } else {
+                       x86_mcinfo_dump(mci);
+                       if (mctc != NULL)
+                               mctelem_dismiss(mctc);
+               }
+       } else if (mctc != NULL) {
+               mctelem_dismiss(mctc);
+       }
+}
+
+static int amd_mcheck_init(struct cpuinfo_x86 *ci)
+{
+       int rc = 0;
 
        switch (ci->x86) {
        case 6:
-               amd_k7_mcheck_init(ci);
+               rc = amd_k7_mcheck_init(ci);
                break;
 
        case 0xf:
-               amd_k8_mcheck_init(ci);
+               rc = amd_k8_mcheck_init(ci);
                break;
 
        case 0x10:
-               amd_f10_mcheck_init(ci);
+               rc = amd_f10_mcheck_init(ci);
                break;
 
        default:
                /* Assume that machine check support is available.
                 * The minimum provided support is at least the K8. */
-               amd_k8_mcheck_init(ci);
-       }
+               rc = amd_k8_mcheck_init(ci);
+       }
+
+       return rc;
 }
 
 /*check the existence of Machine Check*/
@@ -116,50 +504,82 @@ int mce_available(struct cpuinfo_x86 *c)
        return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
 }
 
+/*
+ * Check if bank 0 is usable for MCE. It isn't for AMD K7,
+ * and Intel P6 family before model 0x1a.
+ */
+int mce_firstbank(struct cpuinfo_x86 *c)
+{
+       if (c->x86 == 6) {
+               if (c->x86_vendor == X86_VENDOR_AMD)
+                       return 1;
+
+               if (c->x86_vendor == X86_VENDOR_INTEL && c->x86_model < 0x1a)
+                       return 1;
+       }
+
+       return 0;
+}
+
 /* This has to be run for each processor */
 void mcheck_init(struct cpuinfo_x86 *c)
 {
+       int inited = 0, i;
+
        if (mce_disabled == 1) {
                printk(XENLOG_INFO "MCE support disabled by bootparam\n");
                return;
        }
 
+       for (i = 0; i < MAX_NR_BANKS; i++)
+               set_bit(i,mca_allbanks);
+
+       /* Enforce at least MCE support in CPUID information.  Individual
+        * families may also need to enforce a check for MCA support. */
        if (!cpu_has(c, X86_FEATURE_MCE)) {
                printk(XENLOG_INFO "CPU%i: No machine check support 
available\n",
                        smp_processor_id());
                return;
        }
 
-       memset(&mc_data, 0, sizeof(struct mc_machine));
+       intpose_init();
+       mctelem_init(sizeof (struct mc_info));
 
        switch (c->x86_vendor) {
        case X86_VENDOR_AMD:
-               amd_mcheck_init(c);
+               inited = amd_mcheck_init(c);
                break;
 
        case X86_VENDOR_INTEL:
+               switch (c->x86) {
+               case 5:
 #ifndef CONFIG_X86_64
-               if (c->x86==5)
-                       intel_p5_mcheck_init(c);
+                       inited = intel_p5_mcheck_init(c);
 #endif
-               /*If it is P6 or P4 family, including CORE 2 DUO series*/
-               if (c->x86 == 6 || c->x86==15)
-               {
-                       printk(KERN_DEBUG "MCE: Intel newly family MC Init\n");
-                       intel_mcheck_init(c);
+                       break;
+
+               case 6:
+               case 15:
+                       inited = intel_mcheck_init(c);
+                       break;
                }
                break;
 
 #ifndef CONFIG_X86_64
        case X86_VENDOR_CENTAUR:
-               if (c->x86==5)
-                       winchip_mcheck_init(c);
+               if (c->x86==5) {
+                       inited = winchip_mcheck_init(c);
+               }
                break;
 #endif
 
        default:
                break;
        }
+
+       if (!inited)
+               printk(XENLOG_INFO "CPU%i: No machine check initialization\n",
+                   smp_processor_id());
 }
 
 
@@ -176,190 +596,11 @@ custom_param("nomce", mcheck_disable);
 custom_param("nomce", mcheck_disable);
 custom_param("mce", mcheck_enable);
 
-
-#include <xen/guest_access.h>
-#include <asm/traps.h>
-
-struct mc_info *x86_mcinfo_getptr(void)
-{
-       struct mc_info *mi;
-       uint32_t entry, next;
-
-       for (;;) {
-               entry = mc_data.error_idx;
-               smp_rmb();
-               next = entry + 1;
-               if (cmpxchg(&mc_data.error_idx, entry, next) == entry)
-                       break;
-       }
-
-       mi = &(mc_data.mc[(entry % MAX_MCINFO)]);
-       BUG_ON(mc_data.error_idx < mc_data.fetch_idx);
-
-       return mi;
-}
-
-static int x86_mcinfo_matches_guest(const struct mc_info *mi,
-                       const struct domain *d, const struct vcpu *v)
-{
-       struct mcinfo_common *mic;
-       struct mcinfo_global *mig;
-
-       x86_mcinfo_lookup(mic, mi, MC_TYPE_GLOBAL);
-       mig = (struct mcinfo_global *)mic;
-       if (mig == NULL)
-               return 0;
-
-       if (d->domain_id != mig->mc_domid)
-               return 0;
-
-       if (v->vcpu_id != mig->mc_vcpuid)
-               return 0;
-
-       return 1;
-}
-
-
-#define x86_mcinfo_mcdata(idx) (mc_data.mc[(idx % MAX_MCINFO)])
-
-static struct mc_info *x86_mcinfo_getfetchptr(uint32_t *fetch_idx,
-                               const struct domain *d, const struct vcpu *v)
-{
-       struct mc_info *mi;
-
-       /* This function is called from the fetch hypercall with
-        * the mc_lock spinlock held. Thus, no need for locking here.
-        */
-       mi = &(x86_mcinfo_mcdata(mc_data.fetch_idx));
-       if ((d != dom0) && !x86_mcinfo_matches_guest(mi, d, v)) {
-               /* Bogus domU command detected. */
-               *fetch_idx = 0;
-               return NULL;
-       }
-
-       *fetch_idx = mc_data.fetch_idx;
-       mc_data.fetch_idx++;
-       BUG_ON(mc_data.fetch_idx > mc_data.error_idx);
-
-       return mi;
-}
-
-
-static void x86_mcinfo_marknotified(struct xen_mc_notifydomain 
*mc_notifydomain)
-{
-       struct mc_machine_notify *mn;
-       struct mcinfo_common *mic = NULL;
-       struct mcinfo_global *mig;
-       struct domain *d;
-       int i;
-
-       /* This function is called from the notifier hypercall with
-        * the mc_notify_lock spinlock held. Thus, no need for locking here.
-        */
-
-       /* First invalidate entries for guests that disappeared after
-        * notification (e.g. shutdown/crash). This step prevents the
-        * notification array from filling up with stalling/leaking entries.
-        */
-       for (i = mc_data.notifyconsumer_idx; i < mc_data.notifyproducer_idx; 
i++) {
-               mn = &(mc_data.notify[(i % MAX_MCINFO)]);
-               x86_mcinfo_lookup(mic, &mn->mc, MC_TYPE_GLOBAL);
-               BUG_ON(mic == NULL);
-               mig = (struct mcinfo_global *)mic;
-               d = get_domain_by_id(mig->mc_domid);
-               if (d == NULL) {
-                       /* Domain does not exist. */
-                       mn->valid = 0;
-               }
-               if ((!mn->valid) && (i == mc_data.notifyconsumer_idx))
-                       mc_data.notifyconsumer_idx++;
-       }
-
-       /* Now put in the error telemetry. Since all error data fetchable
-        * by domUs are uncorrectable errors, they are very important.
-        * So we dump them before overriding them. When a guest takes that long,
-        * then we can assume something bad already happened (crash, hang, etc.)
-        */
-       mn = &(mc_data.notify[(mc_data.notifyproducer_idx % MAX_MCINFO)]);
-
-       if (mn->valid) {
-               struct mcinfo_common *mic = NULL;
-               struct mcinfo_global *mig;
-
-               /* To not loose the information, we dump it. */
-               x86_mcinfo_lookup(mic, &mn->mc, MC_TYPE_GLOBAL);
-               BUG_ON(mic == NULL);
-               mig = (struct mcinfo_global *)mic;
-               printk(XENLOG_WARNING "Domain ID %u was notified by Dom0 to "
-                       "fetch machine check error telemetry. But Domain ID "
-                       "did not do that in time.\n",
-                       mig->mc_domid);
-               x86_mcinfo_dump(&mn->mc);
-       }
-
-       memcpy(&mn->mc, &(x86_mcinfo_mcdata(mc_notifydomain->fetch_idx)),
-               sizeof(struct mc_info));
-       mn->fetch_idx = mc_notifydomain->fetch_idx;
-       mn->valid = 1;
-
-       mc_data.notifyproducer_idx++;
-
-       /* By design there can never be more notifies than machine check errors.
-        * If that ever happens, then we hit a bug. */
-       BUG_ON(mc_data.notifyproducer_idx > mc_data.fetch_idx);
-       BUG_ON(mc_data.notifyconsumer_idx > mc_data.notifyproducer_idx);
-}
-
-static struct mc_info *x86_mcinfo_getnotifiedptr(uint32_t *fetch_idx,
-                               const struct domain *d, const struct vcpu *v)
-{
-       struct mc_machine_notify *mn = NULL;
-       uint32_t i;
-       int found;
-
-       /* This function is called from the fetch hypercall with
-        * the mc_notify_lock spinlock held. Thus, no need for locking here.
-        */
-
-       /* The notifier data is filled in the order guests get notified, but
-        * guests may fetch them in a different order. That's why we need
-        * the game with valid/invalid entries. */
-       found = 0;
-       for (i = mc_data.notifyconsumer_idx; i < mc_data.notifyproducer_idx; 
i++) {
-               mn = &(mc_data.notify[(i % MAX_MCINFO)]);
-               if (!mn->valid) {
-                       if (i == mc_data.notifyconsumer_idx)
-                               mc_data.notifyconsumer_idx++;
-                       continue;
-               }
-               if (x86_mcinfo_matches_guest(&mn->mc, d, v)) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found) {
-               /* This domain has never been notified. This must be
-                * a bogus domU command. */
-               *fetch_idx = 0;
-               return NULL;
-       }
-
-       BUG_ON(mn == NULL);
-       *fetch_idx = mn->fetch_idx;
-       mn->valid = 0;
-
-       BUG_ON(mc_data.notifyconsumer_idx > mc_data.notifyproducer_idx);
-       return &mn->mc;
-}
-
-
-void x86_mcinfo_clear(struct mc_info *mi)
+static void mcinfo_clear(struct mc_info *mi)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>