# 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, ¶ms, 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
|