[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User Isaku Yamahata <yamahata@xxxxxxxxxxxxx> # Date 1238119631 -32400 # Node ID e54eeff2de547b173ee13557157e05ce3e3c3fe1 # Parent 5e4dd7079c484192e8621e64d817d58b995b4f75 # Parent 0b13d9787622d5e1d447a21657394805bb96d26f merge with xen-unstable.hg --- tools/hotplug/Linux/blktap | 93 Makefile | 2 config/NetBSD.mk | 4 config/StdGNU.mk | 3 docs/misc/vtd.txt | 92 extras/mini-os/arch/ia64/mm.c | 6 extras/mini-os/arch/x86/mm.c | 142 + extras/mini-os/include/mm.h | 1 extras/mini-os/include/x86/arch_mm.h | 3 stubdom/Makefile | 22 tools/Makefile | 6 tools/blktap/drivers/blktapctrl.c | 78 tools/blktap/drivers/tapdisk.h | 29 tools/blktap/lib/blktaplib.h | 10 tools/blktap/lib/xenbus.c | 150 + tools/console/client/main.c | 50 tools/console/daemon/main.c | 2 tools/examples/xend-config.sxp | 1 tools/examples/xmexample.hvm | 8 tools/firmware/Makefile | 3 tools/firmware/hvmloader/acpi/dsdt.asl | 1218 +++++++++ tools/firmware/hvmloader/acpi/dsdt.c | 954 +++++++ tools/firmware/hvmloader/config.h | 3 tools/firmware/hvmloader/hvmloader.c | 20 tools/firmware/rombios/32bit/pmm.c | 5 tools/firmware/rombios/rombios.c | 14 tools/fs-back/Makefile | 2 tools/fs-back/fs-backend.c | 402 +-- tools/fs-back/fs-backend.h | 10 tools/fs-back/fs-debug.h | 12 tools/fs-back/fs-ops.c | 175 - tools/fs-back/fs-xenbus.c | 87 tools/fs-back/sys-queue.h | 338 ++ tools/hotplug/Linux/Makefile | 3 tools/hotplug/Linux/xen-backend.rules | 1 tools/hotplug/Linux/xen-hotplug-cleanup | 10 tools/hotplug/Linux/xend.rules | 3 tools/hotplug/NetBSD/Makefile | 8 tools/libfsimage/zfs/fsys_zfs.c | 3 tools/libfsimage/zfs/zfs-include/zfs.h | 12 tools/libxc/Makefile | 2 tools/libxc/xc_core.c | 10 tools/libxc/xc_dom_x86.c | 14 tools/libxc/xc_domain_save.c | 2 tools/libxc/xc_pm.c | 56 tools/libxc/xc_ptrace_core.c | 2 tools/libxc/xc_solaris.c | 2 tools/libxc/xc_suspend.c | 117 tools/libxc/xenctrl.h | 22 tools/libxc/xenguest.h | 6 tools/libxc/xg_private.c | 2 tools/misc/xenpm.c | 137 + tools/pygrub/src/pygrub | 24 tools/python/setup.py | 8 tools/python/xen/lowlevel/process/process.c | 164 + tools/python/xen/util/pci.py | 57 tools/python/xen/util/vscsi_util.py | 13 tools/python/xen/web/SrvDir.py | 4 tools/python/xen/web/connection.py | 37 tools/python/xen/web/unix.py | 32 tools/python/xen/xend/XendAPIStore.py | 49 tools/python/xen/xend/XendCheckpoint.py | 2 tools/python/xen/xend/XendConfig.py | 40 tools/python/xen/xend/XendConstants.py | 5 tools/python/xen/xend/XendDomain.py | 28 tools/python/xen/xend/XendDomainInfo.py | 89 tools/python/xen/xend/XendNode.py | 108 tools/python/xen/xend/XendOptions.py | 7 tools/python/xen/xend/XendPPCI.py | 10 tools/python/xen/xend/image.py | 59 tools/python/xen/xend/osdep.py | 75 tools/python/xen/xend/server/BlktapController.py | 3 tools/python/xen/xend/server/SrvDaemon.py | 2 tools/python/xen/xend/server/SrvDomain.py | 3 tools/python/xen/xend/server/netif.py | 22 tools/python/xen/xend/server/pciif.py | 4 tools/python/xen/xend/server/udevevent.py | 68 tools/python/xen/xm/create.dtd | 1 tools/python/xen/xm/create.py | 27 tools/python/xen/xm/main.py | 53 tools/python/xen/xm/xenapi_create.py | 1 tools/xcutils/xc_save.c | 127 - tools/xenstore/Makefile | 4 tools/xenstore/xs.c | 25 tools/xenstore/xs.h | 1 tools/xentrace/formats | 4 tools/xentrace/xentrace_format | 6 unmodified_drivers/linux-2.6/compat-include/linux/scatterlist.h | 10 xen/arch/ia64/xen/hypercall.c | 22 xen/arch/x86/acpi/cpu_idle.c | 71 xen/arch/x86/acpi/cpufreq/cpufreq.c | 135 - xen/arch/x86/acpi/power.c | 24 xen/arch/x86/acpi/suspend.c | 8 xen/arch/x86/boot/build32.mk | 3 xen/arch/x86/cpu/common.c | 3 xen/arch/x86/cpu/mcheck/Makefile | 1 xen/arch/x86/cpu/mcheck/amd_f10.c | 43 xen/arch/x86/cpu/mcheck/amd_k8.c | 229 - xen/arch/x86/cpu/mcheck/amd_nonfatal.c | 150 - xen/arch/x86/cpu/mcheck/k7.c | 11 xen/arch/x86/cpu/mcheck/mce.c | 1257 ++++++---- xen/arch/x86/cpu/mcheck/mce.h | 115 xen/arch/x86/cpu/mcheck/mce_intel.c | 1016 +++++--- xen/arch/x86/cpu/mcheck/mctelem.c | 443 +++ xen/arch/x86/cpu/mcheck/mctelem.h | 71 xen/arch/x86/cpu/mcheck/non-fatal.c | 87 xen/arch/x86/cpu/mcheck/p5.c | 15 xen/arch/x86/cpu/mcheck/winchip.c | 8 xen/arch/x86/cpu/mcheck/x86_mca.h | 60 xen/arch/x86/domain.c | 11 xen/arch/x86/domctl.c | 8 xen/arch/x86/hpet.c | 403 +++ xen/arch/x86/hvm/emulate.c | 2 xen/arch/x86/hvm/hvm.c | 14 xen/arch/x86/hvm/rtc.c | 7 xen/arch/x86/hvm/svm/svm.c | 12 xen/arch/x86/hvm/vmsi.c | 56 xen/arch/x86/hvm/vmx/vpmu_core2.c | 6 xen/arch/x86/mm.c | 83 xen/arch/x86/mm/shadow/multi.c | 82 xen/arch/x86/msi.c | 2 xen/arch/x86/oprofile/op_model_ppro.c | 2 xen/arch/x86/physdev.c | 26 xen/arch/x86/setup.c | 2 xen/arch/x86/smpboot.c | 8 xen/arch/x86/sysctl.c | 24 xen/arch/x86/time.c | 11 xen/arch/x86/traps.c | 48 xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_64/compat/entry.S | 2 xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/traps.c | 47 xen/common/domain.c | 2 xen/common/memory.c | 11 xen/common/page_alloc.c | 105 xen/common/sched_credit.c | 9 xen/common/schedule.c | 10 xen/common/sysctl.c | 29 xen/drivers/acpi/pmstat.c | 90 xen/drivers/cpufreq/cpufreq_misc_governors.c | 83 xen/drivers/cpufreq/cpufreq_ondemand.c | 4 xen/drivers/cpufreq/utility.c | 28 xen/drivers/passthrough/io.c | 141 - xen/drivers/passthrough/iommu.c | 18 xen/drivers/passthrough/pci.c | 41 xen/drivers/passthrough/vtd/dmar.c | 18 xen/drivers/passthrough/vtd/dmar.h | 2 xen/drivers/passthrough/vtd/extern.h | 6 xen/drivers/passthrough/vtd/intremap.c | 69 xen/drivers/passthrough/vtd/iommu.c | 139 - xen/drivers/passthrough/vtd/qinval.c | 29 xen/include/acpi/cpufreq/cpufreq.h | 9 xen/include/asm-ia64/linux-xen/asm/processor.h | 8 xen/include/asm-x86/desc.h | 4 xen/include/asm-x86/domain.h | 28 xen/include/asm-x86/hpet.h | 5 xen/include/asm-x86/mm.h | 31 xen/include/asm-x86/msr-index.h | 24 xen/include/asm-x86/processor.h | 3 xen/include/asm-x86/softirq.h | 3 xen/include/asm-x86/traps.h | 2 xen/include/asm-x86/x86_64/page.h | 2 xen/include/public/arch-x86/xen-mca.h | 133 - xen/include/public/domctl.h | 2 xen/include/public/io/fsif.h | 3 xen/include/public/io/usbif.h | 121 xen/include/public/io/vscsiif.h | 105 xen/include/public/physdev.h | 16 xen/include/public/sysctl.h | 35 xen/include/xen/hvm/irq.h | 4 xen/include/xen/iommu.h | 2 xen/include/xen/irq.h | 2 xen/include/xen/lib.h | 1 xen/include/xen/pci.h | 11 xen/include/xen/sched.h | 7 175 files changed, 9032 insertions(+), 2524 deletions(-) diff -r 5e4dd7079c48 -r e54eeff2de54 Makefile --- a/Makefile Fri Mar 27 10:54:08 2009 +0900 +++ b/Makefile Fri Mar 27 11:07:11 2009 +0900 @@ -203,6 +203,8 @@ uninstall: rm -rf $(D)/etc/hotplug/xen-backend.agent rm -f $(D)/etc/udev/rules.d/xen-backend.rules rm -f $(D)/etc/udev/xen-backend.rules + rm -f $(D)/etc/udev/rules.d/xend.rules + rm -f $(D)/etc/udev/xend.rules rm -f $(D)/etc/sysconfig/xendomains rm -rf $(D)/var/run/xen* $(D)/var/lib/xen* rm -rf $(D)/boot/*xen* diff -r 5e4dd7079c48 -r e54eeff2de54 config/NetBSD.mk --- a/config/NetBSD.mk Fri Mar 27 10:54:08 2009 +0900 +++ b/config/NetBSD.mk Fri Mar 27 11:07:11 2009 +0900 @@ -2,3 +2,7 @@ include $(XEN_ROOT)/config/StdGNU.mk # Override settings for this OS CURSES_LIBS = -lcurses + +LIBLEAFDIR_x86_64 = lib +LIBEXEC = $(PREFIX)/libexec +PRIVATE_BINDIR = $(BINDIR) diff -r 5e4dd7079c48 -r e54eeff2de54 config/StdGNU.mk --- a/config/StdGNU.mk Fri Mar 27 10:54:08 2009 +0900 +++ b/config/StdGNU.mk Fri Mar 27 11:07:11 2009 +0900 @@ -25,9 +25,12 @@ BINDIR = $(PREFIX)/bin BINDIR = $(PREFIX)/bin INCLUDEDIR = $(PREFIX)/include LIBLEAFDIR = lib +LIBLEAFDIR_x86_32 = lib LIBLEAFDIR_x86_64 = lib64 LIBDIR = $(PREFIX)/$(LIBLEAFDIR) +LIBDIR_x86_32 = $(PREFIX)/$(LIBLEAFDIR_x86_32) LIBDIR_x86_64 = $(PREFIX)/$(LIBLEAFDIR_x86_64) +LIBEXEC = $(LIBDIR_x86_32)/xen/bin MANDIR = $(PREFIX)/share/man MAN1DIR = $(MANDIR)/man1 MAN8DIR = $(MANDIR)/man8 diff -r 5e4dd7079c48 -r e54eeff2de54 docs/misc/vtd.txt --- a/docs/misc/vtd.txt Fri Mar 27 10:54:08 2009 +0900 +++ b/docs/misc/vtd.txt Fri Mar 27 11:07:11 2009 +0900 @@ -26,7 +26,18 @@ title Xen-Fedora Core (2.6.18-xen) module /boot/vmlinuz-2.6.18.8-xen root=LABEL=/ ro xencons=ttyS console=tty0 console=ttyS0, pciback.hide=(01:00.0)(03:00.0) module /boot/initrd-2.6.18-xen.img -12) reboot system + or use dynamic hiding via PCI backend sysfs interface: + a) check if the driver has binded to the device + ls -l /sys/bus/pci/devices/0000:01:00.0/driver + ... /sys/bus/pci/devices/0000:01:00.0/driver -> ../../../../bus/pci/drivers/igb + b) if yes, then unload the driver first + echo -n 0000:01:00.0 >/sys/bus/pci/drivers/igb/unbind + c) add the device to the PCI backend + echo -n 0000:01:00.0 >/sys/bus/pci/drivers/pciback/new_slot + d) let the PCI backend bind to the device + echo -n 0000:01:00.0 >/sys/bus/pci/drivers/pciback/bind + +12) reboot system (not requires if you use the dynamic hiding method) 13) add "pci" line in /etc/xen/hvm.conf for to assigned devices pci = [ '01:00.0', '03:00.0' ] 15) start hvm guest and use "lspci" to see the passthru device and @@ -160,3 +171,82 @@ buffer specified by driver. buffer specified by driver. Such devices assigned to HVM domain currently do not work. + + +Using SR-IOV with VT-d +-------------------------------- + +The Single Root I/O Virtualization is a PCI Express feature supported by +some devices such as Intel 82576 which allows you to create virtual PCI +devices (Virtual Function) and assign them to the HVM guest. + +You can use latest lspci (v3.1 and above) to check if your PCIe device +supports the SR-IOV capability or not. + + $ lspci -s 01:00.0 -vvv + + 01:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01) + Subsystem: Intel Corporation Gigabit ET Dual Port Server Adapter + + ... + + Capabilities: [160] Single Root I/O Virtualization (SR-IOV) + IOVCap: Migration-, Interrupt Message Number: 000 + IOVCtl: Enable+ Migration- Interrupt- MSE+ ARIHierarchy+ + IOVSta: Migration- + Initial VFs: 8, Total VFs: 8, Number of VFs: 7, Function Dependency Link: 00 + VF offset: 128, stride: 2, Device ID: 10ca + Supported Page Size: 00000553, System Page Size: 00000001 + VF Migration: offset: 00000000, BIR: 0 + Kernel driver in use: igb + + +The function that has the SR-IOV capability is also known as Physical +Function. You need the Physical Function driver (runs in the Dom0 and +controls the physical resources allocation) to enable the Virtual Function. +Following is the Virtual Functions associated with above Physical Function. + + $ lspci | grep -e 01:1[01].[0246] + + 01:10.0 Ethernet controller: Intel Corporation Device 10ca (rev 01) + 01:10.2 Ethernet controller: Intel Corporation Device 10ca (rev 01) + 01:10.4 Ethernet controller: Intel Corporation Device 10ca (rev 01) + 01:10.6 Ethernet controller: Intel Corporation Device 10ca (rev 01) + 01:11.0 Ethernet controller: Intel Corporation Device 10ca (rev 01) + 01:11.2 Ethernet controller: Intel Corporation Device 10ca (rev 01) + 01:11.4 Ethernet controller: Intel Corporation Device 10ca (rev 01) + +We can tell that Physical Function 01:00.0 has 7 Virtual Functions (01:10.0, +01:10.2, 01:10.4, 01:10.6, 01:11.0, 01:11.2, 01:11.4). And the Virtual +Function PCI Configuration Space looks just like normal PCI device. + + $ lspci -s 01:10.0 -vvv + + 01:10.0 Ethernet controller: Intel Corporation 82576 Gigabit Virtual Function + Subsystem: Intel Corporation Gigabit Virtual Function + Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- + Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- + Region 0: [virtual] Memory at d2840000 (64-bit, non-prefetchable) [size=16K] + Region 3: [virtual] Memory at d2860000 (64-bit, non-prefetchable) [size=16K] + Capabilities: [70] MSI-X: Enable+ Mask- TabSize=3 + Vector table: BAR=3 offset=00000000 + PBA: BAR=3 offset=00002000 + Capabilities: [a0] Express (v2) Endpoint, MSI 00 + + ... + + +The Virtual Function only appears after the Physical Function driver +is loaded. Once the Physical Function driver is unloaded. All Virtual +Functions associated with this Physical Function disappear. + +The Virtual Function is essentially same as the normal PCI device when +using it in VT-d environment. You need to hide the Virtual Function, +use the Virtual Function bus, device and function number in the HVM +guest configuration file and then boot the HVM guest. You also need the +Virtual Function driver which is the normal PCI device driver in the +HMV guest to drive the Virtual Function. The PCIe SR-IOV specification +requires that the Virtual Function can only support MSI/MSI-x if it +uses interrupt. This means you also need to enable Xen/MSI support. +Since the Virtual Function is dynamically allocated by Physical Function +driver, you might want to use the dynamic hiding method mentioned above. diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/arch/ia64/mm.c --- a/extras/mini-os/arch/ia64/mm.c Fri Mar 27 10:54:08 2009 +0900 +++ b/extras/mini-os/arch/ia64/mm.c Fri Mar 27 11:07:11 2009 +0900 @@ -162,6 +162,12 @@ int unmap_frames(unsigned long virt_addr ASSERT(0); } +unsigned long alloc_contig_pages(int order, unsigned int addr_bits) +{ + /* TODO */ + ASSERT(0); +} + void arch_init_p2m(unsigned long max_pfn) { printk("Warn: p2m map not implemented.\n"); diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/arch/x86/mm.c --- a/extras/mini-os/arch/x86/mm.c Fri Mar 27 10:54:08 2009 +0900 +++ b/extras/mini-os/arch/x86/mm.c Fri Mar 27 11:07:11 2009 +0900 @@ -702,6 +702,148 @@ int unmap_frames(unsigned long va, unsig } /* + * Allocate pages which are contiguous in machine memory. + * Returns a VA to where they are mapped or 0 on failure. + * + * addr_bits indicates if the region has restrictions on where it is + * located. Typical values are 32 (if for example PCI devices can't access + * 64bit memory) or 0 for no restrictions. + * + * Allocated pages can be freed using the page allocators free_pages() + * function. + * + * based on Linux function xen_create_contiguous_region() + */ +#define MAX_CONTIG_ORDER 9 /* 2MB */ +unsigned long alloc_contig_pages(int order, unsigned int addr_bits) +{ + unsigned long in_va, va; + unsigned long in_frames[1UL << order], out_frames, mfn; + multicall_entry_t call[1UL << order]; + unsigned int i, num_pages = 1UL << order; + int ret, exch_success; + + /* pass in num_pages 'extends' of size 1 and + * request 1 extend of size 'order */ + struct xen_memory_exchange exchange = { + .in = { + .nr_extents = num_pages, + .extent_order = 0, + .domid = DOMID_SELF + }, + .out = { + .nr_extents = 1, + .extent_order = order, + .address_bits = addr_bits, + .domid = DOMID_SELF + }, + .nr_exchanged = 0 + }; + + if ( order > MAX_CONTIG_ORDER ) + { + printk("alloc_contig_pages: order too large 0x%x > 0x%x\n", + order, MAX_CONTIG_ORDER); + return 0; + } + + /* Allocate some potentially discontiguous pages */ + in_va = alloc_pages(order); + if ( !in_va ) + { + printk("alloc_contig_pages: could not get enough pages (order=0x%x\n", + order); + return 0; + } + + /* set up arguments for exchange hyper call */ + set_xen_guest_handle(exchange.in.extent_start, in_frames); + set_xen_guest_handle(exchange.out.extent_start, &out_frames); + + /* unmap current frames, keep a list of MFNs */ + for ( i = 0; i < num_pages; i++ ) + { + int arg = 0; + + va = in_va + (PAGE_SIZE * i); + in_frames[i] = virt_to_mfn(va); + + /* update P2M mapping */ + phys_to_machine_mapping[virt_to_pfn(va)] = INVALID_P2M_ENTRY; + + /* build multi call */ + call[i].op = __HYPERVISOR_update_va_mapping; + call[i].args[arg++] = va; + call[i].args[arg++] = 0; +#ifdef __i386__ + call[i].args[arg++] = 0; +#endif + call[i].args[arg++] = UVMF_INVLPG; + } + + ret = HYPERVISOR_multicall(call, i); + if ( ret ) + { + printk("Odd, update_va_mapping hypercall failed with rc=%d.\n", ret); + return 0; + } + + /* try getting a contig range of MFNs */ + out_frames = virt_to_pfn(in_va); /* PFNs to populate */ + ret = HYPERVISOR_memory_op(XENMEM_exchange, &exchange); + if ( ret ) { + printk("mem exchanged order=0x%x failed with rc=%d, nr_exchanged=%d\n", + order, ret, exchange.nr_exchanged); + /* we still need to return the allocated pages above to the pool + * ie. map them back into the 1:1 mapping etc. so we continue but + * in the end return the pages to the page allocator and return 0. */ + exch_success = 0; + } + else + exch_success = 1; + + /* map frames into 1:1 and update p2m */ + for ( i = 0; i < num_pages; i++ ) + { + int arg = 0; + pte_t pte; + + va = in_va + (PAGE_SIZE * i); + mfn = i < exchange.nr_exchanged ? (out_frames + i) : in_frames[i]; + pte = __pte(mfn << PAGE_SHIFT | L1_PROT); + + /* update P2M mapping */ + phys_to_machine_mapping[virt_to_pfn(va)] = mfn; + + /* build multi call */ + call[i].op = __HYPERVISOR_update_va_mapping; + call[i].args[arg++] = va; +#ifdef __x86_64__ + call[i].args[arg++] = (pgentry_t)pte.pte; +#else + call[i].args[arg++] = pte.pte_low; + call[i].args[arg++] = pte.pte_high; +#endif + call[i].args[arg++] = UVMF_INVLPG; + } + ret = HYPERVISOR_multicall(call, i); + if ( ret ) + { + printk("update_va_mapping hypercall no. 2 failed with rc=%d.\n", ret); + return 0; + } + + if ( !exch_success ) + { + /* since the exchanged failed we just free the pages as well */ + free_pages((void *) in_va, order); + return 0; + } + + return in_va; +} + +/* * Check if a given MFN refers to real memory */ static long system_ram_end_mfn; diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/include/mm.h --- a/extras/mini-os/include/mm.h Fri Mar 27 10:54:08 2009 +0900 +++ b/extras/mini-os/include/mm.h Fri Mar 27 11:07:11 2009 +0900 @@ -72,6 +72,7 @@ void do_map_frames(unsigned long addr, unsigned long *f, unsigned long n, unsigned long stride, unsigned long increment, domid_t id, int may_fail, unsigned long prot); int unmap_frames(unsigned long va, unsigned long num_frames); +unsigned long alloc_contig_pages(int order, unsigned int addr_bits); #ifdef HAVE_LIBC extern unsigned long heap, brk, heap_mapped, heap_end; #endif diff -r 5e4dd7079c48 -r e54eeff2de54 extras/mini-os/include/x86/arch_mm.h --- a/extras/mini-os/include/x86/arch_mm.h Fri Mar 27 10:54:08 2009 +0900 +++ b/extras/mini-os/include/x86/arch_mm.h Fri Mar 27 11:07:11 2009 +0900 @@ -137,6 +137,9 @@ typedef unsigned long pgentry_t; #define IO_PROT (L1_PROT) #define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD) +/* for P2M */ +#define INVALID_P2M_ENTRY (~0UL) + #include "arch_limits.h" #define PAGE_SIZE __PAGE_SIZE #define PAGE_SHIFT __PAGE_SHIFT diff -r 5e4dd7079c48 -r e54eeff2de54 stubdom/Makefile --- a/stubdom/Makefile Fri Mar 27 10:54:08 2009 +0900 +++ b/stubdom/Makefile Fri Mar 27 11:07:11 2009 +0900 @@ -6,8 +6,6 @@ export stubdom=y export stubdom=y export debug=y include $(XEN_ROOT)/Config.mk - -IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-vnc-tls --disable-brlapi --disable-kqemu #ZLIB_URL?=http://www.zlib.net ZLIB_URL=$(XEN_EXTFILES_URL) @@ -237,8 +235,12 @@ ioemu: cross-zlib cross-libpci libxc [ -f ioemu/config-host.mak ] || \ ( $(absolutify_xen_root); \ cd ioemu ; \ - CONFIG_STUBDOM=yes XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) CFLAGS="$(TARGET_CFLAGS)" sh ./xen-setup --cc=$(CC) --disable-gcc-check $(IOEMU_OPTIONS)) - CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) TOOLS= CONFIG_STUBDOM=yes + LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) \ + TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" \ + TARGET_CFLAGS="$(TARGET_CFLAGS)" \ + TARGET_LDFLAGS="$(TARGET_LDFLAGS)" \ + ./xen-setup-stubdom ) + $(MAKE) -C ioemu ###### # caml @@ -312,14 +314,14 @@ install-readme: $(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.stubdom install-ioemu: ioemu-stubdom - $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/bin" - $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin" - $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot" - $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/ioemu-stubdom.gz" + $(INSTALL_DIR) "$(DESTDIR)$(LIBEXEC)" + $(INSTALL_PROG) stubdom-dm "$(DESTDIR)$(LIBEXEC)" + $(INSTALL_DIR) "$(DESTDIR)$(LIBDIR_x86_32)/xen/boot" + $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz "$(DESTDIR)$(LIBDIR_x86_32)/xen/boot/ioemu-stubdom.gz" install-grub: pv-grub - $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot" - $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/pv-grub-$(XEN_TARGET_ARCH).gz" + $(INSTALL_DIR) "$(DESTDIR)$(LIBDIR_x86_32)/xen/boot" + $(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz "$(DESTDIR)$(LIBDIR_x86_32)/xen/boot/pv-grub-$(XEN_TARGET_ARCH).gz" ####### # clean diff -r 5e4dd7079c48 -r e54eeff2de54 tools/Makefile --- a/tools/Makefile Fri Mar 27 10:54:08 2009 +0900 +++ b/tools/Makefile Fri Mar 27 11:07:11 2009 +0900 @@ -19,11 +19,11 @@ SUBDIRS-$(VTPM_TOOLS) += vtpm_manager SUBDIRS-$(VTPM_TOOLS) += vtpm_manager SUBDIRS-$(VTPM_TOOLS) += vtpm SUBDIRS-y += xenstat -SUBDIRS-y += libaio -SUBDIRS-y += blktap +SUBDIRS-$(CONFIG_Linux) += libaio +SUBDIRS-$(CONFIG_Linux) += blktap SUBDIRS-y += libfsimage SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen -SUBDIRS-y += fs-back +SUBDIRS-$(CONFIG_Linux) += fs-back SUBDIRS-$(CONFIG_IOEMU) += ioemu-dir SUBDIRS-y += xenpmd diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/drivers/blktapctrl.c --- a/tools/blktap/drivers/blktapctrl.c Fri Mar 27 10:54:08 2009 +0900 +++ b/tools/blktap/drivers/blktapctrl.c Fri Mar 27 11:07:11 2009 +0900 @@ -148,7 +148,8 @@ static int get_tapdisk_pid(blkif_t *blki * return 0 on success, -1 on error. */ -static int test_path(char *path, char **dev, int *type, blkif_t **blkif) +static int test_path(char *path, char **dev, int *type, blkif_t **blkif, + int* use_ioemu) { char *ptr, handle[10]; int i, size, found = 0; @@ -157,6 +158,17 @@ static int test_path(char *path, char ** size = sizeof(dtypes)/sizeof(disk_info_t *); *type = MAX_DISK_TYPES + 1; *blkif = NULL; + + if (!strncmp(path, "tapdisk:", strlen("tapdisk:"))) { + *use_ioemu = 0; + path += strlen("tapdisk:"); + } else if (!strncmp(path, "ioemu:", strlen("ioemu:"))) { + *use_ioemu = 1; + path += strlen("ioemu:"); + } else { + // Use the default for the image type + *use_ioemu = -1; + } if ( (ptr = strstr(path, ":"))!=NULL) { handle_len = (ptr - path); @@ -174,6 +186,8 @@ static int test_path(char *path, char ** } if (found) { + if (*use_ioemu == -1) + *use_ioemu = dtypes[i]->use_ioemu; *type = dtypes[i]->idnum; if (dtypes[i]->single_handler == 1) { @@ -185,6 +199,7 @@ static int test_path(char *path, char ** *blkif = active_disks[dtypes[i] ->idnum]->blkif; } + return 0; } } @@ -216,6 +231,24 @@ static void add_disktype(blkif_t *blkif, entry->pprev = pprev; } +static int qemu_instance_has_disks(pid_t pid) +{ + int i; + int count = 0; + driver_list_entry_t *entry; + + for (i = 0; i < MAX_DISK_TYPES; i++) { + entry = active_disks[i]; + while (entry) { + if ((entry->blkif->tappid == pid) && dtypes[i]->use_ioemu) + count++; + entry = entry->next; + } + } + + return (count != 0); +} + static int del_disktype(blkif_t *blkif) { driver_list_entry_t *entry, **pprev; @@ -239,6 +272,14 @@ static int del_disktype(blkif_t *blkif) DPRINTF("DEL_DISKTYPE: Freeing entry\n"); free(entry); + + /* + * When using ioemu, all disks of one VM are connected to the same + * qemu-dm instance. We may close the file handle only if there is + * no other disk left for this domain. + */ + if (dtypes[type]->use_ioemu) + return !qemu_instance_has_disks(blkif->tappid); /* Caller should close() if no single controller, or list is empty. */ return (!dtypes[type]->single_handler || (active_disks[type] == NULL)); @@ -504,7 +545,8 @@ static int connect_qemu(blkif_t *blkif, static int tapdisk_ioemu_pid = 0; static int dom0_readfd = 0; static int dom0_writefd = 0; - + int refresh_pid = 0; + if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0) return -1; @@ -523,15 +565,23 @@ static int connect_qemu(blkif_t *blkif, if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) { /* No device model and tapdisk-ioemu doesn't run yet */ DPRINTF("Launching tapdisk-ioemu\n"); - tapdisk_ioemu_pid = launch_tapdisk_ioemu(); + launch_tapdisk_ioemu(); dom0_readfd = open_ctrl_socket(wrctldev); dom0_writefd = open_ctrl_socket(rdctldev); + + refresh_pid = 1; } DPRINTF("Using tapdisk-ioemu connection\n"); blkif->fds[READ] = dom0_readfd; blkif->fds[WRITE] = dom0_writefd; + + if (refresh_pid) { + get_tapdisk_pid(blkif); + tapdisk_ioemu_pid = blkif->tappid; + } + } else if (access(rdctldev, R_OK | W_OK) == 0) { /* Use existing pipe to the device model */ DPRINTF("Using qemu-dm connection\n"); @@ -605,13 +655,11 @@ static int blktapctrl_new_blkif(blkif_t image_t *image; blkif_t *exist = NULL; static uint16_t next_cookie = 0; + int use_ioemu; DPRINTF("Received a poll for a new vbd\n"); if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) { - if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0) - return -1; - - if (test_path(blk->params, &ptr, &type, &exist) != 0) { + if (test_path(blk->params, &ptr, &type, &exist, &use_ioemu) != 0) { DPRINTF("Error in blktap device string(%s).\n", blk->params); goto fail; @@ -620,7 +668,7 @@ static int blktapctrl_new_blkif(blkif_t blkif->cookie = next_cookie++; if (!exist) { - if (type == DISK_TYPE_IOEMU) { + if (use_ioemu) { if (connect_qemu(blkif, blkif->domid)) goto fail; } else { @@ -633,10 +681,6 @@ static int blktapctrl_new_blkif(blkif_t blkif->fds[READ] = exist->fds[READ]; blkif->fds[WRITE] = exist->fds[WRITE]; } - - add_disktype(blkif, type); - blkif->major = major; - blkif->minor = minor; image = (image_t *)malloc(sizeof(image_t)); blkif->prv = (void *)image; @@ -661,11 +705,18 @@ static int blktapctrl_new_blkif(blkif_t goto fail; } + if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0) + return -1; + + blkif->major = major; + blkif->minor = minor; + + add_disktype(blkif, type); + } else return -1; return 0; fail: - ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor); return -EINVAL; } @@ -696,6 +747,7 @@ static int unmap_blktapctrl(blkif_t *blk } if (del_disktype(blkif)) { + DPRINTF("Closing communication pipe to pid %d\n", blkif->tappid); close(blkif->fds[WRITE]); close(blkif->fds[READ]); } diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/drivers/tapdisk.h --- a/tools/blktap/drivers/tapdisk.h Fri Mar 27 10:54:08 2009 +0900 +++ b/tools/blktap/drivers/tapdisk.h Fri Mar 27 11:07:11 2009 +0900 @@ -145,6 +145,8 @@ typedef struct disk_info { char handle[10]; /* xend handle, e.g. 'ram' */ int single_handler; /* is there a single controller for all */ /* instances of disk type? */ + int use_ioemu; /* backend provider: 0 = tapdisk; 1 = ioemu */ + #ifdef TAPDISK struct tap_disk *drv; #endif @@ -159,16 +161,6 @@ extern struct tap_disk tapdisk_qcow; extern struct tap_disk tapdisk_qcow; extern struct tap_disk tapdisk_qcow2; -#define MAX_DISK_TYPES 20 - -#define DISK_TYPE_AIO 0 -#define DISK_TYPE_SYNC 1 -#define DISK_TYPE_VMDK 2 -#define DISK_TYPE_RAM 3 -#define DISK_TYPE_QCOW 4 -#define DISK_TYPE_QCOW2 5 -#define DISK_TYPE_IOEMU 6 - /*Define Individual Disk Parameters here */ static disk_info_t aio_disk = { @@ -176,6 +168,7 @@ static disk_info_t aio_disk = { "raw image (aio)", "aio", 0, + 0, #ifdef TAPDISK &tapdisk_aio, #endif @@ -185,6 +178,7 @@ static disk_info_t sync_disk = { DISK_TYPE_SYNC, "raw image (sync)", "sync", + 0, 0, #ifdef TAPDISK &tapdisk_sync, @@ -196,6 +190,7 @@ static disk_info_t vmdk_disk = { "vmware image (vmdk)", "vmdk", 1, + 0, #ifdef TAPDISK &tapdisk_vmdk, #endif @@ -206,6 +201,7 @@ static disk_info_t ram_disk = { "ramdisk image (ram)", "ram", 1, + 0, #ifdef TAPDISK &tapdisk_ram, #endif @@ -216,6 +212,7 @@ static disk_info_t qcow_disk = { "qcow disk (qcow)", "qcow", 0, + 0, #ifdef TAPDISK &tapdisk_qcow, #endif @@ -226,18 +223,9 @@ static disk_info_t qcow2_disk = { "qcow2 disk (qcow2)", "qcow2", 0, + 0, #ifdef TAPDISK &tapdisk_qcow2, -#endif -}; - -static disk_info_t ioemu_disk = { - DISK_TYPE_IOEMU, - "ioemu disk", - "ioemu", - 1, -#ifdef TAPDISK - NULL #endif }; @@ -249,7 +237,6 @@ static disk_info_t *dtypes[] = { &ram_disk, &qcow_disk, &qcow2_disk, - &ioemu_disk, }; typedef struct driver_list_entry { diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/lib/blktaplib.h --- a/tools/blktap/lib/blktaplib.h Fri Mar 27 10:54:08 2009 +0900 +++ b/tools/blktap/lib/blktaplib.h Fri Mar 27 11:07:11 2009 +0900 @@ -210,6 +210,16 @@ typedef struct msg_pid { #define CTLMSG_PID 9 #define CTLMSG_PID_RSP 10 +/* disk driver types */ +#define MAX_DISK_TYPES 20 + +#define DISK_TYPE_AIO 0 +#define DISK_TYPE_SYNC 1 +#define DISK_TYPE_VMDK 2 +#define DISK_TYPE_RAM 3 +#define DISK_TYPE_QCOW 4 +#define DISK_TYPE_QCOW2 5 + /* xenstore/xenbus: */ #define DOMNAME "Domain-0" int setup_probe_watch(struct xs_handle *h); diff -r 5e4dd7079c48 -r e54eeff2de54 tools/blktap/lib/xenbus.c --- a/tools/blktap/lib/xenbus.c Fri Mar 27 10:54:08 2009 +0900 +++ b/tools/blktap/lib/xenbus.c Fri Mar 27 11:07:11 2009 +0900 @@ -48,6 +48,7 @@ #include <poll.h> #include <time.h> #include <sys/time.h> +#include <unistd.h> #include "blktaplib.h" #include "list.h" #include "xs_api.h" @@ -149,6 +150,137 @@ static int backend_remove(struct xs_hand return 0; } +static int check_sharing(struct xs_handle *h, struct backend_info *be) +{ + char *dom_uuid; + char *cur_dom_uuid; + char *path; + char *mode; + char *params; + char **domains; + char **devices; + int i, j; + unsigned int num_dom, num_dev; + blkif_info_t *info; + int ret = 0; + + /* If the mode contains '!' or doesn't contain 'w' don't check anything */ + xs_gather(h, be->backpath, "mode", NULL, &mode, NULL); + if (strchr(mode, '!')) + goto out; + if (strchr(mode, 'w') == NULL) + goto out; + + /* Get the UUID of the domain we want to attach to */ + if (asprintf(&path, "/local/domain/%ld", be->frontend_id) == -1) + goto fail; + xs_gather(h, path, "vm", NULL, &dom_uuid, NULL); + free(path); + + /* Iterate through the devices of all VMs */ + domains = xs_directory(h, XBT_NULL, "backend/tap", &num_dom); + if (domains == NULL) + num_dom = 0; + + for (i = 0; !ret && (i < num_dom); i++) { + + /* If it's the same VM, no action needed */ + if (asprintf(&path, "/local/domain/%s", domains[i]) == -1) { + ret = -1; + break; + } + xs_gather(h, path, "vm", NULL, &cur_dom_uuid, NULL); + free(path); + + if (!strcmp(cur_dom_uuid, dom_uuid)) { + free(cur_dom_uuid); + continue; + } + + /* Check the devices */ + if (asprintf(&path, "backend/tap/%s", domains[i]) == -1) { + ret = -1; + free(cur_dom_uuid); + break; + } + devices = xs_directory(h, XBT_NULL, path, &num_dev); + if (devices == NULL) + num_dev = 0; + free(path); + + for (j = 0; !ret && (j < num_dev); j++) { + if (asprintf(&path, "backend/tap/%s/%s", domains[i], devices[j]) == -1) { + ret = -1; + break; + } + xs_gather(h, path, "params", NULL, ¶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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |