[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.