# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID b76e86966e7ee5e8bcdab787701a733cfc78b279
# Parent 4acc6d51f3893d2b0c33c021f459ac12482858d9
# Parent aa1ab056bfbffc28c8f2f8c7142ceb076d9a784d
merge with xen-unstable.hg
---
tools/ioemu/CVS/Entries | 109
tools/ioemu/CVS/Repository | 1
tools/ioemu/CVS/Root | 1
tools/ioemu/CVS/Tag | 1
tools/ioemu/audio/CVS/Entries | 19
tools/ioemu/audio/CVS/Repository | 1
tools/ioemu/audio/CVS/Root | 1
tools/ioemu/audio/CVS/Tag | 1
tools/ioemu/fpu/CVS/Entries | 7
tools/ioemu/fpu/CVS/Repository | 1
tools/ioemu/fpu/CVS/Root | 1
tools/ioemu/fpu/CVS/Tag | 1
tools/ioemu/hw/CVS/Entries | 72
tools/ioemu/hw/CVS/Repository | 1
tools/ioemu/hw/CVS/Root | 1
tools/ioemu/hw/CVS/Tag | 1
tools/ioemu/keymaps/CVS/Entries | 36
tools/ioemu/keymaps/CVS/Repository | 1
tools/ioemu/keymaps/CVS/Root | 1
tools/ioemu/keymaps/CVS/Tag | 1
tools/ioemu/pc-bios/CVS/Entries | 15
tools/ioemu/pc-bios/CVS/Repository | 1
tools/ioemu/pc-bios/CVS/Root | 1
tools/ioemu/pc-bios/CVS/Tag | 1
tools/ioemu/target-i386/CVS/Entries | 13
tools/ioemu/target-i386/CVS/Repository | 1
tools/ioemu/target-i386/CVS/Root | 1
tools/ioemu/target-i386/CVS/Tag | 1
tools/ioemu/tests/CVS/Entries | 18
tools/ioemu/tests/CVS/Repository | 1
tools/ioemu/tests/CVS/Root | 1
tools/ioemu/tests/CVS/Tag | 1
.hgignore | 1
buildconfigs/linux-defconfig_xen0_ia64 | 14
buildconfigs/linux-defconfig_xenU_ia64 | 16
buildconfigs/linux-defconfig_xen_ia64 | 14
docs/figs/acm_ezpolicy.eps | 650 +++++
docs/figs/acm_overview.eps | 1459 +++++++++++
docs/src/user.tex | 982 +++++++
linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c | 1
linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c | 2
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 3
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c | 3
linux-2.6-xen-sparse/drivers/xen/netback/common.h | 16
linux-2.6-xen-sparse/drivers/xen/netback/interface.c | 48
linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 541 +++-
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 27
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 474 ++-
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c | 4
linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c | 3
linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c | 9
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c | 114
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 4
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h | 3
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h | 1
tools/blktap/drivers/blktapctrl.c | 21
tools/firmware/hvmloader/hvmloader.c | 10
tools/firmware/vmxassist/vm86.c | 31
tools/ioemu/.CVS/Entries | 109
tools/ioemu/.CVS/Repository | 1
tools/ioemu/.CVS/Root | 1
tools/ioemu/.CVS/Tag | 1
tools/ioemu/audio/.CVS/Entries | 19
tools/ioemu/audio/.CVS/Repository | 1
tools/ioemu/audio/.CVS/Root | 1
tools/ioemu/audio/.CVS/Tag | 1
tools/ioemu/fpu/.CVS/Entries | 7
tools/ioemu/fpu/.CVS/Repository | 1
tools/ioemu/fpu/.CVS/Root | 1
tools/ioemu/fpu/.CVS/Tag | 1
tools/ioemu/hw/.CVS/Entries | 72
tools/ioemu/hw/.CVS/Repository | 1
tools/ioemu/hw/.CVS/Root | 1
tools/ioemu/hw/.CVS/Tag | 1
tools/ioemu/keymaps/.CVS/Entries | 36
tools/ioemu/keymaps/.CVS/Repository | 1
tools/ioemu/keymaps/.CVS/Root | 1
tools/ioemu/keymaps/.CVS/Tag | 1
tools/ioemu/patches/ioemu-ia64 | 15
tools/ioemu/pc-bios/.CVS/Entries | 15
tools/ioemu/pc-bios/.CVS/Repository | 1
tools/ioemu/pc-bios/.CVS/Root | 1
tools/ioemu/pc-bios/.CVS/Tag | 1
tools/ioemu/target-i386/.CVS/Entries | 13
tools/ioemu/target-i386/.CVS/Repository | 1
tools/ioemu/target-i386/.CVS/Root | 1
tools/ioemu/target-i386/.CVS/Tag | 1
tools/ioemu/tests/.CVS/Entries | 18
tools/ioemu/tests/.CVS/Repository | 1
tools/ioemu/tests/.CVS/Root | 1
tools/ioemu/tests/.CVS/Tag | 1
tools/misc/lomount/lomount.c | 6
tools/python/xen/util/auxbin.py | 4
tools/python/xen/xm/main.py | 4
tools/security/Makefile | 2
tools/security/xensec_ezpolicy | 1628 +++++++++++++
tools/xenstore/Makefile | 4
tools/xenstore/xenstore_client.c | 106
tools/xenstore/xenstored_core.c | 9
tools/xenstore/xenstored_core.h | 1
tools/xenstore/xenstored_transaction.c | 10
tools/xenstore/xsls.c | 103
xen/Makefile | 22
xen/Rules.mk | 7
xen/arch/ia64/xen/dom_fw.c | 14
xen/arch/ia64/xen/domain.c | 5
xen/arch/ia64/xen/xensetup.c | 10
xen/arch/powerpc/boot_of.c | 8
xen/arch/powerpc/domain_build.c | 4
xen/arch/powerpc/mpic_init.c | 1
xen/arch/powerpc/ofd_fixup.c | 4
xen/arch/powerpc/powerpc64/traps.c | 4
xen/arch/x86/dom0_ops.c | 2
xen/arch/x86/domain.c | 2
xen/arch/x86/domain_build.c | 7
xen/arch/x86/hvm/hvm.c | 60
xen/arch/x86/hvm/i8259.c | 4
xen/arch/x86/hvm/io.c | 5
xen/arch/x86/hvm/platform.c | 1
xen/arch/x86/hvm/svm/intr.c | 18
xen/arch/x86/hvm/svm/svm.c | 102
xen/arch/x86/hvm/vioapic.c | 37
xen/arch/x86/hvm/vlapic.c | 557 ++--
xen/arch/x86/hvm/vmx/io.c | 17
xen/arch/x86/hvm/vmx/vmx.c | 111
xen/arch/x86/setup.c | 22
xen/arch/x86/shadow32.c | 6
xen/arch/x86/shadow_public.c | 6
xen/arch/x86/traps.c | 122
xen/arch/x86/x86_32/traps.c | 14
xen/arch/x86/x86_64/traps.c | 16
xen/common/Makefile | 3
xen/common/kernel.c | 16
xen/common/sched_credit.c | 17
xen/common/version.c | 56
xen/drivers/char/Makefile | 3
xen/drivers/char/console.c | 12
xen/include/asm-ia64/vmx_platform.h | 11
xen/include/asm-x86/domain.h | 2
xen/include/asm-x86/hvm/hvm.h | 5
xen/include/asm-x86/hvm/support.h | 4
xen/include/asm-x86/hvm/svm/vmmcall.h | 8
xen/include/asm-x86/hvm/vlapic.h | 113
xen/include/asm-x86/hvm/vmx/vmcs.h | 1
xen/include/asm-x86/hvm/vmx/vmx.h | 2
xen/include/asm-x86/processor.h | 4
xen/include/public/io/netif.h | 8
xen/include/xen/version.h | 16
148 files changed, 7164 insertions(+), 1274 deletions(-)
diff -r 4acc6d51f389 -r b76e86966e7e .hgignore
--- a/.hgignore Tue Aug 01 14:58:20 2006 -0600
+++ b/.hgignore Wed Aug 02 13:39:47 2006 -0600
@@ -156,6 +156,7 @@
^tools/xenstat/xentop/xentop$
^tools/xenstore/testsuite/tmp/.*$
^tools/xenstore/xen$
+^tools/xenstore/xenstore-chmod$
^tools/xenstore/xenstore-exists$
^tools/xenstore/xenstore-list$
^tools/xenstore/xenstore-read$
diff -r 4acc6d51f389 -r b76e86966e7e buildconfigs/linux-defconfig_xen0_ia64
--- a/buildconfigs/linux-defconfig_xen0_ia64 Tue Aug 01 14:58:20 2006 -0600
+++ b/buildconfigs/linux-defconfig_xen0_ia64 Wed Aug 02 13:39:47 2006 -0600
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16.13-xen0
-# Fri Jun 30 12:59:19 2006
+# Fri Jul 28 16:33:47 2006
#
#
@@ -92,6 +92,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_XEN=y
CONFIG_XEN_IA64_DOM0_VP=y
+CONFIG_XEN_IA64_VDSO_PARAVIRT=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_DMA_IS_DMA32=y
# CONFIG_IA64_GENERIC is not set
@@ -180,6 +181,8 @@ CONFIG_ACPI_CONTAINER=y
#
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
@@ -1513,7 +1516,7 @@ CONFIG_XEN_NETDEV_BACKEND=y
CONFIG_XEN_NETDEV_BACKEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_XEN_DEVMEM is not set
-# CONFIG_XEN_REBOOT is not set
+CONFIG_XEN_REBOOT=y
# CONFIG_XEN_SMPBOOT is not set
CONFIG_XEN_INTERFACE_VERSION=0x00030202
@@ -1523,13 +1526,16 @@ CONFIG_XEN_PRIVILEGED_GUEST=y
CONFIG_XEN_PRIVILEGED_GUEST=y
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
CONFIG_XEN_BACKEND=y
-# CONFIG_XEN_PCIDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_BACKEND=y
-CONFIG_XEN_XENBUS_DEV=y
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_NETDEV_LOOPBACK=y
+CONFIG_XEN_PCIDEV_BACKEND=y
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
# CONFIG_XEN_SCRUB_PAGES is not set
diff -r 4acc6d51f389 -r b76e86966e7e buildconfigs/linux-defconfig_xenU_ia64
--- a/buildconfigs/linux-defconfig_xenU_ia64 Tue Aug 01 14:58:20 2006 -0600
+++ b/buildconfigs/linux-defconfig_xenU_ia64 Wed Aug 02 13:39:47 2006 -0600
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16.13-xenU
-# Mon May 22 15:05:32 2006
+# Fri Jul 28 16:32:18 2006
#
#
@@ -89,6 +89,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_XEN=y
CONFIG_XEN_IA64_DOM0_VP=y
+CONFIG_XEN_IA64_VDSO_PARAVIRT=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_DMA_IS_DMA32=y
# CONFIG_IA64_GENERIC is not set
@@ -177,6 +178,8 @@ CONFIG_ACPI_SYSTEM=y
#
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
@@ -1380,8 +1383,15 @@ CONFIG_CRYPTO_DES=y
#
# Hardware crypto devices
#
+# CONFIG_XEN_UTIL is not set
CONFIG_HAVE_ARCH_ALLOC_SKB=y
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_XEN_DEVMEM is not set
+CONFIG_XEN_REBOOT=y
+# CONFIG_XEN_SMPBOOT is not set
CONFIG_XEN_INTERFACE_VERSION=0x00030202
#
@@ -1389,13 +1399,15 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
#
# CONFIG_XEN_PRIVILEGED_GUEST is not set
CONFIG_XEN_UNPRIVILEGED_GUEST=y
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
# CONFIG_XEN_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_XEN_SCRUB_PAGES is not set
# CONFIG_XEN_DISABLE_SERIAL is not set
CONFIG_XEN_SYSFS=y
CONFIG_XEN_COMPAT_030002_AND_LATER=y
# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
CONFIG_NO_IDLE_HZ=y
diff -r 4acc6d51f389 -r b76e86966e7e buildconfigs/linux-defconfig_xen_ia64
--- a/buildconfigs/linux-defconfig_xen_ia64 Tue Aug 01 14:58:20 2006 -0600
+++ b/buildconfigs/linux-defconfig_xen_ia64 Wed Aug 02 13:39:47 2006 -0600
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16.13-xen
-# Thu Jun 29 16:23:48 2006
+# Fri Jul 28 16:33:08 2006
#
#
@@ -92,6 +92,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_XEN=y
CONFIG_XEN_IA64_DOM0_VP=y
+CONFIG_XEN_IA64_VDSO_PARAVIRT=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_DMA_IS_DMA32=y
# CONFIG_IA64_GENERIC is not set
@@ -180,6 +181,8 @@ CONFIG_ACPI_CONTAINER=y
#
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
@@ -1519,7 +1522,7 @@ CONFIG_XEN_NETDEV_BACKEND=y
CONFIG_XEN_NETDEV_BACKEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_XEN_DEVMEM is not set
-# CONFIG_XEN_REBOOT is not set
+CONFIG_XEN_REBOOT=y
# CONFIG_XEN_SMPBOOT is not set
CONFIG_XEN_INTERFACE_VERSION=0x00030202
@@ -1529,13 +1532,16 @@ CONFIG_XEN_PRIVILEGED_GUEST=y
CONFIG_XEN_PRIVILEGED_GUEST=y
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
CONFIG_XEN_BACKEND=y
-# CONFIG_XEN_PCIDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_BACKEND=y
-CONFIG_XEN_XENBUS_DEV=y
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_NETDEV_LOOPBACK=y
+CONFIG_XEN_PCIDEV_BACKEND=y
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
# CONFIG_XEN_SCRUB_PAGES is not set
diff -r 4acc6d51f389 -r b76e86966e7e docs/src/user.tex
--- a/docs/src/user.tex Tue Aug 01 14:58:20 2006 -0600
+++ b/docs/src/user.tex Wed Aug 02 13:39:47 2006 -0600
@@ -2059,6 +2059,988 @@ iptables:
# this command disables all access to the Xen relocation port
iptables -A INPUT -p tcp -{}-destination-port 8002 -j REJECT
\end{verbatim}
+
+%% Chapter Xen Mandatory Access Control Framework
+\chapter{sHype/Xen Access Control}
+
+The Xen mandatory access control framework is an implementation of the
+sHype Hypervisor Security Architecture
+(www.research.ibm.com/ssd\_shype). It permits or denies communication
+and resource access of domains based on a security policy. The
+mandatory access controls are enforced in addition to the Xen core
+controls, such as memory protection. They are designed to remain
+transparent during normal operation of domains (policy-conform
+behavior) but to intervene when domains move outside their intended
+sharing behavior. This chapter will describe how the sHype access
+controls in Xen can be configured to prevent viruses from spilling
+over from one into another workload type and secrets from leaking from
+one workload type to another. sHype/Xen depends on the correct
+behavior of Domain0 (cf previous chapter).
+
+Benefits of configuring sHype/ACM in Xen include:
+\begin{itemize}
+\item robust workload and resource protection effective against rogue
+ user domains
+\item simple, platform- and operating system-independent security
+ policies (ideal for heterogeneous distributed environments)
+\item safety net with minimal performance overhead in case operating
+ system security is missing, does not scale, or fails
+\end{itemize}
+
+These benefits are very valuable because today's operating systems
+become increasingly complex and often have no or insufficient
+mandatory access controls. (Discretionary access controls, supported
+by of most operating systems, are not effective against viruses or
+misbehaving programs.) Where mandatory access control exists (e.g.,
+SELinux), they usually deploy complex and difficult to understand
+security policies. Additionally, multi-tier applications in business
+environments usually require different types of operating systems
+(e.g., AIX, Windows, Linux) which cannot be configured with compatible
+security policies. Related distributed transactions and workloads
+cannot be easily protected on the OS level. The Xen access control
+framework steps in to offer a coarse-grained but very robust security
+layer and safety net in case operating system security fails or is
+missing.
+
+To control sharing between domains, Xen mediates all inter-domain
+communication (shared memory, events) as well as the access of domains
+to resources such as disks. Thus, Xen can confine distributed
+workloads (domain payloads) by permitting sharing among domains
+running the same type of workload and denying sharing between pairs of
+domains that run different workload types. We assume that--from a Xen
+perspective--only one workload type is running per user domain. To
+enable Xen to associate domains and resources with workload types,
+security labels including the workload types are attached to domains
+and resources. These labels and the hypervisor sHype controls cannot
+be manipulated or bypassed and are effective even against rogue
+domains.
+
+\section{Overview}
+This section gives an overview of how workloads can be protected using
+the sHype mandatory access control framework in Xen.
+Figure~\ref{fig:acmoverview} shows the necessary steps in activating
+the Xen workload protection. These steps are described in detail in
+Section~\ref{section:acmexample}.
+
+\begin{figure}
+\centering
+\includegraphics[width=13cm]{figs/acm_overview.eps}
+\caption{Overview of activating sHype workload protection in Xen.
+ Section numbers point to representative examples.}
+\label{fig:acmoverview}
+\end{figure}
+
+First, the sHype/ACM access control must be enabled in the Xen
+distribution and the distribution must be built and installed (cf
+Subsection~\ref{subsection:acmexampleconfigure}). Before we can
+enforce security, a Xen security policy must be created (cf
+Subsection~\ref{subsection:acmexamplecreate}) and deployed (cf
+Subsection~\ref{subsection:acmexampleinstall}). This policy defines
+the workload types differentiated during access control. It also
+defines the rules that compare workload types of domains and resources
+to provide access decisions. Workload types are represented by
+security labels that can be attached to domains and resources (cf
+Subsections~\ref{subsection:acmexamplelabeldomains}
+and~\ref{subsection:acmexamplelabelresources}). The functioning of
+the active sHype/Xen workload protection is demonstrated using simple
+resource assignment, and domain creation tests in
+Subsection~\ref{subsection:acmexampletest}.
+Section~\ref{section:acmpolicy} describes the syntax and semantics of
+the sHype/Xen security policy in detail and introduces briefly the
+tools that are available to help create valid security policies.
+
+The next section describes all the necessary steps to create, deploy,
+and test a simple workload protection policy. It is meant to enable
+anybody to quickly try out the sHype/Xen workload protection. Those
+readers who are interested in learning more about how the sHype access
+control in Xen works and how it is configured using the XML security
+policy should read Section~\ref{section:acmpolicy} as well.
+Section~\ref{section:acmlimitations} concludes this chapter with
+current limitations of the sHype implementation for Xen.
+
+\section{Xen Workload Protection Step-by-Step}
+\label{section:acmexample}
+
+What you are about to do consists of the following sequence:
+\begin{itemize}
+\item configure and install sHype/Xen
+\item create a simple workload protection security policy
+\item deploy the sHype/Xen security policy
+\item associate domains and resources with workload labels,
+\item test the workload protection
+\end{itemize}
+The essential commands to create and deploy a sHype/Xen security
+policy are numbered throughout the following sections. If you want a
+quick-guide or return at a later time to go quickly through this
+demonstration, simply look for the numbered commands and apply them in
+order.
+
+\subsection{Configuring/Building sHype Support into Xen}
+\label{subsection:acmexampleconfigure}
+First, we need to configure the access control module in Xen and
+install the ACM-enabled Xen hypervisor. This step installs security
+tools and compiles sHype/ACM controls into the Xen hypervisor.
+
+To enable sHype/ACM in Xen, please edit the Config.mk file in the top
+Xen directory.
+
+\begin{verbatim}
+ (1) In Config.mk
+ Change: ACM_SECURITY ?= n
+ To: ACM_SECURITY ?= y
+\end{verbatim}
+
+Then install the security-enabled Xen environment as follows:
+
+\begin{verbatim}
+ (2) # make world
+ # make install
+\end{verbatim}
+
+\subsection{Creating A WLP Policy in 3 Simple Steps with ezPolicy}
+\label{subsection:acmexamplecreate}
+
+We will use the ezPolicy tool to quickly create a policy that protects
+workloads. You will need both the Python and wxPython packages to run
+this tool. To run the tool in Domain0, you can download the wxPython
+package from www.wxpython.org or use the command
+\verb|yum install wxPython| in Redhat/Fedora. To run the tool on MS
+Windows, you also need to download the Python package from
+www.python.org. After these packages are installed, start the ezPolicy
+tool with the following command:
+
+\begin{verbatim}
+ (3) # xensec_ezpolicy
+\end{verbatim}
+
+Figure~\ref{fig:acmezpolicy} shows a screen-shot of the tool. The
+following steps show you how to create the policy shown in
+Figure~\ref{fig:acmezpolicy}. You can use \verb|<CTRL>-h| to pop up a
+help window at any time. The indicators (a), (b), and (c) in
+Figure~\ref{fig:acmezpolicy} show the buttons that are used during the
+3 steps of creating a policy:
+\begin{enumerate}
+\item defining workloads
+\item defining run-time conflicts
+\item translating the workload definition into a sHype/Xen access
+ control policy
+\end{enumerate}
+
+\paragraph{Defining workloads.} Workloads are defined for each
+organization and department that you enter in the left panel. Please
+use the ``New Org'' button (a) to create the organizations ``Avis'',
+``Hertz'', ``CocaCola'', and ``PepsiCo''.
+
+You can refine an organization to differentiate between multiple
+department workloads by right-clicking the organization and selecting
+\verb|Add Department| (or selecting an organization and pressing
+\verb|<CRTL>-a|). Create department workloads ``Intranet'',
+``Extranet'', ``HumanResources'', and ``Payroll'' for the ``CocaCola''
+organization and department workloads ``Intranet'' and ``Extranet''
+for the ``PepsiCo'' organization. The resulting layout of the tool
+should be similar to the left panel shown in
+Figure~\ref{fig:acmezpolicy}.
+
+\paragraph{Defining run-time conflicts.} Workloads that shall be
+prohibited from running concurrently on the same hypervisor platform
+are grouped into ``Run-time Exclusion rules'' on the right panel of
+the window.
+
+To prevent PepsiCo and CocaCola workloads (including their
+departmental workloads) from running simultaneously on the same
+hypervisor system, select the organization ``PepsiCo'' and, while
+pressing the \verb|<CTRL>|-key, select the organization ``CocaCola''.
+Now press the button (b) named ``Create run-time exclusion rule from
+selection''. A popup window will ask for the name for this run-time
+exclusion rule (enter a name or just hit \verb|<ENTER>|). A rule will
+appear on the right panel. The name is used as reference only and does
+not affect the hypervisor policy.
+
+Repeat the process to create a run-time exclusion rule just for the
+department workloads CocaCola.Extranet and CocaCola.Payroll.
+
+\begin{figure}[htb]
+\centering
+\includegraphics[width=13cm]{figs/acm_ezpolicy.eps}
+\caption{Final layout including workload definition and Run-time Exclusion
rules.}
+\label{fig:acmezpolicy}
+\end{figure}
+
+The resulting layout of your window should be similar to
+Figure~\ref{fig:acmezpolicy}. Save this workload definition by
+selecting ``Save Workload Definition as ...'' in the ``File'' menu
+(c). This workload definition can be later refined if required.
+
+\paragraph{Translating the workload definition into a sHype/Xen access
+ control policy.} To translate the workload definition into a access
+control policy understood by Xen, please select the ``Save as Xen ACM
+Security Policy'' in the ``File'' menu (c). Enter the following policy
+name in the popup window: \verb|example.chwall_ste.test-wld|. If you
+are running ezPolicy in Domain0, the resulting policy file
+test-wld\_security-policy.xml will automatically be placed into the
+right directory (/etc/xen/acm-security/ policies/example/chwall\_ste).
+If you run the tool on another system, then you need to copy the
+resulting policy file into Domain0 before continuing. See
+Section~\ref{subsection:acmnaming} for naming conventions of security
+policies.
+
+\subsection{Deploying a WLP Policy}
+\label{subsection:acmexampleinstall}
+To deploy the workload protection policy we created in
+Section~\ref{subsection:acmexamplecreate}, we create a policy
+representation (test-wld.bin) that can be loaded into the Xen
+hypervisor and we configure Xen to actually load this policy at
+startup time.
+
+The following command translates the source policy representation
+into a format that can be loaded into Xen with sHype/ACM support.
+Refer to the \verb|xm| man page for further details:
+
+\begin{verbatim}
+ (4) # xm makepolicy example.chwall_ste.test-wld
+\end{verbatim}
+
+The easiest way to install a security policy for Xen is to include the
+policy in the boot sequence. The following command does just this:
+
+\begin{verbatim}
+ (5) # xm cfgbootpolicy example.chwall_ste.test-wld
+\end{verbatim}
+
+\textit{Alternatively, if this command fails} (e.g., because it cannot
+identify the Xen boot entry), you can manually install the policy in 2
+steps. First, manually copy the policy binary file into the boot
+directory:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # cp /etc/xen/acm-security/policies/example/chwall_ste/test-wld.bin \
+ /boot/example.chwall_ste.test-wld.bin
+\end{verbatim}
+\end{scriptsize}
+
+Second, manually add a module line to your Xen boot entry so that grub
+loads this policy file during startup:
+
+\begin{scriptsize}
+\begin{verbatim}
+ title Xen (2.6.16.13)
+ root (hd0,0)
+ kernel /xen.gz dom0_mem=2000000 console=vga
+ module /vmlinuz-2.6.16.13-xen ro root=/dev/hda3
+ module /initrd-2.6.16.13-xen.img
+ module /example.chwall_ste.test-wld.bin
+\end{verbatim}
+\end{scriptsize}
+
+Now reboot into this Xen boot entry to activate the policy and the
+security-enabled Xen hypervisor.
+
+\begin{verbatim}
+ (6) # reboot
+\end{verbatim}
+
+After reboot, check if security is enabled:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # xm list --label
+ Name ID Mem(MiB) VCPUs State Time(s) Label
+ Domain-0 0 1949 4 r----- 163.9 SystemManagement
+\end{verbatim}
+\end{scriptsize}
+
+If the security label at the end of the line says ``INACTIV'' then the
+security is not enabled. Verify the previous steps. Note: Domain0 is
+assigned a default label (see \verb|bootstrap| policy attribute
+explained in Section~\ref{section:acmpolicy}). All other domains must
+be labeled in order to start on this sHype/ACM-enabled Xen hypervisor
+(see following sections for labeling domains and resources).
+
+\subsection{Labeling Domains}
+\label{subsection:acmexamplelabeldomains}
+You should have a Xen domain configuration file that looks like the
+following (Note: www.jailtime.org or www.xen-get.org might be good
+places to look for example domU images). The following configuration
+file defines \verb|domain1|:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # cat domain1.xm
+ kernel = "/boot/vmlinuz-2.6.16.13-xen"
+ memory = 128
+ name = "domain1"
+ vif = [ '' ]
+ dhcp = "dhcp"
+ disk = ['file:/home/xen/dom_fc5/fedora.fc5.img,sda1,w', \
+ 'file:/home/xen/dom_fc5/fedora.swap,sda2,w']
+ root = "/dev/sda1 ro"
+\end{verbatim}
+\end{scriptsize}
+
+If you try to start domain1, you will get the following error:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # xm create domain1.xm
+ Using config file "domain1.xm".
+ domain1: DENIED
+ --> Domain not labeled
+ Checking resources: (skipped)
+ Security configuration prevents domain from starting
+\end{verbatim}
+\end{scriptsize}
+
+Every domain must be associated with a security label before it can
+start on sHype/Xen. Otherwise, sHype/Xen would not be able to enforce
+the policy consistently. The following command prints all domain
+labels available in the active policy:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # xm labels type=dom
+ Avis
+ CocaCola
+ CocaCola.Extranet
+ CocaCola.HumanResources
+ CocaCola.Intranet
+ CocaCola.Payroll
+ Hertz
+ PepsiCo
+ PepsiCo.Extranet
+ PepsiCo.Intranet
+ SystemManagement
+\end{verbatim}
+\end{scriptsize}
+
+Now label domain1 with the CocaCola label and another domain2 with the
+PepsiCo.Extranet label. Please refer to the xm man page for further
+information.
+
+\begin{verbatim}
+ (7) # xm addlabel CocaCola dom domain1.xm
+ # xm addlabel PepsiCo.Extranet dom domain2.xm
+\end{verbatim}
+
+Let us try to start the domain again:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # xm create domain1.xm
+ Using config file "domain1.xm".
+ file:/home/xen/dom_fc5/fedora.fc5.img: DENIED
+ --> res:__NULL_LABEL__ (NULL)
+ --> dom:CocaCola (example.chwall_ste.test-wld)
+ file:/home/xen/dom_fc5/fedora.swap: DENIED
+ --> res:__NULL_LABEL__ (NULL)
+ --> dom:CocaCola (example.chwall_ste.test-wld)
+ Security configuration prevents domain from starting
+\end{verbatim}
+\end{scriptsize}
+
+This error indicates that domain1, if started, would not be able to
+access its image and swap files because they are not labeled. This
+makes sense because to confine workloads, access of domains to
+resources must be controlled. Otherwise, domains that are not allowed
+to communicate or run simultaneously could share data through storage
+resources.
+
+\subsection{Labeling Resources}
+\label{subsection:acmexamplelabelresources}
+You can use the \verb|xm labels type=res| command to list available
+resource labels. Let us assign the CocaCola resource label to the domain1
+image file representing \verb|/dev/sda1| and to its swap file:
+
+\begin{verbatim}
+ (8) # xm addlabel CocaCola res \
+ file:/home/xen/dom_fc5/fedora.fc5.img
+ Resource file not found, creating new file at:
+ /etc/xen/acm-security/policies/resource_labels
+ # xm addlabel CocaCola res \
+ file:/home/xen/dom_fc5/fedora.swap
+\end{verbatim}
+
+Starting \verb|domain1| now will succeed:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # xm create domain1.xm
+ # xm list --label
+ Name ID Mem(MiB) VCPUs State Time(s) Label
+ domain1 1 128 1 r----- 2.8 CocaCola
+ Domain-0 0 1949 4 r----- 387.7 SystemManagement
+\end{verbatim}
+\end{scriptsize}
+
+The following command lists all labeled resources on the
+system, e.g., to lookup or verify the labeling:
+
+\begin{scriptsize}
+\begin{verbatim}
+ # xm resources
+ file:/home/xen/dom_fc5/fedora.swap
+ policy: example.chwall_ste.test-wld
+ label: CocaCola
+ file:/home/xen/dom_fc5/fedora.fc5.img
+ policy: example.chwall_ste.test-wld
+ label: CocaCola
+\end{verbatim}
+\end{scriptsize}
+
+Currently, if a labeled resource is moved to another location, the
+label must first be manually removed, and after the move re-attached
+using the xm commands \verb|xm rmlabel| and \verb|xm addlabel|
+respectively. Please see Section~\ref{section:acmlimitations} for
+further details.
+
+\begin{verbatim}
+ (9) Label the resources of domain2 as PepsiCo.Extranet
+ Do not try to start this domain yet
+\end{verbatim}
+
+\subsection{Testing The Xen Workload Protection}
+\label{subsection:acmexampletest}
+We are about to demonstrate how the workload protection works by
+verifying:
+\begin{itemize}
+\item that domains with conflicting workloads cannot run
+ simultaneously
+\item that domains cannot access resources of other workloads
+\item that domains cannot exchange network packets if they are not
+ associated with the same workload type
+\end{itemize}
+
+\paragraph{Test 1: Run-time exclusion rules.} We assume that domain1
+with the CocaCola label is still running. While domain1 is running,
+the run-time exclusion set of our policy says that domain2 cannot
+start because the label of domain1 includes the CHWALL type CocaCola
+and the label of domain2 includes the CHWALL type PepsiCo. The
+run-time exclusion rule of our policy enforces that PepsiCo and
+CocaCola cannot run at the same time on the same hypervisor platform.
+Once domain1 is stopped or saved, domain2 can start but domain1 can no
+longer start or be resumed. The ezPolicy tool, when creating the
+Chinese Wall types for the workload labels, ensures that department
+workloads inherit the organization type (and with it any organization
+exclusions).
+
+\begin{scriptsize}
+\begin{verbatim}
+# xm list --label
+Name ID Mem(MiB) VCPUs State Time(s) Label
+domain1 2 128 1 -b---- 6.9 CocaCola
+Domain-0 0 1949 4 r----- 273.1 SystemManagement
+
+# xm create domain2.xm
+Using config file "domain2.xm".
+Error: (1, 'Operation not permitted')
+
+# xm destroy domain1
+# xm create domain2.xm
+Using config file "domain2.xm".
+Started domain domain2
+
+# xm list --label
+Name ID Mem(MiB) VCPUs State Time(s) Label
+domain2 4 164 1 r----- 4.3 PepsiCo.Extranet
+Domain-0 0 1949 4 r----- 298.4 SystemManagement
+
+# xm create domain1.xm
+Using config file "domain1.xm".
+Error: (1, 'Operation not permitted')
+
+# xm destroy domain2
+# xm list
+Name ID Mem(MiB) VCPUs State Time(s)
+Domain-0 0 1949 4 r----- 391.2
+\end{verbatim}
+\end{scriptsize}
+
+You can verify that domains with Avis label can run together with
+domains labeled CocaCola, PepsiCo, or Hertz.
+
+\paragraph{Test2: Resource access.} In this test, we will re-label the
+swap file for domain1 with the Avis resource label. We expect that
+Domain1 will no longer start because it cannot access this resource.
+This test checks the sharing abilities of domains, which are defined
+by the Simple Type Enforcement Policy component.
+
+\begin{scriptsize}
+\begin{verbatim}
+# xm rmlabel res file:/home/xen/dom_fc5/fedora.swap
+# xm addlabel Avis res file:/home/xen/dom_fc5/fedora.swap
+# xm resources
+file:/home/xen/dom_fc5/fedora.swap
+ policy: example.chwall_ste.test-wld
+ label: Avis
+file:/home/xen/dom_fc5/fedora.fc5.img
+ policy: example.chwall_ste.test-wld
+ label: CocaCola
+
+# xm create domain1.xm
+Using config file "domain1.xm".
+ file:/home/xen/dom_fc4/fedora.swap: DENIED
+ --> res:Avis (example.chwall_ste.test-wld)
+ --> dom:CocaCola (example.chwall_ste.test-wld)
+Security configuration prevents domain from starting
+\end{verbatim}
+\end{scriptsize}
+
+\paragraph{Test 3: Communication.} In this test we would verify that
+two domains with labels Hertz and Avis cannot exchange network packets
+by using the 'ping' connectivity test. It is also related to the STE
+policy.{\bf Note:} sHype/Xen does control direct communication between
+domains. However, domains associated with different workloads can
+currently still communicate through the Domain0 virtual network. We
+are working on the sHype/ACM controls for local and remote network
+traffic through Domain0. Please monitor the xen-devel mailing list
+for updated information.
+
+\section{Xen Access Control Policy}
+\label{section:acmpolicy}
+
+This section describes the sHype/Xen access control policy in detail.
+It gives enough information to enable the reader to write custom
+access control policies and to use the available Xen policy tools. The
+policy language is expressive enough to specify most symmetric access
+relationships between domains and resources efficiently.
+
+The Xen access control policy consists of two policy components. The
+first component, called Chinese Wall (CHWALL) policy, controls which
+domains can run simultaneously on the same virtualized platform. The
+second component, called Simple Type Enforcement (STE) policy,
+controls the sharing between running domains, i.e., communication or
+access to shared resources. The CHWALL and STE policy components can
+be configured to run alone, however in our examples we will assume
+that both policy components are configured together since they
+complement each other. The XML policy file includes all information
+needed by Xen to enforce the policies.
+
+Figures~\ref{fig:acmxmlfilea} and \ref{fig:acmxmlfileb} show a fully
+functional but very simple example policy for Xen. The policy can
+distinguish two workload types \verb|CocaCola| and \verb|PepsiCo| and
+defines the labels necessary to associate domains and resources with
+one of these workload types. The XML Policy consists of four parts:
+\begin{enumerate}
+\item policy header including the policy name
+\item Simple Type Enforcement block
+\item Chinese Wall Policy block
+\item label definition block
+\end{enumerate}
+
+\begin{figure}
+\begin{scriptsize}
+\begin{verbatim}
+01 <?xml version="1.0" encoding="UTF-8"?>
+02 <!-- Auto-generated by ezPolicy -->
+03 <SecurityPolicyDefinition
+ xmlns="http://www.ibm.com"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=
+ "http://www.ibm.com ../../security_policy.xsd ">
+04 <PolicyHeader>
+05 <PolicyName>example.chwall_ste.test</PolicyName>
+06 <Date>Wed Jul 12 17:32:59 2006</Date>
+07 </PolicyHeader>
+08
+09 <SimpleTypeEnforcement>
+10 <SimpleTypeEnforcementTypes>
+11 <Type>SystemManagement</Type>
+12 <Type>PepsiCo</Type>
+13 <Type>CocaCola</Type>
+14 </SimpleTypeEnforcementTypes>
+15 </SimpleTypeEnforcement>
+16
+17 <ChineseWall priority="PrimaryPolicyComponent">
+18 <ChineseWallTypes>
+19 <Type>SystemManagement</Type>
+20 <Type>PepsiCo</Type>
+21 <Type>CocaCola</Type>
+22 </ChineseWallTypes>
+23
+24 <ConflictSets>
+25 <Conflict name="RER1">
+26 <Type>CocaCola</Type>
+27 <Type>PepsiCo</Type>
+28 </Conflict>
+29 </ConflictSets>
+30 </ChineseWall>
+31
+\end{verbatim}
+\end{scriptsize}
+\caption{Example XML security policy file -- Part I: Types and Rules
Definition.}
+\label{fig:acmxmlfilea}
+\end{figure}
+
+\subsection{Policy Header and Policy Name}
+\label{subsection:acmnaming}
+Lines 1-2 (cf Figure~\ref{fig:acmxmlfilea}) include the usual XML
+header. The security policy definition starts in Line 3 and refers to
+the policy schema. The XML-Schema definition for the Xen policy can be
+found in the file
+\textit{/etc/xen/acm-security/policies/security-policy.xsd}. Examples
+for security policies can be found in the example subdirectory. The
+acm-security directory is only installed if ACM security is configured
+during installation (cf Section~\ref{subsection:acmexampleconfigure}).
+
+The \verb|Policy Header| spans lines 4-7. It includes a date field and
+defines the policy name \verb|example.chwall_ste.test|. It can also
+include optional fields that are not shown and are for future use (see
+schema definition).
+
+The policy name serves two purposes: First, it provides a unique name
+for the security policy. This name is also exported by the Xen
+hypervisor to the Xen management tools in order to ensure that both
+enforce the same policy. We plan to extend the policy name with a
+digital fingerprint of the policy contents to better protect this
+correlation. Second, it implicitly points the xm tools to the
+location where the XML policy file is stored on the Xen system.
+Replacing the colons in the policy name by slashes yields the local
+path to the policy file starting from the global policy directory
+\verb|/etc/xen/acm-security/policies|. The last part of the policy
+name is the prefix for the XML policy file name, completed by
+\verb|-security_policy.xml|. Consequently, the policy with the name
+\verb|example.chwall_ste.test| can be found in the XML policy file
+named \verb|test-security_policy.xml| that is stored in the local
+directory \verb|example/chwall_ste| under the global policy directory.
+
+\subsection{Simple Type Enforcement Policy Component}
+
+The Simple Type Enforcement (STE) policy controls which domains can
+communicate or share resources. This way, Xen can enforce confinement
+of workload types by confining the domains running those workload
+types. The mandatory access control framework enforces its policy when
+domains access intended ways of communication or cooperation (shared
+memory, events, shared resources such as block devices). It builds on
+top of the core hypervisor isolation, which restricts the ways of
+inter-communication to those intended means. STE does not protect or
+intend to protect from covert channels in the hypervisor or hardware;
+this is an orthogonal problem that can be mitigated by using the
+Run-time Exclusion rules described above or by fixing the problem in
+the core hypervisor.
+
+Xen controls sharing between domains on the resource and domain level
+because this is the abstraction the hypervisor and its management
+understand naturally. While this is coarse-grained, it is also very
+reliable and robust and it requires minimal changes to implement
+mandatory access controls in the hypervisor. It enables platform- and
+operation system-independent policies as part of a layered security
+approach.
+
+Lines 9-15 (cf Figure~\ref{fig:acmxmlfilea}) define the Simple Type
+Enforcement policy component. Essentially, they define the workload
+type names \verb|SystemManagement|, \verb|PepsiCo|, and
+\verb|CocaCola| that are available in the STE policy component. The
+policy rules are implicit: Xen permits a domain to communicate with
+another domain if and only if the labels of the domains share an
+common STE type. Xen permits a domain to access a resource if and
+only if the labels of the domain and the resource share a common STE
+workload type.
+
+\subsection{Chinese Wall Policy Component}
+
+The Chinese Wall security policy interpretation of sHype enables users
+to prevent certain workloads from running simultaneously on the same
+hypervisor platform. Run-time Exclusion rules (RER), also called
+Conflict Sets, define a set of workload types that are not permitted
+to run simultaneously. Of all the workloads specified in a Run-time
+Exclusion rule, at most one type can run on the same hypervisor
+platform at a time. Run-time Exclusion Rules implement a less
+rigorous variant of the original Chinese Wall security component. They
+do not implement the *-property of the policy, which would require to
+restrict also types that are not part of an exclusion rule once they
+are running together with a type in an exclusion rule (please refer to
+http://www.gammassl.co.uk/topics/chinesewall.html for more information
+on the original Chinese Wall policy).
+
+Xen considers the \verb|ChineseWallTypes| part of the label for the
+enforcement of the Run-time Exclusion rules. It is illegal to define
+labels including conflicting Chinese Wall types.
+
+Lines 17-30 (cf Figure~\ref{fig:acmxmlfilea}) define the Chinese Wall
+policy component. Lines 17-22 define the known Chinese Wall types,
+which coincide here with the STE types defined above. This usually
+holds if the criteria for sharing among domains and sharing of the
+hardware platform are the same. Lines 24-29 define one Run-time
+Exclusion rule:
+
+\begin{scriptsize}
+\begin{verbatim}
+ <Conflict name="RER1">
+ <Type>CocaCola</Type>
+ <Type>PepsiCo</Type>
+ </Conflict>
+\end{verbatim}
+\end{scriptsize}
+
+Based on this rule, Xen enforces that only one of the types
+\verb|CocaCola| or \verb|PepsiCo| will run on a single hypervisor
+platform at a time. For example, once a domain assigned a
+\verb|CocaCola| workload type is started, domains with the
+\verb|PepsiCo| type will be denied to start. When the former domain
+stops and no other domains with the \verb|CocaCola| type are running,
+then domains with the \verb|PepsiCo| type can start.
+
+Xen maintains reference counts on each running workload type to keep
+track of which workload types are running. Every time a domain starts
+or resumes, the reference count on those Chinese Wall types that are
+referenced in the domain's label are incremented. Every time a domain
+is destroyed or saved, the reference counts of its Chinese Wall types
+are decremented. sHype in Xen covers migration and live-migration,
+which is treated the same way as saving a domain on the source
+platform and resuming it on the destination platform.
+
+Reasons why users would want to restrict which workloads or domains
+can share the system hardware include:
+
+\begin{itemize}
+\item Imperfect resource management or control might enable a rogue
+ domain to starve another domain and the workload running in it.
+\item Redundant domains might run the same workload to increase
+ availability; such domains should not run on the same hardware to
+ avoid single points of failure.
+\item Imperfect Xen core domain isolation might enable two rogue
+ domains running different workload types to use unintended and
+ unknown ways (covert channels) to exchange some data. This way, they
+ bypass the policed Xen access control mechanisms. Such
+ imperfections cannot be completely eliminated and are a result of
+ trade-offs between security and other design requirements. For a
+ simple example of a covert channel see
+ http://www.multicians.org/timing-chn.html. Such covert channels
+ exist also between workloads running on different platforms if they
+ are connected through networks. The Xen Chinese Wall policy provides
+ an approximation of this imperfect ``air-gap'' between selected
+ workload types.
+\end{itemize}
+
+\subsection{Security Labels}
+
+To enable Xen to associate domains with workload types running in
+them, each domain is assigned a security label that includes the
+workload types of the domain.
+
+\begin{figure}
+\begin{scriptsize}
+\begin{verbatim}
+32 <SecurityLabelTemplate>
+33 <SubjectLabels bootstrap="SystemManagement">
+34 <VirtualMachineLabel>
+35 <Name>SystemManagement</Name>
+36 <SimpleTypeEnforcementTypes>
+37 <Type>SystemManagement</Type>
+38 <Type>PepsiCo</Type>
+39 <Type>CocaCola</Type>
+40 </SimpleTypeEnforcementTypes>
+41 <ChineseWallTypes>
+42 <Type>SystemManagement</Type>
+43 </ChineseWallTypes>
+44 </VirtualMachineLabel>
+45
+46 <VirtualMachineLabel>
+47 <Name>PepsiCo</Name>
+48 <SimpleTypeEnforcementTypes>
+49 <Type>PepsiCo</Type>
+50 </SimpleTypeEnforcementTypes>
+51 <ChineseWallTypes>
+52 <Type>PepsiCo</Type>
+53 </ChineseWallTypes>
+54 </VirtualMachineLabel>
+55
+56 <VirtualMachineLabel>
+57 <Name>CocaCola</Name>
+58 <SimpleTypeEnforcementTypes>
+59 <Type>CocaCola</Type>
+60 </SimpleTypeEnforcementTypes>
+61 <ChineseWallTypes>
+62 <Type>CocaCola</Type>
+63 </ChineseWallTypes>
+64 </VirtualMachineLabel>
+65 </SubjectLabels>
+66
+67 <ObjectLabels>
+68 <ResourceLabel>
+69 <Name>SystemManagement</Name>
+70 <SimpleTypeEnforcementTypes>
+71 <Type>SystemManagement</Type>
+72 </SimpleTypeEnforcementTypes>
+73 </ResourceLabel>
+74
+75 <ResourceLabel>
+76 <Name>PepsiCo</Name>
+77 <SimpleTypeEnforcementTypes>
+78 <Type>PepsiCo</Type>
+79 </SimpleTypeEnforcementTypes>
+80 </ResourceLabel>
+81
+82 <ResourceLabel>
+83 <Name>CocaCola</Name>
+84 <SimpleTypeEnforcementTypes>
+85 <Type>CocaCola</Type>
+86 </SimpleTypeEnforcementTypes>
+87 </ResourceLabel>
+88 </ObjectLabels>
+89 </SecurityLabelTemplate>
+90 </SecurityPolicyDefinition>
+\end{verbatim}
+\end{scriptsize}
+\caption{Example XML security policy file -- Part II: Label Definition.}
+\label{fig:acmxmlfileb}
+\end{figure}
+
+Lines 32-89 (cf Figure~\ref{fig:acmxmlfileb}) define the
+\verb|SecurityLabelTemplate|, which includes the labels that can be
+attached to domains and resources when this policy is active. The
+domain labels include Chinese Wall types while resource labels do not
+include Chinese Wall types. Lines 33-65 define the
+\verb|SubjectLabels| that can be assigned to domains. For example, the
+virtual machine label \verb|CocaCola| (cf lines 56-64 in
+Figure~\ref{fig:acmxmlfileb}) associates the domain that carries it
+with the workload type \verb|CocaCola|.
+
+The \verb|bootstrap| attribute names the label
+\verb|SystemManagement|. Xen will assign this label to Domain0 at
+boot time. All other domains are assigned labels according to their
+domain configuration file (see
+Section~\ref{subsection:acmexamplelabeldomains} for examples of how to
+label domains). Lines 67-88 define the \verb|ObjectLabels|. Those
+labels can be assigned to resources when this policy is active.
+
+In general, user domains should be assigned labels that have only a
+single SimpleTypeEnforcement workload type. This way, workloads remain
+confined even if user domains become rogue. Any domain that is
+assigned a label with multiple STE types must be trusted to keep
+information belonging to the different STE types separate (confined).
+For example, Domain0 is assigned the bootstrap label
+\verb|SystemsManagement|, which includes all existing STE types.
+Therefore, Domain0 must take care not to enable unauthorized
+information flow (eg. through block devices or virtual networking)
+between domains or resources that are assigned different STE types.
+
+Security administrators simply use the name of a label (specified in
+the \verb|<Name>| field) to associate a label with a domain (cf.
+Section~\ref{subsection:acmexamplelabeldomains}). The types inside the
+label are used by the Xen access control enforcement. While the name
+can be arbitrarily chosen (as long as it is unique), it is advisable
+to choose the label name in accordance to the security types included.
+While the XML representation in the above label seems unnecessary
+flexible, labels in general can consist of multiple types as we will
+see in the following example.
+
+Assume that \verb|PepsiCo| and \verb|CocaCola| workloads use virtual
+disks that are provided by a virtual I/O domain hosting a physical
+storage device and carrying the following label:
+
+\begin{scriptsize}
+\begin{verbatim}
+ <VirtualMachineLabel>
+ <Name>VIO</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>CocaCola</Type>
+ <Type>PepsiCo</Type>
+ </SimpleTypeEnforcementTypes>
+ <ChineseWallTypes>
+ <Type>VIOServer</Type>
+ </ChineseWallTypes>
+ </VirtualMachineLabel>
+\end{verbatim}
+\end{scriptsize}
+
+This Virtual I/O domain (VIO) exports its virtualized disks by
+communicating both to domains labeled with the \verb|PepsiCo| label
+and domains labeled with the \verb|CocaCola| label. This requires the
+VIO domain to carry both the STE types \verb|CocaCola| and
+\verb|PepsiCo|. In this example, the confinement of \verb|CocaCola|
+and \verb|PepsiCo| workload depends on a VIO domain that must keep the
+data of those different workloads separate. The virtual disks are
+labeled as well (see Section~\ref{subsection:acmexamplelabelresources}
+for labeling resources) and enforcement functions inside the VIO
+domain must ensure that the labels of the domain mounting a virtual
+disk and the virtual disk label share a common STE type. The VIO label
+carrying its own VIOServer CHWALL type introduces the flexibility to
+permit the trusted VIO server to run together with CocaCola or PepsiCo
+workloads.
+
+Alternatively, a system that has two hard-drives does not need a VIO
+domain but can directly assign one hardware storage device to each of
+the workloads (if the platform offers an IO-MMU, cf
+Section~\ref{s:ddsecurity}. Sharing hardware through virtualization
+is a trade-off between the amount of trusted code (size of the trusted
+computing base) and the amount of acceptable over-provisioning. This
+holds both for peripherals and for system platforms.
+
+\subsection{Tools For Creating sHype/Xen Security Policies}
+To create a security policy for Xen, you can use one of the following
+tools:
+\begin{itemize}
+\item \verb|ezPolicy| GUI tool -- start writing policies
+\item \verb|xensec_gen| tool -- refine policies created with \verb|ezPolicy|
+\item text or XML editor
+\end{itemize}
+
+We use the \verb|ezPolicy| tool in
+Section~\ref{subsection:acmexamplecreate} to quickly create a workload
+protection policy. If desired, the resulting XML policy file can be
+loaded into the \verb|xensec_gen| tool to refine it. It can also be
+directly edited using an XML editor. Any XML policy file is verified
+against the security policy schema when it is translated (see
+Subsection~\ref{subsection:acmexampleinstall}).
+
+\section{Current Limitations}
+\label{section:acmlimitations}
+
+The sHype/ACM configuration for Xen is work in progress. There is
+ongoing work for protecting virtualized resources and planned and
+ongoing work for protecting access to remote resources and domains.
+The following sections describe limitations of some of the areas into
+which access control is being extended.
+
+\subsection{Network Traffic}
+Local and remote network traffic is currently not controlled.
+Solutions to add sHype/ACM policy enforcement to the virtual network
+exist but need to be discussed before they can become part of Xen.
+Subjecting external network traffic to the ACM security policy is work
+in progress. Manually setting up filters in domain 0 is required for
+now but does not scale well.
+
+\subsection{Resource Access and Usage Control}
+
+Enforcing the security policy across multiple hypervisor systems and
+on access to remote shared resources is work in progress. Extending
+access control to new types of resources is ongoing work (e.g. network
+storage).
+
+On a single Xen system, information about the association of resources
+and security labels is stored in
+\verb|/etc/xen/acm-security/policy/resource_labels|. This file relates
+a full resource path with a security label. This association is weak
+and will break if resources are moved or renamed without adapting the
+label file. Improving the protection of label-resource relationships
+is ongoing work.
+
+Controlling resource usage and enforcing resource limits in general is
+ongoing work in the Xen community.
+
+\subsection{Domain Migration}
+
+Labels on domains are enforced during domain migration and the
+destination hypervisor will ensure that the domain label is valid and
+the domain is permitted to run (considering the Chinese Wall policy
+rules) before it accepts the migration. However, the network between
+the source and destination hypervisor as well as both hypervisors must
+be trusted. Architectures and prototypes exist that both protect the
+network connection and ensure that the hypervisors enforce access
+control consistently but patches are not yet available for the main
+stream.
+
+\subsection{Covert Channels}
+
+The sHype access control aims at system independent security policies.
+It builds on top of the core hypervisor isolation. Any covert channels
+that exist in the core hypervisor or in the hardware (e.g., shared
+processor cache) will be inherited. If those covert channels are not
+the result of trade-offs between security and other system properties,
+then they are most effectively minimized or eliminated where they are
+caused. sHype offers however some means to mitigate their impact
+(cf. run-time exclusion rules).
\part{Reference}
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c Tue Aug 01 14:58:20
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c Wed Aug 02 13:39:47
2006 -0600
@@ -109,6 +109,7 @@ int init_new_context(struct task_struct
init_MUTEX(&mm->context.sem);
mm->context.size = 0;
+ mm->context.has_foreign_mappings = 0;
old_mm = current->mm;
if (old_mm && old_mm->context.size > 0) {
down(&old_mm->context.sem);
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Tue Aug 01 14:58:20
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Wed Aug 02 13:39:47
2006 -0600
@@ -126,6 +126,8 @@ int direct_remap_pfn_range(struct vm_are
if (domid == DOMID_SELF)
return -EINVAL;
+ vma->vm_mm->context.has_foreign_mappings = 1;
+
return __direct_remap_pfn_range(
vma->vm_mm, address, mfn, size, prot, domid);
}
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Tue Aug 01 14:58:20
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Wed Aug 02 13:39:47
2006 -0600
@@ -694,6 +694,7 @@ void _arch_exit_mmap(struct mm_struct *m
task_unlock(tsk);
if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) &&
- (atomic_read(&mm->mm_count) == 1))
+ (atomic_read(&mm->mm_count) == 1) &&
+ !mm->context.has_foreign_mappings)
mm_unpin(mm);
}
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Wed Aug 02
13:39:47 2006 -0600
@@ -159,7 +159,8 @@ void _arch_exit_mmap(struct mm_struct *m
task_unlock(tsk);
- if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) )
+ if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
+ !mm->context.has_foreign_mappings )
mm_unpin(mm);
}
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Tue Aug 01 14:58:20
2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 02 13:39:47
2006 -0600
@@ -76,6 +76,10 @@ typedef struct netif_st {
struct vm_struct *tx_comms_area;
struct vm_struct *rx_comms_area;
+ /* Set of features that can be turned on in dev->features. */
+ int features;
+ int can_queue;
+
/* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */
RING_IDX rx_req_cons_peek;
@@ -119,4 +123,16 @@ struct net_device_stats *netif_be_get_st
struct net_device_stats *netif_be_get_stats(struct net_device *dev);
irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+static inline int netbk_can_queue(struct net_device *dev)
+{
+ netif_t *netif = netdev_priv(dev);
+ return netif->can_queue;
+}
+
+static inline int netbk_can_sg(struct net_device *dev)
+{
+ netif_t *netif = netdev_priv(dev);
+ return netif->features & NETIF_F_SG;
+}
+
#endif /* __NETIF__BACKEND__COMMON_H__ */
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Aug 02
13:39:47 2006 -0600
@@ -51,23 +51,59 @@ static int net_open(struct net_device *d
netif_t *netif = netdev_priv(dev);
if (netif_carrier_ok(dev))
__netif_up(netif);
- netif_start_queue(dev);
return 0;
}
static int net_close(struct net_device *dev)
{
netif_t *netif = netdev_priv(dev);
- netif_stop_queue(dev);
if (netif_carrier_ok(dev))
__netif_down(netif);
return 0;
}
+static int netbk_change_mtu(struct net_device *dev, int mtu)
+{
+ int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
+
+ if (mtu > max)
+ return -EINVAL;
+ dev->mtu = mtu;
+ return 0;
+}
+
+static int netbk_set_sg(struct net_device *dev, u32 data)
+{
+ if (data) {
+ netif_t *netif = netdev_priv(dev);
+
+ if (!(netif->features & NETIF_F_SG))
+ return -ENOSYS;
+ }
+
+ return ethtool_op_set_sg(dev, data);
+}
+
+static int netbk_set_tso(struct net_device *dev, u32 data)
+{
+ if (data) {
+ netif_t *netif = netdev_priv(dev);
+
+ if (!(netif->features & NETIF_F_TSO))
+ return -ENOSYS;
+ }
+
+ return ethtool_op_set_tso(dev, data);
+}
+
static struct ethtool_ops network_ethtool_ops =
{
.get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = netbk_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = netbk_set_tso,
.get_link = ethtool_op_get_link,
};
@@ -103,12 +139,16 @@ netif_t *netif_alloc(domid_t domid, unsi
dev->get_stats = netif_be_get_stats;
dev->open = net_open;
dev->stop = net_close;
+ dev->change_mtu = netbk_change_mtu;
dev->features = NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
- /* Disable queuing. */
- dev->tx_queue_len = 0;
+ /*
+ * Reduce default TX queuelen so that each guest interface only
+ * allows it to eat around 6.4MB of host memory.
+ */
+ dev->tx_queue_len = 100;
for (i = 0; i < ETH_ALEN; i++)
if (be_mac[i] != 0)
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 02
13:39:47 2006 -0600
@@ -40,17 +40,22 @@
/*#define NETBE_DEBUG_INTERRUPT*/
+struct netbk_rx_meta {
+ skb_frag_t frag;
+ int id;
+};
+
static void netif_idx_release(u16 pending_idx);
static void netif_page_release(struct page *page);
static void make_tx_response(netif_t *netif,
netif_tx_request_t *txp,
s8 st);
-static int make_rx_response(netif_t *netif,
- u16 id,
- s8 st,
- u16 offset,
- u16 size,
- u16 flags);
+static netif_rx_response_t *make_rx_response(netif_t *netif,
+ u16 id,
+ s8 st,
+ u16 offset,
+ u16 size,
+ u16 flags);
static void net_tx_action(unsigned long unused);
static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
@@ -100,21 +105,27 @@ static unsigned long mfn_list[MAX_MFN_AL
static unsigned long mfn_list[MAX_MFN_ALLOC];
static unsigned int alloc_index = 0;
-static unsigned long alloc_mfn(void)
-{
- unsigned long mfn = 0;
+static inline unsigned long alloc_mfn(void)
+{
+ return mfn_list[--alloc_index];
+}
+
+static int check_mfn(int nr)
+{
struct xen_memory_reservation reservation = {
- .nr_extents = MAX_MFN_ALLOC,
.extent_order = 0,
.domid = DOMID_SELF
};
- set_xen_guest_handle(reservation.extent_start, mfn_list);
- if ( unlikely(alloc_index == 0) )
- alloc_index = HYPERVISOR_memory_op(
- XENMEM_increase_reservation, &reservation);
- if ( alloc_index != 0 )
- mfn = mfn_list[--alloc_index];
- return mfn;
+
+ if (likely(alloc_index >= nr))
+ return 0;
+
+ set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index);
+ reservation.nr_extents = MAX_MFN_ALLOC - alloc_index;
+ alloc_index += HYPERVISOR_memory_op(XENMEM_increase_reservation,
+ &reservation);
+
+ return alloc_index >= nr ? 0 : -ENOMEM;
}
static inline void maybe_schedule_tx_action(void)
@@ -136,6 +147,96 @@ static inline int is_xen_skb(struct sk_b
return (cp == skbuff_cachep);
}
+static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
+{
+ struct skb_shared_info *ninfo;
+ struct sk_buff *nskb;
+ unsigned long offset;
+ int ret;
+ int len;
+ int headlen;
+
+ nskb = alloc_skb(SKB_MAX_HEAD(0), GFP_ATOMIC);
+ if (unlikely(!nskb))
+ goto err;
+
+ skb_reserve(nskb, 16);
+ headlen = nskb->end - nskb->data;
+ if (headlen > skb_headlen(skb))
+ headlen = skb_headlen(skb);
+ ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen);
+ BUG_ON(ret);
+
+ ninfo = skb_shinfo(nskb);
+ ninfo->gso_size = skb_shinfo(skb)->gso_size;
+ ninfo->gso_type = skb_shinfo(skb)->gso_type;
+
+ offset = headlen;
+ len = skb->len - headlen;
+
+ nskb->len = skb->len;
+ nskb->data_len = len;
+ nskb->truesize += len;
+
+ while (len) {
+ struct page *page;
+ int copy;
+ int zero;
+
+ if (unlikely(ninfo->nr_frags >= MAX_SKB_FRAGS)) {
+ dump_stack();
+ goto err_free;
+ }
+
+ copy = len >= PAGE_SIZE ? PAGE_SIZE : len;
+ zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO;
+
+ page = alloc_page(GFP_ATOMIC | zero);
+ if (unlikely(!page))
+ goto err_free;
+
+ ret = skb_copy_bits(skb, offset, page_address(page), copy);
+ BUG_ON(ret);
+
+ ninfo->frags[ninfo->nr_frags].page = page;
+ ninfo->frags[ninfo->nr_frags].page_offset = 0;
+ ninfo->frags[ninfo->nr_frags].size = copy;
+ ninfo->nr_frags++;
+
+ offset += copy;
+ len -= copy;
+ }
+
+ offset = nskb->data - skb->data;
+
+ nskb->h.raw = skb->h.raw + offset;
+ nskb->nh.raw = skb->nh.raw + offset;
+ nskb->mac.raw = skb->mac.raw + offset;
+
+ return nskb;
+
+ err_free:
+ kfree_skb(nskb);
+ err:
+ return NULL;
+}
+
+static inline int netbk_max_required_rx_slots(netif_t *netif)
+{
+ if (netif->features & (NETIF_F_SG|NETIF_F_TSO))
+ return MAX_SKB_FRAGS + 2; /* header + extra_info + frags */
+ return 1; /* all in one */
+}
+
+static inline int netbk_queue_full(netif_t *netif)
+{
+ RING_IDX peek = netif->rx_req_cons_peek;
+ RING_IDX needed = netbk_max_required_rx_slots(netif);
+
+ return ((netif->rx.sring->req_prod - peek) < needed) ||
+ ((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed);
+}
+
int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
netif_t *netif = netdev_priv(dev);
@@ -143,30 +244,26 @@ int netif_be_start_xmit(struct sk_buff *
BUG_ON(skb->dev != dev);
/* Drop the packet if the target domain has no receive buffers. */
- if (unlikely(!netif_running(dev) || !netif_carrier_ok(dev)) ||
- (netif->rx_req_cons_peek == netif->rx.sring->req_prod) ||
- ((netif->rx_req_cons_peek - netif->rx.rsp_prod_pvt) ==
- NET_RX_RING_SIZE))
+ if (unlikely(!netif_running(dev) || !netif_carrier_ok(dev)))
goto drop;
+
+ if (unlikely(netbk_queue_full(netif))) {
+ /* Not a BUG_ON() -- misbehaving netfront can trigger this. */
+ if (netbk_can_queue(dev))
+ DPRINTK("Queue full but not stopped!\n");
+ goto drop;
+ }
/*
* We do not copy the packet unless:
* 1. The data is shared; or
* 2. The data is not allocated from our special cache.
- * NB. We also couldn't cope with fragmented packets, but we won't get
- * any because we not advertise the NETIF_F_SG feature.
+ * 3. The data is fragmented.
*/
- if (skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb)) {
- int hlen = skb->data - skb->head;
- int ret;
- struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len);
+ if (skb_cloned(skb) || skb_is_nonlinear(skb) || !is_xen_skb(skb)) {
+ struct sk_buff *nskb = netbk_copy_skb(skb);
if ( unlikely(nskb == NULL) )
goto drop;
- skb_reserve(nskb, hlen);
- __skb_put(nskb, skb->len);
- ret = skb_copy_bits(skb, -hlen, nskb->data - hlen,
- skb->len + hlen);
- BUG_ON(ret);
/* Copy only the header fields we use in this driver. */
nskb->dev = skb->dev;
nskb->ip_summed = skb->ip_summed;
@@ -175,8 +272,17 @@ int netif_be_start_xmit(struct sk_buff *
skb = nskb;
}
- netif->rx_req_cons_peek++;
+ netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
+ !!skb_shinfo(skb)->gso_size;
netif_get(netif);
+
+ if (netbk_can_queue(dev) && netbk_queue_full(netif)) {
+ netif->rx.sring->req_event = netif->rx_req_cons_peek +
+ netbk_max_required_rx_slots(netif);
+ mb(); /* request notification /then/ check & stop the queue */
+ if (netbk_queue_full(netif))
+ netif_stop_queue(dev);
+ }
skb_queue_tail(&rx_queue, skb);
tasklet_schedule(&net_rx_tasklet);
@@ -208,116 +314,85 @@ int xen_network_done(void)
}
#endif
-static void net_rx_action(unsigned long unused)
-{
- netif_t *netif = NULL;
- s8 status;
- u16 size, id, irq, flags;
- multicall_entry_t *mcl;
- mmu_update_t *mmu;
- gnttab_transfer_t *gop;
- unsigned long vdata, old_mfn, new_mfn;
- struct sk_buff_head rxq;
- struct sk_buff *skb;
- int notify_nr = 0;
- int ret;
+static u16 netbk_gop_frag(netif_t *netif, struct page *page, int count, int i)
+{
+ multicall_entry_t *mcl = rx_mcl + count;
+ mmu_update_t *mmu = rx_mmu + count;
+ gnttab_transfer_t *gop = grant_rx_op + count;
+ netif_rx_request_t *req;
+ unsigned long old_mfn, new_mfn;
+
+ old_mfn = virt_to_mfn(page_address(page));
+
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ new_mfn = alloc_mfn();
+
+ /*
+ * Set the new P2M table entry before reassigning
+ * the old data page. Heed the comment in
+ * pgtable-2level.h:pte_page(). :-)
+ */
+ set_phys_to_machine(page_to_pfn(page), new_mfn);
+
+ MULTI_update_va_mapping(mcl, (unsigned long)page_address(page),
+ pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
+
+ mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
+ MMU_MACHPHYS_UPDATE;
+ mmu->val = page_to_pfn(page);
+ }
+
+ req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i);
+ gop->mfn = old_mfn;
+ gop->domid = netif->domid;
+ gop->ref = req->gref;
+ return req->id;
+}
+
+static void netbk_gop_skb(struct sk_buff *skb, struct netbk_rx_meta *meta,
+ int count)
+{
+ netif_t *netif = netdev_priv(skb->dev);
+ int nr_frags = skb_shinfo(skb)->nr_frags;
+ int i;
+ int extra;
+
+ meta[count].frag.page_offset = skb_shinfo(skb)->gso_type;
+ meta[count].frag.size = skb_shinfo(skb)->gso_size;
+ extra = !!meta[count].frag.size + 1;
+
+ for (i = 0; i < nr_frags; i++) {
+ meta[++count].frag = skb_shinfo(skb)->frags[i];
+ meta[count].id = netbk_gop_frag(netif, meta[count].frag.page,
+ count, i + extra);
+ }
+
/*
- * Putting hundreds of bytes on the stack is considered rude.
- * Static works because a tasklet can only be on one CPU at any time.
+ * This must occur at the end to ensure that we don't trash
+ * skb_shinfo until we're done.
*/
- static u16 notify_list[NET_RX_RING_SIZE];
-
- skb_queue_head_init(&rxq);
-
- mcl = rx_mcl;
- mmu = rx_mmu;
- gop = grant_rx_op;
-
- while ((skb = skb_dequeue(&rx_queue)) != NULL) {
- netif = netdev_priv(skb->dev);
- vdata = (unsigned long)skb->data;
- old_mfn = virt_to_mfn(vdata);
-
- if (!xen_feature(XENFEAT_auto_translated_physmap)) {
- /* Memory squeeze? Back off for an arbitrary while. */
- if ((new_mfn = alloc_mfn()) == 0) {
- if ( net_ratelimit() )
- WPRINTK("Memory squeeze in netback "
- "driver.\n");
- mod_timer(&net_timer, jiffies + HZ);
- skb_queue_head(&rx_queue, skb);
- break;
- }
- /*
- * Set the new P2M table entry before reassigning
- * the old data page. Heed the comment in
- * pgtable-2level.h:pte_page(). :-)
- */
- set_phys_to_machine(
- __pa(skb->data) >> PAGE_SHIFT,
- new_mfn);
-
- MULTI_update_va_mapping(mcl, vdata,
- pfn_pte_ma(new_mfn,
- PAGE_KERNEL), 0);
- mcl++;
-
- mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
- MMU_MACHPHYS_UPDATE;
- mmu->val = __pa(vdata) >> PAGE_SHIFT;
- mmu++;
- }
-
- gop->mfn = old_mfn;
- gop->domid = netif->domid;
- gop->ref = RING_GET_REQUEST(
- &netif->rx, netif->rx.req_cons)->gref;
- netif->rx.req_cons++;
- gop++;
-
- __skb_queue_tail(&rxq, skb);
-
- /* Filled the batch queue? */
- if ((gop - grant_rx_op) == ARRAY_SIZE(grant_rx_op))
- break;
- }
-
- if (!xen_feature(XENFEAT_auto_translated_physmap)) {
- if (mcl == rx_mcl)
- return;
-
- mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
-
- if (mmu - rx_mmu) {
- mcl->op = __HYPERVISOR_mmu_update;
- mcl->args[0] = (unsigned long)rx_mmu;
- mcl->args[1] = mmu - rx_mmu;
- mcl->args[2] = 0;
- mcl->args[3] = DOMID_SELF;
- mcl++;
- }
-
- ret = HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
- BUG_ON(ret != 0);
- }
-
- ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
- gop - grant_rx_op);
- BUG_ON(ret != 0);
-
- mcl = rx_mcl;
- gop = grant_rx_op;
- while ((skb = __skb_dequeue(&rxq)) != NULL) {
- netif = netdev_priv(skb->dev);
- size = skb->tail - skb->data;
-
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-
- netif->stats.tx_bytes += size;
- netif->stats.tx_packets++;
-
+ meta[count - nr_frags].id = netbk_gop_frag(netif,
+ virt_to_page(skb->data),
+ count - nr_frags, 0);
+ netif->rx.req_cons += nr_frags + extra;
+}
+
+static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta)
+{
+ int i;
+
+ for (i = 0; i < nr_frags; i++)
+ put_page(meta[i].frag.page);
+}
+
+static int netbk_check_gop(int nr_frags, domid_t domid, int count)
+{
+ multicall_entry_t *mcl = rx_mcl + count;
+ gnttab_transfer_t *gop = grant_rx_op + count;
+ int status = NETIF_RSP_OKAY;
+ int i;
+
+ for (i = 0; i <= nr_frags; i++) {
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
/* The update_va_mapping() must not fail. */
BUG_ON(mcl->result != 0);
@@ -325,10 +400,9 @@ static void net_rx_action(unsigned long
}
/* Check the reassignment error code. */
- status = NETIF_RSP_OKAY;
if (gop->status != 0) {
DPRINTK("Bad status %d from grant transfer to DOM%u\n",
- gop->status, netif->domid);
+ gop->status, domid);
/*
* Page no longer belongs to us unless GNTST_bad_page,
* but that should be a fatal error anyway.
@@ -336,24 +410,166 @@ static void net_rx_action(unsigned long
BUG_ON(gop->status == GNTST_bad_page);
status = NETIF_RSP_ERROR;
}
- irq = netif->irq;
- id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id;
- flags = 0;
+ gop++;
+ }
+
+ return status;
+}
+
+static void netbk_add_frag_responses(netif_t *netif, int status,
+ struct netbk_rx_meta *meta, int nr_frags)
+{
+ int i;
+
+ for (i = 0; i < nr_frags; i++) {
+ int id = meta[i].id;
+ int flags = (i == nr_frags - 1) ? 0 : NETRXF_more_data;
+
+ make_rx_response(netif, id, status, meta[i].frag.page_offset,
+ meta[i].frag.size, flags);
+ }
+}
+
+static void net_rx_action(unsigned long unused)
+{
+ netif_t *netif = NULL;
+ s8 status;
+ u16 id, irq, flags;
+ netif_rx_response_t *resp;
+ struct netif_extra_info *extra;
+ multicall_entry_t *mcl;
+ struct sk_buff_head rxq;
+ struct sk_buff *skb;
+ int notify_nr = 0;
+ int ret;
+ int nr_frags;
+ int count;
+
+ /*
+ * Putting hundreds of bytes on the stack is considered rude.
+ * Static works because a tasklet can only be on one CPU at any time.
+ */
+ static u16 notify_list[NET_RX_RING_SIZE];
+ static struct netbk_rx_meta meta[NET_RX_RING_SIZE];
+
+ skb_queue_head_init(&rxq);
+
+ count = 0;
+
+ while ((skb = skb_dequeue(&rx_queue)) != NULL) {
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ *(int *)skb->cb = nr_frags;
+
+ if (!xen_feature(XENFEAT_auto_translated_physmap) &&
+ check_mfn(nr_frags + 1)) {
+ /* Memory squeeze? Back off for an arbitrary while. */
+ if ( net_ratelimit() )
+ WPRINTK("Memory squeeze in netback "
+ "driver.\n");
+ mod_timer(&net_timer, jiffies + HZ);
+ skb_queue_head(&rx_queue, skb);
+ break;
+ }
+
+ netbk_gop_skb(skb, meta, count);
+
+ count += nr_frags + 1;
+
+ __skb_queue_tail(&rxq, skb);
+
+ /* Filled the batch queue? */
+ if (count + MAX_SKB_FRAGS >= NET_RX_RING_SIZE)
+ break;
+ }
+
+ if (!count)
+ return;
+
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ mcl = rx_mcl + count;
+
+ mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
+
+ mcl->op = __HYPERVISOR_mmu_update;
+ mcl->args[0] = (unsigned long)rx_mmu;
+ mcl->args[1] = count;
+ mcl->args[2] = 0;
+ mcl->args[3] = DOMID_SELF;
+
+ ret = HYPERVISOR_multicall(rx_mcl, count + 1);
+ BUG_ON(ret != 0);
+ }
+
+ ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, count);
+ BUG_ON(ret != 0);
+
+ count = 0;
+ while ((skb = __skb_dequeue(&rxq)) != NULL) {
+ nr_frags = *(int *)skb->cb;
+
+ atomic_set(&(skb_shinfo(skb)->dataref), 1);
+ skb_shinfo(skb)->nr_frags = 0;
+ skb_shinfo(skb)->frag_list = NULL;
+
+ netif = netdev_priv(skb->dev);
+ netif->stats.tx_bytes += skb->len;
+ netif->stats.tx_packets++;
+
+ netbk_free_pages(nr_frags, meta + count + 1);
+ status = netbk_check_gop(nr_frags, netif->domid, count);
+
+ id = meta[count].id;
+ flags = nr_frags ? NETRXF_more_data : 0;
+
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
flags |= NETRXF_csum_blank | NETRXF_data_validated;
else if (skb->proto_data_valid) /* remote but checksummed? */
flags |= NETRXF_data_validated;
- if (make_rx_response(netif, id, status,
- (unsigned long)skb->data & ~PAGE_MASK,
- size, flags) &&
- (rx_notify[irq] == 0)) {
+
+ resp = make_rx_response(netif, id, status,
+ offset_in_page(skb->data),
+ skb_headlen(skb), flags);
+
+ extra = NULL;
+
+ if (meta[count].frag.size) {
+ struct netif_extra_info *gso =
+ (struct netif_extra_info *)
+ RING_GET_RESPONSE(&netif->rx,
+ netif->rx.rsp_prod_pvt++);
+
+ if (extra)
+ extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
+ else
+ resp->flags |= NETRXF_extra_info;
+
+ gso->u.gso.size = meta[count].frag.size;
+ gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+ gso->u.gso.pad = 0;
+ gso->u.gso.features = 0;
+
+ gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+ gso->flags = 0;
+ extra = gso;
+ }
+
+ netbk_add_frag_responses(netif, status, meta + count + 1,
+ nr_frags);
+
+ RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret);
+ irq = netif->irq;
+ if (ret && !rx_notify[irq]) {
rx_notify[irq] = 1;
notify_list[notify_nr++] = irq;
}
+ if (netif_queue_stopped(netif->dev) &&
+ !netbk_queue_full(netif))
+ netif_wake_queue(netif->dev);
+
netif_put(netif);
dev_kfree_skb(skb);
- gop++;
+ count += nr_frags + 1;
}
while (notify_nr != 0) {
@@ -974,8 +1190,13 @@ irqreturn_t netif_be_int(int irq, void *
irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
{
netif_t *netif = dev_id;
+
add_to_net_schedule_list_tail(netif);
maybe_schedule_tx_action();
+
+ if (netif_queue_stopped(netif->dev) && !netbk_queue_full(netif))
+ netif_wake_queue(netif->dev);
+
return IRQ_HANDLED;
}
@@ -1009,16 +1230,15 @@ static void make_tx_response(netif_t *ne
#endif
}
-static int make_rx_response(netif_t *netif,
- u16 id,
- s8 st,
- u16 offset,
- u16 size,
- u16 flags)
+static netif_rx_response_t *make_rx_response(netif_t *netif,
+ u16 id,
+ s8 st,
+ u16 offset,
+ u16 size,
+ u16 flags)
{
RING_IDX i = netif->rx.rsp_prod_pvt;
netif_rx_response_t *resp;
- int notify;
resp = RING_GET_RESPONSE(&netif->rx, i);
resp->offset = offset;
@@ -1029,9 +1249,8 @@ static int make_rx_response(netif_t *net
resp->status = (s16)st;
netif->rx.rsp_prod_pvt = ++i;
- RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, notify);
-
- return notify;
+
+ return resp;
}
#ifdef NETBE_DEBUG_INTERRUPT
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Tue Aug 01 14:58:20
2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Aug 02 13:39:47
2006 -0600
@@ -101,14 +101,12 @@ static int netback_probe(struct xenbus_d
goto abort_transaction;
}
-#if 0 /* KAF: After the protocol is finalised. */
err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
"%d", 1);
if (err) {
message = "writing feature-gso-tcpv4";
goto abort_transaction;
}
-#endif
err = xenbus_transaction_end(xbt, 0);
} while (err == -EAGAIN);
@@ -353,6 +351,7 @@ static int connect_rings(struct backend_
unsigned long tx_ring_ref, rx_ring_ref;
unsigned int evtchn;
int err;
+ int val;
DPRINTK("");
@@ -365,6 +364,30 @@ static int connect_rings(struct backend_
"reading %s/ring-ref and event-channel",
dev->otherend);
return err;
+ }
+
+ if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-rx-notify", "%d",
+ &val) < 0)
+ val = 0;
+ if (val)
+ be->netif->can_queue = 1;
+ else
+ /* Must be non-zero for pfifo_fast to work. */
+ be->netif->dev->tx_queue_len = 1;
+
+ if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0)
+ val = 0;
+ if (val) {
+ be->netif->features |= NETIF_F_SG;
+ be->netif->dev->features |= NETIF_F_SG;
+ }
+
+ if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d",
+ &val) < 0)
+ val = 0;
+ if (val) {
+ be->netif->features |= NETIF_F_TSO;
+ be->netif->dev->features |= NETIF_F_TSO;
}
/* Map the shared frame, irq etc. */
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 02
13:39:47 2006 -0600
@@ -46,11 +46,11 @@
#include <linux/ethtool.h>
#include <linux/in.h>
#include <linux/if_ether.h>
+#include <linux/io.h>
#include <net/sock.h>
#include <net/pkt_sched.h>
#include <net/arp.h>
#include <net/route.h>
-#include <asm/io.h>
#include <asm/uaccess.h>
#include <xen/evtchn.h>
#include <xen/xenbus.h>
@@ -62,17 +62,12 @@
#include <xen/interface/grant_table.h>
#include <xen/gnttab.h>
+#define RX_COPY_THRESHOLD 256
+
#define GRANT_INVALID_REF 0
#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
-
-static inline void init_skb_shinfo(struct sk_buff *skb)
-{
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-}
struct netfront_info {
struct list_head list;
@@ -119,6 +114,11 @@ struct netfront_info {
unsigned long rx_pfn_array[NET_RX_RING_SIZE];
struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
struct mmu_update rx_mmu[NET_RX_RING_SIZE];
+};
+
+struct netfront_rx_info {
+ struct netif_rx_response rx;
+ struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
};
/*
@@ -329,6 +329,18 @@ again:
err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
if (err) {
message = "writing feature-rx-notify";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
+ if (err) {
+ message = "writing feature-sg";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1);
+ if (err) {
+ message = "writing feature-gso-tcpv4";
goto abort_transaction;
}
@@ -575,10 +587,13 @@ static void network_alloc_rx_buffers(str
unsigned short id;
struct netfront_info *np = netdev_priv(dev);
struct sk_buff *skb;
+ struct page *page;
int i, batch_target, notify;
RING_IDX req_prod = np->rx.req_prod_pvt;
struct xen_memory_reservation reservation;
grant_ref_t ref;
+ unsigned long pfn;
+ void *vaddr;
if (unlikely(!netif_carrier_ok(dev)))
return;
@@ -591,15 +606,16 @@ static void network_alloc_rx_buffers(str
*/
batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
- /*
- * Subtract dev_alloc_skb headroom (16 bytes) and shared info
- * tailroom then round down to SKB_DATA_ALIGN boundary.
- */
- skb = __dev_alloc_skb(
- ((PAGE_SIZE - sizeof(struct skb_shared_info)) &
- (-SKB_DATA_ALIGN(1))) - 16,
- GFP_ATOMIC|__GFP_NOWARN);
- if (skb == NULL) {
+ /* Allocate an skb and a page. */
+ skb = __dev_alloc_skb(RX_COPY_THRESHOLD,
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (unlikely(!skb))
+ goto no_skb;
+
+ page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+ if (!page) {
+ kfree_skb(skb);
+no_skb:
/* Any skbuffs queued for refill? Force them out. */
if (i != 0)
goto refill;
@@ -608,6 +624,9 @@ static void network_alloc_rx_buffers(str
jiffies + (HZ/10));
break;
}
+
+ skb_shinfo(skb)->frags[0].page = page;
+ skb_shinfo(skb)->nr_frags = 1;
__skb_queue_tail(&np->rx_batch, skb);
}
@@ -639,18 +658,20 @@ static void network_alloc_rx_buffers(str
ref = gnttab_claim_grant_reference(&np->gref_rx_head);
BUG_ON((signed short)ref < 0);
np->grant_rx_ref[id] = ref;
+
+ pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
+ vaddr = page_address(skb_shinfo(skb)->frags[0].page);
+
gnttab_grant_foreign_transfer_ref(ref,
- np->xbdev->otherend_id,
- __pa(skb->head)>>PAGE_SHIFT);
+ np->xbdev->otherend_id, pfn);
RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref;
- np->rx_pfn_array[i] = virt_to_mfn(skb->head);
+ np->rx_pfn_array[i] = pfn_to_mfn(pfn);
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
/* Remove this page before passing back to Xen. */
- set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
- INVALID_P2M_ENTRY);
+ set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
MULTI_update_va_mapping(np->rx_mcl+i,
- (unsigned long)skb->head,
+ (unsigned long)vaddr,
__pte(0), 0);
}
}
@@ -889,41 +910,76 @@ static void xennet_move_rx_slot(struct n
np->rx.req_prod_pvt++;
}
-static int netif_poll(struct net_device *dev, int *pbudget)
-{
- struct netfront_info *np = netdev_priv(dev);
- struct sk_buff *skb, *nskb;
- struct netif_rx_response *rx;
- RING_IDX i, rp;
- struct mmu_update *mmu = np->rx_mmu;
- struct multicall_entry *mcl = np->rx_mcl;
- int work_done, budget, more_to_do = 1;
- struct sk_buff_head rxq;
- unsigned long flags;
- unsigned long mfn;
- grant_ref_t ref;
-
- spin_lock(&np->rx_lock);
-
- if (unlikely(!netif_carrier_ok(dev))) {
- spin_unlock(&np->rx_lock);
- return 0;
- }
-
- skb_queue_head_init(&rxq);
-
- if ((budget = *pbudget) > dev->quota)
- budget = dev->quota;
- rp = np->rx.sring->rsp_prod;
- rmb(); /* Ensure we see queued responses up to 'rp'. */
-
- for (i = np->rx.rsp_cons, work_done = 0;
- (i != rp) && (work_done < budget);
- i++, work_done++) {
- rx = RING_GET_RESPONSE(&np->rx, i);
-
- skb = xennet_get_rx_skb(np, i);
- ref = xennet_get_rx_ref(np, i);
+int xennet_get_extras(struct netfront_info *np,
+ struct netif_extra_info *extras, RING_IDX rp)
+
+{
+ struct netif_extra_info *extra;
+ RING_IDX cons = np->rx.rsp_cons;
+ int err = 0;
+
+ do {
+ struct sk_buff *skb;
+ grant_ref_t ref;
+
+ if (unlikely(cons + 1 == rp)) {
+ if (net_ratelimit())
+ WPRINTK("Missing extra info\n");
+ err = -EBADR;
+ break;
+ }
+
+ extra = (struct netif_extra_info *)
+ RING_GET_RESPONSE(&np->rx, ++cons);
+
+ if (unlikely(!extra->type ||
+ extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+ if (net_ratelimit())
+ WPRINTK("Invalid extra type: %d\n",
+ extra->type);
+ err = -EINVAL;
+ } else
+ memcpy(&extras[extra->type - 1], extra, sizeof(*extra));
+
+ skb = xennet_get_rx_skb(np, cons);
+ ref = xennet_get_rx_ref(np, cons);
+ xennet_move_rx_slot(np, skb, ref);
+ } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
+
+ np->rx.rsp_cons = cons;
+ return err;
+}
+
+static int xennet_get_responses(struct netfront_info *np,
+ struct netfront_rx_info *rinfo, RING_IDX rp,
+ struct sk_buff_head *list, int count)
+{
+ struct mmu_update *mmu = np->rx_mmu + count;
+ struct multicall_entry *mcl = np->rx_mcl + count;
+ struct netif_rx_response *rx = &rinfo->rx;
+ struct netif_extra_info *extras = rinfo->extras;
+ RING_IDX cons = np->rx.rsp_cons;
+ struct sk_buff *skb = xennet_get_rx_skb(np, cons);
+ grant_ref_t ref = xennet_get_rx_ref(np, cons);
+ int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
+ int frags = 1;
+ int err = 0;
+
+ if (rx->flags & NETRXF_extra_info) {
+ err = xennet_get_extras(np, extras, rp);
+ cons = np->rx.rsp_cons;
+ }
+
+ for (;;) {
+ unsigned long mfn;
+
+ if (unlikely(rx->status < 0 ||
+ rx->offset + rx->status > PAGE_SIZE)) {
+ if (net_ratelimit())
+ WPRINTK("rx->offset: %x, size: %u\n",
+ rx->offset, rx->status);
+ err = -EINVAL;
+ }
/*
* This definitely indicates a bug, either in this driver or in
@@ -932,8 +988,8 @@ static int netif_poll(struct net_device
*/
if (ref == GRANT_INVALID_REF) {
WPRINTK("Bad rx response id %d.\n", rx->id);
- work_done--;
- continue;
+ err = -EINVAL;
+ goto next;
}
/* Memory pressure, insufficient buffer headroom, ... */
@@ -942,16 +998,200 @@ static int netif_poll(struct net_device
WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n",
rx->id, rx->status);
xennet_move_rx_slot(np, skb, ref);
+ err = -ENOMEM;
+ goto next;
+ }
+
+ gnttab_release_grant_reference(&np->gref_rx_head, ref);
+
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ /* Remap the page. */
+ struct page *page = skb_shinfo(skb)->frags[0].page;
+ unsigned long pfn = page_to_pfn(page);
+ void *vaddr = page_address(page);
+
+ MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
+ pfn_pte_ma(mfn, PAGE_KERNEL),
+ 0);
+ mcl++;
+ mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
+ | MMU_MACHPHYS_UPDATE;
+ mmu->val = pfn;
+ mmu++;
+
+ set_phys_to_machine(pfn, mfn);
+ }
+
+ __skb_queue_tail(list, skb);
+
+next:
+ if (!(rx->flags & NETRXF_more_data))
+ break;
+
+ if (cons + frags == rp) {
+ if (net_ratelimit())
+ WPRINTK("Need more frags\n");
+ err = -ENOENT;
+ break;
+ }
+
+ rx = RING_GET_RESPONSE(&np->rx, cons + frags);
+ skb = xennet_get_rx_skb(np, cons + frags);
+ ref = xennet_get_rx_ref(np, cons + frags);
+ frags++;
+ }
+
+ if (unlikely(frags > max)) {
+ if (net_ratelimit())
+ WPRINTK("Too many frags\n");
+ err = -E2BIG;
+ }
+
+ return err;
+}
+
+static RING_IDX xennet_fill_frags(struct netfront_info *np,
+ struct sk_buff *skb,
+ struct sk_buff_head *list)
+{
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+ int nr_frags = shinfo->nr_frags;
+ RING_IDX cons = np->rx.rsp_cons;
+ skb_frag_t *frag = shinfo->frags + nr_frags;
+ struct sk_buff *nskb;
+
+ while ((nskb = __skb_dequeue(list))) {
+ struct netif_rx_response *rx =
+ RING_GET_RESPONSE(&np->rx, ++cons);
+
+ frag->page = skb_shinfo(nskb)->frags[0].page;
+ frag->page_offset = rx->offset;
+ frag->size = rx->status;
+
+ skb->data_len += rx->status;
+
+ skb_shinfo(nskb)->nr_frags = 0;
+ kfree_skb(nskb);
+
+ frag++;
+ nr_frags++;
+ }
+
+ shinfo->nr_frags = nr_frags;
+ return cons;
+}
+
+static int xennet_set_skb_gso(struct sk_buff *skb, struct netif_extra_info
*gso)
+{
+ if (!gso->u.gso.size) {
+ if (net_ratelimit())
+ WPRINTK("GSO size must not be zero.\n");
+ return -EINVAL;
+ }
+
+ /* Currently only TCPv4 S.O. is supported. */
+ if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+ if (net_ratelimit())
+ WPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
+ return -EINVAL;
+ }
+
+ skb_shinfo(skb)->gso_size = gso->u.gso.size;
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+
+ /* Header must be checked, and gso_segs computed. */
+ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+ skb_shinfo(skb)->gso_segs = 0;
+
+ return 0;
+}
+
+static int netif_poll(struct net_device *dev, int *pbudget)
+{
+ struct netfront_info *np = netdev_priv(dev);
+ struct sk_buff *skb;
+ struct netfront_rx_info rinfo;
+ struct netif_rx_response *rx = &rinfo.rx;
+ struct netif_extra_info *extras = rinfo.extras;
+ RING_IDX i, rp;
+ struct multicall_entry *mcl;
+ int work_done, budget, more_to_do = 1;
+ struct sk_buff_head rxq;
+ struct sk_buff_head errq;
+ struct sk_buff_head tmpq;
+ unsigned long flags;
+ unsigned int len;
+ int pages_done;
+ int err;
+
+ spin_lock(&np->rx_lock);
+
+ if (unlikely(!netif_carrier_ok(dev))) {
+ spin_unlock(&np->rx_lock);
+ return 0;
+ }
+
+ skb_queue_head_init(&rxq);
+ skb_queue_head_init(&errq);
+ skb_queue_head_init(&tmpq);
+
+ if ((budget = *pbudget) > dev->quota)
+ budget = dev->quota;
+ rp = np->rx.sring->rsp_prod;
+ rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+ for (i = np->rx.rsp_cons, work_done = 0, pages_done = 0;
+ (i != rp) && (work_done < budget);
+ np->rx.rsp_cons = ++i, work_done++) {
+ memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
+ memset(extras, 0, sizeof(extras));
+
+ err = xennet_get_responses(np, &rinfo, rp, &tmpq, pages_done);
+ pages_done += skb_queue_len(&tmpq);
+
+ if (unlikely(err)) {
+err:
+ i = np->rx.rsp_cons + skb_queue_len(&tmpq) - 1;
work_done--;
+ while ((skb = __skb_dequeue(&tmpq)))
+ __skb_queue_tail(&errq, skb);
+ np->stats.rx_errors++;
continue;
}
- gnttab_release_grant_reference(&np->gref_rx_head, ref);
-
- /* NB. We handle skb overflow later. */
- skb->data = skb->head + rx->offset;
- skb->len = rx->status;
- skb->tail = skb->data + skb->len;
+ skb = __skb_dequeue(&tmpq);
+
+ if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
+ struct netif_extra_info *gso;
+ gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+
+ if (unlikely(xennet_set_skb_gso(skb, gso))) {
+ __skb_queue_head(&tmpq, skb);
+ goto err;
+ }
+ }
+
+ skb->nh.raw = (void *)skb_shinfo(skb)->frags[0].page;
+ skb->h.raw = skb->nh.raw + rx->offset;
+
+ len = rx->status;
+ if (len > RX_COPY_THRESHOLD)
+ len = RX_COPY_THRESHOLD;
+ skb_put(skb, len);
+
+ if (rx->status > len) {
+ skb_shinfo(skb)->frags[0].page_offset =
+ rx->offset + len;
+ skb_shinfo(skb)->frags[0].size = rx->status - len;
+ skb->data_len = rx->status - len;
+ } else {
+ skb_shinfo(skb)->frags[0].page = NULL;
+ skb_shinfo(skb)->nr_frags = 0;
+ }
+
+ i = xennet_fill_frags(np, skb, &tmpq);
+ skb->truesize += skb->data_len;
+ skb->len += skb->data_len;
/*
* Old backends do not assert data_validated but we
@@ -967,96 +1207,38 @@ static int netif_poll(struct net_device
skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank);
np->stats.rx_packets++;
- np->stats.rx_bytes += rx->status;
-
- if (!xen_feature(XENFEAT_auto_translated_physmap)) {
- /* Remap the page. */
- MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
- pfn_pte_ma(mfn, PAGE_KERNEL),
- 0);
- mcl++;
- mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
- | MMU_MACHPHYS_UPDATE;
- mmu->val = __pa(skb->head) >> PAGE_SHIFT;
- mmu++;
-
- set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
- mfn);
- }
+ np->stats.rx_bytes += skb->len;
__skb_queue_tail(&rxq, skb);
}
/* Some pages are no longer absent... */
- balloon_update_driver_allowance(-work_done);
+ balloon_update_driver_allowance(-pages_done);
/* Do all the remapping work, and M2P updates, in one big hypercall. */
- if (likely((mcl - np->rx_mcl) != 0)) {
+ if (likely(pages_done)) {
+ mcl = np->rx_mcl + pages_done;
mcl->op = __HYPERVISOR_mmu_update;
mcl->args[0] = (unsigned long)np->rx_mmu;
- mcl->args[1] = mmu - np->rx_mmu;
+ mcl->args[1] = pages_done;
mcl->args[2] = 0;
mcl->args[3] = DOMID_SELF;
- mcl++;
- (void)HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
- }
+ (void)HYPERVISOR_multicall(np->rx_mcl, pages_done + 1);
+ }
+
+ while ((skb = __skb_dequeue(&errq)))
+ kfree_skb(skb);
while ((skb = __skb_dequeue(&rxq)) != NULL) {
- if (skb->len > (dev->mtu + ETH_HLEN + 4)) {
- if (net_ratelimit())
- printk(KERN_INFO "Received packet too big for "
- "MTU (%d > %d)\n",
- skb->len - ETH_HLEN - 4, dev->mtu);
- skb->len = 0;
- skb->tail = skb->data;
- init_skb_shinfo(skb);
- dev_kfree_skb(skb);
- continue;
- }
-
- /*
- * Enough room in skbuff for the data we were passed? Also,
- * Linux expects at least 16 bytes headroom in each rx buffer.
- */
- if (unlikely(skb->tail > skb->end) ||
- unlikely((skb->data - skb->head) < 16)) {
- if (net_ratelimit()) {
- if (skb->tail > skb->end)
- printk(KERN_INFO "Received packet "
- "is %zd bytes beyond tail.\n",
- skb->tail - skb->end);
- else
- printk(KERN_INFO "Received packet "
- "is %zd bytes before head.\n",
- 16 - (skb->data - skb->head));
- }
-
- nskb = __dev_alloc_skb(skb->len + 2,
- GFP_ATOMIC|__GFP_NOWARN);
- if (nskb != NULL) {
- skb_reserve(nskb, 2);
- skb_put(nskb, skb->len);
- memcpy(nskb->data, skb->data, skb->len);
- /* Copy any other fields we already set up. */
- nskb->dev = skb->dev;
- nskb->ip_summed = skb->ip_summed;
- nskb->proto_data_valid = skb->proto_data_valid;
- nskb->proto_csum_blank = skb->proto_csum_blank;
- }
-
- /* Reinitialise and then destroy the old skbuff. */
- skb->len = 0;
- skb->tail = skb->data;
- init_skb_shinfo(skb);
- dev_kfree_skb(skb);
-
- /* Switch old for new, if we copied the buffer. */
- if ((skb = nskb) == NULL)
- continue;
- }
-
- /* Set the shinfo area, which is hidden behind the data. */
- init_skb_shinfo(skb);
+ struct page *page = (struct page *)skb->nh.raw;
+ void *vaddr = page_address(page);
+
+ memcpy(skb->data, vaddr + (skb->h.raw - skb->nh.raw),
+ skb_headlen(skb));
+
+ if (page != skb_shinfo(skb)->frags[0].page)
+ __free_page(page);
+
/* Ethernet work: Delayed to here as it peeks the header. */
skb->protocol = eth_type_trans(skb, dev);
@@ -1064,8 +1246,6 @@ static int netif_poll(struct net_device
netif_receive_skb(skb);
dev->last_rx = jiffies;
}
-
- np->rx.rsp_cons = i;
/* If we get a callback with very few responses, reduce fill target. */
/* NB. Note exponential increase, linear decrease. */
@@ -1145,9 +1325,7 @@ static int xennet_set_tso(struct net_dev
if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
"feature-gso-tcpv4", "%d", &val) < 0)
val = 0;
-#if 0 /* KAF: After the protocol is finalised. */
if (!val)
-#endif
return -ENOSYS;
}
@@ -1210,7 +1388,7 @@ static void network_connect(struct net_d
gnttab_grant_foreign_transfer_ref(
ref, np->xbdev->otherend_id,
- __pa(skb->data) >> PAGE_SHIFT);
+ page_to_pfn(skb_shinfo(skb)->frags->page));
RING_GET_REQUEST(&np->rx, requeue_idx)->gref = ref;
RING_GET_REQUEST(&np->rx, requeue_idx)->id = requeue_idx;
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Wed Aug 02
13:39:47 2006 -0600
@@ -232,6 +232,10 @@ static int __devinit pcistub_match_one(s
&& dev->bus->number == pdev_id->bus
&& dev->devfn == pdev_id->devfn)
return 1;
+
+ /* Sometimes topmost bridge links to itself. */
+ if (dev == dev->bus->self)
+ break;
}
return 0;
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Tue Aug 01 14:58:20
2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Wed Aug 02 13:39:47
2006 -0600
@@ -445,6 +445,9 @@ static struct xenbus_driver xenbus_pciba
int __init pciback_xenbus_register(void)
{
+ if (!is_running_on_xen())
+ return -ENODEV;
+
return xenbus_register_backend(&xenbus_pciback_driver);
}
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Wed Aug 02
13:39:47 2006 -0600
@@ -284,11 +284,10 @@ static struct xenbus_driver xenbus_pcifr
static int __init pcifront_init(void)
{
- int err = 0;
-
- err = xenbus_register_frontend(&xenbus_pcifront_driver);
-
- return err;
+ if (!is_running_on_xen())
+ return -ENODEV;
+
+ return xenbus_register_frontend(&xenbus_pcifront_driver);
}
/* Initialize after the Xen PCI Frontend Stub is initialized */
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Wed Aug 02
13:39:47 2006 -0600
@@ -58,6 +58,9 @@ struct xenbus_dev_data {
/* In-progress transaction. */
struct list_head transactions;
+ /* Active watches. */
+ struct list_head watches;
+
/* Partial request. */
unsigned int len;
union {
@@ -70,6 +73,8 @@ struct xenbus_dev_data {
char read_buffer[PAGE_SIZE];
unsigned int read_cons, read_prod;
wait_queue_head_t read_waitq;
+
+ struct mutex reply_mutex;
};
static struct proc_dir_entry *xenbus_dev_intf;
@@ -100,13 +105,59 @@ static void queue_reply(struct xenbus_de
{
int i;
+ mutex_lock(&u->reply_mutex);
+
for (i = 0; i < len; i++, u->read_prod++)
u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
+ mutex_unlock(&u->reply_mutex);
+
wake_up(&u->read_waitq);
}
+
+struct watch_adapter
+{
+ struct list_head list;
+ struct xenbus_watch watch;
+ struct xenbus_dev_data *dev_data;
+ char *token;
+};
+
+static void free_watch_adapter (struct watch_adapter *watch)
+{
+ kfree(watch->watch.node);
+ kfree(watch->token);
+ kfree(watch);
+}
+
+static void watch_fired(struct xenbus_watch *watch,
+ const char **vec,
+ unsigned int len)
+{
+ struct watch_adapter *adap =
+ container_of(watch, struct watch_adapter, watch);
+ struct xsd_sockmsg hdr;
+ const char *path, *token;
+ int path_len, tok_len, body_len;
+
+ path = vec[XS_WATCH_PATH];
+ token = adap->token;
+
+ path_len = strlen(path) + 1;
+ tok_len = strlen(token) + 1;
+ body_len = path_len + tok_len;
+
+ hdr.type = XS_WATCH_EVENT;
+ hdr.len = body_len;
+
+ queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
+ queue_reply(adap->dev_data, (char *)path, path_len);
+ queue_reply(adap->dev_data, (char *)token, tok_len);
+}
+
+static LIST_HEAD(watch_list);
static ssize_t xenbus_dev_write(struct file *filp,
const char __user *ubuf,
@@ -116,6 +167,9 @@ static ssize_t xenbus_dev_write(struct f
struct xenbus_dev_transaction *trans = NULL;
uint32_t msg_type;
void *reply;
+ char *path, *token;
+ struct watch_adapter *watch, *tmp_watch;
+ int err;
if ((len + u->len) > sizeof(u->u.buffer))
return -EINVAL;
@@ -169,6 +223,56 @@ static ssize_t xenbus_dev_write(struct f
kfree(reply);
break;
+ case XS_WATCH:
+ case XS_UNWATCH:
+ path = u->u.buffer + sizeof(u->u.msg);
+ token = memchr(path, 0, u->u.msg.len);
+ if (token == NULL)
+ return -EILSEQ;
+ token++;
+
+ if (msg_type == XS_WATCH) {
+ static const char * XS_WATCH_RESP = "OK";
+ struct xsd_sockmsg hdr;
+
+ watch = kmalloc(sizeof(*watch), GFP_KERNEL);
+ watch->watch.node = kmalloc(strlen(path)+1,
+ GFP_KERNEL);
+ strcpy((char *)watch->watch.node, path);
+ watch->watch.callback = watch_fired;
+ watch->token = kmalloc(strlen(token)+1, GFP_KERNEL);
+ strcpy(watch->token, token);
+ watch->dev_data = u;
+
+ err = register_xenbus_watch(&watch->watch);
+ if (err) {
+ free_watch_adapter(watch);
+ return err;
+ }
+
+ list_add(&watch->list, &u->watches);
+
+ hdr.type = XS_WATCH;
+ hdr.len = strlen(XS_WATCH_RESP) + 1;
+ queue_reply(u, (char *)&hdr, sizeof(hdr));
+ queue_reply(u, (char *)XS_WATCH_RESP, hdr.len);
+ } else {
+ list_for_each_entry_safe(watch, tmp_watch,
+ &u->watches, list) {
+ if (!strcmp(watch->token, token) &&
+ !strcmp(watch->watch.node, path))
+ break;
+ {
+ unregister_xenbus_watch(&watch->watch);
+ list_del(&watch->list);
+ free_watch_adapter(watch);
+ break;
+ }
+ }
+ }
+
+ break;
+
default:
return -EINVAL;
}
@@ -191,7 +295,10 @@ static int xenbus_dev_open(struct inode
return -ENOMEM;
INIT_LIST_HEAD(&u->transactions);
+ INIT_LIST_HEAD(&u->watches);
init_waitqueue_head(&u->read_waitq);
+
+ mutex_init(&u->reply_mutex);
filp->private_data = u;
@@ -202,11 +309,18 @@ static int xenbus_dev_release(struct ino
{
struct xenbus_dev_data *u = filp->private_data;
struct xenbus_dev_transaction *trans, *tmp;
+ struct watch_adapter *watch, *tmp_watch;
list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
xenbus_transaction_end(trans->handle, 1);
list_del(&trans->list);
kfree(trans);
+ }
+
+ list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
+ unregister_xenbus_watch(&watch->watch);
+ list_del(&watch->list);
+ free_watch_adapter(watch);
}
kfree(u);
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Aug 02
13:39:47 2006 -0600
@@ -141,7 +141,9 @@ static int read_otherend_details(struct
}
if (strlen(xendev->otherend) == 0 ||
!xenbus_exists(XBT_NIL, xendev->otherend, "")) {
- xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
+ xenbus_dev_fatal(xendev, -ENOENT,
+ "unable to read other end from %s. "
+ "missing or inaccessible.",
xendev->nodename);
free_otherend_details(xendev);
return -ENOENT;
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h Tue Aug 01
14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h Wed Aug 02
13:39:47 2006 -0600
@@ -12,6 +12,9 @@ typedef struct {
int size;
struct semaphore sem;
void *ldt;
+#ifdef CONFIG_XEN
+ int has_foreign_mappings;
+#endif
} mm_context_t;
/* mm/memory.c:exit_mmap hook */
diff -r 4acc6d51f389 -r b76e86966e7e
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h Tue Aug
01 14:58:20 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h Wed Aug
02 13:39:47 2006 -0600
@@ -17,6 +17,7 @@ typedef struct {
struct semaphore sem;
#ifdef CONFIG_XEN
unsigned pinned:1;
+ unsigned has_foreign_mappings:1;
struct list_head unpinned;
#endif
} mm_context_t;
diff -r 4acc6d51f389 -r b76e86966e7e tools/blktap/drivers/blktapctrl.c
--- a/tools/blktap/drivers/blktapctrl.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/blktap/drivers/blktapctrl.c Wed Aug 02 13:39:47 2006 -0600
@@ -61,6 +61,7 @@
#define MSG_SIZE 4096
#define MAX_TIMEOUT 10
#define MAX_RAND_VAL 0xFFFF
+#define MAX_ATTEMPTS 10
int run = 1;
int max_timeout = MAX_TIMEOUT;
@@ -626,13 +627,14 @@ int main(int argc, char *argv[])
{
char *devname;
tapdev_info_t *ctlinfo;
- int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count;
+ int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
struct xs_handle *h;
struct pollfd pfd[NUM_POLL_FDS];
pid_t process;
__init_blkif();
openlog("BLKTAPCTRL", LOG_CONS|LOG_ODELAY, LOG_DAEMON);
+ daemon(0,0);
print_drivers();
init_driver_list();
@@ -651,18 +653,28 @@ int main(int argc, char *argv[])
goto open_failed;
}
+ retry:
/* Set up store connection and watch. */
h = xs_daemon_open();
if (h == NULL) {
DPRINTF("xs_daemon_open failed -- "
"is xenstore running?\n");
- goto open_failed;
+ if (count < MAX_ATTEMPTS) {
+ count++;
+ sleep(2);
+ goto retry;
+ } else goto open_failed;
}
ret = add_blockdevice_probe_watch(h, "Domain-0");
if (ret != 0) {
- DPRINTF("adding device probewatch\n");
- goto open_failed;
+ DPRINTF("Failed adding device probewatch\n");
+ if (count < MAX_ATTEMPTS) {
+ count++;
+ sleep(2);
+ xs_daemon_close(h);
+ goto retry;
+ } else goto open_failed;
}
ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
@@ -691,6 +703,7 @@ int main(int argc, char *argv[])
}
}
+ xs_daemon_close(h);
ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
close(ctlfd);
closelog();
diff -r 4acc6d51f389 -r b76e86966e7e tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/firmware/hvmloader/hvmloader.c Wed Aug 02 13:39:47 2006 -0600
@@ -31,7 +31,7 @@
#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
/* invoke SVM's paged realmode support */
-#define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001
+#define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001
/*
* C runtime start off
@@ -133,15 +133,15 @@ cirrus_check(void)
return inb(0x3C5) == 0x12;
}
-int
-vmmcall(int edi, int esi, int edx, int ecx, int ebx)
+int
+vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx)
{
int eax;
__asm__ __volatile__(
".byte 0x0F,0x01,0xD9"
: "=a" (eax)
- : "a"(0x58454E00), /* XEN\0 key */
+ : "a"(function),
"b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
);
return eax;
@@ -200,7 +200,7 @@ main(void)
if (check_amd()) {
/* AMD implies this is SVM */
puts("SVM go ...\n");
- vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
+ vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0);
} else {
puts("Loading VMXAssist ...\n");
memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
diff -r 4acc6d51f389 -r b76e86966e7e tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/firmware/vmxassist/vm86.c Wed Aug 02 13:39:47 2006 -0600
@@ -52,6 +52,31 @@ static char *rnames[] = { "ax", "cx", "d
static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
#endif /* DEBUG */
+#define PT_ENTRY_PRESENT 0x1
+
+static unsigned
+guest_linear_to_real(unsigned long base, unsigned off)
+{
+ unsigned int gcr3 = oldctx.cr3;
+ unsigned int l1_mfn;
+ unsigned int l0_mfn;
+
+ if (!(oldctx.cr0 & CR0_PG))
+ return base + off;
+
+ l1_mfn = ((unsigned int *)gcr3)[(base >> 22) & 0x3ff ];
+ if (!(l1_mfn & PT_ENTRY_PRESENT))
+ panic("l2 entry not present\n");
+ l1_mfn = l1_mfn & 0xfffff000 ;
+
+ l0_mfn = ((unsigned int *)l1_mfn)[(base >> 12) & 0x3ff];
+ if (!(l0_mfn & PT_ENTRY_PRESENT))
+ panic("l1 entry not present\n");
+ l0_mfn = l0_mfn & 0xfffff000;
+
+ return l0_mfn + off + (base & 0xfff);
+}
+
static unsigned
address(struct regs *regs, unsigned seg, unsigned off)
{
@@ -70,7 +95,7 @@ address(struct regs *regs, unsigned seg,
(mode == VM86_REAL_TO_PROTECTED && regs->cs == seg))
return ((seg & 0xFFFF) << 4) + off;
- entry = ((unsigned long long *) oldctx.gdtr_base)[seg >> 3];
+ entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base,
0))[seg >> 3];
entry_high = entry >> 32;
entry_low = entry & 0xFFFFFFFF;
@@ -94,7 +119,7 @@ trace(struct regs *regs, int adjust, cha
trace(struct regs *regs, int adjust, char *fmt, ...)
{
unsigned off = regs->eip - adjust;
- va_list ap;
+ va_list ap;
if ((traceset & (1 << mode)) &&
(mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) {
@@ -755,7 +780,7 @@ load_seg(unsigned long sel, uint32_t *ba
return 1;
}
- entry = ((unsigned long long *) oldctx.gdtr_base)[sel >> 3];
+ entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base,
0))[sel >> 3];
/* Check the P bit first */
if (!((entry >> (15+32)) & 0x1) && sel != 0)
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/patches/ioemu-ia64
--- a/tools/ioemu/patches/ioemu-ia64 Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/ioemu/patches/ioemu-ia64 Wed Aug 02 13:39:47 2006 -0600
@@ -1,7 +1,7 @@ Index: ioemu/hw/iommu.c
Index: ioemu/hw/iommu.c
===================================================================
---- ioemu.orig/hw/iommu.c 2006-07-28 09:56:58.571272016 +0100
-+++ ioemu/hw/iommu.c 2006-07-28 10:02:10.171049510 +0100
+--- ioemu.orig/hw/iommu.c 2006-08-02 09:46:38.774790244 +0100
++++ ioemu/hw/iommu.c 2006-08-02 09:46:39.030761544 +0100
@@ -82,7 +82,11 @@
#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
#define IOPTE_WAZ 0x00000001 /* Write as zeros */
@@ -16,8 +16,8 @@ Index: ioemu/hw/iommu.c
Index: ioemu/cpu-all.h
===================================================================
---- ioemu.orig/cpu-all.h 2006-07-28 09:58:38.815935452 +0100
-+++ ioemu/cpu-all.h 2006-07-28 10:02:10.171049510 +0100
+--- ioemu.orig/cpu-all.h 2006-08-02 09:46:38.969768383 +0100
++++ ioemu/cpu-all.h 2006-08-02 09:46:39.030761544 +0100
@@ -835,6 +835,31 @@
:"=m" (*(volatile long *)addr)
:"dIr" (nr));
@@ -52,8 +52,8 @@ Index: ioemu/cpu-all.h
/* memory API */
Index: ioemu/vl.c
===================================================================
---- ioemu.orig/vl.c 2006-07-28 09:58:59.672577418 +0100
-+++ ioemu/vl.c 2006-07-28 10:02:10.174049171 +0100
+--- ioemu.orig/vl.c 2006-08-02 09:46:39.020762665 +0100
++++ ioemu/vl.c 2006-08-02 09:47:02.896085814 +0100
@@ -5578,6 +5578,7 @@
exit(-1);
}
@@ -82,7 +82,7 @@ Index: ioemu/vl.c
+ }
+
+ if (xc_ia64_get_pfn_list(xc_handle, domid, page_array,
-+ nr_pages + (GFW_SIZE >> PAGE_SHIFT), 1)!= 1){
++ IO_PAGE_START >> PAGE_SHIFT, 1) != 1){
+ fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno);
+ exit(-1);
+ }
@@ -91,7 +91,7 @@ Index: ioemu/vl.c
+ PROT_READ|PROT_WRITE,
+ page_array[0]);
+
-+ fprintf(logfile, "shared page at pfn:%lx, mfn: %l016x\n",
++ fprintf(logfile, "shared page at pfn:%lx, mfn: %016lx\n",
+ IO_PAGE_START >> PAGE_SHIFT, page_array[0]);
+#endif
#else /* !CONFIG_DM */
@@ -99,8 +99,8 @@ Index: ioemu/vl.c
#ifdef CONFIG_SOFTMMU
Index: ioemu/target-i386-dm/exec-dm.c
===================================================================
---- ioemu.orig/target-i386-dm/exec-dm.c 2006-07-28 09:58:22.882736989
+0100
-+++ ioemu/target-i386-dm/exec-dm.c 2006-07-28 10:03:19.972165675 +0100
+--- ioemu.orig/target-i386-dm/exec-dm.c 2006-08-02 09:46:38.903775782
+0100
++++ ioemu/target-i386-dm/exec-dm.c 2006-08-02 09:46:39.034761096 +0100
@@ -341,6 +341,23 @@
return io_mem_read[io_index >> IO_MEM_SHIFT];
}
@@ -137,8 +137,8 @@ Index: ioemu/target-i386-dm/exec-dm.c
memset(buf, 0xff, len);
Index: ioemu/exec-all.h
===================================================================
---- ioemu.orig/exec-all.h 2006-07-28 09:56:58.572271903 +0100
-+++ ioemu/exec-all.h 2006-07-28 10:02:10.175049059 +0100
+--- ioemu.orig/exec-all.h 2006-08-02 09:46:38.881778248 +0100
++++ ioemu/exec-all.h 2006-08-02 09:46:39.034761096 +0100
@@ -462,12 +462,13 @@
}
#endif
@@ -158,8 +158,8 @@ Index: ioemu/exec-all.h
Index: ioemu/target-i386-dm/cpu.h
===================================================================
---- ioemu.orig/target-i386-dm/cpu.h 2006-07-28 09:56:58.572271903 +0100
-+++ ioemu/target-i386-dm/cpu.h 2006-07-28 10:02:10.175049059 +0100
+--- ioemu.orig/target-i386-dm/cpu.h 2006-08-02 09:46:38.902775894 +0100
++++ ioemu/target-i386-dm/cpu.h 2006-08-02 09:46:39.034761096 +0100
@@ -80,7 +80,11 @@
/* helper2.c */
int main_loop(void);
@@ -175,7 +175,7 @@ Index: ioemu/ia64_intrinsic.h
Index: ioemu/ia64_intrinsic.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/ia64_intrinsic.h 2006-07-28 10:02:10.176048946 +0100
++++ ioemu/ia64_intrinsic.h 2006-08-02 09:46:39.035760983 +0100
@@ -0,0 +1,276 @@
+#ifndef IA64_INTRINSIC_H
+#define IA64_INTRINSIC_H
diff -r 4acc6d51f389 -r b76e86966e7e tools/misc/lomount/lomount.c
--- a/tools/misc/lomount/lomount.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/misc/lomount/lomount.c Wed Aug 02 13:39:47 2006 -0600
@@ -158,7 +158,7 @@ load_gpt (const char *diskimage, struct
entry_size = read_le4 (&data[84]);
#ifdef DEBUG
- fprintf(stderr, "lba entries: %lu, nbr_part: %u, entry_size: %lu\n",
+ fprintf(stderr, "lba entries: %llu, nbr_part: %u, entry_size: %lu\n",
entries_lba, nbr_part, entry_size);
#endif
part = malloc (nbr_part * sizeof (struct pentry));
@@ -404,7 +404,7 @@ int main(int argc, char ** argv)
value is off by (larger than) a value less than one. */
sec = 512; /* TODO: calculate real sector size */
#ifdef DEBUG
- printf("sec: %d\n", sec);
+ printf("sec: %llu\n", sec);
#endif
if (partition > nbr_part)
{
@@ -421,7 +421,7 @@ int main(int argc, char ** argv)
pnum = sec * num;
#ifdef DEBUG
- printf("offset = %d\n", pnum);
+ printf("offset = %llu\n", pnum);
#endif
snprintf(buf, sizeof(buf), "mount -oloop,offset=%lld %s %s",
pnum, diskimage, argv2);
diff -r 4acc6d51f389 -r b76e86966e7e tools/python/xen/util/auxbin.py
--- a/tools/python/xen/util/auxbin.py Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/python/xen/util/auxbin.py Wed Aug 02 13:39:47 2006 -0600
@@ -21,8 +21,8 @@ LIB_BIN_SUFFIX = "xen/bin"
LIB_BIN_SUFFIX = "xen/bin"
## The architectures on which the LIB_64 directory is used. This
-# deliberately excludes ia64.
-LIB_64_ARCHS = [ 'x86_64', 'ppc64', 's390x', 'sparc64']
+# deliberately excludes ia64 and ppc64.
+LIB_64_ARCHS = [ 'x86_64', 's390x', 'sparc64']
import os
diff -r 4acc6d51f389 -r b76e86966e7e tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/python/xen/xm/main.py Wed Aug 02 13:39:47 2006 -0600
@@ -78,7 +78,9 @@ sysrq_help = "sysrq <DomId> <letter>
sysrq_help = "sysrq <DomId> <letter> Send a sysrq to a domain"
domid_help = "domid <DomName> Converts a domain name to a
domain id"
domname_help = "domname <DomId> Convert a domain id to a
domain name"
-vcpu_set_help = """vcpu-set <DomId> <VCPUs> Set the number of VCPUs
for a domain"""
+vcpu_set_help = """vcpu-set <DomId> <VCPUs> Set the number of active
VCPUs for a domain
+ within the range allowed by the domain
+ configuration"""
vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain
(or all domains)"
vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can
use"
dmesg_help = "dmesg [-c|--clear] Read or clear Xen's message
buffer"
diff -r 4acc6d51f389 -r b76e86966e7e tools/security/Makefile
--- a/tools/security/Makefile Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/security/Makefile Wed Aug 02 13:39:47 2006 -0600
@@ -32,6 +32,7 @@ OBJS_XML2BIN := $(patsubst %.c,%.o,$(fil
OBJS_XML2BIN := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_XML2BIN)))
ACM_INST_TOOLS = xensec_tool xensec_xml2bin xensec_gen
+ACM_EZPOLICY = xensec_ezpolicy
ACM_OBJS = $(OBJS_TOOL) $(OBJS_XML2BIN) $(OBJS_GETD)
ACM_SCRIPTS = python/xensec_tools/acm_getlabel
@@ -56,6 +57,7 @@ install: all $(ACM_CONFIG_FILE)
install: all $(ACM_CONFIG_FILE)
$(INSTALL_DIR) -p $(DESTDIR)/usr/sbin
$(INSTALL_PROG) -p $(ACM_INST_TOOLS) $(DESTDIR)/usr/sbin
+ $(INSTALL_PROG) -p $(ACM_EZPOLICY) $(DESTDIR)/usr/sbin
$(INSTALL_DIR) -p $(DESTDIR)$(ACM_CONFIG_DIR)
$(INSTALL_DIR) -p $(DESTDIR)$(ACM_POLICY_DIR)
$(INSTALL_DATA) -p policies/$(ACM_SCHEMA) $(DESTDIR)$(ACM_POLICY_DIR)
diff -r 4acc6d51f389 -r b76e86966e7e tools/xenstore/Makefile
--- a/tools/xenstore/Makefile Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/xenstore/Makefile Wed Aug 02 13:39:47 2006 -0600
@@ -26,7 +26,7 @@ TESTFLAGS= -DTESTING
TESTFLAGS= -DTESTING
TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
-CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm
+CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm
xenstore-chmod
CLIENTS += xenstore-write
CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
@@ -102,7 +102,7 @@ libxenstore.a: xs.o xs_lib.o
.PHONY: clean
clean: testsuite-clean
- rm -f *.o *.opic *.so*
+ rm -f *.a *.o *.opic *.so*
rm -f xenstored xs_random xs_stress xs_crashme
rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
rm -f $(CLIENTS)
diff -r 4acc6d51f389 -r b76e86966e7e tools/xenstore/xenstore_client.c
--- a/tools/xenstore/xenstore_client.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/xenstore/xenstore_client.c Wed Aug 02 13:39:47 2006 -0600
@@ -60,6 +60,8 @@ usage(const char *progname)
errx(1, "Usage: %s [-h] [-s] [-t] key [...]", progname);
#elif defined(CLIENT_exists) || defined(CLIENT_list)
errx(1, "Usage: %s [-h] [-s] key [...]", progname);
+#elif defined(CLIENT_chmod)
+ errx(1, "Usage: %s [-h] [-s] key <mode [modes...]>", progname);
#endif
}
@@ -78,10 +80,61 @@ do_rm(char *path, struct xs_handle *xsh,
}
#endif
+#if defined(CLIENT_chmod)
+#define PATH_SEP '/'
+#define MAX_PATH_LEN 256
+
+static void
+do_chmod(char *path, struct xs_permissions *perms, int nperms, int upto,
+ int recurse, struct xs_handle *xsh, xs_transaction_t xth)
+{
+ int ret;
+
+ if (!path[0])
+ return;
+
+ ret = xs_set_permissions(xsh, xth, path, perms, nperms);
+ if (!ret)
+ err(1, "Error occurred setting permissions on '%s'", path);
+
+ if (upto) {
+ /* apply same permissions to all parent entries: */
+ char *path_sep_ptr = strrchr(path, PATH_SEP);
+ if (!path_sep_ptr)
+ errx(1, "Unable to locate path separator '%c' in '%s'",
+ PATH_SEP, path);
+
+ *path_sep_ptr = '\0'; /* truncate path */
+
+ do_chmod(path, perms, nperms, 1, 0, xsh, xth);
+
+ *path_sep_ptr = PATH_SEP;
+ }
+
+ if (recurse) {
+ char buf[MAX_PATH_LEN];
+
+ /* apply same permissions to all child entries: */
+ unsigned int xsval_n;
+ char **xsval = xs_directory(xsh, xth, path, &xsval_n);
+
+ if (xsval) {
+ int i;
+ for (i = 0; i < xsval_n; i++) {
+ snprintf(buf, MAX_PATH_LEN, "%s/%s", path, xsval[i]);
+
+ do_chmod(buf, perms, nperms, 0, 1, xsh, xth);
+ }
+
+ free(xsval);
+ }
+ }
+}
+#endif
static int
perform(int optind, int argc, char **argv, struct xs_handle *xsh,
- xs_transaction_t xth, int prefix, int tidy)
+ xs_transaction_t xth, int prefix, int tidy, int upto, int recurse)
{
while (optind < argc) {
#if defined(CLIENT_read)
@@ -168,6 +221,41 @@ perform(int optind, int argc, char **arg
}
free(list);
optind++;
+#elif defined(CLIENT_chmod)
+#define MAX_PERMS 16
+ struct xs_permissions perms[MAX_PERMS];
+ int nperms = 0;
+ /* save path pointer: */
+ char *path = argv[optind++];
+ for (; argv[optind]; optind++, nperms++)
+ {
+ if (MAX_PERMS <= nperms)
+ errx(1, "Too many permissions specified. "
+ "Maximum per invocation is %d.", MAX_PERMS);
+
+ perms[nperms].id = atoi(argv[optind]+1);
+
+ switch (argv[optind][0])
+ {
+ case 'n':
+ perms[nperms].perms = XS_PERM_NONE;
+ break;
+ case 'r':
+ perms[nperms].perms = XS_PERM_READ;
+ break;
+ case 'w':
+ perms[nperms].perms = XS_PERM_WRITE;
+ break;
+ case 'b':
+ perms[nperms].perms = XS_PERM_READ | XS_PERM_WRITE;
+ break;
+ default:
+ errx(1, "Invalid permission specification: '%c'",
+ argv[optind][0]);
+ }
+ }
+
+ do_chmod(path, perms, nperms, upto, recurse, xsh, xth);
#endif
}
@@ -183,6 +271,8 @@ main(int argc, char **argv)
int ret = 0, socket = 0;
int prefix = 0;
int tidy = 0;
+ int upto = 0;
+ int recurse = 0;
while (1) {
int c, index = 0;
@@ -193,6 +283,9 @@ main(int argc, char **argv)
{"prefix", 0, 0, 'p'},
#elif defined(CLIENT_rm)
{"tidy", 0, 0, 't'},
+#elif defined(CLIENT_chmod)
+ {"upto", 0, 0, 'u'},
+ {"recurse", 0, 0, 'r'},
#endif
{0, 0, 0, 0}
};
@@ -202,6 +295,8 @@ main(int argc, char **argv)
"p"
#elif defined(CLIENT_rm)
"t"
+#elif defined(CLIENT_chmod)
+ "ur"
#endif
, long_options, &index);
if (c == -1)
@@ -222,6 +317,13 @@ main(int argc, char **argv)
case 't':
tidy = 1;
break;
+#elif defined(CLIENT_chmod)
+ case 'u':
+ upto = 1;
+ break;
+ case 'r':
+ recurse = 1;
+ break;
#endif
}
}
@@ -246,7 +348,7 @@ main(int argc, char **argv)
if (xth == XBT_NULL)
errx(1, "couldn't start transaction");
- ret = perform(optind, argc, argv, xsh, xth, prefix, tidy);
+ ret = perform(optind, argc, argv, xsh, xth, prefix, tidy, upto, recurse);
if (!xs_transaction_end(xsh, xth, ret)) {
if (ret == 0 && errno == EAGAIN) {
diff -r 4acc6d51f389 -r b76e86966e7e tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/xenstore/xenstored_core.c Wed Aug 02 13:39:47 2006 -0600
@@ -80,6 +80,7 @@ int quota_nb_entry_per_domain = 1000;
int quota_nb_entry_per_domain = 1000;
int quota_nb_watch_per_domain = 128;
int quota_max_entry_size = 2048; /* 2K */
+int quota_max_transaction = 10;
#ifdef TESTING
static bool failtest = false;
@@ -1342,6 +1343,7 @@ struct connection *new_connection(connwr
new->write = write;
new->read = read;
new->can_write = true;
+ new->transaction_started = 0;
INIT_LIST_HEAD(&new->out_list);
INIT_LIST_HEAD(&new->watches);
INIT_LIST_HEAD(&new->transaction_list);
@@ -1739,6 +1741,7 @@ static void usage(void)
" --entry-nb <nb> limit the number of entries per domain,\n"
" --entry-size <size> limit the size of entry per domain, and\n"
" --entry-watch <nb> limit the number of watches per domain,\n"
+" --transaction <nb> limit the number of transaction allowed per domain,\n"
" --no-recovery to request that no recovery should be attempted when\n"
" the store is corrupted (debug only),\n"
" --preserve-local to request that /local is preserved on start-up,\n"
@@ -1755,6 +1758,7 @@ static struct option options[] = {
{ "output-pid", 0, NULL, 'P' },
{ "entry-size", 1, NULL, 'S' },
{ "trace-file", 1, NULL, 'T' },
+ { "transaction", 1, NULL, 't' },
{ "no-recovery", 0, NULL, 'R' },
{ "preserve-local", 0, NULL, 'L' },
{ "verbose", 0, NULL, 'V' },
@@ -1774,7 +1778,7 @@ int main(int argc, char *argv[])
const char *pidfile = NULL;
int evtchn_fd = -1;
- while ((opt = getopt_long(argc, argv, "DE:F:HNPS:T:RLVW:", options,
+ while ((opt = getopt_long(argc, argv, "DE:F:HNPS:t:T:RLVW:", options,
NULL)) != -1) {
switch (opt) {
case 'D':
@@ -1804,6 +1808,9 @@ int main(int argc, char *argv[])
case 'S':
quota_max_entry_size = strtol(optarg, NULL, 10);
break;
+ case 't':
+ quota_max_transaction = strtol(optarg, NULL, 10);
+ break;
case 'T':
tracefile = optarg;
break;
diff -r 4acc6d51f389 -r b76e86966e7e tools/xenstore/xenstored_core.h
--- a/tools/xenstore/xenstored_core.h Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/xenstore/xenstored_core.h Wed Aug 02 13:39:47 2006 -0600
@@ -79,6 +79,7 @@ struct connection
/* List of in-progress transactions. */
struct list_head transaction_list;
uint32_t next_transaction_id;
+ unsigned int transaction_started;
/* The domain I'm associated with, if any. */
struct domain *domain;
diff -r 4acc6d51f389 -r b76e86966e7e tools/xenstore/xenstored_transaction.c
--- a/tools/xenstore/xenstored_transaction.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/xenstore/xenstored_transaction.c Wed Aug 02 13:39:47 2006 -0600
@@ -66,6 +66,7 @@ struct transaction
struct list_head changes;
};
+extern int quota_max_transaction;
static unsigned int generation;
/* Return tdb context to use for this connection. */
@@ -125,7 +126,6 @@ void do_transaction_start(struct connect
{
struct transaction *trans, *exists;
char id_str[20];
- int started;
/* We don't support nested transactions. */
if (conn->transaction) {
@@ -133,11 +133,7 @@ void do_transaction_start(struct connect
return;
}
- started = 0;
- list_for_each_entry(trans, &conn->transaction_list, list)
- started++;
-
- if (started > 5) {
+ if (conn->transaction_started > quota_max_transaction) {
send_error(conn, ENOSPC);
return;
}
@@ -166,6 +162,7 @@ void do_transaction_start(struct connect
list_add_tail(&trans->list, &conn->transaction_list);
talloc_steal(conn, trans);
talloc_set_destructor(trans, destroy_transaction);
+ conn->transaction_started++;
sprintf(id_str, "%u", trans->id);
send_reply(conn, XS_TRANSACTION_START, id_str, strlen(id_str)+1);
@@ -188,6 +185,7 @@ void do_transaction_end(struct connectio
conn->transaction = NULL;
list_del(&trans->list);
+ conn->transaction_started--;
/* Attach transaction to arg for auto-cleanup */
talloc_steal(arg, trans);
diff -r 4acc6d51f389 -r b76e86966e7e tools/xenstore/xsls.c
--- a/tools/xenstore/xsls.c Tue Aug 01 14:58:20 2006 -0600
+++ b/tools/xenstore/xsls.c Wed Aug 02 13:39:47 2006 -0600
@@ -3,8 +3,19 @@
#include <string.h>
#include <err.h>
#include <xs.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
-void print_dir(struct xs_handle *h, char *path, int cur_depth)
+static int max_width = 80;
+static int desired_width = 60;
+
+#define TAG " = \"...\""
+#define TAG_LEN strlen(TAG)
+
+#define MIN(a, b) (((a) < (b))? (a) : (b))
+
+void print_dir(struct xs_handle *h, char *path, int cur_depth, int show_perms)
{
char **e;
char newpath[512], *val;
@@ -16,33 +27,103 @@ void print_dir(struct xs_handle *h, char
err(1, "xs_directory (%s)", path);
for (i = 0; i<num; i++) {
- int j;
- for (j=0; j<cur_depth; j++) printf(" ");
- printf("%s", e[i]);
+ char buf[MAX_STRLEN(unsigned int)+1];
+ struct xs_permissions *perms;
+ unsigned int nperms;
+ int linewid;
+
+ for (linewid=0; linewid<cur_depth; linewid++) putchar(' ');
+ linewid += printf("%.*s",
+ (int) (max_width - TAG_LEN - linewid), e[i]);
sprintf(newpath, "%s%s%s", path,
path[strlen(path)-1] == '/' ? "" : "/",
e[i]);
val = xs_read(h, XBT_NULL, newpath, &len);
- if (val == NULL)
+ if (val == NULL) {
printf(":\n");
- else if ((unsigned)len > (151 - strlen(e[i])))
- printf(" = \"%.*s...\"\n", (int)(148 - strlen(e[i])), val);
- else
- printf(" = \"%s\"\n", val);
+ }
+ else {
+ if (max_width < (linewid + len + TAG_LEN)) {
+ printf(" = \"%.*s...\"",
+ (int)(max_width - TAG_LEN - linewid), val);
+ }
+ else {
+ linewid += printf(" = \"%s\"", val);
+ if (show_perms) {
+ putchar(' ');
+ for (linewid++;
+ linewid < MIN(desired_width, max_width);
+ linewid++)
+ putchar((linewid & 1)? '.' : ' ');
+ }
+ }
+ }
free(val);
- print_dir(h, newpath, cur_depth+1);
+
+ if (show_perms) {
+ perms = xs_get_permissions(h, XBT_NULL, newpath, &nperms);
+ if (perms == NULL) {
+ warn("\ncould not access permissions for %s", e[i]);
+ }
+ else {
+ int i;
+ fputs(" (", stdout);
+ for (i = 0; i < nperms; i++) {
+ if (i)
+ putchar(',');
+ xs_perm_to_string(perms+i, buf);
+ fputs(buf, stdout);
+ }
+ putchar(')');
+ }
+ }
+
+ putchar('\n');
+
+ print_dir(h, newpath, cur_depth+1, show_perms);
}
free(e);
}
+void usage(int argc, char *argv[])
+{
+ fprintf(stderr, "Usage: %s [-p] [path]\n", argv[0]);
+}
+
int main(int argc, char *argv[])
{
+ struct winsize ws;
+ int ret;
+ int c;
+ int show_perm = 0;
+
struct xs_handle *xsh = xs_daemon_open();
if (xsh == NULL)
err(1, "xs_daemon_open");
- print_dir(xsh, argc == 1 ? "/" : argv[1], 0);
+#define PAD 2
+
+ memset(&ws, 0, sizeof(ws));
+ ret = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
+ if (!ret)
+ max_width = ws.ws_col - PAD;
+
+ while (0 < (c = getopt(argc, argv, "p"))) {
+ switch (c) {
+ case 'p':
+ show_perm = 1;
+ max_width -= 16;
+ break;
+ case ':':
+ case '?':
+ default:
+ usage(argc, argv);
+ return 0;
+ }
+ }
+
+ print_dir(xsh, (argc - optind) == 1 ? argv[optind] : "/", 0, show_perm);
return 0;
}
diff -r 4acc6d51f389 -r b76e86966e7e xen/Makefile
--- a/xen/Makefile Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/Makefile Wed Aug 02 13:39:47 2006 -0600
@@ -72,7 +72,7 @@ _distclean: clean
.PHONY: delete-unfresh-files
delete-unfresh-files:
@if [ ! -r include/xen/compile.h -o -O include/xen/compile.h ]; then \
- rm -f include/xen/{banner,compile}.h; \
+ rm -f include/xen/compile.h; \
fi
# acm_policy.h contains security policy for Xen
@@ -91,7 +91,7 @@ include/xen/acm_policy.h:
# compile.h contains dynamic build info. Rebuilt on every 'make' invocation.
include/xen/compile.h: LANG=C
-include/xen/compile.h: include/xen/compile.h.in include/xen/banner.h
+include/xen/compile.h: include/xen/compile.h.in
@sed -e 's/@@date@@/$(shell date)/g' \
-e 's/@@time@@/$(shell date +%T)/g' \
-e 's/@@whoami@@/$(shell whoami)/g' \
@@ -103,11 +103,7 @@ include/xen/compile.h: include/xen/compi
-e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \
-e 's!@@changeset@@!$(shell ((hg parents || head -n 7 ../ChangeLog
|| echo date: unavailable) | awk '{FS="changeset:[
]+"}/^changeset/{CS=$$2};{FS="date:[ ]+"}/^date/{D=$$2}; END {print D, CS}')
2>/dev/null)!g' \
< include/xen/compile.h.in > $@.new
- @cat include/xen/banner.h >> $@.new
- @mv -f $@.new $@
-
-include/xen/banner.h:
- tools/figlet/figlet -d tools/figlet Xen $(XEN_FULLVERSION) > $@.new
+ tools/figlet/figlet -d tools/figlet Xen $(XEN_FULLVERSION) >> $@.new
@mv -f $@.new $@
include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
@@ -150,3 +146,15 @@ _cscope:
.PHONY: MAP
MAP:
$(NM) $(TARGET) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw]
\)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
+
+.PHONY: FORCE
+FORCE:
+
+%.o %.i: %.c FORCE
+ $(MAKE) -f $(BASEDIR)/Rules.mk -C $(*D) $(@F)
+
+%.o %.s: %.S FORCE
+ $(MAKE) -f $(BASEDIR)/Rules.mk -C $(*D) $(@F)
+
+%/: FORCE
+ $(MAKE) -f $(BASEDIR)/Rules.mk -C $* built_in.o
diff -r 4acc6d51f389 -r b76e86966e7e xen/Rules.mk
--- a/xen/Rules.mk Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/Rules.mk Wed Aug 02 13:39:47 2006 -0600
@@ -43,7 +43,6 @@ include $(BASEDIR)/arch/$(TARGET_ARCH)/R
# Do not depend on auto-generated header files.
HDRS := $(subst $(BASEDIR)/include/asm-$(TARGET_ARCH)/asm-offsets.h,,$(HDRS))
-HDRS := $(subst $(BASEDIR)/include/xen/banner.h,,$(HDRS))
HDRS := $(subst $(BASEDIR)/include/xen/compile.h,,$(HDRS))
# Note that link order matters!
@@ -106,3 +105,9 @@ _clean_%/: FORCE
%.o: %.S $(HDRS) Makefile
$(CC) $(CFLAGS) $(AFLAGS) -c $< -o $@
+
+%.i: %.c $(HDRS) Makefile
+ $(CPP) $(CFLAGS) $< -o $@
+
+%.s: %.S $(HDRS) Makefile
+ $(CPP) $(CFLAGS) $(AFLAGS) $< -o $@
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/ia64/xen/dom_fw.c
--- a/xen/arch/ia64/xen/dom_fw.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/ia64/xen/dom_fw.c Wed Aug 02 13:39:47 2006 -0600
@@ -19,7 +19,7 @@
#include <asm/sal.h>
#include <asm/meminit.h>
#include <asm/fpswa.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/acpi.h>
#include <asm/dom_fw.h>
@@ -353,7 +353,8 @@ dom_fw_fake_acpi(struct domain *d, struc
strcpy(xsdt->oem_id, "XEN");
strcpy(xsdt->oem_table_id, "Xen/ia64");
strcpy(xsdt->asl_compiler_id, "XEN");
- xsdt->asl_compiler_revision = (XEN_VERSION<<16)|(XEN_SUBVERSION);
+ xsdt->asl_compiler_revision = (xen_major_version() << 16) |
+ xen_minor_version();
xsdt->table_offset_entry[0] = dom_pa((unsigned long) fadt);
tables->madt_ptr = dom_pa((unsigned long) madt);
@@ -367,7 +368,8 @@ dom_fw_fake_acpi(struct domain *d, struc
strcpy(fadt->oem_id, "XEN");
strcpy(fadt->oem_table_id, "Xen/ia64");
strcpy(fadt->asl_compiler_id, "XEN");
- fadt->asl_compiler_revision = (XEN_VERSION<<16)|(XEN_SUBVERSION);
+ fadt->asl_compiler_revision = (xen_major_version() << 16) |
+ xen_minor_version();
strncpy(facs->signature, FACS_SIG, 4);
facs->version = 1;
@@ -413,7 +415,8 @@ dom_fw_fake_acpi(struct domain *d, struc
strcpy(dsdt->oem_id, "XEN");
strcpy(dsdt->oem_table_id, "Xen/ia64");
strcpy(dsdt->asl_compiler_id, "XEN");
- dsdt->asl_compiler_revision = (XEN_VERSION<<16)|(XEN_SUBVERSION);
+ dsdt->asl_compiler_revision = (xen_major_version() << 16) |
+ xen_minor_version();
/* Trivial namespace, avoids ACPI CA complaints */
tables->aml[0] = 0x10; /* Scope */
@@ -454,7 +457,8 @@ dom_fw_fake_acpi(struct domain *d, struc
strcpy(madt->header.oem_id, "XEN");
strcpy(madt->header.oem_table_id, "Xen/ia64");
strcpy(madt->header.asl_compiler_id, "XEN");
- madt->header.asl_compiler_revision = (XEN_VERSION<<16)|(XEN_SUBVERSION);
+ madt->header.asl_compiler_revision = (xen_major_version() << 16) |
+ xen_minor_version();
/* An LSAPIC entry describes a CPU. */
for (i = 0; i < MAX_VIRT_CPUS; i++) {
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/ia64/xen/domain.c Wed Aug 02 13:39:47 2006 -0600
@@ -30,7 +30,7 @@
#include <asm/processor.h>
#include <xen/event.h>
#include <xen/console.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/elf.h>
#include <asm/pgalloc.h>
#include <asm/offsets.h> /* for IA64_THREAD_INFO_SIZE */
@@ -1069,7 +1069,8 @@ int construct_dom0(struct domain *d,
panic("can't allocate start info page");
si = page_to_virt(start_info_page);
memset(si, 0, PAGE_SIZE);
- sprintf(si->magic, "xen-%i.%i-ia64", XEN_VERSION, XEN_SUBVERSION);
+ sprintf(si->magic, "xen-%i.%i-ia64",
+ xen_major_version(), xen_minor_version());
si->nr_pages = max_pages;
si->flags = SIF_INITDOMAIN|SIF_PRIVILEGED;
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/ia64/xen/xensetup.c Wed Aug 02 13:39:47 2006 -0600
@@ -13,7 +13,7 @@
#include <xen/mm.h>
#include <public/version.h>
#include <xen/gdbstub.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/console.h>
#include <xen/domain.h>
#include <xen/serial.h>
@@ -547,11 +547,13 @@ void arch_get_xen_caps(xen_capabilities_
void arch_get_xen_caps(xen_capabilities_info_t info)
{
char *p=info;
-
- p += sprintf(p,"xen-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION);
+ int major = xen_major_version();
+ int minor = xen_minor_version();
+
+ p += sprintf(p,"xen-%d.%d-ia64 ", major, minor);
if (vmx_enabled)
- p += sprintf(p,"hvm-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p,"hvm-%d.%d-ia64 ", major, minor);
*(p-1) = 0;
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/powerpc/boot_of.c
--- a/xen/arch/powerpc/boot_of.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/powerpc/boot_of.c Wed Aug 02 13:39:47 2006 -0600
@@ -22,7 +22,7 @@
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/multiboot.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/spinlock.h>
#include <xen/serial.h>
#include <xen/time.h>
@@ -976,9 +976,9 @@ multiboot_info_t __init *boot_of_init(
of_printf("%s\n", "---------------------------------------------------");
of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
- XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
- XEN_COMPILER, XEN_COMPILE_DATE);
+ xen_major_version(), xen_minor_version(), xen_extra_version(),
+ xen_compile_by(), xen_compile_domain(),
+ xen_compiler(), xen_compile_date());
of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
"boot msr: 0x%lx\n",
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/powerpc/domain_build.c
--- a/xen/arch/powerpc/domain_build.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/powerpc/domain_build.c Wed Aug 02 13:39:47 2006 -0600
@@ -25,7 +25,7 @@
#include <xen/init.h>
#include <xen/ctype.h>
#include <xen/iocap.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <asm/processor.h>
#include <asm/papr.h>
#include "oftree.h"
@@ -153,7 +153,7 @@ int construct_dom0(struct domain *d,
printk("xen_start_info: %p\n", si);
sprintf(si->magic, "xen-%i.%i-powerpc%d%s",
- XEN_VERSION, XEN_SUBVERSION, BITS_PER_LONG, "HV");
+ xen_major_version(), xen_minor_version(), BITS_PER_LONG, "HV");
si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
si->shared_info = ((ulong)d->shared_info) - rma;
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/powerpc/mpic_init.c
--- a/xen/arch/powerpc/mpic_init.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/powerpc/mpic_init.c Wed Aug 02 13:39:47 2006 -0600
@@ -21,7 +21,6 @@
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
-#include <xen/compile.h>
#include <asm/mpic.h>
#include "mpic_init.h"
#include "oftree.h"
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/powerpc/ofd_fixup.c
--- a/xen/arch/powerpc/ofd_fixup.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/powerpc/ofd_fixup.c Wed Aug 02 13:39:47 2006 -0600
@@ -21,7 +21,7 @@
#include <xen/config.h>
#include <xen/lib.h>
#include <xen/sched.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <public/xen.h>
#include "of-devtree.h"
@@ -420,7 +420,7 @@ static ofdn_t ofd_xen_props(void *m, str
ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
xl = snprintf(xen, sizeof (xen), "Xen-%d.%d%s",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION);
+ xen_major_version(), xen_minor_version(), xen_extra_version());
ASSERT(xl < sizeof (xen));
ofd_prop_add(m, n, "version", xen, xl + 1);
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/powerpc/powerpc64/traps.c
--- a/xen/arch/powerpc/powerpc64/traps.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/powerpc/powerpc64/traps.c Wed Aug 02 13:39:47 2006 -0600
@@ -22,7 +22,7 @@
#include <xen/lib.h>
#include <xen/console.h>
#include <public/xen.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/sched.h>
void show_registers(struct cpu_user_regs *regs)
@@ -32,7 +32,7 @@ void show_registers(struct cpu_user_regs
console_start_sync();
printk("----[ Xen-%d.%d%s ]----\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION);
+ xen_major_version(), xen_minor_version(), xen_extra_version());
printk("CPU: %08x DOMID: %08x\n",
smp_processor_id(), current->domain->domain_id);
printk("pc %016lx msr %016lx\n"
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/dom0_ops.c Wed Aug 02 13:39:47 2006 -0600
@@ -429,7 +429,7 @@ long arch_do_dom0_op(struct dom0_op *op,
ret = 0;
hypercall_page = map_domain_page(mfn);
- hypercall_page_initialise(hypercall_page);
+ hypercall_page_initialise(d, hypercall_page);
unmap_domain_page(hypercall_page);
put_page_and_type(mfn_to_page(mfn));
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/domain.c Wed Aug 02 13:39:47 2006 -0600
@@ -819,7 +819,7 @@ unsigned long hypercall_create_continuat
#if defined(__i386__)
regs->eax = op;
- if ( supervisor_mode_kernel )
+ if ( supervisor_mode_kernel || hvm_guest(current) )
regs->eip &= ~31; /* re-execute entire hypercall entry stub */
else
regs->eip -= 2; /* re-execute 'int 0x82' */
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/domain_build.c Wed Aug 02 13:39:47 2006 -0600
@@ -15,7 +15,7 @@
#include <xen/elf.h>
#include <xen/kernel.h>
#include <xen/domain.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/iocap.h>
#include <xen/bitops.h>
#include <asm/regs.h>
@@ -704,7 +704,7 @@ int construct_dom0(struct domain *d,
return -1;
}
- hypercall_page_initialise((void *)hypercall_page);
+ hypercall_page_initialise(d, (void *)hypercall_page);
}
/* Copy the initial ramdisk. */
@@ -726,7 +726,8 @@ int construct_dom0(struct domain *d,
si->nr_pt_frames = nr_pt_pages;
si->mfn_list = vphysmap_start;
sprintf(si->magic, "xen-%i.%i-x86_%d%s",
- XEN_VERSION, XEN_SUBVERSION, BITS_PER_LONG, xen_pae ? "p" : "");
+ xen_major_version(), xen_minor_version(),
+ BITS_PER_LONG, xen_pae ? "p" : "");
/* Write the phys->machine and machine->phys table entries. */
for ( pfn = 0; pfn < d->tot_pages; pfn++ )
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/hvm.c Wed Aug 02 13:39:47 2006 -0600
@@ -27,6 +27,7 @@
#include <xen/softirq.h>
#include <xen/domain.h>
#include <xen/domain_page.h>
+#include <xen/hypercall.h>
#include <asm/current.h>
#include <asm/io.h>
#include <asm/shadow.h>
@@ -329,6 +330,65 @@ void hvm_print_line(struct vcpu *v, cons
pbuf[(*index)++] = c;
}
+#if defined(__i386__)
+
+typedef unsigned long hvm_hypercall_t(
+ unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+#define HYPERCALL(x) [ __HYPERVISOR_ ## x ] = (hvm_hypercall_t *) do_ ## x
+static hvm_hypercall_t *hvm_hypercall_table[] = {
+ HYPERCALL(mmu_update),
+ HYPERCALL(memory_op),
+ HYPERCALL(multicall),
+ HYPERCALL(update_va_mapping),
+ HYPERCALL(event_channel_op_compat),
+ HYPERCALL(xen_version),
+ HYPERCALL(grant_table_op),
+ HYPERCALL(event_channel_op)
+ /*HYPERCALL(hvm_op)*/
+};
+#undef HYPERCALL
+
+void hvm_do_hypercall(struct cpu_user_regs *pregs)
+{
+ if ( ring_3(pregs) )
+ {
+ pregs->eax = -EPERM;
+ return;
+ }
+
+ if ( pregs->eax > ARRAY_SIZE(hvm_hypercall_table) ||
+ !hvm_hypercall_table[pregs->eax] )
+ {
+ DPRINTK("HVM vcpu %d:%d did a bad hypercall %d.\n",
+ current->domain->domain_id, current->vcpu_id,
+ pregs->eax);
+ pregs->eax = -ENOSYS;
+ }
+ else
+ {
+ pregs->eax = hvm_hypercall_table[pregs->eax](
+ pregs->ebx, pregs->ecx, pregs->edx, pregs->esi, pregs->edi);
+ }
+}
+
+#else /* __x86_64__ */
+
+void hvm_do_hypercall(struct cpu_user_regs *pregs)
+{
+ printk("not supported yet!\n");
+}
+
+#endif
+
+/* Initialise a hypercall transfer page for a VMX domain using
+ paravirtualised drivers. */
+void hvm_hypercall_page_initialise(struct domain *d,
+ void *hypercall_page)
+{
+ hvm_funcs.init_hypercall_page(d, hypercall_page);
+}
+
+
/*
* only called in HVM domain BSP context
* when booting, vcpuid is always equal to apic_id
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/i8259.c
--- a/xen/arch/x86/hvm/i8259.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/i8259.c Wed Aug 02 13:39:47 2006 -0600
@@ -590,7 +590,7 @@ int cpu_get_pic_interrupt(struct vcpu *v
/* read the irq from the PIC */
intno = pic_read_irq(s);
- *type = VLAPIC_DELIV_MODE_EXT;
+ *type = APIC_DM_EXTINT;
return intno;
}
@@ -598,7 +598,7 @@ int is_pit_irq(struct vcpu *v, int irq,
{
int pit_vec;
- if (type == VLAPIC_DELIV_MODE_EXT)
+ if (type == APIC_DM_EXTINT)
pit_vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base;
else
pit_vec =
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/io.c Wed Aug 02 13:39:47 2006 -0600
@@ -695,12 +695,11 @@ void hvm_io_assist(struct vcpu *v)
if ( p->type == IOREQ_TYPE_PIO )
hvm_pio_assist(regs, p, io_opp);
- else {
+ else
hvm_mmio_assist(regs, p, io_opp);
- hvm_load_cpu_guest_regs(v, regs);
- }
/* Copy register changes back into current guest state. */
+ hvm_load_cpu_guest_regs(v, regs);
memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
}
/* else an interrupt send event raced us */
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/platform.c Wed Aug 02 13:39:47 2006 -0600
@@ -827,7 +827,6 @@ void handle_mmio(unsigned long va, unsig
/* Copy current guest state into io instruction state structure. */
memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
-
hvm_store_cpu_guest_regs(v, regs, NULL);
if ((inst_len = hvm_instruction_length(v)) <= 0) {
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/svm/intr.c Wed Aug 02 13:39:47 2006 -0600
@@ -76,7 +76,7 @@ interrupt_post_injection(struct vcpu * v
switch(type)
{
- case VLAPIC_DELIV_MODE_EXT:
+ case APIC_DM_EXTINT:
break;
default:
@@ -112,7 +112,7 @@ asmlinkage void svm_intr_assist(void)
struct hvm_domain *plat=&v->domain->arch.hvm_domain;
struct periodic_time *pt = &plat->pl_time.periodic_tm;
struct hvm_virpic *pic= &plat->vpic;
- int intr_type = VLAPIC_DELIV_MODE_EXT;
+ int intr_type = APIC_DM_EXTINT;
int intr_vector = -1;
int re_injecting = 0;
unsigned long rflags;
@@ -172,9 +172,9 @@ asmlinkage void svm_intr_assist(void)
/* have we got an interrupt to inject? */
if (intr_vector >= 0) {
switch (intr_type) {
- case VLAPIC_DELIV_MODE_EXT:
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
+ case APIC_DM_EXTINT:
+ case APIC_DM_FIXED:
+ case APIC_DM_LOWEST:
/* Re-injecting a PIT interruptt? */
if (re_injecting &&
is_pit_irq(v, intr_vector, intr_type)) {
@@ -185,10 +185,10 @@ asmlinkage void svm_intr_assist(void)
svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
interrupt_post_injection(v, intr_vector, intr_type);
break;
- case VLAPIC_DELIV_MODE_SMI:
- case VLAPIC_DELIV_MODE_NMI:
- case VLAPIC_DELIV_MODE_INIT:
- case VLAPIC_DELIV_MODE_STARTUP:
+ case APIC_DM_SMI:
+ case APIC_DM_NMI:
+ case APIC_DM_INIT:
+ case APIC_DM_STARTUP:
default:
printk("Unsupported interrupt type: %d\n", intr_type);
BUG();
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c Wed Aug 02 13:39:47 2006 -0600
@@ -456,6 +456,28 @@ void svm_init_ap_context(struct vcpu_gue
ctxt->flags = VGCF_HVM_GUEST;
}
+static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
+{
+ char *p;
+ int i;
+
+ memset(hypercall_page, 0, PAGE_SIZE);
+
+ for ( i = 0; i < (PAGE_SIZE / 32); i++ )
+ {
+ p = (char *)(hypercall_page + (i * 32));
+ *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */
+ *(u32 *)(p + 1) = i;
+ *(u8 *)(p + 5) = 0x0f; /* vmmcall */
+ *(u8 *)(p + 6) = 0x01;
+ *(u8 *)(p + 7) = 0xd9;
+ *(u8 *)(p + 8) = 0xc3; /* ret */
+ }
+
+ /* Don't support HYPERVISOR_iret at the moment */
+ *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
+}
+
int start_svm(void)
{
u32 eax, ecx, edx;
@@ -503,6 +525,8 @@ int start_svm(void)
hvm_funcs.instruction_length = svm_instruction_length;
hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
hvm_funcs.init_ap_context = svm_init_ap_context;
+
+ hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
hvm_enabled = 1;
@@ -1392,6 +1416,7 @@ static void svm_io_instruction(struct vc
/* Copy current guest state into io instruction state structure. */
memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
+ hvm_store_cpu_guest_regs(v, regs, NULL);
info.bytes = vmcb->exitinfo1;
@@ -1459,7 +1484,7 @@ static void svm_io_instruction(struct vc
count = (addr & ~PAGE_MASK) / size;
}
else
- vmcb->rip = vmcb->exitinfo2;
+ regs->eip = vmcb->exitinfo2;
send_pio_req(regs, port, count, size, addr, dir, 1);
}
@@ -1470,7 +1495,7 @@ static void svm_io_instruction(struct vc
* On SVM, the RIP of the intruction following the IN/OUT is saved in
* ExitInfo2
*/
- vmcb->rip = vmcb->exitinfo2;
+ regs->eip = vmcb->exitinfo2;
if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
hvm_print_line(v, regs->eax); /* guest debug output */
@@ -1980,11 +2005,13 @@ static int svm_cr_access(struct vcpu *v,
return result;
}
-static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs
*regs)
+static inline void svm_do_msr_access(
+ struct vcpu *v, struct cpu_user_regs *regs)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
int inst_len;
u64 msr_content=0;
+ u32 eax, edx;
ASSERT(vmcb);
@@ -2018,6 +2045,14 @@ static inline void svm_do_msr_access(str
default:
if (long_mode_do_msr_read(regs))
goto done;
+
+ if ( rdmsr_hypervisor_regs(regs->ecx, &eax, &edx) )
+ {
+ regs->eax = eax;
+ regs->edx = edx;
+ goto done;
+ }
+
rdmsr_safe(regs->ecx, regs->eax, regs->edx);
break;
}
@@ -2047,7 +2082,8 @@ static inline void svm_do_msr_access(str
vlapic_msr_set(VLAPIC(v), msr_content);
break;
default:
- long_mode_do_msr_write(regs);
+ if ( !long_mode_do_msr_write(regs) )
+ wrmsr_hypervisor_regs(regs->ecx, regs->eax, regs->edx);
break;
}
}
@@ -2314,33 +2350,41 @@ static int svm_do_vmmcall(struct vcpu *v
inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
ASSERT(inst_len > 0);
- /* VMMCALL sanity check */
- if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
- {
- printf("VMMCALL CPL check failed\n");
- return -1;
- }
-
- /* handle the request */
- switch (regs->edi)
- {
- case VMMCALL_RESET_TO_REALMODE:
- if (svm_do_vmmcall_reset_to_realmode(v, regs))
- {
- printf("svm_do_vmmcall_reset_to_realmode() failed\n");
+ if ( regs->eax & 0x80000000 )
+ {
+ /* VMMCALL sanity check */
+ if ( vmcb->cpl > get_vmmcall_cpl(regs->edi) )
+ {
+ printf("VMMCALL CPL check failed\n");
return -1;
}
-
- /* since we just reset the VMCB, return without adjusting the eip */
- return 0;
- case VMMCALL_DEBUG:
- printf("DEBUG features not implemented yet\n");
- break;
- default:
- break;
- }
-
- hvm_print_line(v, regs->eax); /* provides the current domain */
+
+ /* handle the request */
+ switch ( regs->eax )
+ {
+ case VMMCALL_RESET_TO_REALMODE:
+ if ( svm_do_vmmcall_reset_to_realmode(v, regs) )
+ {
+ printf("svm_do_vmmcall_reset_to_realmode() failed\n");
+ return -1;
+ }
+ /* since we just reset the VMCB, return without adjusting
+ * the eip */
+ return 0;
+
+ case VMMCALL_DEBUG:
+ printf("DEBUG features not implemented yet\n");
+ break;
+ default:
+ break;
+ }
+
+ hvm_print_line(v, regs->eax); /* provides the current domain */
+ }
+ else
+ {
+ hvm_do_hypercall(regs);
+ }
__update_guest_eip(vmcb, inst_len);
return 0;
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/vioapic.c Wed Aug 02 13:39:47 2006 -0600
@@ -197,7 +197,7 @@ static void hvm_vioapic_write_indirect(s
redir_content = ((redir_content >> 32) << 32) |
(val & 0xffffffff);
s->redirtbl[redir_index].value = redir_content;
- hvm_vioapic_update_imr(s, redir_index);
+ hvm_vioapic_update_imr(s, redir_index);
} else {
printk("hvm_vioapic_write_indirect "
"error register %x\n", s->ioregsel);
@@ -295,8 +295,8 @@ static int ioapic_inj_irq(hvm_vioapic_t
vector, trig_mode, delivery_mode);
switch (delivery_mode) {
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
+ case dest_Fixed:
+ case dest_LowestPrio:
if (vlapic_set_irq(target, vector, trig_mode) && (trig_mode == 1))
printk("<ioapic_inj_irq> level interrupt happen before cleared\n");
result = 1;
@@ -314,6 +314,7 @@ static int ioapic_match_logical_addr(hvm
static int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint8_t
dest)
{
int result = 0;
+ uint32_t logical_dest = vlapic_get_reg(s->lapic_info[number], APIC_LDR);
ASSERT(s && s->lapic_info[number]);
@@ -321,17 +322,17 @@ static int ioapic_match_logical_addr(hvm
"number %i dest %x\n",
number, dest);
- switch (((s->lapic_info[number]->dest_format >> 28) & 0xf)) {
- case 0xf:
+ switch (vlapic_get_reg(s->lapic_info[number], APIC_DFR))
+ {
+ case APIC_DFR_FLAT:
result =
- (dest & ((s->lapic_info[number]->logical_dest >> 24) & 0xff)) != 0;
- break;
- case 0x0:
+ (dest & GET_APIC_LOGICAL_ID(logical_dest)) != 0;
+ break;
+ case APIC_DFR_CLUSTER:
/* Should we support flat cluster mode ?*/
- if ( ((s->lapic_info[number]->logical_dest >> 28)
+ if ( (GET_APIC_LOGICAL_ID(logical_dest) >> 4
== ((dest >> 0x4) & 0xf)) &&
- (((s->lapic_info[number]->logical_dest >> 24) & 0xf)
- & (dest & 0xf)) )
+ (logical_dest & (dest & 0xf)) )
result = 1;
break;
default:
@@ -410,7 +411,7 @@ static void ioapic_deliver(hvm_vioapic_t
}
switch (delivery_mode) {
- case VLAPIC_DELIV_MODE_LPRI:
+ case dest_LowestPrio:
{
struct vlapic* target;
@@ -430,8 +431,8 @@ static void ioapic_deliver(hvm_vioapic_t
break;
}
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_EXT:
+ case dest_Fixed:
+ case dest_ExtINT:
{
uint8_t bit;
for (bit = 0; bit < s->lapic_count; bit++) {
@@ -452,10 +453,10 @@ static void ioapic_deliver(hvm_vioapic_t
break;
}
- case VLAPIC_DELIV_MODE_SMI:
- case VLAPIC_DELIV_MODE_NMI:
- case VLAPIC_DELIV_MODE_INIT:
- case VLAPIC_DELIV_MODE_STARTUP:
+ case dest_SMI:
+ case dest_NMI:
+ case dest_INIT:
+ case dest__reserved_2:
default:
printk("Not support delivey mode %d\n", delivery_mode);
break;
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/vlapic.c Wed Aug 02 13:39:47 2006 -0600
@@ -43,35 +43,43 @@ extern u32 get_apic_bus_cycle(void);
static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
{
- 0x310ff, 0x117ff, 0x117ff, 0x1f7ff, 0x1f7ff, 0x117ff
+ /* LVTT */
+ LVT_MASK | APIC_LVT_TIMER_PERIODIC,
+ /* LVTTHMR */
+ LVT_MASK | APIC_MODE_MASK,
+ /* LVTPC */
+ LVT_MASK | APIC_MODE_MASK,
+ /* LVT0-1 */
+ LINT_MASK, LINT_MASK,
+ /* LVTERR */
+ LVT_MASK
};
+int hvm_apic_support(struct domain *d)
+{
+ return d->arch.hvm_domain.apic_enabled;
+}
+
int vlapic_find_highest_irr(struct vlapic *vlapic)
{
int result;
- result = find_highest_bit(vlapic->irr, MAX_VECTOR);
-
- if ( result != -1 && result < 16 )
- {
- printk("VLAPIC: irr on reserved bits %d\n ", result);
- domain_crash_synchronous();
- }
-
- return result;
-}
-
-int hvm_apic_support(struct domain *d)
-{
- return d->arch.hvm_domain.apic_enabled;
+ result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_IRR),
+ MAX_VECTOR);
+
+ ASSERT( result == -1 || result > 16);
+
+ return result;
}
s_time_t get_apictime_scheduled(struct vcpu *v)
{
struct vlapic *vlapic = VLAPIC(v);
- if ( !hvm_apic_support(v->domain) || !vlapic_lvt_timer_enabled(vlapic) )
+ if ( !hvm_apic_support(v->domain) ||
+ !vlapic_lvt_enabled(vlapic, APIC_LVTT) )
return -1;
+
return vlapic->vlapic_timer.expires;
}
@@ -79,16 +87,10 @@ int vlapic_find_highest_isr(struct vlapi
{
int result;
- result = find_highest_bit(vlapic->isr, MAX_VECTOR);
-
- if ( result != -1 && result < 16 )
- {
- int i = 0;
- printk("VLAPIC: isr on reserved bits %d, isr is\n ", result);
- for ( i = 0; i < ARRAY_SIZE(vlapic->isr); i++ )
- printk("%d: %p\n", i, (void *)vlapic->isr[i]);
- return -1;
- }
+ result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_ISR),
+ MAX_VECTOR);
+
+ ASSERT( result == -1 || result > 16);
return result;
}
@@ -98,20 +100,21 @@ uint32_t vlapic_update_ppr(struct vlapic
uint32_t tpr, isrv, ppr;
int isr;
- tpr = (vlapic->task_priority >> 4) & 0xf; /* we want 7:4 */
+ tpr = vlapic_get_reg(vlapic, APIC_TASKPRI);
isr = vlapic_find_highest_isr(vlapic);
+
if ( isr != -1 )
isrv = (isr >> 4) & 0xf; /* ditto */
else
isrv = 0;
- if ( tpr >= isrv )
- ppr = vlapic->task_priority & 0xff;
+ if ( (tpr >> 4) >= isrv )
+ ppr = tpr & 0xff;
else
ppr = isrv << 4; /* low 4 bits of PPR have to be cleared */
- vlapic->processor_priority = ppr;
+ vlapic_set_reg(vlapic, APIC_PROCPRI, ppr);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
"vlapic %p, ppr 0x%x, isr 0x%x, isrv 0x%x.",
@@ -133,9 +136,9 @@ static int vlapic_match_dest(struct vcpu
target, source, dest, dest_mode, short_hand, delivery_mode);
if ( unlikely(target == NULL) &&
- ((delivery_mode != VLAPIC_DELIV_MODE_INIT) &&
- (delivery_mode != VLAPIC_DELIV_MODE_STARTUP) &&
- (delivery_mode != VLAPIC_DELIV_MODE_NMI)) )
+ ((delivery_mode != APIC_DM_INIT) &&
+ (delivery_mode != APIC_DM_STARTUP) &&
+ (delivery_mode != APIC_DM_NMI)) )
{
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "uninitialized target vcpu %p, "
"delivery_mode 0x%x, dest 0x%x.\n", v, delivery_mode,
dest);
@@ -143,22 +146,27 @@ static int vlapic_match_dest(struct vcpu
}
switch ( short_hand ) {
- case VLAPIC_NO_SHORTHAND:
+ case APIC_DEST_NOSHORT: /* no shorthand */
if ( !dest_mode ) /* Physical */
{
- result = (target != NULL ? target->id : v->vcpu_id) == dest;
+ result = ( ((target != NULL) ?
+ GET_APIC_ID(vlapic_get_reg(target, APIC_ID)):
+ v->vcpu_id)) == dest;
}
else /* Logical */
{
+ uint32_t ldr = vlapic_get_reg(target, APIC_LDR);
+
if ( target == NULL )
break;
- if ( ((target->dest_format >> 28) & 0xf) == 0xf ) /* Flat mode */
+ /* Flat mode */
+ if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT)
{
- result = (target->logical_dest >> 24) & dest;
+ result = GET_APIC_LOGICAL_ID(ldr) & dest;
}
else
{
- if ( (delivery_mode == VLAPIC_DELIV_MODE_LPRI) &&
+ if ( (delivery_mode == APIC_DM_LOWEST) &&
(dest == 0xff) )
{
/* What shall we do now? */
@@ -166,22 +174,22 @@ static int vlapic_match_dest(struct vcpu
"delivery mode\n");
domain_crash_synchronous();
}
- result = (target->logical_dest == (dest & 0xf)) ?
- ((target->logical_dest >> 4) & (dest >> 4)) : 0;
+ result = (GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
+ (GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0;
}
}
break;
- case VLAPIC_SHORTHAND_SELF:
+ case APIC_DEST_SELF:
if ( target == source )
result = 1;
break;
- case VLAPIC_SHORTHAND_INCLUDE_SELF:
+ case APIC_DEST_ALLINC:
result = 1;
break;
- case VLAPIC_SHORTHAND_EXCLUDE_SELF:
+ case APIC_DEST_ALLBUT:
if ( target != source )
result = 1;
break;
@@ -204,13 +212,13 @@ static int vlapic_accept_irq(struct vcpu
struct vlapic *vlapic = VLAPIC(v);
switch ( delivery_mode ) {
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
+ case APIC_DM_FIXED:
+ case APIC_DM_LOWEST:
/* FIXME add logic for vcpu on reset */
if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) )
break;
- if ( test_and_set_bit(vector, &vlapic->irr[0]) )
+ if ( test_and_set_bit(vector, vlapic->regs + APIC_IRR) )
{
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"level trig mode repeatedly for vector %d\n", vector);
@@ -221,25 +229,25 @@ static int vlapic_accept_irq(struct vcpu
{
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"level trig mode for vector %d\n", vector);
- set_bit(vector, &vlapic->tmr[0]);
+ set_bit(vector, vlapic->regs + APIC_TMR);
}
evtchn_set_pending(v, iopacket_port(v));
result = 1;
break;
- case VLAPIC_DELIV_MODE_RESERVED:
+ case APIC_DM_REMRD:
printk("Ignore deliver mode 3 in vlapic_accept_irq\n");
break;
- case VLAPIC_DELIV_MODE_SMI:
- case VLAPIC_DELIV_MODE_NMI:
+ case APIC_DM_SMI:
+ case APIC_DM_NMI:
/* Fixme */
printk("TODO: for guest SMI/NMI\n");
break;
- case VLAPIC_DELIV_MODE_INIT:
- if ( !level && trig_mode == 1 ) //Deassert
+ case APIC_DM_INIT:
+ if ( level && !(trig_mode & APIC_INT_ASSERT) ) //Deassert
printk("This hvm_vlapic is for P4, no work for De-assert init\n");
else
{
@@ -255,7 +263,7 @@ static int vlapic_accept_irq(struct vcpu
}
break;
- case VLAPIC_DELIV_MODE_STARTUP:
+ case APIC_DM_STARTUP:
if ( v->arch.hvm_vcpu.init_sipi_sipi_state ==
HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM )
break;
@@ -346,22 +354,23 @@ void vlapic_EOI_set(struct vlapic *vlapi
if ( vector == -1 )
return ;
- clear_bit(vector, &vlapic->isr[0]);
+ clear_bit(vector, vlapic->regs + APIC_ISR);
vlapic_update_ppr(vlapic);
- if ( test_and_clear_bit(vector, &vlapic->tmr[0]) )
+ if ( test_and_clear_bit(vector, vlapic->regs + APIC_TMR) )
ioapic_update_EOI(vlapic->domain, vector);
}
-int vlapic_check_vector(struct vlapic *vlapic,
- unsigned char dm, int vector)
-{
- if ( (dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16) )
+static int vlapic_check_vector(struct vlapic *vlapic,
+ uint32_t dm, uint32_t vector)
+{
+ if ( (dm == APIC_DM_FIXED) && (vector < 16) )
{
vlapic->err_status |= 0x40;
- vlapic_accept_irq(vlapic->vcpu, VLAPIC_DELIV_MODE_FIXED,
- vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
- printk("<vlapic_check_vector>: check failed.\n");
+ vlapic_accept_irq(vlapic->vcpu, APIC_DM_FIXED,
+ vlapic_lvt_vector(vlapic, APIC_LVTERR), 0, 0);
+ printk("<vlapic_check_vector>: check failed "
+ " dm %x vector %x\n", dm, vector);
return 0;
}
return 1;
@@ -369,13 +378,16 @@ int vlapic_check_vector(struct vlapic *v
void vlapic_ipi(struct vlapic *vlapic)
{
- unsigned int dest = (vlapic->icr_high >> 24) & 0xff;
- unsigned int short_hand = (vlapic->icr_low >> 18) & 3;
- unsigned int trig_mode = (vlapic->icr_low >> 15) & 1;
- unsigned int level = (vlapic->icr_low >> 14) & 1;
- unsigned int dest_mode = (vlapic->icr_low >> 11) & 1;
- unsigned int delivery_mode = (vlapic->icr_low >> 8) & 7;
- unsigned int vector = (vlapic->icr_low & 0xff);
+ uint32_t icr_low = vlapic_get_reg(vlapic, APIC_ICR);
+ uint32_t icr_high = vlapic_get_reg(vlapic, APIC_ICR2);
+
+ unsigned int dest = GET_APIC_DEST_FIELD(icr_high);
+ unsigned int short_hand = icr_low & APIC_SHORT_MASK;
+ unsigned int trig_mode = icr_low & APIC_INT_ASSERT;
+ unsigned int level = icr_low & APIC_INT_LEVELTRIG;
+ unsigned int dest_mode = icr_low & APIC_DEST_MASK;
+ unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
+ unsigned int vector = icr_low & APIC_VECTOR_MASK;
struct vlapic *target;
struct vcpu *v = NULL;
@@ -384,7 +396,7 @@ void vlapic_ipi(struct vlapic *vlapic)
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr_high 0x%x, icr_low 0x%x, "
"short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
"dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x.",
- vlapic->icr_high, vlapic->icr_low, short_hand, dest,
+ icr_high, icr_low, short_hand, dest,
trig_mode, level, dest_mode, delivery_mode, vector);
for_each_vcpu ( vlapic->domain, v )
@@ -392,7 +404,7 @@ void vlapic_ipi(struct vlapic *vlapic)
if ( vlapic_match_dest(v, vlapic, short_hand,
dest, dest_mode, delivery_mode) )
{
- if ( delivery_mode == VLAPIC_DELIV_MODE_LPRI )
+ if ( delivery_mode == APIC_DM_LOWEST)
set_bit(v->vcpu_id, &lpr_map);
else
vlapic_accept_irq(v, delivery_mode,
@@ -400,7 +412,7 @@ void vlapic_ipi(struct vlapic *vlapic)
}
}
- if ( delivery_mode == VLAPIC_DELIV_MODE_LPRI )
+ if ( delivery_mode == APIC_DM_LOWEST)
{
v = vlapic->vcpu;
target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
@@ -411,158 +423,73 @@ void vlapic_ipi(struct vlapic *vlapic)
}
}
+static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
+{
+ uint32_t counter_passed;
+ s_time_t passed, now = NOW();
+ uint32_t tmcct = vlapic_get_reg(vlapic, APIC_TMCCT);
+
+ ASSERT(vlapic != NULL);
+
+ if ( unlikely(now <= vlapic->timer_last_update) )
+ {
+ passed = ~0x0LL - vlapic->timer_last_update + now;
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "time elapsed.");
+ }
+ else
+ passed = now - vlapic->timer_last_update;
+
+ counter_passed = passed /
+ (APIC_BUS_CYCLE_NS * vlapic->timer_divide_count);
+
+ tmcct -= counter_passed;
+
+ if ( tmcct <= 0 )
+ {
+ if ( unlikely(!vlapic_lvtt_period(vlapic)) )
+ {
+ tmcct = 0;
+ // FIXME: should we add interrupt here?
+ }
+ else
+ {
+ do {
+ tmcct += vlapic_get_reg(vlapic, APIC_TMICT);
+ } while ( tmcct < 0 );
+ }
+ }
+
+ vlapic->timer_last_update = now;
+ vlapic_set_reg(vlapic, APIC_TMCCT, tmcct);
+
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ "timer initial count 0x%x, timer current count 0x%x, "
+ "update 0x%016"PRIx64", now 0x%016"PRIx64", offset 0x%x.",
+ vlapic_get_reg(vlapic, APIC_TMICT),
+ vlapic_get_reg(vlapic, APIC_TMCCT),
+ vlapic->timer_last_update, now, counter_passed);
+
+ return tmcct;
+}
+
static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
unsigned int len, unsigned int *result)
{
- if ( len != 4 )
- printk("<vlapic_read_aligned> read with len=%d (should be 4).\n", len);
+ ASSERT(len == 4 && offset > 0 && offset <= APIC_TDCR);
*result = 0;
switch ( offset ) {
- case APIC_ID:
- *result = vlapic->id << 24;
- break;
-
- case APIC_LVR:
- *result = vlapic->version;
- break;
-
- case APIC_TASKPRI:
- *result = vlapic->task_priority;
- break;
-
case APIC_ARBPRI:
printk("access local APIC ARBPRI register which is for P6\n");
break;
- case APIC_PROCPRI:
- *result = vlapic->processor_priority;
- break;
-
- case APIC_EOI: /* EOI is write only */
- break;
-
- case APIC_LDR:
- *result = vlapic->logical_dest;
- break;
-
- case APIC_DFR:
- *result = vlapic->dest_format;
- break;
-
- case APIC_SPIV:
- *result = vlapic->spurious_vec;
- break;
-
- case APIC_ISR:
- case 0x110:
- case 0x120:
- case 0x130:
- case 0x140:
- case 0x150:
- case 0x160:
- case 0x170:
- *result = vlapic->isr[(offset - APIC_ISR) >> 4];
- break;
-
- case APIC_TMR:
- case 0x190:
- case 0x1a0:
- case 0x1b0:
- case 0x1c0:
- case 0x1d0:
- case 0x1e0:
- case 0x1f0:
- *result = vlapic->tmr[(offset - APIC_TMR) >> 4];
- break;
-
- case APIC_IRR:
- case 0x210:
- case 0x220:
- case 0x230:
- case 0x240:
- case 0x250:
- case 0x260:
- case 0x270:
- *result = vlapic->irr[(offset - APIC_IRR) >> 4];
- break;
-
- case APIC_ESR:
- if ( vlapic->err_write_count )
- *result = vlapic->err_status;
- break;
-
- case APIC_ICR:
- *result = vlapic->icr_low;
- break;
-
- case APIC_ICR2:
- *result = vlapic->icr_high;
- break;
-
- case APIC_LVTT: /* LVT Timer Reg */
- case APIC_LVTTHMR: /* LVT Thermal Monitor */
- case APIC_LVTPC: /* LVT Performance Counter */
- case APIC_LVT0: /* LVT LINT0 Reg */
- case APIC_LVT1: /* LVT Lint1 Reg */
- case APIC_LVTERR: /* LVT Error Reg */
- *result = vlapic->lvt[(offset - APIC_LVTT) >> 4];
- break;
-
- case APIC_TMICT:
- *result = vlapic->timer_initial_count;
- break;
-
case APIC_TMCCT: //Timer CCR
- {
- uint32_t counter_passed;
- s_time_t passed, now = NOW();
-
- if ( unlikely(now <= vlapic->timer_current_update) )
- {
- passed = ~0x0LL - vlapic->timer_current_update + now;
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "time elapsed.");
- }
- else
- passed = now - vlapic->timer_current_update;
-
- counter_passed = passed /
- (APIC_BUS_CYCLE_NS * vlapic->timer_divide_count);
- vlapic->timer_current_count -= counter_passed;
- if ( vlapic->timer_current_count <= 0 )
- {
- if ( unlikely(!vlapic_lvt_timer_period(vlapic)) )
- {
- vlapic->timer_current_count = 0;
- // FIXME: should we add interrupt here?
- }
- else
- {
- do {
- vlapic->timer_current_count +=
vlapic->timer_initial_count;
- } while ( vlapic->timer_current_count < 0 );
- }
- }
-
- *result = vlapic->timer_current_count;
- vlapic->timer_current_update = now;
-
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
- "timer initial count 0x%x, timer current count 0x%x, "
- "update 0x%016"PRIx64", now 0x%016"PRIx64", offset
0x%x.",
- vlapic->timer_initial_count,
vlapic->timer_current_count,
- vlapic->timer_current_update, now, counter_passed);
- }
- break;
-
- case APIC_TDCR:
- *result = vlapic->timer_divconf;
+ *result = vlapic_get_tmcct(vlapic);
break;
default:
- printk("Read local APIC address 0x%x not implemented\n", offset);
- *result = 0;
+ *result = vlapic_get_reg(vlapic, offset);
break;
}
}
@@ -575,6 +502,9 @@ static unsigned long vlapic_read(struct
unsigned long result;
struct vlapic *vlapic = VLAPIC(v);
unsigned int offset = address - vlapic->base_address;
+
+ if ( offset > APIC_TDCR)
+ return 0;
/* some bugs on kernel cause read this with byte*/
if ( len != 4 )
@@ -671,11 +601,11 @@ static void vlapic_write(struct vcpu *v,
switch ( offset ) {
case APIC_ID: /* Local APIC ID */
- vlapic->id = ((val) >> 24) & VAPIC_ID_MASK;
+ vlapic_set_reg(vlapic, APIC_ID, val);
break;
case APIC_TASKPRI:
- vlapic->task_priority = val & 0xff;
+ vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff);
vlapic_update_ppr(vlapic);
break;
@@ -684,24 +614,41 @@ static void vlapic_write(struct vcpu *v,
break;
case APIC_LDR:
- vlapic->logical_dest = val & VAPIC_LDR_MASK;
+ vlapic_set_reg(vlapic, APIC_LDR, val & APIC_LDR_MASK);
break;
case APIC_DFR:
- vlapic->dest_format = val ;
+ vlapic_set_reg(vlapic, APIC_DFR, val);
break;
case APIC_SPIV:
- vlapic->spurious_vec = val & 0x1ff;
- if ( !(vlapic->spurious_vec & 0x100) )
+ vlapic_set_reg(vlapic, APIC_SPIV, val & 0x1ff);
+
+ if ( !( val & APIC_SPIV_APIC_ENABLED) )
{
int i;
+ uint32_t lvt_val;
+
+ vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK;
+
for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
- vlapic->lvt[i] |= 0x10000;
- vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK;
+ {
+ lvt_val = vlapic_get_reg(vlapic, APIC_LVT1 + 0x10 * i);
+ vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i,
+ lvt_val | APIC_LVT_MASKED);
+ }
+
+ if ( (vlapic_get_reg(vlapic, APIC_LVT0) & APIC_MODE_MASK)
+ == APIC_DM_EXTINT )
+ clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
}
else
+ {
vlapic->status &= ~VLAPIC_SOFTWARE_DISABLE_MASK;
+ if ( (vlapic_get_reg(vlapic, APIC_LVT0) & APIC_MODE_MASK)
+ == APIC_DM_EXTINT )
+ set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+ }
break;
case APIC_ESR:
@@ -712,12 +659,12 @@ static void vlapic_write(struct vcpu *v,
case APIC_ICR:
/* No delay here, so we always clear the pending bit*/
- vlapic->icr_low = val & ~(1 << 12);
+ vlapic_set_reg(vlapic, APIC_ICR, val & ~(1 << 12));
vlapic_ipi(vlapic);
break;
case APIC_ICR2:
- vlapic->icr_high = val & 0xff000000;
+ vlapic_set_reg(vlapic, APIC_ICR2, val & 0xff000000);
break;
case APIC_LVTT: // LVT Timer Reg
@@ -727,26 +674,25 @@ static void vlapic_write(struct vcpu *v,
case APIC_LVT1: // LVT Lint1 Reg
case APIC_LVTERR: // LVT Error Reg
{
- int vt = (offset - APIC_LVTT) >> 4;
-
- vlapic->lvt[vt] = val & vlapic_lvt_mask[vt];
if ( vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK )
- vlapic->lvt[vt] |= VLAPIC_LVT_BIT_MASK;
+ val |= APIC_LVT_MASKED;
+
+ val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
+
+ vlapic_set_reg(vlapic, offset, val);
/* On hardware, when write vector less than 0x20 will error */
- vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic->lvt[vt]),
- vlapic_lvt_vector(vlapic, vt));
+ if ( !(val & APIC_LVT_MASKED) )
+ vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic, offset),
+ vlapic_lvt_vector(vlapic, offset));
if ( !vlapic->vcpu_id && (offset == APIC_LVT0) )
{
- if ( (vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_DELIMOD)
- == 0x700 )
- {
- if ( vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_MASK )
+ if ( (val & APIC_MODE_MASK) == APIC_DM_EXTINT )
+ if ( val & APIC_LVT_MASKED)
clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
else
set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
- }
else
clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
}
@@ -758,16 +704,14 @@ static void vlapic_write(struct vcpu *v,
{
s_time_t now = NOW(), offset;
- if ( vlapic_timer_active(vlapic) )
- stop_timer(&vlapic->vlapic_timer);
-
- vlapic->timer_initial_count = val;
- vlapic->timer_current_count = val;
- vlapic->timer_current_update = now;
+ stop_timer(&vlapic->vlapic_timer);
+
+ vlapic_set_reg(vlapic, APIC_TMICT, val);
+ vlapic_set_reg(vlapic, APIC_TMCCT, val);
+ vlapic->timer_last_update = now;
offset = APIC_BUS_CYCLE_NS *
- vlapic->timer_divide_count *
- vlapic->timer_initial_count;
+ vlapic->timer_divide_count * val;
set_timer(&vlapic->vlapic_timer, now + offset);
@@ -775,7 +719,8 @@ static void vlapic_write(struct vcpu *v,
"bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
"timer initial count 0x%x, offset 0x%016"PRIx64", "
"expire @ 0x%016"PRIx64".",
- APIC_BUS_CYCLE_NS, now, vlapic->timer_initial_count,
+ APIC_BUS_CYCLE_NS, now,
+ vlapic_get_reg(vlapic, APIC_TMICT),
offset, now + offset);
}
break;
@@ -787,6 +732,8 @@ static void vlapic_write(struct vcpu *v,
tmp1 = val & 0xf;
tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
vlapic->timer_divide_count = 0x1 << (tmp2 & 0x7);
+
+ vlapic_set_reg(vlapic, APIC_TDCR, val);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divide count is 0x%x",
vlapic->timer_divide_count);
@@ -827,19 +774,18 @@ void vlapic_msr_set(struct vlapic *vlapi
value &= ~MSR_IA32_APICBASE_BSP;
vlapic->apic_base_msr = value;
- vlapic->base_address = vlapic_get_base_address(vlapic);
-
- if ( !(value & 0x800) )
+ vlapic->base_address = vlapic->apic_base_msr &
+ MSR_IA32_APICBASE_BASE;
+
+ /* with FSB delivery interrupt, we can restart APIC functionality */
+ if ( !(value & MSR_IA32_APICBASE_ENABLE) )
set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
+ else
+ clear_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"apic base msr is 0x%016"PRIx64", and base address is 0x%lx.",
vlapic->apic_base_msr, vlapic->base_address);
-}
-
-static inline int vlapic_get_init_id(struct vcpu *v)
-{
- return v->vcpu_id;
}
void vlapic_timer_fn(void *data)
@@ -850,31 +796,32 @@ void vlapic_timer_fn(void *data)
s_time_t now;
if ( unlikely(!vlapic_enabled(vlapic) ||
- !vlapic_lvt_timer_enabled(vlapic)) )
+ !vlapic_lvt_enabled(vlapic, APIC_LVTT)) )
return;
v = vlapic->vcpu;
- timer_vector = vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER);
+ timer_vector = vlapic_lvt_vector(vlapic, APIC_LVTT);
now = NOW();
- vlapic->timer_current_update = now;
-
- if ( test_and_set_bit(timer_vector, &vlapic->irr[0]) )
+ vlapic->timer_last_update = now;
+
+ if ( test_and_set_bit(timer_vector, vlapic->regs + APIC_IRR ))
vlapic->intr_pending_count[timer_vector]++;
- if ( vlapic_lvt_timer_period(vlapic) )
+ if ( vlapic_lvtt_period(vlapic) )
{
s_time_t offset;
-
- vlapic->timer_current_count = vlapic->timer_initial_count;
+ uint32_t tmict = vlapic_get_reg(vlapic, APIC_TMICT);
+
+ vlapic_set_reg(vlapic, APIC_TMCCT, tmict);
offset = APIC_BUS_CYCLE_NS *
- vlapic->timer_divide_count *
- vlapic->timer_initial_count;
+ vlapic->timer_divide_count * tmict;
+
set_timer(&vlapic->vlapic_timer, now + offset);
}
else
- vlapic->timer_current_count = 0;
+ vlapic_set_reg(vlapic, APIC_TMCCT, 0);
#if 0
if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
@@ -887,8 +834,8 @@ void vlapic_timer_fn(void *data)
"now 0x%016"PRIx64", expire @ 0x%016"PRIx64", "
"timer initial count 0x%x, timer current count 0x%x.",
now, vlapic->vlapic_timer.expires,
- vlapic->timer_initial_count,
- vlapic->timer_current_count);
+ vlapic_get_reg(vlapic, APIC_TMICT),
+ vlapic_get_reg(vlapic, APIC_TMCCT));
}
#if 0
@@ -922,23 +869,24 @@ int cpu_get_apic_interrupt(struct vcpu *
{
int highest_irr = vlapic_find_highest_irr(vlapic);
- if ( highest_irr != -1 && highest_irr >= vlapic->processor_priority )
+ if ( highest_irr != -1 &&
+ ( (highest_irr & 0xF0) > vlapic_get_reg(vlapic, APIC_PROCPRI) ) )
{
if ( highest_irr < 0x10 )
{
uint32_t err_vector;
vlapic->err_status |= 0x20;
- err_vector = vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR);
+ err_vector = vlapic_lvt_vector(vlapic, APIC_LVTERR);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"Sending an illegal vector 0x%x.", highest_irr);
- set_bit(err_vector, &vlapic->irr[0]);
+ set_bit(err_vector, vlapic->regs + APIC_IRR);
highest_irr = err_vector;
}
- *mode = VLAPIC_DELIV_MODE_FIXED;
+ *mode = APIC_DM_FIXED;
return highest_irr;
}
}
@@ -952,7 +900,8 @@ int cpu_has_apic_interrupt(struct vcpu*
if (vlapic && vlapic_enabled(vlapic)) {
int highest_irr = vlapic_find_highest_irr(vlapic);
- if (highest_irr != -1 && highest_irr >= vlapic->processor_priority) {
+ if ( highest_irr != -1 &&
+ ( (highest_irr & 0xF0) > vlapic_get_reg(vlapic, APIC_PROCPRI) ) )
{
return 1;
}
}
@@ -967,30 +916,30 @@ void vlapic_post_injection(struct vcpu *
return;
switch ( deliver_mode ) {
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
- set_bit(vector, &vlapic->isr[0]);
- clear_bit(vector, &vlapic->irr[0]);
+ case APIC_DM_FIXED:
+ case APIC_DM_LOWEST:
+ set_bit(vector, vlapic->regs + APIC_ISR);
+ clear_bit(vector, vlapic->regs + APIC_IRR);
vlapic_update_ppr(vlapic);
- if ( vector == vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER) )
+ if ( vector == vlapic_lvt_vector(vlapic, APIC_LVTT) )
{
vlapic->intr_pending_count[vector]--;
if ( vlapic->intr_pending_count[vector] > 0 )
- test_and_set_bit(vector, &vlapic->irr[0]);
+ test_and_set_bit(vector, vlapic->regs + APIC_IRR);
}
break;
/*XXX deal with these later */
- case VLAPIC_DELIV_MODE_RESERVED:
+ case APIC_DM_REMRD:
printk("Ignore deliver mode 3 in vlapic_post_injection\n");
break;
- case VLAPIC_DELIV_MODE_SMI:
- case VLAPIC_DELIV_MODE_NMI:
- case VLAPIC_DELIV_MODE_INIT:
- case VLAPIC_DELIV_MODE_STARTUP:
- vlapic->direct_intr.deliver_mode &= ~(1 << deliver_mode);
+ case APIC_DM_SMI:
+ case APIC_DM_NMI:
+ case APIC_DM_INIT:
+ case APIC_DM_STARTUP:
+ vlapic->direct_intr.deliver_mode &= deliver_mode;
break;
default:
@@ -1002,7 +951,7 @@ static int vlapic_reset(struct vlapic *v
static int vlapic_reset(struct vlapic *vlapic)
{
struct vcpu *v;
- int apic_id, i;
+ int i;
ASSERT( vlapic != NULL );
@@ -1010,29 +959,28 @@ static int vlapic_reset(struct vlapic *v
ASSERT( v != NULL );
- apic_id = v->vcpu_id;
-
vlapic->domain = v->domain;
- vlapic->id = apic_id;
-
vlapic->vcpu_id = v->vcpu_id;
- vlapic->version = VLAPIC_VERSION;
-
- vlapic->apic_base_msr = VLAPIC_BASE_MSR_INIT_VALUE;
-
- if ( apic_id == 0 )
+ vlapic_set_reg(vlapic, APIC_ID, v->vcpu_id << 24);
+
+ vlapic_set_reg(vlapic, APIC_LVR, VLAPIC_VERSION);
+
+ for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
+ vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
+
+ vlapic_set_reg(vlapic, APIC_DFR, 0xffffffffU);
+
+ vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
+
+ vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+
+ if ( v->vcpu_id == 0 )
vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
- vlapic->base_address = vlapic_get_base_address(vlapic);
-
- for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
- vlapic->lvt[i] = VLAPIC_LVT_BIT_MASK;
-
- vlapic->dest_format = 0xffffffffU;
-
- vlapic->spurious_vec = 0xff;
+ vlapic->base_address = vlapic->apic_base_msr &
+ MSR_IA32_APICBASE_BASE;
hvm_vioapic_add_lapic(vlapic, v);
@@ -1046,8 +994,8 @@ static int vlapic_reset(struct vlapic *v
*/
if ( !v->vcpu_id )
{
- vlapic->lvt[VLAPIC_LVT_LINT0] = 0x700;
- vlapic->lvt[VLAPIC_LVT_LINT1] = 0x500;
+ vlapic_set_reg(vlapic, APIC_LVT0, APIC_MODE_EXTINT << 8);
+ vlapic_set_reg(vlapic, APIC_LVT1, APIC_MODE_NMI << 8);
set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
}
#endif
@@ -1055,7 +1003,8 @@ static int vlapic_reset(struct vlapic *v
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"vcpu=%p, id=%d, vlapic_apic_base_msr=0x%016"PRIx64", "
"base_address=0x%0lx.",
- v, vlapic->id, vlapic->apic_base_msr, vlapic->base_address);
+ v, GET_APIC_ID(vlapic_get_reg(vlapic, APIC_ID)),
+ vlapic->apic_base_msr, vlapic->base_address);
return 1;
}
@@ -1077,6 +1026,18 @@ int vlapic_init(struct vcpu *v)
memset(vlapic, 0, sizeof(struct vlapic));
+ vlapic->regs_page = alloc_domheap_page(NULL);
+ if ( vlapic->regs_page == NULL )
+ {
+ printk("malloc vlapic regs error for vcpu %x\n", v->vcpu_id);
+ xfree(vlapic);
+ return -ENOMEM;
+ }
+
+ vlapic->regs = map_domain_page_global(page_to_mfn(vlapic->regs_page));
+
+ memset(vlapic->regs, 0, PAGE_SIZE);
+
VLAPIC(v) = vlapic;
vlapic->vcpu = v;
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/vmx/io.c Wed Aug 02 13:39:47 2006 -0600
@@ -81,7 +81,7 @@ interrupt_post_injection(struct vcpu * v
switch(type)
{
- case VLAPIC_DELIV_MODE_EXT:
+ case APIC_DM_EXTINT:
break;
default:
@@ -198,16 +198,17 @@ asmlinkage void vmx_intr_assist(void)
highest_vector = cpu_get_interrupt(v, &intr_type);
switch (intr_type) {
- case VLAPIC_DELIV_MODE_EXT:
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
+ case APIC_DM_EXTINT:
+ case APIC_DM_FIXED:
+ case APIC_DM_LOWEST:
vmx_inject_extint(v, highest_vector, VMX_DELIVER_NO_ERROR_CODE);
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
break;
- case VLAPIC_DELIV_MODE_SMI:
- case VLAPIC_DELIV_MODE_NMI:
- case VLAPIC_DELIV_MODE_INIT:
- case VLAPIC_DELIV_MODE_STARTUP:
+
+ case APIC_DM_SMI:
+ case APIC_DM_NMI:
+ case APIC_DM_INIT:
+ case APIC_DM_STARTUP:
default:
printk("Unsupported interrupt type\n");
BUG();
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Aug 02 13:39:47 2006 -0600
@@ -137,6 +137,8 @@ static void vmx_relinquish_guest_resourc
if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
{
kill_timer(&VLAPIC(v)->vlapic_timer);
+ unmap_domain_page_global(VLAPIC(v)->regs);
+ free_domheap_page(VLAPIC(v)->regs_page);
xfree(VLAPIC(v));
}
}
@@ -477,7 +479,7 @@ static void vmx_ctxt_switch_to(struct vc
vmx_restore_dr(v);
}
-void stop_vmx(void)
+static void stop_vmx(void)
{
if (read_cr4() & X86_CR4_VMXE)
__vmxoff();
@@ -562,7 +564,7 @@ static void fixup_vm86_seg_bases(struct
BUG_ON(err);
}
-void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
+static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
{
vmx_vmcs_enter(v);
@@ -588,7 +590,7 @@ void vmx_load_cpu_guest_regs(struct vcpu
vmx_vmcs_exit(v);
}
-int vmx_realmode(struct vcpu *v)
+static int vmx_realmode(struct vcpu *v)
{
unsigned long rflags;
@@ -596,7 +598,7 @@ int vmx_realmode(struct vcpu *v)
return rflags & X86_EFLAGS_VM;
}
-int vmx_instruction_length(struct vcpu *v)
+static int vmx_instruction_length(struct vcpu *v)
{
unsigned long inst_len;
@@ -605,7 +607,7 @@ int vmx_instruction_length(struct vcpu *
return inst_len;
}
-unsigned long vmx_get_ctrl_reg(struct vcpu *v, unsigned int num)
+static unsigned long vmx_get_ctrl_reg(struct vcpu *v, unsigned int num)
{
switch ( num )
{
@@ -622,7 +624,7 @@ unsigned long vmx_get_ctrl_reg(struct vc
}
/* SMP VMX guest support */
-void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
+static void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
int vcpuid, int trampoline_vector)
{
int i;
@@ -667,6 +669,50 @@ static int check_vmx_controls(u32 ctrls,
return 0;
}
return 1;
+}
+
+/* Setup HVM interfaces */
+static void vmx_setup_hvm_funcs(void)
+{
+ if ( hvm_enabled )
+ return;
+
+ hvm_funcs.disable = stop_vmx;
+
+ hvm_funcs.initialize_guest_resources = vmx_initialize_guest_resources;
+ hvm_funcs.relinquish_guest_resources = vmx_relinquish_guest_resources;
+
+ hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs;
+ hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs;
+
+ hvm_funcs.realmode = vmx_realmode;
+ hvm_funcs.paging_enabled = vmx_paging_enabled;
+ hvm_funcs.instruction_length = vmx_instruction_length;
+ hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
+
+ hvm_funcs.init_ap_context = vmx_init_ap_context;
+}
+
+static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page)
+{
+ char *p;
+ int i;
+
+ memset(hypercall_page, 0, PAGE_SIZE);
+
+ for ( i = 0; i < (PAGE_SIZE / 32); i++ )
+ {
+ p = (char *)(hypercall_page + (i * 32));
+ *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */
+ *(u32 *)(p + 1) = i;
+ *(u8 *)(p + 5) = 0x0f; /* vmcall */
+ *(u8 *)(p + 6) = 0x01;
+ *(u8 *)(p + 7) = 0xc1;
+ *(u8 *)(p + 8) = 0xc3; /* ret */
+ }
+
+ /* Don't support HYPERVISOR_iret at the moment */
+ *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
}
int start_vmx(void)
@@ -733,21 +779,9 @@ int start_vmx(void)
vmx_save_init_msrs();
- /* Setup HVM interfaces */
- hvm_funcs.disable = stop_vmx;
-
- hvm_funcs.initialize_guest_resources = vmx_initialize_guest_resources;
- hvm_funcs.relinquish_guest_resources = vmx_relinquish_guest_resources;
-
- hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs;
- hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs;
-
- hvm_funcs.realmode = vmx_realmode;
- hvm_funcs.paging_enabled = vmx_paging_enabled;
- hvm_funcs.instruction_length = vmx_instruction_length;
- hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
-
- hvm_funcs.init_ap_context = vmx_init_ap_context;
+ vmx_setup_hvm_funcs();
+
+ hvm_funcs.init_hypercall_page = vmx_init_hypercall_page;
hvm_enabled = 1;
@@ -1075,10 +1109,12 @@ static void vmx_io_instruction(unsigned
/* Copy current guest state into io instruction state structure. */
memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
-
- __vmread(GUEST_RIP, &eip);
- __vmread(GUEST_CS_SELECTOR, &cs);
- __vmread(GUEST_RFLAGS, &eflags);
+ hvm_store_cpu_guest_regs(current, regs, NULL);
+
+ eip = regs->eip;
+ cs = regs->cs;
+ eflags = regs->eflags;
+
vm86 = eflags & X86_EFLAGS_VM ? 1 : 0;
HVM_DBG_LOG(DBG_LEVEL_IO,
@@ -1130,7 +1166,7 @@ static void vmx_io_instruction(unsigned
else
count = (addr & ~PAGE_MASK) / size;
} else
- __update_guest_eip(inst_len);
+ regs->eip += inst_len;
send_pio_req(regs, port, count, size, addr, dir, 1);
}
@@ -1138,7 +1174,7 @@ static void vmx_io_instruction(unsigned
if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
hvm_print_line(current, regs->eax); /* guest debug output */
- __update_guest_eip(inst_len);
+ regs->eip += inst_len;
send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
}
}
@@ -1877,6 +1913,7 @@ static inline void vmx_do_msr_read(struc
static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
{
u64 msr_content = 0;
+ u32 eax, edx;
struct vcpu *v = current;
HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
@@ -1899,8 +1936,16 @@ static inline void vmx_do_msr_read(struc
msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
break;
default:
- if(long_mode_do_msr_read(regs))
+ if (long_mode_do_msr_read(regs))
return;
+
+ if ( rdmsr_hypervisor_regs(regs->ecx, &eax, &edx) )
+ {
+ regs->eax = eax;
+ regs->edx = edx;
+ return;
+ }
+
rdmsr_safe(regs->ecx, regs->eax, regs->edx);
break;
}
@@ -1942,7 +1987,8 @@ static inline void vmx_do_msr_write(stru
vlapic_msr_set(VLAPIC(v), msr_content);
break;
default:
- long_mode_do_msr_write(regs);
+ if ( !long_mode_do_msr_write(regs) )
+ wrmsr_hypervisor_regs(regs->ecx, regs->eax, regs->edx);
break;
}
@@ -2273,16 +2319,16 @@ asmlinkage void vmx_vmexit_handler(struc
__update_guest_eip(inst_len);
break;
}
-#if 0 /* keep this for debugging */
case EXIT_REASON_VMCALL:
+ {
__get_instruction_length(inst_len);
__vmread(GUEST_RIP, &eip);
__vmread(EXIT_QUALIFICATION, &exit_qualification);
- hvm_print_line(v, regs.eax); /* provides the current domain */
+ hvm_do_hypercall(®s);
__update_guest_eip(inst_len);
break;
-#endif
+ }
case EXIT_REASON_CR_ACCESS:
{
__vmread(GUEST_RIP, &eip);
@@ -2323,7 +2369,6 @@ asmlinkage void vmx_vmexit_handler(struc
case EXIT_REASON_MWAIT_INSTRUCTION:
__hvm_bug(®s);
break;
- case EXIT_REASON_VMCALL:
case EXIT_REASON_VMCLEAR:
case EXIT_REASON_VMLAUNCH:
case EXIT_REASON_VMPTRLD:
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/setup.c Wed Aug 02 13:39:47 2006 -0600
@@ -12,7 +12,7 @@
#include <xen/trace.h>
#include <xen/multiboot.h>
#include <xen/domain_page.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/gdbstub.h>
#include <xen/percpu.h>
#include <public/version.h>
@@ -612,30 +612,32 @@ void arch_get_xen_caps(xen_capabilities_
void arch_get_xen_caps(xen_capabilities_info_t info)
{
char *p = info;
+ int major = xen_major_version();
+ int minor = xen_minor_version();
#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
- p += sprintf(p, "xen-%d.%d-x86_32 ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p, "xen-%d.%d-x86_32 ", major, minor);
if ( hvm_enabled )
- p += sprintf(p, "hvm-%d.%d-x86_32 ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
#elif defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE)
- p += sprintf(p, "xen-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p, "xen-%d.%d-x86_32p ", major, minor);
if ( hvm_enabled )
{
- p += sprintf(p, "hvm-%d.%d-x86_32 ", XEN_VERSION, XEN_SUBVERSION);
- p += sprintf(p, "hvm-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
+ p += sprintf(p, "hvm-%d.%d-x86_32p ", major, minor);
}
#elif defined(CONFIG_X86_64)
- p += sprintf(p, "xen-%d.%d-x86_64 ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p, "xen-%d.%d-x86_64 ", major, minor);
if ( hvm_enabled )
{
- p += sprintf(p, "hvm-%d.%d-x86_32 ", XEN_VERSION, XEN_SUBVERSION);
- p += sprintf(p, "hvm-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION);
- p += sprintf(p, "hvm-%d.%d-x86_64 ", XEN_VERSION, XEN_SUBVERSION);
+ p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
+ p += sprintf(p, "hvm-%d.%d-x86_32p ", major, minor);
+ p += sprintf(p, "hvm-%d.%d-x86_64 ", major, minor);
}
#else
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/shadow32.c Wed Aug 02 13:39:47 2006 -0600
@@ -990,18 +990,20 @@ alloc_p2m_table(struct domain *d)
list_ent = d->page_list.next;
- for ( gpfn = 0; list_ent != &d->page_list; gpfn++ )
+ while ( list_ent != &d->page_list )
{
page = list_entry(list_ent, struct page_info, list);
mfn = page_to_mfn(page);
+ gpfn = get_gpfn_from_mfn(mfn);
+
if ( !(error = map_p2m_entry(l1tab, gpfn, mfn)) )
{
domain_crash(d);
break;
}
- list_ent = frame_table[mfn].list.next;
+ list_ent = page->list.next;
}
unmap_domain_page(l1tab);
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/shadow_public.c Wed Aug 02 13:39:47 2006 -0600
@@ -1617,20 +1617,22 @@ alloc_p2m_table(struct domain *d)
list_ent = d->page_list.next;
- for ( gpfn = 0; list_ent != &d->page_list; gpfn++ )
+ while ( list_ent != &d->page_list )
{
struct page_info *page;
page = list_entry(list_ent, struct page_info, list);
mfn = page_to_mfn(page);
+ gpfn = get_gpfn_from_mfn(mfn);
+
if ( !(error = map_p2m_entry(top_tab, gpfn, mfn)) )
{
domain_crash(d);
break;
}
- list_ent = frame_table[mfn].list.next;
+ list_ent = page->list.next;
}
unmap_domain_page(top_tab);
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/traps.c Wed Aug 02 13:39:47 2006 -0600
@@ -44,6 +44,7 @@
#include <xen/symbols.h>
#include <xen/iocap.h>
#include <xen/nmi.h>
+#include <xen/version.h>
#include <asm/shadow.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -429,18 +430,95 @@ DO_ERROR(17, "alignment check", alignmen
DO_ERROR(17, "alignment check", alignment_check)
DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
+int rdmsr_hypervisor_regs(
+ uint32_t idx, uint32_t *eax, uint32_t *edx)
+{
+ idx -= 0x40000000;
+ if ( idx > 0 )
+ return 0;
+
+ *eax = *edx = 0;
+ return 1;
+}
+
+int wrmsr_hypervisor_regs(
+ uint32_t idx, uint32_t eax, uint32_t edx)
+{
+ struct domain *d = current->domain;
+
+ idx -= 0x40000000;
+ if ( idx > 0 )
+ return 0;
+
+ switch ( idx )
+ {
+ case 0:
+ {
+ void *hypercall_page;
+ unsigned long mfn;
+ unsigned long gmfn = ((unsigned long)edx << 20) | (eax >> 12);
+ unsigned int idx = eax & 0xfff;
+
+ if ( idx > 0 )
+ {
+ DPRINTK("Dom%d: Out of range index %u to MSR %08x\n",
+ d->domain_id, idx, 0x40000000);
+ return 0;
+ }
+
+ mfn = gmfn_to_mfn(d, gmfn);
+
+ if ( !mfn_valid(mfn) ||
+ !get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) )
+ {
+ DPRINTK("Dom%d: Bad GMFN %lx (MFN %lx) to MSR %08x\n",
+ d->domain_id, gmfn, mfn, 0x40000000);
+ return 0;
+ }
+
+ hypercall_page = map_domain_page(mfn);
+ hypercall_page_initialise(d, hypercall_page);
+ unmap_domain_page(hypercall_page);
+
+ put_page_and_type(mfn_to_page(mfn));
+ break;
+ }
+
+ default:
+ BUG();
+ }
+
+ return 1;
+}
+
int cpuid_hypervisor_leaves(
uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
- if ( (idx < 0x40000000) || (idx > 0x40000000) )
+ idx -= 0x40000000;
+ if ( idx > 2 )
return 0;
- switch ( idx - 0x40000000 )
+ switch ( idx )
{
case 0:
- *eax = 0x40000000;
- *ebx = 0x006e6558; /* "Xen\0" */
- *ecx = *edx = 0;
+ *eax = 0x40000002; /* Largest leaf */
+ *ebx = 0x566e6558; /* Signature 1: "XenV" */
+ *ecx = 0x65584d4d; /* Signature 2: "MMXe" */
+ *edx = 0x4d4d566e; /* Signature 3: "nVMM" */
+ break;
+
+ case 1:
+ *eax = (xen_major_version() << 16) | xen_minor_version();
+ *ebx = 0; /* Reserved */
+ *ecx = 0; /* Reserved */
+ *edx = 0; /* Reserved */
+ break;
+
+ case 2:
+ *eax = 1; /* Number of hypercall-transfer pages */
+ *ebx = 0x40000000; /* MSR base address */
+ *ecx = 0; /* Features 1 */
+ *edx = 0; /* Features 2 */
break;
default:
@@ -733,7 +811,10 @@ static int __spurious_page_fault(
(l2e_get_flags(l2e) & disallowed_flags) )
return 0;
if ( l2e_get_flags(l2e) & _PAGE_PSE )
- return 1;
+ {
+ l1e = l1e_empty(); /* define before use in debug tracing */
+ goto spurious;
+ }
l1t = map_domain_page(mfn);
l1e = l1t[l1_table_offset(addr)];
@@ -742,6 +823,22 @@ static int __spurious_page_fault(
if ( !(l1e_get_flags(l1e) & required_flags) ||
(l1e_get_flags(l1e) & disallowed_flags) )
return 0;
+
+ spurious:
+ DPRINTK("Spurious fault in domain %u:%u at addr %lx, e/c %04x\n",
+ current->domain->domain_id, current->vcpu_id,
+ addr, regs->error_code);
+#if CONFIG_PAGING_LEVELS >= 4
+ DPRINTK(" l4e = %"PRIpte"\n", l4e_get_intpte(l4e));
+#endif
+#if CONFIG_PAGING_LEVELS >= 3
+ DPRINTK(" l3e = %"PRIpte"\n", l3e_get_intpte(l3e));
+#endif
+ DPRINTK(" l2e = %"PRIpte"\n", l2e_get_intpte(l2e));
+ DPRINTK(" l1e = %"PRIpte"\n", l1e_get_intpte(l1e));
+#ifndef NDEBUG
+ show_registers(regs);
+#endif
return 1;
}
@@ -839,11 +936,7 @@ asmlinkage int do_page_fault(struct cpu_
if ( unlikely(!guest_mode(regs)) )
{
if ( spurious_page_fault(addr, regs) )
- {
- DPRINTK("Spurious fault in domain %u:%u at addr %lx\n",
- current->domain->domain_id, current->vcpu_id, addr);
return EXCRET_not_a_fault;
- }
if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
{
@@ -1282,6 +1375,9 @@ static int emulate_privileged_op(struct
break;
#endif
default:
+ if ( wrmsr_hypervisor_regs(regs->ecx, regs->eax, regs->edx) )
+ break;
+
if ( (rdmsr_safe(regs->ecx, l, h) != 0) ||
(regs->eax != l) || (regs->edx != h) )
DPRINTK("Domain attempted WRMSR %p from "
@@ -1313,6 +1409,12 @@ static int emulate_privileged_op(struct
goto fail;
break;
default:
+ if ( rdmsr_hypervisor_regs(regs->ecx, &l, &h) )
+ {
+ regs->eax = l;
+ regs->edx = h;
+ break;
+ }
/* Everyone can read the MSR space. */
/*DPRINTK("Domain attempted RDMSR %p.\n", _p(regs->ecx));*/
if ( rdmsr_safe(regs->ecx, regs->eax, regs->edx) )
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/x86_32/traps.c Wed Aug 02 13:39:47 2006 -0600
@@ -1,6 +1,6 @@
#include <xen/config.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/domain_page.h>
#include <xen/init.h>
#include <xen/sched.h>
@@ -52,7 +52,7 @@ void show_registers(struct cpu_user_regs
}
printk("----[ Xen-%d.%d%s %s ]----\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
+ xen_major_version(), xen_minor_version(), xen_extra_version(),
print_tainted(taint_str));
printk("CPU: %d\nEIP: %04x:[<%08x>]",
smp_processor_id(), fault_regs.cs, fault_regs.eip);
@@ -131,7 +131,7 @@ asmlinkage void do_double_fault(void)
/* Find information saved during fault and dump it to the console. */
tss = &init_tss[cpu];
printk("*** DOUBLE FAULT: Xen-%d.%d%s %s\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
+ xen_major_version(), xen_minor_version(), xen_extra_version(),
print_tainted(taint_str));
printk("CPU: %d\nEIP: %04x:[<%08x>]",
cpu, tss->cs, tss->eip);
@@ -490,9 +490,11 @@ static void hypercall_page_initialise_ri
*(u16 *)(p+ 6) = 0x82cd; /* int $0x82 */
}
-void hypercall_page_initialise(void *hypercall_page)
-{
- if ( supervisor_mode_kernel )
+void hypercall_page_initialise(struct domain *d, void *hypercall_page)
+{
+ if ( hvm_guest(d->vcpu[0]) )
+ hvm_hypercall_page_initialise(d, hypercall_page);
+ else if ( supervisor_mode_kernel )
hypercall_page_initialise_ring0_kernel(hypercall_page);
else
hypercall_page_initialise_ring1_kernel(hypercall_page);
diff -r 4acc6d51f389 -r b76e86966e7e xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/arch/x86/x86_64/traps.c Wed Aug 02 13:39:47 2006 -0600
@@ -1,6 +1,6 @@
#include <xen/config.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/init.h>
#include <xen/sched.h>
#include <xen/lib.h>
@@ -45,7 +45,7 @@ void show_registers(struct cpu_user_regs
}
printk("----[ Xen-%d.%d%s %s ]----\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
+ xen_major_version(), xen_minor_version(), xen_extra_version(),
print_tainted(taint_str));
printk("CPU: %d\nRIP: %04x:[<%016lx>]",
smp_processor_id(), fault_regs.cs, fault_regs.rip);
@@ -128,7 +128,7 @@ asmlinkage void do_double_fault(struct c
/* Find information saved during fault and dump it to the console. */
printk("*** DOUBLE FAULT: Xen-%d.%d%s %s\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
+ xen_major_version(), xen_minor_version(), xen_extra_version(),
print_tainted(taint_str));
printk("CPU: %d\nRIP: %04x:[<%016lx>]",
cpu, regs->cs, regs->rip);
@@ -432,7 +432,7 @@ long do_set_callbacks(unsigned long even
return 0;
}
-void hypercall_page_initialise(void *hypercall_page)
+static void hypercall_page_initialise_ring3_kernel(void *hypercall_page)
{
char *p;
int i;
@@ -465,6 +465,14 @@ void hypercall_page_initialise(void *hyp
*(u16 *)(p+ 9) = 0x050f; /* syscall */
}
+void hypercall_page_initialise(struct domain *d, void *hypercall_page)
+{
+ if ( hvm_guest(d->vcpu[0]) )
+ hvm_hypercall_page_initialise(d, hypercall_page);
+ else
+ hypercall_page_initialise_ring3_kernel(hypercall_page);
+}
+
/*
* Local variables:
* mode: C
diff -r 4acc6d51f389 -r b76e86966e7e xen/common/Makefile
--- a/xen/common/Makefile Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/common/Makefile Wed Aug 02 13:39:47 2006 -0600
@@ -21,6 +21,7 @@ obj-y += symbols.o
obj-y += symbols.o
obj-y += trace.o
obj-y += timer.o
+obj-y += version.o
obj-y += vsprintf.o
obj-y += xmalloc.o
@@ -28,4 +29,4 @@ obj-$(crash_debug) += gdbstub.o
obj-$(crash_debug) += gdbstub.o
# Object file contains changeset and compiler information.
-kernel.o: $(BASEDIR)/include/xen/compile.h
+version.o: $(BASEDIR)/include/xen/compile.h
diff -r 4acc6d51f389 -r b76e86966e7e xen/common/kernel.c
--- a/xen/common/kernel.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/common/kernel.c Wed Aug 02 13:39:47 2006 -0600
@@ -8,7 +8,7 @@
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/errno.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/sched.h>
#include <xen/shadow.h>
#include <xen/guest_access.h>
@@ -125,13 +125,13 @@ long do_xen_version(int cmd, XEN_GUEST_H
{
case XENVER_version:
{
- return (XEN_VERSION<<16) | (XEN_SUBVERSION);
+ return (xen_major_version() << 16) | xen_minor_version();
}
case XENVER_extraversion:
{
xen_extraversion_t extraversion;
- safe_strcpy(extraversion, XEN_EXTRAVERSION);
+ safe_strcpy(extraversion, xen_extra_version());
if ( copy_to_guest(arg, (char *)extraversion, sizeof(extraversion)) )
return -EFAULT;
return 0;
@@ -140,10 +140,10 @@ long do_xen_version(int cmd, XEN_GUEST_H
case XENVER_compile_info:
{
struct xen_compile_info info;
- safe_strcpy(info.compiler, XEN_COMPILER);
- safe_strcpy(info.compile_by, XEN_COMPILE_BY);
- safe_strcpy(info.compile_domain, XEN_COMPILE_DOMAIN);
- safe_strcpy(info.compile_date, XEN_COMPILE_DATE);
+ safe_strcpy(info.compiler, xen_compiler());
+ safe_strcpy(info.compile_by, xen_compile_by());
+ safe_strcpy(info.compile_domain, xen_compile_domain());
+ safe_strcpy(info.compile_date, xen_compile_date());
if ( copy_to_guest(arg, &info, 1) )
return -EFAULT;
return 0;
@@ -176,7 +176,7 @@ long do_xen_version(int cmd, XEN_GUEST_H
case XENVER_changeset:
{
xen_changeset_info_t chgset;
- safe_strcpy(chgset, XEN_CHANGESET);
+ safe_strcpy(chgset, xen_changeset());
if ( copy_to_guest(arg, (char *)chgset, sizeof(chgset)) )
return -EFAULT;
return 0;
diff -r 4acc6d51f389 -r b76e86966e7e xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/common/sched_credit.c Wed Aug 02 13:39:47 2006 -0600
@@ -296,11 +296,16 @@ __runq_tickle(unsigned int cpu, struct c
cpumask_raise_softirq(mask, SCHEDULE_SOFTIRQ);
}
-static void
+static int
csched_pcpu_init(int cpu)
{
struct csched_pcpu *spc;
unsigned long flags;
+
+ /* Allocate per-PCPU info */
+ spc = xmalloc(struct csched_pcpu);
+ if ( spc == NULL )
+ return -1;
spin_lock_irqsave(&csched_priv.lock, flags);
@@ -311,9 +316,6 @@ csched_pcpu_init(int cpu)
if ( csched_priv.master >= csched_priv.ncpus )
csched_priv.master = cpu;
- /* Allocate per-PCPU info */
- spc = xmalloc(struct csched_pcpu);
- BUG_ON( spc == NULL );
INIT_LIST_HEAD(&spc->runq);
spc->runq_sort_last = csched_priv.runq_sort;
schedule_data[cpu].sched_priv = spc;
@@ -323,6 +325,8 @@ csched_pcpu_init(int cpu)
cpu_set(cpu, csched_priv.idlers);
spin_unlock_irqrestore(&csched_priv.lock, flags);
+
+ return 0;
}
#ifndef NDEBUG
@@ -490,7 +494,10 @@ csched_vcpu_init(struct vcpu *vc)
/* Allocate per-PCPU info */
if ( unlikely(!CSCHED_PCPU(vc->processor)) )
- csched_pcpu_init(vc->processor);
+ {
+ if ( csched_pcpu_init(vc->processor) != 0 )
+ return -1;
+ }
CSCHED_VCPU_CHECK(vc);
diff -r 4acc6d51f389 -r b76e86966e7e xen/drivers/char/Makefile
--- a/xen/drivers/char/Makefile Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/drivers/char/Makefile Wed Aug 02 13:39:47 2006 -0600
@@ -1,6 +1,3 @@ obj-y += console.o
obj-y += console.o
obj-y += ns16550.o
obj-y += serial.o
-
-# Object file contains changeset and compiler information.
-console.o: $(BASEDIR)/include/xen/compile.h
diff -r 4acc6d51f389 -r b76e86966e7e xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/drivers/char/console.c Wed Aug 02 13:39:47 2006 -0600
@@ -8,7 +8,7 @@
#include <stdarg.h>
#include <xen/config.h>
-#include <xen/compile.h>
+#include <xen/version.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/errno.h>
@@ -488,14 +488,14 @@ void init_console(void)
serial_set_rx_handler(sercon_handle, serial_rx);
/* HELLO WORLD --- start-of-day banner text. */
- printk(XEN_BANNER);
+ printk(xen_banner());
printk(" http://www.cl.cam.ac.uk/netos/xen\n");
printk(" University of Cambridge Computer Laboratory\n\n");
printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n",
- XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
- XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
- XEN_COMPILER, XEN_COMPILE_DATE);
- printk(" Latest ChangeSet: %s\n\n", XEN_CHANGESET);
+ xen_major_version(), xen_minor_version(), xen_extra_version(),
+ xen_compile_by(), xen_compile_domain(),
+ xen_compiler(), xen_compile_date());
+ printk(" Latest ChangeSet: %s\n\n", xen_changeset());
set_printk_prefix("(XEN) ");
if ( opt_sync_console )
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-ia64/vmx_platform.h
--- a/xen/include/asm-ia64/vmx_platform.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-ia64/vmx_platform.h Wed Aug 02 13:39:47 2006 -0600
@@ -59,6 +59,17 @@ static inline int vlapic_set_irq(struct
return vmx_vcpu_pend_interrupt(t->vcpu, vec);
}
+enum ioapic_irq_destination_types {
+ dest_Fixed = 0,
+ dest_LowestPrio = 1,
+ dest_SMI = 2,
+ dest__reserved_1 = 3,
+ dest_NMI = 4,
+ dest_INIT = 5,
+ dest__reserved_2 = 6,
+ dest_ExtINT = 7
+};
+
/* As long as we register vlsapic to ioapic controller, it's said enabled */
#define vlapic_enabled(l) 1
#define hvm_apic_support(d) 1
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/domain.h Wed Aug 02 13:39:47 2006 -0600
@@ -55,7 +55,7 @@ extern void toggle_guest_mode(struct vcp
* Initialise a hypercall-transfer page. The given pointer must be mapped
* in Xen virtual address space (accesses are not validated or checked).
*/
-extern void hypercall_page_initialise(void *);
+extern void hypercall_page_initialise(struct domain *d, void *);
struct arch_domain
{
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/hvm/hvm.h Wed Aug 02 13:39:47 2006 -0600
@@ -61,6 +61,8 @@ struct hvm_function_table {
void (*init_ap_context)(struct vcpu_guest_context *ctxt,
int vcpuid, int trampoline_vector);
+
+ void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
};
extern struct hvm_function_table hvm_funcs;
@@ -121,6 +123,9 @@ hvm_instruction_length(struct vcpu *v)
return hvm_funcs.instruction_length(v);
}
+void hvm_hypercall_page_initialise(struct domain *d,
+ void *hypercall_page);
+
static inline unsigned long
hvm_get_guest_ctrl_reg(struct vcpu *v, unsigned int num)
{
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/hvm/support.h
--- a/xen/include/asm-x86/hvm/support.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/hvm/support.h Wed Aug 02 13:39:47 2006 -0600
@@ -29,7 +29,7 @@
#ifndef NDEBUG
#define HVM_DEBUG 1
#else
-#define HVM_DEBUG 0
+#define HVM_DEBUG 1
#endif
#define hvm_guest(v) ((v)->arch.guest_context.flags & VGCF_HVM_GUEST)
@@ -148,4 +148,6 @@ extern void hvm_print_line(struct vcpu *
extern void hvm_print_line(struct vcpu *v, const char c);
extern void hlt_timer_fn(void *data);
+void hvm_do_hypercall(struct cpu_user_regs *pregs);
+
#endif /* __ASM_X86_HVM_SUPPORT_H__ */
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/hvm/svm/vmmcall.h
--- a/xen/include/asm-x86/hvm/svm/vmmcall.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/hvm/svm/vmmcall.h Wed Aug 02 13:39:47 2006 -0600
@@ -23,11 +23,11 @@
#define __ASM_X86_HVM_SVM_VMMCALL_H__
/* VMMCALL command fields */
-#define VMMCALL_CODE_CPL_MASK 0xC0000000
-#define VMMCALL_CODE_MBZ_MASK 0x3FFF0000
+#define VMMCALL_CODE_CPL_MASK 0x60000000
+#define VMMCALL_CODE_MBZ_MASK 0x1FFF0000
#define VMMCALL_CODE_COMMAND_MASK 0x0000FFFF
-#define MAKE_VMMCALL_CODE(cpl,func) ((cpl << 30) | (func))
+#define MAKE_VMMCALL_CODE(cpl,func) ((cpl << 29) | (func) | 0x80000000)
/* CPL=0 VMMCALL Requests */
#define VMMCALL_RESET_TO_REALMODE MAKE_VMMCALL_CODE(0,1)
@@ -38,7 +38,7 @@
/* return the cpl required for the vmmcall cmd */
static inline int get_vmmcall_cpl(int cmd)
{
- return (cmd & VMMCALL_CODE_CPL_MASK) >> 30;
+ return (cmd & VMMCALL_CODE_CPL_MASK) >> 29;
}
#endif /* __ASM_X86_HVM_SVM_VMMCALL_H__ */
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/hvm/vlapic.h Wed Aug 02 13:39:47 2006 -0600
@@ -33,58 +33,31 @@ static __inline__ int find_highest_bit(u
#define VLAPIC(v) (v->arch.hvm_vcpu.vlapic)
-#define VAPIC_ID_MASK 0xff
-#define VAPIC_LDR_MASK (VAPIC_ID_MASK << 24)
#define VLAPIC_VERSION 0x00050014
-#define VLAPIC_BASE_MSR_MASK 0x00000000fffff900ULL
-#define VLAPIC_BASE_MSR_INIT_BASE_ADDR 0xfee00000U
-#define VLAPIC_BASE_MSR_BASE_ADDR_MASK 0xfffff000U
-#define VLAPIC_BASE_MSR_INIT_VALUE (VLAPIC_BASE_MSR_INIT_BASE_ADDR | \
- MSR_IA32_APICBASE_ENABLE)
#define VLOCAL_APIC_MEM_LENGTH (1 << 12)
-#define VLAPIC_LVT_TIMER 0
-#define VLAPIC_LVT_THERMAL 1
-#define VLAPIC_LVT_PERFORM 2
-#define VLAPIC_LVT_LINT0 3
-#define VLAPIC_LVT_LINT1 4
-#define VLAPIC_LVT_ERROR 5
#define VLAPIC_LVT_NUM 6
-#define VLAPIC_LVT_BIT_MASK (1 << 16)
-#define VLAPIC_LVT_BIT_VECTOR 0xff
-#define VLAPIC_LVT_BIT_DELIMOD (0x7 << 8)
-#define VLAPIC_LVT_BIT_DELISTATUS (1 << 12)
-#define VLAPIC_LVT_BIT_POLARITY (1 << 13)
-#define VLAPIC_LVT_BIT_IRR (1 << 14)
-#define VLAPIC_LVT_BIT_TRIG (1 << 15)
-#define VLAPIC_LVT_TIMERMODE (1 << 17)
+#define VLAPIC_ID(vlapic) \
+ (GET_APIC_ID(vlapic_get_reg(vlapic, APIC_ID)))
-#define VLAPIC_DELIV_MODE_FIXED 0x0
-#define VLAPIC_DELIV_MODE_LPRI 0x1
-#define VLAPIC_DELIV_MODE_SMI 0x2
-#define VLAPIC_DELIV_MODE_RESERVED 0x3
-#define VLAPIC_DELIV_MODE_NMI 0x4
-#define VLAPIC_DELIV_MODE_INIT 0x5
-#define VLAPIC_DELIV_MODE_STARTUP 0x6
-#define VLAPIC_DELIV_MODE_EXT 0x7
+/* followed define is not in apicdef.h */
+#define APIC_SHORT_MASK 0xc0000
+#define APIC_DEST_NOSHORT 0x0
+#define APIC_DEST_MASK 0x800
+#define vlapic_lvt_enabled(vlapic, lvt_type) \
+ (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
-#define VLAPIC_NO_SHORTHAND 0x0
-#define VLAPIC_SHORTHAND_SELF 0x1
-#define VLAPIC_SHORTHAND_INCLUDE_SELF 0x2
-#define VLAPIC_SHORTHAND_EXCLUDE_SELF 0x3
+#define vlapic_lvt_vector(vlapic, lvt_type) \
+ (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
-#define vlapic_lvt_timer_enabled(vlapic) \
- (!((vlapic)->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_BIT_MASK))
+#define vlapic_lvt_dm(vlapic, lvt_type) \
+ (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
-#define vlapic_lvt_vector(vlapic, type) \
- ((vlapic)->lvt[(type)] & VLAPIC_LVT_BIT_VECTOR)
-
-#define vlapic_lvt_dm(value) (((value) >> 8) && 7)
-#define vlapic_lvt_timer_period(vlapic) \
- ((vlapic)->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_TIMERMODE)
+#define vlapic_lvtt_period(vlapic) \
+ (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
#define _VLAPIC_GLOB_DISABLE 0x0
#define VLAPIC_GLOB_DISABLE_MASK 0x1
@@ -98,8 +71,12 @@ static __inline__ int find_highest_bit(u
#define vlapic_global_enabled(vlapic) \
(!(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status)))
-#define VLAPIC_IRR(t) ((t)->irr[0])
-#define VLAPIC_ID(t) ((t)->id)
+#define LVT_MASK \
+ APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
+
+#define LINT_MASK \
+ LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
+ APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER
typedef struct direct_intr_info {
int deliver_mode;
@@ -109,72 +86,52 @@ typedef struct direct_intr_info {
#define MAX_VECTOR 256
struct vlapic {
- uint32_t version;
uint32_t status;
- uint32_t id;
uint32_t vcpu_id;
+ uint64_t apic_base_msr;
unsigned long base_address;
- unsigned long isr[BITS_TO_LONGS(MAX_VECTOR)];
- unsigned long irr[BITS_TO_LONGS(MAX_VECTOR)];
- unsigned long tmr[BITS_TO_LONGS(MAX_VECTOR)];
- uint32_t task_priority;
- uint32_t processor_priority;
- uint32_t logical_dest;
- uint32_t dest_format;
- uint32_t spurious_vec;
- uint32_t lvt[6];
- uint32_t timer_initial_count;
- uint32_t timer_current_count;
- uint32_t timer_divconf;
uint32_t timer_divide_count;
struct timer vlapic_timer;
int intr_pending_count[MAX_VECTOR];
- s_time_t timer_current_update;
- uint32_t icr_high;
- uint32_t icr_low;
+ s_time_t timer_last_update;
direct_intr_info_t direct_intr;
uint32_t err_status;
- unsigned long init_ticks;
uint32_t err_write_count;
- uint64_t apic_base_msr;
struct vcpu *vcpu;
struct domain *domain;
+ struct page_info *regs_page;
+ void *regs;
};
-static inline int vlapic_set_irq(struct vlapic *t, uint8_t vec, uint8_t trig)
+static inline int vlapic_set_irq(struct vlapic *vlapic,
+ uint8_t vec, uint8_t trig)
{
int ret;
- ret = test_and_set_bit(vec, &t->irr[0]);
+ ret = test_and_set_bit(vec, vlapic->regs + APIC_IRR);
if ( trig )
- set_bit(vec, &t->tmr[0]);
+ set_bit(vec, vlapic->regs + APIC_TMR);
/* We may need to wake up target vcpu, besides set pending bit here */
return ret;
}
-static inline int vlapic_timer_active(struct vlapic *vlapic)
+static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
{
- return active_timer(&vlapic->vlapic_timer);
+ return *( (uint32_t *)(vlapic->regs + reg));
}
-int vlapic_find_highest_irr(struct vlapic *vlapic);
+static inline void vlapic_set_reg(struct vlapic *vlapic,
+ uint32_t reg, uint32_t val)
+{
+ *((uint32_t *)(vlapic->regs + reg)) = val;
+}
-int vlapic_find_highest_isr(struct vlapic *vlapic);
-
-static uint32_t inline vlapic_get_base_address(struct vlapic *vlapic)
-{
- return (vlapic->apic_base_msr & VLAPIC_BASE_MSR_BASE_ADDR_MASK);
-}
void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
int cpu_has_apic_interrupt(struct vcpu* v);
int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
-
-extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
-
-int vlapic_update(struct vcpu *v);
extern int vlapic_init(struct vcpu *vc);
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Aug 02 13:39:47 2006 -0600
@@ -25,7 +25,6 @@
#include <public/hvm/vmx_assist.h>
extern int start_vmx(void);
-extern void stop_vmx(void);
extern void vmcs_dump_vcpu(void);
extern void vmx_init_vmcs_config(void);
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Wed Aug 02 13:39:47 2006 -0600
@@ -153,7 +153,7 @@ extern unsigned int cpu_rev;
/*
* Exit Qualifications for MOV for Control Register Access
*/
-#define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control
register */
+#define CONTROL_REG_ACCESS_NUM 0xf /* 3:0, number of control
register */
#define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */
#define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose
register */
#define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/asm-x86/processor.h Wed Aug 02 13:39:47 2006 -0600
@@ -547,6 +547,10 @@ extern void mcheck_init(struct cpuinfo_x
int cpuid_hypervisor_leaves(
uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+int rdmsr_hypervisor_regs(
+ uint32_t idx, uint32_t *eax, uint32_t *edx);
+int wrmsr_hypervisor_regs(
+ uint32_t idx, uint32_t eax, uint32_t edx);
#endif /* !__ASSEMBLY__ */
diff -r 4acc6d51f389 -r b76e86966e7e xen/include/public/io/netif.h
--- a/xen/include/public/io/netif.h Tue Aug 01 14:58:20 2006 -0600
+++ b/xen/include/public/io/netif.h Wed Aug 02 13:39:47 2006 -0600
@@ -124,6 +124,14 @@ typedef struct netif_rx_request netif_rx
#define _NETRXF_csum_blank (1)
#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank)
+/* Packet continues in the next request descriptor. */
+#define _NETRXF_more_data (2)
+#define NETRXF_more_data (1U<<_NETRXF_more_data)
+
+/* Packet to be followed by extra descriptor(s). */
+#define _NETRXF_extra_info (3)
+#define NETRXF_extra_info (1U<<_NETRXF_extra_info)
+
struct netif_rx_response {
uint16_t id;
uint16_t offset; /* Offset in page of start of received packet */
diff -r 4acc6d51f389 -r b76e86966e7e docs/figs/acm_ezpolicy.eps
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/figs/acm_ezpolicy.eps Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,657 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%BoundingBox: 0 0 610 400
+%
+% created by bmeps 1.2.6a (SCCS=1.78)
+%
+/pstr
+ 610 string
+def
+/inputf
+ currentfile
+ /ASCII85Decode filter
+ /RunLengthDecode filter
+def
+gsave
+0 400 translate
+610 400 scale
+610 400 8 [610 0 0 -400 0 0]
+{ inputf pstr readstring pop }
+image
+r;Qmd6ps=,r^.#_8PW)W:fC4d:Jq*eJka?]JkgnmP"tsM!)EGd%7s,^8OZ0@77fs;
+77'??705qG4Sf!e6pt0dBlJ$6H@:BtK8,-ULk:B'L4Y6'Lk:B'LAZi1L4b55LA6Du
+I0Fb9BjEhVr;R-m;-@(3Bk_O*G'831IK"hMI=cm!I=cmrIK"NpI=6EfrcJ3er,r'_
+rHA*Xrb2IA?VWW\rrbGT86&[h<YAS@?"./K?t*JP@UEMP?XI8M@=hm=@$4oL>KU.P
+?s?uGrEfn8='8U';G^7f;cEWm%T$&$92/,W:eEo6!<5/JrCmAj;cQlt>52>&>5_TU
+=+XM*=+XN'<sVf+;c?Oj:/+I^9E%Np8P)EB770F.5smgo+94/a6N0LZ9heG_;cWft
+rE0#!!*0"rJl'QcJkptoO\bjL#Ydra8P)EB77I&?"@5=;5!8g*%Q6't*ATB46qBjC
+9i+berDies#ZXl';c-Cf:/6C8Jk^hkJkZ>A:QXo4rs"Q\9heEFlgauZO%i5;8rW'*
+rt:&I2DR$=.30ck4@D_29hnM`;u9So;Z]fm;#X2j9hg44b"I=Ya\%.Vn4>s,jHtgV
+I!BaVEH,o8Bk_3g>%QEJ8P+s'R#6KCG]\+KEGoc0BkLjXA_N/87uZW-R?<GaKSG,3
+J:N#pH?F+JhM2"b$RdA<+>PuC84ZHM;#O;n<E8ur!DuYl:B!t>8qKZt8qKY(8Qc"]
+Xg"XjQ&q#bMM[(?IsQ-K=^(,_8cP6]YbdeROH,9WM2$Y4H?*\%>3e[Ks/*9:Ybn+b
+S=,_1P`h&aK6h<Hl8CCN-mocQ1-.]l9jqaG@UWeYB4><7s+3no97fdX8qKY(8Q>_M
+ZF-X&R$3VkN/NLGJ:)KU>snW`8cOgV[A][aPE:c_Mhm(;I!'726iTYEs-p[8Z`0do
+SXZ%8QBRAfL44&>s#)bg-mocQ1-@oo8l\nn='Jo.<rc@fs+3mq97ffq92GS@W2lVY
+Oc5*LJ:;fjG&hM8?:Orf9E0[DX.blBN/3.;IX6<`Ec5Yu7fPqGs-'dtXJDJWQBI>i
+MMd.@J9u69s#)bg-n,oS1-@oo9%j!_lMlH/JkL\gN(Y,iJ=W=!O,8O?H?O=GChdZt
+Ame7292#;8SY)8Bs!VPm?qUGg7/r=IX/+AIP)bETK7JFNaa8;R=oUB<0.87b,W7YM
+8PB*YrqcWrn"3GU5QXKCkPG5V9+(@lPY78@PY78@p%(fWl1t3L!U9FI9*+;Qr(I%h
+!r:o[fh2A7n*NdIrrW#WY4kQml1mtFn*f[;q>^"Y!U9E39BSs"8FT.Zs*U)uOc+pC
+H?O:FC2!QX$"-C*84`c.Q'[X,rsNFN?qUGg7/r4?Un@Yd"H%teJ:.@r&UAV@=oUB<
+0.81`,W7eQ8k]3Zrql]tLDXF&rkATFBGc!gr;QaLrC[OTs//K!s//K!s4/st9*5.n
+0)S?Ds8O_>9*5.n0)\EIs8O0emJjZd9**Z;n4Nf6p&7Scn*W+%9*YFr++!>S\+iT#
+s8O]En*W+%9*67Xs8W$>o1K/bs"8mrJkO]g)uk,DOc>0KI<]jPCM79h@Us%W9)hOW
+s*'QeNV<A\A7]+?s$fEVLRk',QN$mcKn4[Ort9L!GB$ab3&WE<.2F0e4[Vb5s7lTl
+rr^k4Gk_%6!f&JMrVlj\rC[O6s2@ISs2@ISs04`Z9*5.n+8eb5s8O2/9*5.n+8nh;
+s8O06UAsdRo1K/bs"a+;!rr9Ur_!8M2XX3Cs8O06UAsdRq+CqlruXm,2E'np!rr9B
+n4Ni_ruZhcJkO]g2#hcWMi!1>HZsLKCM.0e@:EbS8cMFVs*'?YM>r-RGB.V;B4PKO
+@Urh;s$]?ULR=KsP`PhD!.b(K'6SA=G&UR`3&`K=.2F0e4\/:Bs7lTmrrT)Pa7fN7
+f/SQbrr>[i9+[?fj?`&1j?`&1H::K`s8UsT9,.F+hXsPAruXnjs1qA.ruXnjs8UsT
+9*Fqfs66<X9*OS[p&G%6rC[k)ruXm,s7nECs8UsK92".As5$CArVm$o9A]^KhYp.O
+d.RG3\4cf#!)*=k"\VMFs8UsT9*P@Vq>]]Sr(@IuruXm,s7nEChZ*W4r_!=mru_7?
+%SKIAp&F]p9BlJO9;DOUqF^niru_55"5a(XhYp.MhZ*W4r_!=mruZhcJkO]g2?.WL
+LkgY6I!BdQD/!Tm@U`hR8H2=Us)<[JL];mPG]dtBBkCoU@Ui_8s$fKXJWlCbP)kS"
+rtK^$FEMbF=8t6=2D6Ts-oaOa925H]rWN9$k:#fjrrYO$s8Vsj./!U$s6'DCs7@C,
+fDiO^s4'h<s8T@11]RIshZ(827fWK1fDiO^s4.*C$o<hAmRp:2s26#Zru_265QCa*
+9pPb0/kuBGZ*Q7<s1P?1eP/d<ruW?>s2Co9gJ-)qehc1*859-a+!45Wru]km]r1n\
+9hkZfS"frG9DqR2s8O08Q2fDffDiO^s4'h<s8O08s8O1gs40!_b"0)CbtH[g]JfX[
+(B=CV92!n:]VkeZ9@s3VVuP7>9E5#6JkL\gf1S%%Ck%(jK7A8nF`MA8B4YR^@pMS(
+92#;$ItNFSIscK`Ec,Z*AcH4L>t4ic8H4.!P*;#gN/@Q6!do9;rcJ`h<rY9C2_QTu
+-oaOa9i1lbrWE3#8@S0i"5bO$s8,PBhZ'k\S,]bneh^(truX`1q*@dUruX^$s8VEb
+bo]DMs8O2;ruX`1q*@d4qYpL#2bs5L+%?50+8nr!s8O1,nG.Ap:B1>97S*CU+%H;+
+5u.I[+&;\4+%?5*5P>$u5u'R1:B1>9:/:ih+8Z!Z7fW9M:B1>99E5#QrD"[=ru[Qr
+q0G:%ruX`1q*@dUruY#9ru^q6+$iXb6Vd:E61t8(7Jfgqs8O09:AXu47fW9MqYqX,
+s7nrUs8O0m:4c6m:,W&bH\$d"J:2`gF`D;6B4PL\>"&Bc:B,!SJV*oPI<p-\EGfN(
+s'oJ@7/ohMs*BQaOcb]ar;RIXH$4=PCfLEr4#\]A)C[d892/7_q#1?pT4%0g!f)%#
+qbT8is5`eop#Q.X5Z%L\+&N";02V]K+&Gf6s7u]U78Qh\ru_:@+&N";0C&SN0E;%o
+;#gP;;#gP;rD<Im($(c9:/Luj+&Gf6ruY);s"@4KruY)7rrXqSru_/8(B=CV:f.2l
++92?_;#gPK;#gP;;#gP;rD<Im($(c9:B1>9;#gPK;#gP;;#gP;s8O2=:^4i;\c:h7
+:A[j's8O0;;#gP;;#gPKs8O0;s8O`Ks8O0m;!:`-:@M"8s'p5#J:W6"H[9mXE,96"
+@piD+s%Z>h@s39Ns+#QFH?XIMCh`oZ?s#er9M5>.L5_1SNrK%pL]@DJH?XLPBiG$r
+5!(PO*%<s992JOdq#1?p)!Chs!P_M2,lhHOrrF8"qboJBs8Uh2huE_&92k]e+&i48
++&i4>+&c,<s,5h8`D]_8ru_+;+&i48+92?_9E5#6;u6M9;uck>rDNass8F)U5YtBX
+s8O0>;u6M9;ucY8;uck>;u6Ol*s2<=+8f%Qs8O0>;uck>qYqX9s7ma8s8O0>s8O2>
+;ZZpurZ;h>:fI5j+&i48+&i4>+&i4>+8Z!ZqbmXjs8T>dqG7t-ruY'6qYqX6s7mc5
+ruY);q&`H5ruZhhJl(&q"TMhJH%#Ph-ZO$=An,.I5lXYWs'K_jIK+bEH[0gYEGfOk
+@pW/#s%H,dF+T7.NrK%[M2-fart0HsE+`#I5<h4c/0$3&6V10Rrr3#urqucs^Hh_s
+#JU6=,p`Nk;>^@oG_c,p2td3U6c8rp+&Z(ks09fJbqN,sruY3>s8O0;q>$4RqYqYj
+s09fJbqS&TMp25$McAU6]N"q2+8o.?s8O2<<&XdV+&l4ms09fJbqN,nruY4gs2E4Y
+fi6E"`DksP<)i_o+&l5>ru]qoZ-<6m0NA)P+&r:?+8o.?s8O2=<#"$cZ-<6m0N@oK
++&r:?+4C2.<9;g4<!:YLruXr2<#5N6+&l4ms09fJbqRiNZ-<6m0N@oK++dID<7b(P
+s&s2[H2@OfEc,W(?s6Djs&;tt>&/5*s*K*=H?XOQDJK2Z>#@H_:/(\*I>*OWrre18
+L4t6YrtBHkA5E4n6U*Xf*%X0?9i=nP2`CLk!IoUsrs1^e4S/T;!%#DXrrKT"qGmjZ
+s*@D/s40..<\3),s48>_<r`1A<`]8#+'-)Ti)IDc]N3kgs48>_<o*f/h>aBO<pBYW
+s8O2><W`=$+8](?s8O2?<\WA0s48>_<lP+=<`[TCs7MXI<m^F;p7=cT`W,s=<r`1A
+<o*fUf,mL`s8O0As8O2><W`=$+8](Wh>dN,+%KAFq7Kc.ruY:go)JET7oiZ[s4/:f
+<W`=$+9#:Ph>dN,+%KAfs8U[m7om>!]Rj2J<e=<?<!<5%Ao;_erss*eC1UaR9fi;R
+<<$!2DKPUP1LF3X3r`&Qs(ck0L!K^RLPCM8J:@O>EGJrUs$T7>3\MI%4%;tC;c?Rn
+<*!+(=]\a6TDecljs:#&rr2uBqYpW;3$8!$#"Th<>?Dt<rEB@p+!4,S>6,ffr`]mT
++'VrJ+%9C41/D+F+!4,S>7=%E8k:%&>?aB83?K@@>6,ffqHEtB+8oCG808pGr`^IA
++!4]k9JR\M<a/d%3?L7^>?arH+'Vqk+'Vr?+!4,S>6Q)j>?`0kr*'1D+8T1D808pG
+r`^"61/D*r+'VrC3?L7^>?eN8Vb$Se!?WE^>6@D<+%lN:"%XLU9)`#r;_h.#>No@D
+=7B8os&39<DZ"JdE,TQ-ARSeB8icoQ=8u3+BQ!`f'6%l+C1UgX<(]1N<)N[.F*`@g
+KDpHHJU`)oGB7Y8?;(;g6pj!j*%!a::/b.o=^,3>?smDP@T]Q,rr^IF!6k0:!T,#O
+>M<9as8Va6;hA5*>I[l@s%QU'ASD!U&SGZa?WpH+7Q19N>Q7E"?tF$LBfKa:@UE;=
+:e!AC<)im,CiaiII!U-dH?j^VEG]E#>"AT_7moBn*%!a::/b(k=]o$;?X[AP@VD,,
+rr^IF!5J7-!P^mO?.rQes5&Yo?%Q:4>I[lqls!.]='Ad1>$>'3=&i0p9Lh<?s'&^o
+>>.pr>$>'4>$5!0<Du[e7mBZH=&eO&?t<tfChmkdCER>)AR]"N;Hj)m7moBn)C@O8
+:/Fkh='&O/?!grI@>B+*rrOJHFT2:A,s7t#rrK<"Jm6o4!Zsj3Jm3h2[p)gtfi1+$
+6:4%+6UF((5<V(h2bVbg>?dEH<'<Q76U=(,6:!k$4Zb\`9@oD0<0Q*H9Mn\c;,^Ck
+;Gg:d9he2_g5eir6om(A-9F[l:ejhd<)m((r`]G0a#O"s#\*i7L!4$,-0G.*!FVOO
+=k-Z,=+XM`<rlHgnc&g[PZ_'h=d8IV#4.OR<)HSVnc''aO%Mo16TQt@-9F[d9)_Nd
+:f:3j<s2Z/s!ZLsrr>1Z!!&elrrVp3mt+Mj<.\)$<97'h;,gCg:ejb]:JOSU9M.qU
+9En*Z8k_iI8,G[^3\hU#4$,hk5!M:tr^6ZR"%WC+5l:QaPYjPb^\e$4BUAaN7Y4+#
+7Y3qK5ljABqEY0I4[&a+!BiRE4V9e>4?>M_3]B#W4$#,8-9F:Wr]U?I5PdVIs8Qc!
+o)Ag43<0#15LhuM5(YtM54UlB4#8W3,rf7*p#lPYs7[r!o`#'_0\?@)K'7gMK'7gM
+`omXq3[Pak3+#APkl1S`cR>.RrrTYX\,QDZk^r#Mk^r$<kQaL:-5n0i?VL.VrVlug
+BK4W?rr_Fl8E]sOK'7gMK'7gM`omXq3[Pak3+#APkkkAea!`WkLVJn"5T$-js+9Hd
+k^r#Mkf2fk6olY5,rf7*p#u5O#1%dD5]D4fq>^6R!!'dt!!%W7K'7gMPir??3[Pak
+3+#AVkkkD_kQ'fHmcaQKr9+7`kQ'fHo&p&RroaC`kQ'c/!!)u]!!)lZ!!%W7K'7gM
+Pir??3[Pak3+#AVkPtVZkPtVNkPtVXkPtV^kPtVRkPtV^kPtVDkPtV]kPtVZkPtU7
+k^r#Mk`k996olY5,rf7*qre"[r9+7`kQ'i1rW)QR!!)o[r;Zo_!9jC^o]Q8TroaIb
+kQ'i1rW!5fkQ'i1!9iVHo]Q8TrTF:_kii!G"6eqKkktL5k^r#MkaCW>6olY5,rf7*
+qrmqX"m>sM!9aF^kPtVTkktJ_ki`$GkQCnL!9aFQkQ_+O!9iVHkQ(VG#QX&gki`$1
+kQ(8=qZ$Z\!<20b!9aFH!<20^!.sEdk^r#ekQaL:-5n0i?VL@\!!)r\!s%NbkkkGQ
+kPtV\kPtV^kQCnL!9aFQkQV%N!9iVHkkkDckQ'fHkQ'fHo]Q8TrTF7^kkkD_kQ'fH
+roa=^K'7gMK'8Ze#=LU")C7@M9`+#R!;u$`!9aFH!:]1P!;u$\!<20b!9aFH!:f7X
+!9aFHkQ'fHr9+=bkQ'fHkQ(8=!!)u]!W_Ear9+1^kQ(VG!!%W7K'7gMRcjuE3[Pak
+3+#AVkPtV\kQCnL!9aF^kPtVTkPtV\kPtV^kQCnL!9aFPkPtV^kQ1bJ!<20a!9iVH
+roa=^oB6/SrTF:_kQ(VG"9@WckQ(VG!!%W7K'7gMRcjuE3[Pak3F>JWkPtV\kQCnL
+!9iYG!;#FP!!2<Ir;[#b!9iVH!:o=R!<20`!9iYG!<20^!<20^!;#CS!<)*_!9iYG
+!!DHK!9j@]K'7gMK'8Wd#=LZu)C7CN9T\H<!.sEdk^r#akQaL<+rVaf?VL@\qZ,sG
+qZ,mEqZ,aAq>g?T!!%W7K'7gMQKSQA4<b[i3F>I3k^r#Mk^r#nkQaL<+rVaf?VH(8
+K'7gMK'8un#=LZu)C7CN9S2J[k^r#MkbI>H6p)Y3,ro=+K'7gMK'7gMUZ_qN4<b[i
+3F>I3s+:9&s+:9Grs(qS+rVaf?VH(8K'7gMK'8un#=LZu)C7CN9S2J[kecQKs+9Hd
+kkXEI6p)Y3,ro=+K'7gM_W^:bK'7gMq</&O4<b[i3F>I3k^r$8kj&2"k^r$okQaL<
++rVad?VH(8K':)8qYpWcT2>MP!_A[@qYu02K'<$o#=LZu)C7=L9S2J[kecQ\rr\#n
+@'BRE"Li%]Gk_.9K'7gMq</&O4<b[i2d]71k^r$8kl(M`f/S$Lq>UMO0ZX.lK'7gM
+q</&O4<b[i2d]71k^r$8kl1S`V_H0brrUe3L]7=*k^r$okQaL<+rVad?VH(8K':)8
+"TSMb..?d-"$jX$s+9HdkkXEI6p)Y3,r]1)K'7gM_WV+%s%'Wirr_.,p]#j/K'<$o
+#=LZu)C7=L9S2J[kecNbs.<]grrRt#s+9HdkkXEI6p)Y3,r]1)qWNOVK$MK`!rj,#
+r;Qb=r?VGRqYpR=htcJfcAKmIchci16p)Y3,r]1)qre(+d":J5kfW)i^Hh_s#BTqG
+4='t-A,H9,G_c.Z!RB&Dk_nX*dE_XQ#=LZu)C7=L9`4)Tcd7:-K':>?!IoUsrs)CI
+PlLb\!'L/Y!OkVskQ0#VK'8'T!R]6kkQaL<+rVad?VLC]!7$2[K'3=#jPJYOg?R2h
+@%[5o"2@\54T#-Za#Nt[!7$2[TBH@;hV7n\rmh#%"5DVfjSe9Bchuu36p)Y3,rT+(
+r9+.+K'7gM"R+_#N_@VN!Ec8trs.\.,p`O;!'L/Y!T,$skQ&n[kb%&@hVaDeoe6J5
+J)fPekQ&p+kQaL<,8qjd?VLC]!7$2[K'3@$gl?O$c2RfXQi-jg,lg&]b_6$Zqu6]3
+5l9aFc@Y8PkQ9P"8+Y^A7ul[/kQ&p+kQaL<,8qjd?VLC]!7$2[K'3=#ge5i7rW.e!
+rVm/I!%$e-s'l$kqu6]#;#BGVc@Y8PkRuZDd*P)*6-qpE6-qpE6-qpE9DmuRcMZl2
+6p)\4,rT+(r9+.+K'7gM!pJAmrqt(=!QR1urs6gK!0mMY,lf7grrHN"qre%*K'8ij
+"PYWV62^HR"4#4Hli$#IcMZl26p)\4,rT+(r9+.+K'7gM"6eMoqTSa:s!ZLtrs(Xd
+!$qV-!%%RC!r!Q#qre%*K'8ij"5GTSc1Ul75KkhJrTF7,r9+AR4<kaj2IB/UkQ&n[
+k^r""khIl8pB(B05lCWeF?F'Js+Q0urVlq4QiHsH!7$2[TBHC40Zc6HpB:34atW2\
+kQ&p+kQaL<,8qjd?VLC]!7$2[K'3:"gb?qE"98C7Qh(.Ya#O,!qre%*K'8ij"5GTN
+a7f0/oJFWCm/?,JcMZl26p)\4,rT+(r9+.+dHCT2!:/hL!!)3G!!&>KquHNU!<<,r
+kQ(Y`lf\B)0['+ls8VgAht6pOmkEAns82![cFW3?!!(O4!<<,ikQ(Y`gZSY<!7L'5
+gb?Z&rUp*hrq-Ed_o"1prTF7,r9+AR4<kaj2IB/UkQ&p&kkbA=kQ(Y`nE9lQ!<20_
+!!)3G!!)o[qZ,O;!<<,ZkQ(Y`qWReVp#lPZ!9iVH!;Pa]!!)6H!!*#^!<<,ckQ9Nn
+p%n:]!!*#j!!)BXquH?\rr3&G.$sZ-!k0Serr;lZ!7'KcqZ,gC!<<-!kQ(Y`l0/!E
+o&p)S!:f7R!!)BLqZ-?R!<<,JkQBTo_86-C$ig;"oDem`o^aoU0^Sc%!7(N+#=L[!
+)C7:K9`4)ScM6T(!!)u]!<<,GkQ(Y`j6-ICqWIq[!<20_!!(s@!<<,ZkQ(Y`qWIq[
+!<20_!!)`V!<<,hkQ(Y`k3)m%0_P;7rW!#loDn:N!<<-!oDnplo^r+^"7Kn_fD>LL
+k?pjDrVucY!7'Kc!<<-!kQ(Y`ki`$I!9E>E!!)HN!<<,RkQ(Y`roa@_!;G[X!!(I2
+"5GTH2#d+U!!)Z`!!)Z`o>/6sm/?,JcMZl26p)\4,rT+(r9+.+puh_Y!<)*f!!)3_
+!9aC_kihmDroj:\"R,%L!9jC^"R,%L!9j:[roj:\!U/bF!!MKc!9iYE!!MNL!!)6^
+!;G[W!;bm[!!)u]!rr>bkkkD`ki`!Hkl(S\kktJdki`!HkPtVHqu?`\qu?`\rW)r]
+qu?l`kPtVHrVuu_kkkGYkQ(Y`rTF=`!9iYE!!2<Ir;[&c!!)3_!9jC^"R,%L!9j=\
+"R#gckihpE"R,%L!9jC^qWJ%:0_G#7oDJXko)SCRr;[/qo)Jd^!!)Tj!<)Ki!!*#i
+#QOkr!!)TjoCMk[!;$*f$HFPKItte"Im=jCqu?QW!7'Kc!<<-!kQLqdki`!HroaLc
+!9aC_kl(SXkkkD_kPtVHqu?`\rW)r]quHWX!<<,tkQ_(fki`!HkihsF#3b7N!9aC_
+roaFa!9iYF!!VTM!!)6Hqu?l`kPtVHrW)iZ!<<-!kQLqdki`!HroaOd!9aC_kihpE
+roj:\i919u0YP0so)Sgkrpp9`1qk[1rTF7,r9+AR4<kaj2IB/UkQ&p'kQ(Y`rTF:_
+!9j=\!pBUaroaIb!9iVHroaC`!9jC^#3b7N!9aC_r9+7`!9iVHroaLc!9iVH!<20b
+!!)3_!<20`!!)6^!!DHK!!)iY!!)iY!<<,ukQCkckPtV^kQ1_akl(Pdki`!Hki`$G
+kQ1_akkkD_ki`!Hroaaj!9iVH!9iVH!9aC_roaC`!9jC^#O(@O!9iVH!;bm[!!)u]
+"98Gc!!*#^$31(ikPtVHkPtVHrW!;hkPtVH!!)6H!!*#^"98Gc!!*#^!WW5arW!&a
+kPtV[kQBTooCMkM!<D]h!"\W#!:o[\!:g*inc/[\!!)ug!<<-!ncAdko)/Onnc/[\
+nc/[\q>UZFIs=4tJ%tgZqre%*hrk(@!<20c!!)6H!!*#^!WW5arW!&akPtVYkQ(Y`
+roajm!9aC_ki`!Hki`!HkPtV^kQ(Y`r9+.]!;u$d!!)6H!!)3_!<20d!9aC_kPtV^
+kQCkckPtV^kQV%N!!)3_!<20`!!)6^!!DHK!!)r\!<<-!kQLqdki`!HroaRe!9aC_
+kPtV^kQCkckPtV^kPtVAkQBTo\ki7p!<<,unc\Ko\hNLLkQ&p+kQaL<,8qjd?VLC]
+!7(B'!<<,ukQCkckPtV]kQ(Y`roa@_!;ks_!!)3_!<20b!!)3_!<)*^!!)lZ"TSPd
+kPtV^kQCkckPtV^kQCkckPtV^kQ(Y`q<.eYq<.hZ!<)*a!!)3_!<20b!!)3_!<20_
+!!)o["98Gc!!)r\!<<-!kR7Fkki`!Hki`!HkPtV^kQCkckPtV^kQLqdki`!HqWIq[
+!<)*a!!)3_!<20j!!)6H!!)6H!!)3_!<20f!!)3_!9iVH!<20b!!)3_!<20b!!)3_
+!<20_!!)o["5GU%oDA([!:o^[!!)Te!!r,q!:g*inc/[gnc8^jrpg0l!:g*irpg3m
+!:o[\!;c6hna,?km/?,JcLg<#cJRj_!<20_!!*#^"98Gc!!*#^!WW5aqu?i_kPtV^
+kRRXnkPtVHkPtVHkPtVH!!*#^!<<,tkkkG[kktJ`ki`!Hr9+7`!9aC_roaC`!9jC^
+rTF@a!9aC_roaIb!9aC_roa@_!;u'X!<20_!!*#^#64bf!!)3_!<20`!!)6^!8coA
+gb?=Nr:0jg!<)HknPHeNm/?,JcMZl26p)\4,rT+(r9+.+puh_Y!<)*a!!)3_!<)*^
+!!*#^!rr>bkkb>]kPtV^kQCkckPtV^kQ(Y`rTO+Y"6eqK!<20b!!)3_!<20b!!)3_
+!<20_!!)lZ!!)fX!<<,ukQ1_akkY8\kPtV^kQ:ebkihmD!pBUar9+.]!<20h!!)6H
+!!)6H!!)6Z!!;?a!<20c!!)6H!!)lZ!<<,ukQ1_akkY8dki`!Hki`!HkPtV^kQh.g
+kPtVHkPtV^kQCkckPtV^kQCkckPtV^kQ(Y`qre.;0_=o5nc/[hncSpmnc/[fo(`:a
+nc8^jrpg0l!:g*irpg3m!:o[\!;c6hna,?km/?,JcLg<#cJRgg!!)3_!<)*^!!*#^
+"98Gc!!*#^!<<,qkQ(Y`roadk!9aC_ki`!Hki`!HkkY;WkQ(Y`qWIq[!<20_!!)r\
+"98Gc!!*#^!rr>bkktJcki`!HkPtV^kQCkckPtV^kQ(Y`r9+7`!9aC_rTF7^!<20c
+!!)3_!9j7Z!U/bG!9!&Cgb?0>p@8@V\$e!WrTF7,r9+AR4<kaj2IB/UkQ&p'kQ(Y`
+rTF@a!9aC_rTF7^!<20b!!)3_!<20b!!)3_!<20f!!)3_!9iVH!<)*^!!*#^"TSPd
+kPtV^kQCkckPtV^kQCkckPtV^kQ(Y`qWInZpuh_Y!<)*a!!)3_!;ks\!!*#^"98Gc
+!!*#^"98Gc!!)r\!<<-!kR7Fkki`!Hki`!HkPtV[kQ(Y`roaLc!9iVH!;bm[!!)u]
+"98Gc!!)lZ#QOkgkPtVH!!*#^#QOkg!!)6H!!*#^"98Gc!!*#^"98Gc!!*#^!<<,s
+kQBToo()\J!!)uf!s%ik!;l9i!!)QZ!!)re!<<-!nH8glnGiRgnHAmmnaQSZqXF^X
+lf9bdrTF7,o]Q;#hrk4D!9iVH!<20_!!*#^"98Gc!!*#^!<<,qkQ(Y`roajm!9aC_
+ki`!Hki`!HkPtVWkQ(Y`qrmtY"6eqK!;u$`!!)3_!<20_!!)u]rW!,c!!)3_!<20b
+!!)3_!<20_!!)r\"TSPdkPtV^kQ(Y`roaRe!9aC_kPtVXkl(S@kQBToZa9T"!<<,u
+nHA>`ZS:bEkQ&p+kQaL<,8qjd?VLC]!7(B'!<<,ukQCkckPtV]kQ:ebkii!G!pBUa
+roaIb!9aC_roaRe!9aC_kPtV\kQ(Y`roaLc!9iVH!<20b!!)3_!<20b!!)3_!<20_
+!!)o[!!)cW!<<-!kQLqdki`!HrTF=`kPtV^kQCkckPtV^kQCkckPtV\kQ(Y`roaaj
+!9iVH!9iVH!9aC_rTF=`kPtV^kQLqdki`!HqWIq[!<20c!!)6H!!)u]$NTDS!!)6H
+!!)3_!<20f!!)3_!9iVH!<20b!!)3_!<20b!!)3_!<20_!!)o["5GU$o)%qW!<)Eh
+!:fUW!!i&a!!)QZ!!)odqu?ihnGiRfnb`C`nHA@Ij=os!kQ&p#kQ&ockQ(Y`roaRe
+!9iVH!9iYG!!;?a!<20_!!)iY!<<-!kRRXnkPtVHkPtVHkPtVH!!)u]!!)r\!<<,t
+kQh.gki`!HkPtV^kQh1P!!)3_!9iYG!!29`roaRe!9aC_kPtV^kQCkckPtV^kQ(Y`
+r9+.]!<20e!!)6H!!)6HrW!,c!!)3_!<)*_!9aF^kQ(Y`iTLC!0XFjYnGrUirUC$[
+['MIQrTF7,r9+AR4<kaj2IB/UkQ&p&kkb>^ki`!Hr94+["R#gckihmD!pBUaroaLc
+!9aC_kkb>\kihmDroj=]"R#gckihpE"6eqK!<20_!!)o[!!)cWqZ-TYqu?c]kkbAZ
+kkb>]kPtV[kl(PjkPtVHkPtVHkPtVHkkkD_ki`!Hroa@_!<23]!;u'X!<)-Z!<20f
+!!)6H!!)3_!<20b!!)3_!<23]!!MKc!9iYE!!DHK!!*#^!<<,skQBTonaXuq!<<,r
+n-&4Fj"TiukQ&p#kQ&ockQ(Y`rTF=`!9iYG!!VQd!9aC_roa@_!;PdW!"\8n!9aC_
+ki`!Hki`!HkihpEqrmnW#j;6gki`!HkihsF"mG.M!9iYG!!MKc!9iYF!!VTM!!)6H
+qu?i_kPtV^kQ(Y`r9+.]!<)*`!!)6HrW!2e!!)3_!9iYE!<23\!9!&Cgb>t9p@&4R
+@'D?OrTF7,r9+AR4<kaj2IB/UkQ&ohkQ(Y`_<:k!jlc^F!.sD<kigeUnaY)tr;cZ_
+"RkX90^Sc%!7(6#!7$2[TBHC40WeaVn-&3^XYB,?kQ&p+kQaL<,8qjd?VLC]!7'im
+!!)u]!<<,9kPtVEkQ(Y`K'3C%khIl]nAju#mci^bm/?,JcLg<#c@Y8PkQBToX/bm^
+"R]!a0^Sc%!7(N+#=L[!)C7:K9`4)ScKOKi!2J`Y!!%W7"6et(0ZEJ`mH<F^mJZ5K
+cLg<#c@Y8PkQBToW(m!S"RW.f0^\i&!7(N+#=L[!)C7:K9`4)Sc@Y83kQ9u'0ZE;[
+kMb2MmJZ5KcLg<#c@Y8PkQBToW2TFT"QrLX0^\i&!7(N+#=L[!)C7:K9`4)Sc@Y83
+kQ^8,5fDO8h9+RXh:pPm5k"[8!7(6#!7$2[TBHsE5c@DU9rLdb9rLdb9rLdbW'KhM
+kQ&p+kQaL<,8qjd?VLC]!7$2[K'3@$hgT:?a3Xt8[:Y'_rTF7,o]Q;#K'8ij"5ePt
+G4^Lj7t^F3kQ&p+kQaL<,8qjd?VLC]!7$2[K'3@$jQM_!`\7K[K_"d6kQ&p#kQ&n[
+kb%&@jQM_!oe6J5K_"d6kQ&p+kQaL<,8qje?VLC]!7$2[K'3C%kj7g1o]>c.q#9pg
+p@e1FrTF7,o]Q;#K'8fi"75OKo_eC]q#9pgp@e1FrTF7,r9+AR4<b[i2d]8VkQ&n[
+k^r$/kQ&p#kQ&n[k_J@%cMZl26p)Y3,r]1)r9+.+K'7gM\`a%>o]Q;#K'8!R!71T,
+#=LZu)C7=L9`4)Tcd7:-K'9i1!R]6ckQ0#VK'8'T!R]6kkQaL<+rVad?VL@\!RB&D
+k^r$3kQ0)Vo&p,"d":J>kQ0)Vqre8Q4<b[i2d]8Tk^q*3cFhF&cg^.McAKmIchci1
+6p)Y3,r]1)K'7gMK'7gMUZ_qN4<b[i2d]71k^r#Mk^r#nkQaL<+rVad?VH(8K'7gM
+K'8un#=LZu)C7=L9S2J[k^r#MkbI>H6p)Y3,r]1)K'7gMK'7gMUZ_qN4<b[i2d]71
+k^r#Mk^r#nkQaL<+rVac?VH(8K'7gMK'8un#=L[!)C7:K9S2J[k^r#MkbI>H6p)\4
+,rT+(K'7gMK'7gMUZ_qN4<kaj2IB.0k^r#Mk^r#nkQaL<,8qjd?VLC]JsV(U\!M^1
+K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IqYpd!q!ctH
+aRk)aK)`mk!1/<$K';dh#=L[!)C7:K9`4)SQi$dhrpAIln&MTRnc".?K)`sm!1/<$
+K';dh#=L[!)C7:K9`4)SQi$diq;BrLnB%i@b3o7\s+:9nrrAC;k^r$hkQaL<,8qjd
+?VLC]!13T_$N8oDeaLP]Zan``K)^H&b5VI.K'7gMo&p<H4<kaj2IB/UkQ$tGrsI]G
+g[N._ZEqEgon*3qs3(EBQ\+FQkjmpB6p)\4,rT+(r9+-IqYpu_oC)=l\&-G3ZHhq;
+qZ$Npp\t6o!.t6&s5X+ZQ\+FQkjmpB6p)\4,r]1)r9+-Iqu7-!iVNEEd`KAF`Nutt
+meZt_!.t6&s4@8NQ\+FQkjmpB6p)Y3,r]1)r9+-IrVmE%mHEL)qXi"OZEq3NZa\'R
+rt,52rr<'!rr<'!rr<'!!!*'!r;_HLK)b*8!1/<$K';dh#=LZu)C7=L9`4)SQi6pp
+gX4<rqYK`q\uiHR[Bm3Cqu79/!<3$!s8N'!s8N'!rr<'!!!%WNK)b!5!1/<$K';dh
+#=LZu)C7=L9`4)SQi6pp^q7(lqYK]l[^3NS['R*Lqu6d!!<3$!rr;os"TSK%!<;ut
+K)^H&kl1XLmHB/IPg09Tp#lWK4<b[i2d]8VkQ$tJrt!#Q[Cc%umC0F2]!o#PZ-<.G
+q>^Qrs8;p$s8N'!s8W#tK)^H&l2LaMmcX\sd":JHkQ0)Vp?2`L4<b[i2d]8VkQ$tJ
+rt!J_ZF/9"k-qY#Wi3),ZJGHY!<<-!rrE*"rr3!!!<3!!!!)ut!<<+Os+::8rrADS
+kQ0#VK'8E^!R]6fkQaL<+rVad?VLC]!13Za&)=Cp['5AA^:^:pI$U\@kPY>\!!*#u
+!<<-!rrE*"rr3$"!<;utK)^H&kl1XLn)sbsrTF=DhV7,FkLKRc"5DVfjS\4pQi-(-
+VZ?bqkQ&s'kQaL<+rVad?VLC]!13Za&(I\m^nl51guG2R?YG(pl%8qes3:QDQga,<
+cMcr/hVaDea=m]]J)fPdkQ$s(rrAD`kQ%OBD?92*rTF7,pZMiM4<b[i2d]8VkQ$tJ
+rstZuh;PV\htlr+F]`<fG0Y^>K)a*q!130<!7(Q,"5JoZbfKedgi\Y<r9+-ILAq7?
+r9+0ZDWh$$aR9*,kQ&p&kQaL<+rVad?VLC]!13Za%t:M;m^%,eoA,I;:L.7+Y(H\*
+s3:QDQga,<cMcr.ge5i2rW<&@9DdoQQ\PM?Qi-%JVf(_u"3AROs8D-]cM-N-6p)Y3
+,r]1)r9+-IrVmD#HZYIGDm$9m?"&/%M2fu9s+:9qrrADSkQ&p,kQ0Elrqsn8"8_XD
+lhorHQeDB=!3cD&Qi-%LVf)P7lKA>kaR9*,kQ&p&kQaL<+rVad?VLC]!1/<;K)`C]
+!130<!7(Q,!o,L+a8#i0mP+#*kQ$tIs8;rbs8;rorr<&&rrAD`kQ@`#s8VBJ"3ARO
+s8D-]cM-N-6p)\4,r]1)r9+-IqYpd!q!ctHaRk)aK)`mk!130<!7(Q,!SfBLpB:3[
+l7hT&kQ$tJrr<&arr<&mrr<&&rrAD`kQ@`#s8VBJ"3AROs8D-]cM-N-6p)\4,r]1)
+r9+-Iqu7!%mG$7]a0*STrdt0%s2k9@Qga,<cMcr-gb@@Q!<<,to`5$mqXk!`n)uIl
+r9+-Irr2ruqZ$Nprr;rt!WW3!!!<3#!;c`p!!N?%!<<)u!4;b+Qi-%LVf)P7roj=\
+#NUn=/MTtVhu3TRkQAoImf37L!7(?&#=L[!)C7=L9`4)SQi$diq;BrLnB%i@b3o7\
+s+:9nrrADSkQ&p,kQ0HmiV!0MqXjjh!;uKj!!)lg"SD0H0^S`$!13]b!!)or!!*#u
+!W`6#q>UKrrrDrr!!*#u!W`6#r;Q`s[Jp5nr9+6\DZBb9kR[^nqN!6aDO6T53%9UX
+s8W&]"3AROs8D-]cM-N-6p)\4,r]1)r9+-Iqu7$%i8iGWa0)bZf_C'uK)a!n!130<
+!7(Q,!o,L&n+6V\!;?'a!;c<g!!)rh!<<,roE=dRk:l9#kQ$tKrr<&rrr<&urrN3#
+!;ulq!!3*"qu6Wrrr3*$rrE*!r;a8*!13WI"/g&:s8M3cs8?a^K(Am?"o4W@?Ma^#
+kQAoImf37L!7(?&#=L[!)C7=L9`4)SQhp^hi8r__`2p8N_T2>$s+:9orrADSkQ&p,
+kQBToo^qSC!<<,qo)o$no)JdioDARhoCMk[qXXj\mH-+hr9+-Irr2ruqu6Wrrr3$"
+rrE#t!!*#u!W`6#qu6Wrrr3*$rrE'!rr2ru[Jp5nr9+6\DZBb9kQLpF-S)_'rr^4p
+JcG]4"3AROs8D-]cM-N-6p)\4,r]1)r9+-IqYpu_oC)=l\&-G3ZHhq;r;Qct!<3!!
+!!)Zk!<<+Os+::7rrADSkQ&p,kQBTooCM>>!<<,sne2!'nc/[\nc/[\nc/[\!!)T\
+!!)ld"S(j?0^S`$!13Za!!)rs!!*#u!W`6#rVlitrr3'#s8N)srr<&urr`?%!<3&u
+rr<&,rrAD`kQ@`#s8W)^"l_(c9e<aLrrT,Je,AJ4aN3fLrTF7,pZMiM4<kaj2d]8V
+kQ$tHrse\\qYKp6ahl$9ZaJ*Hr;Qct!<3!!!!)Zk!<<+Os+::7rrADSkQ&p,kQBTo
+oCMkMr;Zigr;cZa!!)rf'*&%'!!)T\!!)T\!!)Qi!:o[\!;c6hna,?km/6&IQi-m^
+!!3-"rW)rtrW!!!s8;rss8;ous8W&u"TSK%s8W#t[Jp5nr9+6\DZBb9kQZl!o^5L*
+[/9k)rC225kQAoImf37L!7(?&#=L[!)C7=L9`4)SQi6ppp?h)%qYKj.`j2q`['R6`
+r;Qct!<3!#!!*'!r;['%rr<'!!<;ut!<;rsK)^H&nG`KTn)sbsrTF@=0_4f$nGrUi
+r:0U`%IjDunaQSZnGiRZnGiRcnHA@Ij=orukQ$s(rrAD`kQ@`#s8W)^#?>F:s6ic7
+Zhsb'K0]D!"3AROs8D-]cM-N-6p)\4,r]1)r9+-IrVmD_dE^8<qXM81XgbpMZa6k5
+s7u^#rr<'!rr<'!r;Zp!!!)or!<<+Os+::?rrADSkQ&p,kQBTonaZ&:!<<,rn,WLh
+rpUEu!:TsgnF-DXn,NIXn,NIbn-&4Fj"TitkQ$s(rrAD`kQ@`#s8W)^!A]E/rr_^e
+/$]$P!Mq=FkQAoImf37L!7(?&#=L[!)C7=L9`4)SQi6pp^q7(lqYK]l[^3NS['R*L
+r;Qct!<3!"!!*&r!!<0#!<3!!!!)rs!<<+Os+::>rrADSkQ&p,kQBTonaZ,<!<<,p
+n,WLhrpU!i!:]LU!!2TYquHT_"RkX90^S`$!1/H?!13WI"/g&:s8M3_0S03&"7T2<
+YPnJ%UFQ6+"3AROs8D-]cM-N-6p)\4,r]1)r9+-IrVmDGZF.=9md7Ki\%9&TZa%aP
+rrE*"rr3*$!<3$!r;Qct!<3!!!!)ut!<<+Os+::=rrADSkQ&p,kQBTonF4Qg"RbO6
+0^S`$!1/H?!13WI"/g&:s8M3_94e&$"7T8>Y5\G%LHb\#"3AROs8D-]cM-N-6p)\4
+,r]1)r9+-IrVmDTZa.!i_</54Yc=Y)Za/EbrrE*"rr3*$!<3$!r;Qct!<3!!!!*#u
+!<<+Os+::<rrADSkQ&p,kQ0Hma6s/ukM\,^r9+-ILAq7?r9+6\DZBb9kQ6Mon,31j
+nPq'?s8>K3rTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13Za&)=Cp['5AA^:^:pI$U\@
+kPY>\!!*#u!rr?$s82iurr<&ts8Duus82kKs+::?rrADSkQ&p,kQ0Hma6EfjiS6-S
+r9+-Irr;osmf*7err;osW;cjar9+6\DZBb9kQ9KgLAUuTnl@3>V^TaekQAoImf37L
+!7(?&#=L[!)C7=L9`4)SQi6ppe?$9tV0:\Mj.pj*BS3JPK)^H&c2Rd1n)sbsrTFF@
+5fDO8h9=^Zh:pPm5k"X7!13]b!!*#u!!)Bc!!&hp!13WI"/g&:s8M3as+)].qu6ik
+=",kGs8D-`aN3fLrTF7,pZMiM4<kaj2d]8VkQ$tJrstZuh;PV\htlr+F]`<fG0Y^>
+K)a*q!130<!7(Q,"5eQAX3&]kca@A;oDIePQi@!b!<3!"!<<)u!!3-"r;cisrW!'#
+!<3&qs8E##rrAD`kQ@`#s8W)^"onF).ZjK)rrr7\-WBd>rTF@)aR9*,kQ&p&kQaL<
+,8qje?VLC]!13Za%t:M;m^%,eoA,I;:L.7+Y(H\*s3:QDQga,<cMcr/jQM_!a=m]]
+K_"d5kQ$tKrr<&urrN3#!<3!"!<3&urrN3#!<)p!!<3&rrr<&urr<&%rrAD`kQ@`#
+s8W)^&-)\'I474"PEU5R.!G7_s8D-`aN3fLrTF7,pZMiM4<kaj2d]8VkQ$tJrst`K
+FH`G;Y-3:[@=<0QNRNLZK)a*q!130<!7(N+"75OKo]Gi0q#9pgp@e1Fr9+-Irr;os
+!WW2t!!3*"rr3'#rr<&urrN3#!;lcr!<2uu!3Z>%Qi-%LVf)P7roj=\#Ln2d.k3`*
+d/F"CkQAoImf37L!7(?&#=L[!)C7=L9`4)SQ\,6hs1/.0Qga,<cF<!;Qi@!b!;uis
+!;uis!<2uu!<3!%!!*$!rrDrr!!*#u!!'2%!13WI"/g&:s6AeMaN3fLrTF7,pZMiM
+4<kaj2d]8VkQ$tGrs&JtnCb=moRd*ps2Y->Qga,<cF<!;Qi@!b!;uis!<3!"!<3&u
+rr<&trriE&!<<'!r;Q`srr2ruY5\Kgr9+6\DZBb%kQAoImf37L!7(?&#=L[!)C7=L
+9`4)SQi$dhrpAIln&MTRnc".?K)`sm!130<!7&(;!13]b!!)orrW!!!s8;ous8W&u
+!rr9#rr;os!WW3!!3Q8$Qi-%LVf)P7lKA>kaR9*,kQ&p&kQaL<,8qje?VLC]!13T_
+$MiW5bOEWV[E@q:K)^H&b5VI.n)sbs\**gYo)A[iQN$rOr9+3[DZAn@!Ug!dkQ&p&
+kQaL<,8qje?VLC]!13T_$N8oDeaLP]Zan``K)^H&b5VI.n)sbs\**gYo)A[iQN$rO
+r9+0ZDW]"@mf37L!7(?&#=L[!)C7=L9`4)SQhp^hi8r__`2p8N_T2>srrE*"K)^H&
+rVlkan)sbsrTF=DhV7,FkLKRc"5DVfjS\3AQ\PM?Qi-%IVr[7Gs8D-]cM-N-6p)\4
+,r]1)r9+-IqYpu_oC)=l\&-G3ZHhq;qu?Qoli6k_q>UHq!.t6&s8DrtQga,<cMcr/
+hVaDea=m]]J)fPdkQ$s(rrAD`ki2X@kQ&p&kQaL<,8qje?VLC]!13T_%JJcWqY&@Z
+_SsL#[Ee4<rrE*"kl1Y`!;6?m!!%WNK)bfL!130<!7(Q,"5JoZbfKedgi\Y<r9+-I
+LAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrt"hjkhu=6oZY=\Zb3ZO\&nRJ!<<,ss8;rs
+s8;ous8W#t"98B$!;lfp!!WE&!!*'!r;_HLK`;%=n)sbsrTF=<9?YBT!r^87qre$H
+LAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrt!l3cID^en\)N9\%B&SZ`j<,!<<,trs/T)
+s8N'!rr<&prr`<%rr<&srs/T)s8N'!rr<&srrE*"K)^Q)!130<!7(Q,!S]=-r5ng<
+qXcK-r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrsuoW\&%q;n@?!6\[]#QZap#6
+!<<,trs/T)s8N'!rr<&ss82iurr<&srsA`+s8N'!rr<'!s82kKs+UIQQga,<cMcr.
+gbATFq#g9W0^S`$!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQi6pp_m6\^oBu"TZa[NT
+Za6p\r;Qct!;uj&!!*'!!!*$!!<)p'!!*'!!!*$!!;uj-!!*'!!!*$!!<3$!s8N'!
+K)^Q)!130<!7(Q,!SfBLpB:3[l7hT&kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13Za
+&(%Yg[FW1V\$E6<W33J4h>I9R!!)rs#QOl)rr<'!!!)ut#QOl)rr<'!!!)rs%fcV0
+rr<'!!!*$!!<<'!!.t6)rrADSkQ&p,kQ0Hmde*V@!;Q3io^Cutm/6&IQ\PM?QeCR&
+cM-N-6p)\4,r]1)r9+-IrVmD`Yd1X?Lto_WV1X/]Vn)!fs82its8W#trr;os!WW2t
+!!3-"qu?cts8;p$s8N'!s8VusK)^Q)!130<!7(Q,!SfBfp&"gao`5$mq"4d^n)uIl
+r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrt!V\]>17dh;%%dG$ep8Y3CQ<K)a*q
+!130<!7(Q,!o,L&o(2q_!;#gd!!)Z`!!)fd!<<,poE=dRk:l9#kQ$s(rrAD=kQ&p&
+kQaL<,8qje?VLC]!13Za&"TWSiN[L^qX]ek=D25gc@Z(Js3:QDQga,<cMcr/gbABm
+p%&1a!:fX]!!*#i!rr>moDJXkoCDq^q""XZmH-+hr9+-ILAq7?g#rF]pZMiM4<kaj
+2d]8VkQ$tJrssRXipO-seFVLW@o$B9<N^rRK)a*q!130<!7(Q,"5GU%oCqeV!!)KY
+!<<-!nd>Etnc/[\nc/[\!!)fb"S(j?0^S`$!1/H?!12C&!7(?&#=L[!)C7=L9`4)S
+Qi6ppT6k[DU2R3<IU-B1Ef#e)K)^H&c2Rd1n)sbsrTF@=0_=o2nc/[do)/Ogo)/Re
+nc8^jrpg*j!:p!e!qH<kq!nRXm,]qfr9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$s$
+s+:9]rrADSkQ&p,kQBToo()PF!<<,gnGrUirp^*k!:^$hr:'df!;Q'enE]-hm/6&I
+Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMh!p:/=PBK)^H&ec,W9n)sbsrTF@=0_+]+
+n,WLhnaHhb!:]IX!:]IX!;u<e!!)f`"RkX90^S`$!1/H?!12C&!7(?&#=L[!)C7=L
+9`4)SQg4SR/2K(23.h0^s4.,LQga,<cMcr/gbA9goC)b\!;#^X!<)Eb!!;Wi!;Q$d
+n*8pem/6&IQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMh,A2)Qj=Mi*CJK)^H&g&D&=
+n)sbsrTF@=0_"SRmf`(Ci\9`skQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N%kTXr
+.:.^^F)(aTpo('eUk8Vus5<nWQga,<cMcr-gb?e;"RYC20^\f%!1/H?!12C&!7(?&
+#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U<C]FBg^qd:0K)^H&i;WeDn)sbsrTF:;0ZWG]
+kMb2MmJQ/JQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s7a@ij0=XB
+s8E#prr<&_rr<%Ns,6mWQga,<cMcr1h*Ap8h;-<3"l7qb\j5`^kQ$s(rrAD=kQ&p&
+kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\Nr/hV!;ZWp!9jF_!.t6/rrADS
+kQ&p,kQB^kBrfA&"OFJfKCf$)!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
+Kp%U<C]F.Fj5[D)qu6]ts8W#t!WW3!!!WB&rrE*!rW!!!s8;rss8E!!s8W&uK)^i1
+!130<!7(Q,"6A[.9?8dh5_S_#r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$t7rsp\=
+2(+*@P&OiVGJW>"Z&\_]!s&B$!<3!"!<3&urrE*"qu6]trrE&u!W`6#rr3$"rr@ZN
+MuNdDn)sbsr9+7LnFQ;7p#l,Lo`Op]p$;P>!1/H?!12C&!7(?&#=L[!)C7=L9`4)S
+Qg4S]/N#C5Kp%U*A7oGjj5[D)qu6`us8N)urrN3#!<2uu!<)rr!!3*"rr3!!s82it
+rr@ZNMuNdDn)sbs\**gYLAq7?g#rF]pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJ
+B>W]hZ&\_]!s&B$!<3!"!<3&urr<&urr<&urrN3#!<3!"!<3&srr<%Ns,6mWQga,<
+cF<!;Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XArrW9$
+rrE&u!W`6#rr2rurr2rurr3$"rrE&u!W`6#rr3$"rr@ZNMuNdDn)sbs\**gYLAq7?
+g#rF]pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\b^rW!!!!<3!&!<<'!
+!<3&ts8;ourrE&u!W`9#rW)rt!<<+Os,I$YQga,<cF<!;Q\PM?QeCR&cM-N-6p)\4
+,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=Vrs+::/rrADSkQ&o;kQ$s(rrAD=kQ&p&
+kQaL<,8qje?VLC]!13!N%kTXr-\[_HC27Tt_W0[]Ne7:_s5<nWQga,<cF<!;Q\PM?
+QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=Jns+::/rrADSkQ&o;
+kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N%nfYm:ipu.AnPafOe88&m"57hs5<nW
+Qga,<cF<!;Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IK)^H&\c2Yrn)sbs\**gYLAq7?
+g#rF]pZMiM4<kaj2d]8VkQ$t7rrf`):J<_=s3Tt]s-<TaQga,<cF<!;Q\PM?QeCR&
+cM-N-6p)\4,r]1)r9+-IlMgu<1G^I>oDd2$K)_,9!130<!7&(;!1/H?!12C&!7(?&
+#=L[!)C7=L9`4)SQg4SV/N#C815h$IM"gqrk^ri"rrADSkQ&o;k_,;UkQ&p&kQaL<
+,8qje?VLC]!13!N%kTXr.:.^^F)(aTpo('eV#LD@k^ri"rrADSkQ&n[k`P'/cM-N-
+6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s8Ibg^pA^ns3Tt]s-<TaQga,<c@Y8BkQ&s'
+kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\NrK%ZkihpEqWInZki`!Hq<3G1
+Q2^iNn)seud":JFkQ0)WpZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P&P4:pVGnMZ&\h`
+!pJhJp?2JVki`!Hq<3G1Q2^iNmcX\sd":JHkQ0)Vp?2`L4<kaj2d]8VkQ$t7rsp\=
+2(+*@P&P4:pVGnMZ&\h`!pJhJr9++\roa@_kl(PckQ'fHkii!G!U/bG!<23]!!2<I
+rW)iZK)_,9!13*:K$KV+!71?%#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U<@=*47j5[D)
+rr3#_kktM\kQLtM!9iVHroa@_!;ks]!9aF^kQ1bJ!<20`!9aFYk^ri"rrAC;k^r$h
+kQaL<,8qje?VLC]!13!N%kTXr-\[_H?=[\Z_rKd^NrK%[ki`$CkPtV^kPtV^kPtV]
+kktJ^kQ(VG!<D?]!!29`q<3G1Q2^iNK'7gMo&p<H4<kaj2d]8VkQ$t7rsp\=2(+*@
+P%ncJB>W]hZ&\h`!pJhJqWInZroa=^roa=^roa=^roaC`kQ(VG!W_Ear9++\q<3G1
+Q2^iNK'7gMo&p<H4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\h`!pJhJqre1`
+kQ'i1!<20^!<20^!<20`!9aF^kQ1bJ!<20`!9aFYk^ri"rrAC;k^r$hkQaL<,8qje
+?VLC]!13!N%kTXr-\[_HC27Tt_W0[]NrK%ZkihpE!U'O_kQV%NkPtVH!<)-[!!29`
+roaC`kii!Groa@_!;ku3s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAH2)Qb8P*0Qq
+CM1NEj0=XDs3Tt]s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NE
+j0=XDs3Tt]s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=L@
+s3Tt]s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAf:/4W-H$O"7B4[3tT8Dq6s3Tt]
+s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IfDj4]K)_,9!1/<$K';dh#=L[!)C7=L9`4)S
+Qg4SR[8'Lk2hM']s4.,LQ\+FQkjmpB6p)\4,r]1)r9+-IlMgu<1G^I>K)^H&ec,W9
+K'7gMo&p<H4<kaj2d]8VkQ$t7rs1262(CA>MMd4As+::(rrAC;k^r$hkQaL<,8qje
+?VLC]!13!N%kTXr.:.^^F)(aTpo('eUk8Vus5<nWQ\+FQkjmpB6p)\4,r]1)r9+-I
+lMhAH2)Qb8P*0d"s8Ibg^pA]Gs+::/rrAC;k^r$hkQaL<,8qje?VLC]!13!N%kTXr
+-\[_HE,5LJ_;jR\Nr8nW!<)ot!9X=[!.t6/rrAC;k^r$hkQaL<,8qje?VLC]!13!N
+%kTXr-\[_HE,5LJ_;jR\Nr8nW!<)ot!9X:]!<2uu!.t60rrADQk^q*Ec2c2`kQaL<
+,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\Nr8nW!<)p!!<3&urrE-"rW!$"!!*#u
+rW!!!s8;p!s8N)urr<&us8E#ts8E!!s8W&u!rr9#rr30&rrE'!s8W&u!WW3!!<3#t
+!.t6\rrADRkQ/uUK'8K`!R]3dkQaL<,8qje?VLC]!13!N%kTXr-\[_HE++*;_;jR\
+Nr8qS!!3*"rr36(rrE*!!<<'!r;QfurrE&u!W`6#rr3'#s8N)urrN3#!<)ot!<3!"
+!<3&urrrK'!!*'!!<)ot!<3!"!<3%Ns0_k,Qga,=cd7:-PNW%pchHW.6p)\4,r]1)
+r9+-IlMhAH2)Qb8P*0-^B4Sp?j0=XBrr<&trrN3#!<3!*!<3'!rrE*!!<<)t!!3*"
+rr3!!s8;rss82iurr<&urr<&urrN3#!<3!"!<3&urr<&ts82iurr<%Ns0hq-Qga,<
+cMcr.jPJYPg?7#cg&p*bhW4UuKU;W#j/2nWrTF7-pZMiM4<kaj2d]8VkQ$t7rsp\=
+2(+*@P%ncJB>W]hZ&\b^!!)ut!W`6#rr3<*rrE*!!<<'!rrE&u!W`6#rr3-%rrE*!
+!<2uu!;c]t!!*$!rr3$"rrE&u!W`6#rr2rurVlitqYpQr!.t6\rrADSkQ&p,kQB]"
+N_@GI"$h@rir&!?Q\PM?Qi-%IVr_dsmf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
+Kp%U6CMRS"j5[D)r;Q`srVlp!rrE&u$3:)+s8N*!rrE'!rr3$"rrE&u!W`6#rr3'#
+s8N)urr<&trrN3#!<3!"!<3&urrN3#!<2uu!<)ot!<2uu!<)ot!.t6\rrADSkQ&p,
+kQBV#Fj.r,"5J$ZjS\3AQ\PM?Qi-%JVf(\t!m'g0rTF7,pZMiM4<kaj2d]8VkQ$t7
+rsp\=2(+*@P%ncJB>W]hZ&\b^!!)ut!W`9#r;[0(!<<'!s8N*!s8;ourrE&u!W`6#
+rVlp!s8W&u!WW3!!<3#t!<3#s!!3*"rVuis!WW3!!!3-"rW%QM\,QGpn)sbsrTF=<
+9?YBT!r^87qre$HLAq7?r9+0ZDWq*&aN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=
+2(+*@P%ncJB>W]hZ&XG9K)ad/!130<!7(Q,!S]=-r5ng<qXcK-r9+-Ig&D$PYQ"Th
+r9+6\DZBb%kQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U6CMRS"j5[D)
+K)^H&i;WeDn)sbsrTF=<0`&ic"8)"8m/6&IQi-m^!:Bgb!;c]q!;?Hj!;c]q!9jF_
+!9*qXQi-%LVf)P7lKA>kaR9*,kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_HC27Tt
+_W0[]MLtk[s5<nWQga,<cMcr-gb?eC"SVBN0^S`$!13Za!!)<a!!)`m!!)`m!!)`m
+!!)6_!!)!X!13WI"/g&:s6AeMaN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsqat:/H%X
+H"L]%AW`UWM<oioK)ad/!130<!7(Q,!SfB\o`5$mr:L'j!;c?ko^Cutm/6&IQi@!b
+!;c`p!<3#t!!3-"rW!$"rrDoqrW!*$rrE*!rW)iq!!)rs!!*#u!<E0!!!WB&rrE*!
+rW!!!s8;rss8E!!s8W&uj8T+Gr9+6\DZBb9kl(MdjGlnc0hmM^rVui["3AROs8D-]
+cM-N-6p)\4,r]1)r9+-IK)^H&\c2Yrn)sbsrTF:;0]D^(!;c?h!!)ri!<<,ro`XpU
+kV2B$kQ$tKrr<&rrr<&urrN3#!;ZWr!<3&rrr<&urrN3#!;uis!;ulq!<3!%!<3'!
+rrE&u!<<,srrN3#!<3!"!<3&urrN3#!9*qXQi-%LVf)P7roamms8%d/12`GCGrR7-
+q>^KnkQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4SR[8'Lk2tR('k^rhmrrADSkQ&p,
+kQ9Nnp$_MR!!)`brW)fe!<<,toDnplqXap^mcQ:jr9+-Irr2ruqu6Wrrr3$"rrDus
+r;Zlu!;lcr!<3!$!<3'!s8;rqrr<&qrr<&urr<&urr<&ts8;ourrE&u!<E/t!!3*"
+iVrnEr9+6\DZBb9kQV"bCaao+rVm&sRkJ+Es8D-`aN3fLrTF7,pZMiM4<kaj2d]8V
+kQ$t7rral/1FY<Ts4Z[gs,6mWQga,<cMcr/gbABmmdgGZ!;Z3h!!)Tj!<2Tf!!2]_
+quHTb"S1sB0^S`$!13]b!!)or!!*#u!W`6#rVlitrr3$"rrDrr!!*#u"9AH%rrE&u
+!!)rs!!)lq!!*#u!!*#u!!*#u!!*#u!W`6#rr3$"rrDus!!)!X!13WI"/g&:s8M3b
+s,ABV\GH4-`A)rDrTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13!N#V@xxxxxx>MMV$,
+g?=.gMuNdDn)sbsrTF@=0_=o&nc8^jqskC#!:g*io'ub\o'ub\nc/[\nc/[dnc\LL
+jY6'!kQ$tJrr<&srr<&urrN3#!<)ot!<3!#!<<'!r;Q`srr3*$rrE'!rr30&s8N*!
+rrDrr"T\Q&s8N)urr<&urr<&urrN3#!<3!"!<3&urrN3#!9*qXQi-%LVf)P7roaOF
+/;$YJ[eg"*W%$3okQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C7?A4)SCB+>/
+W2?Gfrr:^9K)^c/!130<!7(Q,"5GU%oDA+W!!)Tg!;Z0c!;uC$!!)Qi!:o[\!:o[\
+!:g*io'ub\qXOdZm,]qfr9+-Ir;Z]q!WW3!!<3#t!!3-"r;cisr;Zlus8E!$s8N*!
+s8;p#s8N*!s82itrrE&u"p"]'!!*$!rVufr!WN0!rrN3#s8E#trrE*"j8T+Gr9+6\
+DZBb9kQZl!o^5L*[/9k)rC225kQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
+Kp%U<C]FBg^qd:0rr;$B!W_EaqriY3MuNdDn)sbsrTF@=0_4f$nGrUir:0U`%IjDu
+naQSZnGiRZnGiRcnHA@Ij=orukQ$s(rrAD`kQ@`#s8W)^#?>F:s6ic7Zhsb'K0]D!
+"3AROs8D-]cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s7a@ij0=XDrrM?Ir;c*G
+!W_EaqriY3MuNdDn)sbsrTF@=0_+]$n,WLhqX=Lc!<2Hu!!)Kg!:]IX!:TsgnF-DX
+qX=XVlJjSbr9+-ILAq7?r9+6\DZBb9kQ*Gnrr3)h;(JpLrrJrHrTF@)aR9*,kQ&p&
+kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\NrK%[ki`$GkPtVJkQ1bJ!;ku3
+s,6mWQga,<cMcr/gbA9gnF-GY!;Q$a!!*#f!rr>jnGE7enF6>UqX=XVlJjSbr9+-I
+LAq7?r9+6\DZBb9kQ*AgrVluh;C\mKrrJlErTF@)aR9*,kQ&p&kQaL<,8qje?VLC]
+!13!N%kTXr-\[_HE,5LJ_;jR\NrK%[ki`$GkQ1bJkl(P`ki`$GkQV%N!9aFHkl(Pb
+ki`$1!;ku3s,6mWQga,<cMcr/gbA6eamTB#l/FD`r9+-ILAq7?r9+6\DZBb9kQ+=f
+r;Qlg<%>'MrrIm=rTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_HE++*;
+_;jR\NrK%[ki`$GkPtV\kQ1bJ!<20d!9aC_ki`$GkQCnL!9aF[k^rhmrrADSkQ&p,
+kQ0Hma6s/ukM\,^r9+-Ig&D$PgA_3SrrCaP!13WI"/g&:s8M3`LGA8qrs/'o.]i[K
+89Xsq"3AROs8D-]cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0-^B4Sp?j0=XDrrM?I
+r;ci\r;[)dkQ'fHki`$GkPtV^kQCnL!9aF[k^rhmrrADSkQ&p,kQ0Hma6EfjiS6-S
+r9+-Ir;Z]qmJm+bqYpNqpAb'kl2LebrrCaP!13WI"/g&:s8M3`gF@sTrs&$p.B99o
+bPgW,aN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\h`!pJhJ
+r9++\roaUfki`$1!9iVHroa=^roaIbkQ'fHqriY3MuNdDn)sbsrTFF@5fDO8h9=^Z
+h:pPm5k"X7!13Za!!)<a!!)`m!!)`m!!*#u!!)<a!W`6#g&D&=r9+6\DZBb9kQCj9
+/%,9S"nPeE0m*HokQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U6CMRS"
+j5[D)rr3&`kQ(PE!!*#^!!*#^!!*#^!!*#^!!*#^"9@WckQ(MDK)^c/!130<!7(Q,
+"5eQAX3&]kca@A;oDIePQi@!b!;c`p!<3#t!!3-"rW!$"rrDoqrW!*$rrE*!rW)iq
+!!*#u!W`9#rW!$"rrE&u"p"Z'rrE*!rW!*$rrE'!g&D&=r9+6\DZBb9kQV"_>q1s3
+rVm&tO=+!$s8D-`aN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]h
+Z&\h`!pJhJqrmtYroa=^roa=^rTO4\"R,%LkQ(MDK)^c/!130<!7(Q,"6A[.9?8dh
+5_S_#r9+-Irr2ruqu6Wrrr3$"rrDlp!W`6#qu6Wrrr3$"rrDus!!)rs!!*#u!!)rs
+!W`6#rr30&rr<'!rrE&u"9AH%rrCaP!13WI"/g&:s8M3ms8Ve@.6;U8PB]2<G4bh7
+rTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_HC27Tt_W0[]NrK(LkPtVJ
+k^rhmrrADSkQ&p+kQC2@oCV2<kP5&L"8;H]lhorHQi@!b!;lcr!<3!"!<3&ss8;ou
+rrDrr!!*#u"9AH%s8W#tr;Z]qrr;os#QOf(rrE*!!<2uu!<3!$!<3'!!87APQi-%L
+Vf)P7roj=\#Ln2d.k3`*d/F"CkQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
+Kp%U6CMRS"j5[D)rr;QQ!!)<JK)^c/!130<!7&(;!13]b!!)or!!*#u!W`6#rVlit
+rr3$"rrDrr!!*#u"9AH%rrE&u!!)rs!!)rs!!*#u#QXo)!<3'!rrE&u!!*#u"9AH%
+rrCaP!13WI"/g&:s6AeMaN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJ
+B>W]hZ&8P\g?=.gMuNdDn)sbs\**gYrVlitr;Q`srr3$"rrE#t!!*#u!s&B$!;uis
+!<3!$!<3'!!<3!&!<<'!s8N)srr<&urr<&urr<&urr<&urr<&urr`?%!<3&PrrAD`
+kQ@`#s8VBJ"3AROs8D-]cM-N-6p)\4,r]1)r9+-IlMhAf:/4W-H$O"7B4[3tT8Dq6
+s4Z[gs,6mWQga,<cF<!;Qi-m^!!3-"rW)rtrW!!!s8;rss8;ous8W&u"TSK%s8W#t
+"onT&s8N)rs8;rsrr<&urr<&ts8E!$s8N*!!87APQi-%LVf)P7lKA>kaR9*,kQ&p&
+kQaL<,8qje?VLC]!12=;g?=.gMuNdDn)sbs\**gY_#FB7aSu7,r9+3[DZAn@!Ug!d
+kQ&p&kQaL<,8qje?VLC]!13Q^#6+Defso,qK)^H&a8Z.+n)sbs\**gY_#FB7aSu7,
+r9+0ZDW]"@mf37L!7(?&#=L[!)C7=L9`4)SQi$dhrpAIln&MTRnc".?K)`sm!130<
+!7(Q,!p&4mjP&eIrn7J/gtq,ikQ$s(rrAD`kQ%OAmK!:ckQ&p&kQaL<,8qje?VLC]
+!13T_$MiW5bOEWV[E@q:K)^H&b5VI.n)sbsrTF@?i/UIO0EXRij5U"#!1/H?!13WI
+irAu@!7(?&#=L[!)C7=L9`4)SQi$dirSZben&MT;\_-\/s+:9nrrADSkQ&p,kQBV#
+Fj.r,"5J$ZjS\3AQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IqYpo\jkK:CXKo1La7Y&a
+K)a$o!130<!7(Q,!o-Gla8Q/=b"MWq!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQhp^j
+iUcO1a1&q2aKj+[rVZ]n!:0Xe!!*'!quD?KK)bQE!130<!7(Q,!S]=-r5ng<qXcK-
+r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$tHrse\\qYKp6ahl$9ZaJ*Hr;Qp#!<<'!
+!9sLa!!%WNK)bEA!130<!7(Q,!o,L+a8#i0mP+#*kQ$s(rrAD=kQ&p&kQaL<,8qje
+?VLC]!13Za&,,DSi;3<Bbf6rp]X5#Sao)/D!!*'!!!*'!r;Zlus82lrs8;p$rr<'!
+!!)orr;_HLK)bcK!130<!7(Q,!SfBLpB:3[l7hT&kQ$s(rrAD=kQ&p&kQaL<,8qje
+?VLC]!13Za&)5LWeGB%3]t1>T]="uOYPeD9!!*'!!!*$!!<<'!!<3$!s8N'!rr<&t
+rr`<%rr<&srriB&s8N'!K)^H&rVlkan)sbsrTF:;0[fUp!!)fe"SD0H0^S`$!1/H?
+!12C&!7(?&#=L[!)C7=L9`4)SQi6pp^q7(lqYK]l[^3NS['R*Lr;ZZp!WW2s!!iN(
+!<<'!!<;ut#64]'!<3$!r;Qp#!<<'!!.t6&s8DrtQga,<cMcr-gb@^[quHKa!<<,p
+o`XpUkV2B$kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13Za&&Y]\]CYIX\$NQT\$NEG
+bl%JA!!)rs!<<,trs&N(s8N'!s8W#t"oeQ&rr<&srriB&s8N'!K)^H&rVlkan)sbs
+rTF=<0_P#/!<<,koE>3po^i+`q"+Re!;Q0hoBtcqm/6&IQ\PM?QeCR&cM-N-6p)Y3
+,r]1)r9+-IrVmDTZa.!i_</54Yc=Y)Za/EbrrE*"r;Qct!;uj#!!*'!!!)ut#64c(
+!!*$!!;uj#!!*'!!!%WNK)bfL!130<!7(Q,"5GU&o_%eV!!)Q\!<<-!o)esmoCMn\
+"7u*a!;Q-go'PQnm/6&IQ\PM?QeCR&cM-N-6p)Y3,r]1)r9+-IrVmD`Yd1X?Lto_W
+V1X/]Vn)!grrE*"qu?Qo!<;rs!WW2u!!WE&!!*'!qu?cts8;qLs+::KrrADSkQ&p,
+kQBTooCM_I!<<,gnc8^jrpgEs!:g*io'ub\nc/[bnc\LLjY6'!kQ$s(rrAD=kQ&p&
+kQaL<+rVad?VLC]!13Za&(I\m^nl51guG2R?YG(pl0eQP!!%WNK)aj1!130<!7(Q,
+"5GU%oD%kV!;c9b!!)Tg!<)Hh!!*#h!WW5kqZ$]g!!)fb"S(j?0^S`$!1/H?!12C&
+!7(?&#=LZu)C7=L9`4)SQi6ppSYt<&Z#nn"o8n)sBOl;3mf*:f!.t6&s5O%YQga,<
+cMcr/gbA<ip[J7a!:TFY!!*#g"98Gl!!)re!<<,pnHA@Ij=orukQ$s(rrAD=kQ&p&
+kQaL<+rVad?VLC]!13Za%t:M;m^%,eoA,I;:L.7+Y(H\*s3:QDQga,<cMcr/gbA9g
+p$_t^!:fOb!!)NX!!)NX!!)rd!<<,pn-&4Fj"TitkQ$s(rrAD=kQ&p&kQaL<+rVad
+?VLC]!13Za&"e2jPG2uuYC9bcI<(1(dt7UOs3:QDQga,<cMcr/gbA9goC)b\!;#^X
+!<)Eb!!;Wi!;Q$dn*8pem/6&IQ\PM?QeCR&cM-N-6p)Y3,r]1)r9+-IK)^H&\c2Yr
+n)sbsrTF@=0_"SRmf`(Ci\9`skQ$s(rrAD=kQ&p&kQaL<+rVad?VLC]!13!N"LV!#
+9K.S'K)aC$!130<!7(Q,!SfBLmf`%@i@sZskQ$s(rrAD=kQ&p&kQaL<+rVad?VLC]
+!13!N"=u>b.6)qZK)aC$!130<!7(Q,!SfBLl3-;/gbA-nkQ$s(rrAD=kQ&p&kQaL<
++rVad?VLC]!13!N#V@xxxxxx>MMQlaK)aO(!130<!7(Q,"l2G^hVI#3h?D`if=F69
+r9+-ILAq7?g#rF]pZMiM4<b[i2d]8VkQ$t7rsp\=2(;jcKl_#/s7iOiVPJhDK)ad/
+!130<!7(Q,"5eQAX3&]kca@A;oDIePQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH
+2)Qb8P*0d"s8Ibg^pA]Gs+::/rrADSkQ&p,kQBo0O\<bL"$hP1o_dnQQ\PM?QeCR&
+cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s7a@ij0=XBs8E#prr<&_rr<%Ns,6mW
+Qga,<cMZl.m-sW=k4Rp4rq-Bep@[bLkQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N
+%kTXr-\[_HE,5LJ_;jR\Nr/hV!;ZWp!9jF_!.t6/rrADSkQ&o;kQ$s(rrAD=kQ&p&
+kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\Nr/hX!<<)t!!3-"rW!-%!<3'!
+s8E!!s8W#trr;rt!WW3!!.t61rrADSkQ&o;kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]
+!13!N%kTXr-\[_HE++*;_;jR\Nr/hY!<<'!rr3$"rrE&u!<<,srrN3#!<3!"!<3&u
+rrN3#!.t6/rrADSkQ&o;kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_H
+?=[\Z_rKd^Nr/hY!<<'!rr3$"rrE&u!!)utr;Zlu!<3!!!<;rs!WN.Os,6mWQga,<
+cF<!;Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XArrW9$
+rrE&u!W`6#rr2rurr2rurr3$"rrE&u!W`6#r;Q`sK)^c/!130<!7&(;!1/H?!12C&
+!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U6CMRS"j5[D)qu6`us8N)urrN3#!<2uu
+!<2uu!<3!"!<3&urrN3#!<3!"!<3%Ns,6mWQga,<cF<!;Q\PM?QeCR&cM-N-6p)\4
+,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XBs8E!!rrE&u"p"]'!!*$!rVufr!WN0!
+rrN3#s8E#trrE*"K)^i1!130<!7&(;!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQg4S]
+/N#C5Kp%U6CMRS"j5[D)K)^H&i;WeDn)sbs\**gYLAq7?g#rF]pZMiM4<kaj2d]8V
+kQ$t7rsp\=2(+*@P%ncJB>W]hZ&XG9K)ad/!130<!7&(;!1/H?!12C&!7(?&#=L[!
+)C7:K9`4)SQg4S]/N#C5Kp%U6CMRS"j5[D%K)^H&i;WeDn)sbs\**gYLAq7?g#rF]
+pZMiM4<kaj2IB/UkQ$t7rsqat:/H%XH"L]%AW`UWM<oioK)ad/!130<!7&(;!1/H?
+!12C&!7(?&#=L[!)C7:K9`4)SQ\,6hs1/.0Qga,<cF<"jQeCR&cM-N-6p)\4,rT+(
+r9+-IlMh!p:/=PBK)^H&ec,W9n)sbsK'8?\!7(?&#=L[!)C7:K9`4)SQg4SR/2K(2
+3.h0^s4.,LQga,<c@Y8BkQ&s'kQaL<,8qjd?VLC]!13!N#V@xxxxxx>MMQlaK)aO(
+!130<!RK,Ek`b32dEhRN#=L[!)C7:K9`4)SQg4S]/N#C7?A4)SCB+>/W2?GfK)^H&
+i;WeDmcX\sd":JHkQ0)Vp?2`L4<kaj2IB/UkQ$t7rsp\=2(+*@P&P4:reA5(Z\3r1
+K)ad/!13*:K$KV+!71?%#=L[!)C7:K9`4)SQg4S]/N#C5Kp%U<C]F.Fj5[D)r;ZZp
+qYpNqkl1V_K)^i1!1/<$K';dh#=L[!)C7:K9`4)SQg4S]/N#C5Kp%U<C]F.Fj5[D)
+r;Q`spAY*mkl1V_K)^i1!1/<$K';dh#=L[!)C7:K9`4)SQg4S]/N#C5Kp%U<C]F.F
+j5[D)r;Q`sr;Q`srr3!!s8E!%rrE'!s8W&u!WW2u!<3#t!!3-"rW%QMO8f3HK'7gM
+o&p<H4<kaj2IB/UkQ$t7rsp\=2(+*@P&OiVGJW>"Z&\b^r;cis"T\Q&s8N)urrE*"
+qu6]trrE&u!W`6#rr3$"rr@ZNNW0!FK'7gMo&p<H4<kaj2IB/UkQ$t7rsp\=2(+*@
+P$V[3AAdHfZ&\b^!!)lq!!*#u!!*#u!!)utr;Zlu!<3!!!<;rs!WN.Os,I$YQ\+FQ
+kjmpB6p)Y3,rT+(r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XBrr<&qrr<&urr<&urr<&u
+rr<&urrN3#!<3!"!<3&srr<%Ns,I$YQ\+FQkjmpB6p)Y3,rT+(r9+-IlMhAH2)Qb8
+P*0QqCM1NEj0=XBrr<&rrriE&!<<'!rr2rurr2rurr3$"rrE&u!W`6#rr3$"rr@ZN
+NW0!FK'7gMo&p<H4<b[i2IB/UkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\b^qu?ct!<3!&
+!<<'!!<3&ts8;ourrE&u!W`9#rW)rt!<<+Os,[0[Q\+FQkjmpB6p)Y3,rT+(r9+-I
+lMhAH2)Qb8P*0QqCM1NEj0=Vrs+::/rrAC;k^r$hkQaL<+rVac?VLC]!13!N%kTXr
+-\[_HC27Tt_W0[]Ne7:_s5<nWQ\+FQkjmpB6p)Y3,rT+(r9+-IlMhAH2)Qb8P*0Qq
+CM1NEj0=Jns+::/rrAC;k^r$hkQaL<+rVac?VLC]!13!N%nfYm:ipu.AnPafOe88&
+m"57hs5<nWQ\+FQkjmpB6p)Y3,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<b[i2IB/U
+kQ$s$s+:9]rrAC;k^r$hkQaL<+rVac?VLC]!1/<;K)`C]!1/<$K';dh#=LZu)C7:K
+9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)Y3,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj
+2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]!1/<$K';dh#=L[!
+)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H
+4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]!1/<$K';dh
+#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&\c2YrK'7gM
+o&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]!1/<$
+K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&\c2Yr
+K'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]
+!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&
+\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;
+K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-I
+K)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]
+!1/<;K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(
+r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd
+?VLC]!1/<;K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4
+,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<
+,8qjd?VLC]!1/<;K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB
+6p)\4,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$h
+kQaL<,8qjd?VLC]!1/<;K)`C]!1/<$K';dh#=L[!)C7=L9`4)SQ\,6hs1/.0Q\+FQ
+kjmpB6p)Y3,r]1)r9+-IK)^H&\c2YrK'7gMo&p<H4<b[i2d]8VkQ$s$s+:9]rrAC;
+k^r$hkQaL<+rVad?VLC]!1/<;K)`C]!1/<$K';dh#=LZu)C7=L9`4)SQ\,6hs1/.0
+Q\+FQkjmpB6p)Y3,r]1)r9+-IK)^H&\c2YrK'7gMo&p<H4<b[i2d]8VkQ$s$s+:9]
+rrAC;k^r$hkQaL<+rVad?VLC]!1/<;K)`C]!1/<$K';dh#=LZu)C7=L9`4)SQ\,6h
+s1/.0Q\+FQkjmpB6p)Y3,r]1)r9/a!JsXNElMlJ"K'<$o#=LZu)C7=L9S2J[kecQK
+s+9HdkkXEI6p)Y3,r]1)K'7gM_W^:bK'7gMq</&O4<b[i2IB.0k^r$8kkb;\n"3GU
+5QXKCkPG41k^r$okQaL<,8qjd?VH(8K':)8qu6bR(gsQH^BD#Z(jPfQs+9HdkkXEI
+6p)\4,rT+(K'7gM_W^su"4oMWp\FgjLG6dIs+9HdkkXEI6p)\4,rT+(K'7gM_W_"!
+#,a/qs-/5%qYpWK3/@M5K'7gMq</&O4<kaj2IB.0k^r$8kR%:hk:#g!s#^9Dq#:F]
+^]4=ck^r$okQaL<,8qjd?VH(8K':)8"98Bl\,QC/49.M=rr_.,p]#j/K'<$o#=L[!
+)C7:K9S2J[kecNbs.<]trrP:_4SSjWLNriNk^r$okQaL<,8qjd?VH(8K':)8!rj,#
+rVls^!'Gu7,lj_;rrF8"K'7gMq</&O4<kaj2IB/UkQ9i%gOe/:g4IlAeH*EMr;QaZ
+rW!'`,ldq?r;QeBLP"`AkkXEI6p)\4,rT+(r9+7>i/UH^0S2"%0EHZQr;R$b!!';(
+o/m"!r;Qf,8:p&WkkXEI6p)\4,rT+(r9+7<NciQts+:9orrHN"r;Qg\!'L8\"/>hr
+bl.PBa#J\7K'<$o#=L[!)C7:K9`4)Uge5hBrdt-lrW--!r;Qg\!'L8\"3^`Fbl.PB
+h]RO7K'<$o#=L[!)C7=L9`4)TgG&X)K):/sbkhESQi-jb49.MCrr^IF!6kEA!P^mO
+k^r$okQaL<,8qje?VLC]!o,L+K)(#ob4u'nGl7RC49-],rr[rT-0G1+!O#=Ok^r$o
+kQaL<,8qje?VLC]!SfA\pO`.]pAr;or;R$b!!#m?UEon;r;Qe*T7Z9YkkXEI6p)\4
+,r]1)r9+1:0S8ulo`5$me+E_A!;6$a!8@)H!!'b+!rj\#rVls^!+R>S!!+D!rVlrn
+)"3(?K'<$o#=L[!)C7=L9`4)TgbA!cquH-W!<<,To`5$mrq-9l!8$lE!!)W`!<<,[
+o`5$mp@SFd!8-rF!!)W`!<<-!o`5$me+EeB^Hhbt#F'qWk&`_-k5>5\BUAaNk^r$o
+kQaL<,8qje?VLC]!o,L&lgt2X!9s+V!!(gH!<<,JoDnple+<Y@!;?$c!!([D!<<,k
+oDnplht-pL!:oaas8Qc!o)Ag43<0#1k^r$okQaL<,8qje?VLC]"5GU&o^)/M!!)rg
+"TSPo!;#g\!<2Tg!!2]_r;ZlioDJ[eo*YNuo)S@^!;#d^!;$*gqXaXc"7lKmoDARg
+oDSahoDJ[doDJXqoCDq^oCDq^oCMn\$hF>uo)Jd^o)Jd^oDJXlo)Jd^oDJXioCMk[
+r::F!!:p3^!!)W^!!)Tj!;#g\!;uHf!!`#p!:p3^oDJXioCMk[!;$0iqt'ad!V>p]
+!!Vuc!!)W^r;cigr;Zihr;Zul!!)W^r;ZlioDAUWo)Sgko^`4cs7[r!o`#'_0\?@)
+K'7gMq</&O4<kaj2d]8VkQBTooCM>>!<<,to)/Omnc/[\nc/[fncSpmnc/[hnc]!n
+o'ub\rUTme%IsK!o'ub\nc/[\nc/[enc8^jrpg^&!:g*io'ub\o'ub\nc/[\nc/[g
+ndb^#o'ub\nc/[\nc/[\!!)ug$NL1t!!)T\!!)Qi!<)I!!!)Qi!:o[\!:g*io'ub\
+rUTme&Fof$o'ub\nc/[\!!)T\!!)ug!rr>lo)/P#nc/[\nc/[\!!)T\!!)T\!!)ug
+!<<,une(p&o'ub\nc/[\!!)T\!!)Qi!<)Hh!!*#h%fcV#!!)T\!!)Qi!:o[\!:KCY
+!!)``rr3&G.$sZ-!k0Serr7T6K'<$o#=L[!)C7=L9`4)VgbA?km.(/W!;uBg!!*#h
+qZ$Zfo)&Ihnc/[ho(rFcnc8^jrpgKu!:o[\!:g*io'ub\o)/Oinc/[hndPR!nc/[\
+nc/[\nc/[\qZ-TcqZ$Zfo)/Ojo'ub\rUL6p!:g*io'ub\o)/P#o'ub\nc/[\nc/[\
+!!)T\!!)ug!<<-!nd,9ro'ub\nc/[\qZ-Tc"TSPnnc/[hndkd$o'ub\nc/[\nc/[\
+nc/[go)/Oho()YX"7cElo(rCgnc/[gnc8^jrpgR"!:g*io'ub\nc/[\nc/[go)/Og
+o)/Ranc/[ao)8Rjmq=]4qYpZ\?qBJZs+9HdkkXEI6p)\4,r]1)r9+7<0_4f$nGrUi
+r:'df!<2Kh!!)re#QOkpnGiRZ!!*#g!<<,qnGrUirp^Bs!:fRZ!:^$hnaQSZqsa[e
+!<2L!!!)Nh!:fRZ!:fRZ!:^$hq=+Ic!;l<b!!Dc]!!)uf$31(r!!)QZ!!)QZr;[E!
+!!)Nh!:fRZ!:^$hnaQSZrUBmg!<2Kr!!)QZ!!)Nh!:^$hq=+Ug!:fRZ!<2L"!!)QZ
+!!)Nh!:fRZ!:fRZ!;uBc!!;Zj!;u?i!!)Nh!;u?f!!)uf!<<-!nIGU"nGiRZnGiRZ
+!!)QZ!!)HW!<<,nnb`=na!`WkLVJn"5T$-js+9HdkkXEI6p)\4,r]1)r9+7<0_+]"
+n,WLhr9s^e!<2Hg!!)rd#QOkon,NIX!!*#f!<<,qn,WLhrpU<r!:]IX!:TsgnF-DX
+qsXUd!<2Hu!!)Kg!:]IX!:]IX!:Tsgq="Cb!;u<l!!)NX!!)Kg!<)Bm!!)Kg!:]IX
+!<)C"!!)Kg!:TsgnF-DXn,NIXn,NIen,WLhrpU9q!:]IX!:Tsgn,NIan-&dlnF-DX
+rpUI!!:]IX!:TsgnF-DXnF-DXqX=Uf!:Tsgr9sgh!:Tsgr9s^e!<)Bf!!*#f%fcV!
+!!)NX!!)Kg!:]IX!:]IY!!)Z\q>UZFIs=4tJ%tgZK'7gMq</&O4<kaj2d]8VkQBTo
+naYr7qu?ff!!)uequ?cenGE7enF6DW!V#UV!<)Bf!!)uequ?rj!!)NX!!)lbrW!Ju
+!!)Kg!:]IX!:]IX!:]LU!;u?a!!r&o!:]IX!:]LV!!Mck!:]LU!!)Ne!!Vl]!!)NX
+r;[)ln,NIXn,NIen,WLhrUB^b"RlBknF6>UrU9sj!:]IX!<)Ec!"8;c!!)NX!!)NX
+!!)uer;cidqu?lh!!)NXqu?cenGN=fnF6DW"RlBknF6AV#Oq3_!:]IX!:oU[!!)3O
+"RkX90^ODTK';dh#=L[!)C7=L9`4)VgbA6eK("<[_!_Eol/FD`K'7gMo&p<H4<b[i
+2d]8VkQ0HmK("<[^@)3lkM\,^K'7gMo&p<H4<b[i2d]8VkQ0HmK'IsQ^?PjaiS6-S
+K'7gMo&p<H4<b[i2d]8VkQTd-`89>+K&2+9_qkRQgXj#%mt0bTkjmpB6p)Y3,r]1)
+r9+7?IVGj7d"9W[cih\&AqT],k^r$hkQaL<+rVad?VLC]"6A[.97ejL0Y]:D5_S_#
+K'7gMo&p<H4<b[i2d]8UkQC2@oCRY-iUqftj7rWH"8;H]l[n>PkjmpB6p)Y3,r]1)
+K'7gMK'7gMUZ_qN4<b[i2d]71k^r#Mk^r#nkQaL<+rVad?VH(8K'7gMK'8un#=LZu
+)C7=L9S2J[k^r#MkbI>H6p)Y3,r]1)K'7gMK'7gMUZ`"P4<kaj2d]7QRf8TQP_,'M
+P(JjKP-:#KPl@!WS>&D6,8qje?VJtmrl,&X_SO(a_"kb=^APZr]RmeJ]RmfI]`#GB
+^&GeT`QU_4,8qje?VKM:rn@G+rn-hopX];m!S,`re:Q/$dt6&#e)AaUdeqPreC)do
+rm_D.gI+.K)C7=L9^D!CkQ'fFkk"!5k547ljFZHEjFZIGjS\'8iW.s9iX"R44<kaj
+2d]8Vn+5uCm/cS?qs3k=K'@mOK'@mOjQQ^/kks]AkR$G86p)\4,r]1)rU'dTmI'E;
+mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)L
+lg+H5q<@kA!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5
+q<@kA!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA
+!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#
+k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#M
+k^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$T
+kkXBLZa8iX6p)Y3,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$TkkXBL
+Za9\p6p)Y3,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$TkkXBMk5YJE
+6p)Y3,r]1)mJcDOm.9Q;lM]rLkih9qqrmn>K'%[IK'%[Ii8t%$qr[k=#=LZu)C7=L
+9_@ZFl4*"Bkih9qkih9qkih9qqrmn>K'%[IK'%[IiT:.%roO`tZf^DVZfU::4<b[i
+2d]8Ulh9W>kl^/5l08*/pZDS>k5OOqk(;`Ik(;aOjq"f)s5gSns5cX2+rVad?VL@]
+rp'CFp#u57!TiGAk(;]HjauTGjj`B*jT#8AjT#8@6p)Y3,r]1)kND'mp?2A9nDs]3
+jS.\die$0Aie$1MiWeH&j5T(Yj8%[>6p)Y3,r]1)o&BQ*p##l.hu2Jbhh'a;hh'b<
+h\G#)Za8NFZa8NFZa8KD6p)Y3,r]1)o\B,okh:XAK%Yb/K%],9'=5%FfsA$bfsA$b
+fL.hG)C7=L9^^O(f(%:Be:Q2%e:Q3-e.hr_eC=NueC4HtdmQ;B)C7=L9\eFsh;d;f
+gOe.2g4J%1g=P$dg"=qF4<b[i2bm^Rnk+L%Jjb2YJjcq5#Wsaa)C7=2:.=_<JinWI
+JinWIZTJ@L/gD8WYTr-Ong!]LnK[TKiZn"<dNdcrnK[TKJg8;\nfk=`![&C$Jf94Z
+Jf94ZS/M
+~>
+grestore
+currentdict /inputf undef
+currentdict /pstr undef
diff -r 4acc6d51f389 -r b76e86966e7e docs/figs/acm_overview.eps
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/figs/acm_overview.eps Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1463 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%BoundingBox: 0 0 1106 631
+%
+% created by bmeps 1.2.6a (SCCS=1.78)
+%
+/pstr
+ 1106 string
+def
+/inputf
+ currentfile
+ /ASCII85Decode filter
+ /RunLengthDecode filter
+def
+gsave
+0 631 translate
+1106 631 scale
+1106 631 8 [1106 0 0 -631 0 0]
+{ inputf pstr readstring pop }
+image
+K)^H&K)^H&K)^H&VuHbSm(WPPK)^H&K)^H&K)^H&K)^H&_Z']3LFD?d!FYAJs-s#g
+mt/<E^B!_Ss+:9&s+:99rrL.gjT#<(hh(m!rrLFWJcM;@!=6Gls+:9&s+:9<rrMk=
+rW!!JGdm%S"J83b!'#T1Sc8\>JcM5>!.TV#K)^H&K)_5<"F'nH#`%UC")%Z7^OlKW
+rr[`N!2kF`T>(F-!.TV#K)^H&K)_8="NLKB.+dV]"7H3iO+RD'rr[`N!8iD.TDnrm
+!.TV#K)^H&K)_;>"SX;E#g_T3![%JFK)_GB"+L:Nhh(m#rrN0#ItI]Ps+:9&s-iri
+NrT08j8T3X!#YH^s.B;nIfKK+K)_JC!WW4MK)^H&K)^H&Rf<FK!#X_q"HNN_8FM01
+T`5+D!!(o.s.B;m!!%M#s+:9&s+:9>rrN0#B]8sk5lL``3/'U!BSY35rr[`N!8iD.
+TDnrm!.TV#K)^H&K)_>?"6TXaTAfeNmmr$1rVut,n"]mbIfKK+K)_JC!WW4MK)^H&
+K)^H&S,WTJ!!'LcrrK<QKKoMSrVus9\"s$+IfKK+K)_JC!WW4MK)^H&K)^H&S,WTJ
+!!'ccs5*bVcWL/H!-k@?"+L:Nhh(m#rrN0#ItI]Ps.TGnkD+Y=\UOX@n&YM2hZ*Yk
+K)aX+"Lf3J!5GE2"+L:Nhh(m#rrN0#ItI]Ps.TGm0S0;6!!$-Brr_-Y!5F-cg]%E>
+&-*jIVuHjK!!(o.s.B;m!!%Mbrrqk`Im?71JcM_L"UI@YBRe@Ks+16Z!!#:*rr_-Y
+!5F-cgA_8I!!$u9rr[`N!8iD.TDnrm!.Vod!N/bG!1X#j+E6MdrrN0#ItI^4rrPFc
+5fis-hZ*YkK)aO("#p8lpSe)oIfKK+K)_JC!WW4M`W#tJ0`:tR#XCY"Jq'\J!a%]1
+r;Zm)E:;$N!WW4MK)`I_!^H`NaSuA"!!'ccs4RDSQN.$+W;csL!!(oprrg)j@q1b,
+rrR9gA,H9+g&B4PrrRm:Z1@nr^P/rgrrN0#=SK'#ldGe6ha%/@!si#,pO`F=rrUf%
+./j2I&<G*9!WW4MK)`I_!^H`NaSuA"!!'ccs4RDShZ*YSW;csL!!(pFrrV>:PhZ3=
+bWPe'!0mE]!6hqP!3uM'"jI#HYrj?2!!4H/UZh^Yk1T_5!0mH_!87#E"Qh!1!5JC1
+!WW3npQbg@e,KWm(]XOIL\HE#S,WN85lL`aB_TjQ!WW4MK)`I_!^H`NaSuA"!!'cc
+s4RDSpAb2cW;csL!!(pKrr@cN,m"&HUYYqNfd6Lq!+Z$."MZ5_-/#j/!'L5\!nmV,
+pAb4kk3N$LKd?^]rr2tPrVurBo`"p8rVuqPqYpTs!)*'P!9M`1"fDV+!-%CYs-N`h
+^E<LV5k!)"!WW4MK)`I_!^H`NaSuA"!!'ccs4I>Q!!&Xirr[`N!8mMM!O3sH!!#mP
+rr>pp!!=Mn4PB`6!'L5\!+WV?!5JL5"&]*ubk;#;--Y`U!%%UE"/GnrL&M&Pbk1o8
+Pl:X_L&1fN!!#[dQ2p$srrfM*!!o3Ks-3Neml1:I3;:i#!WW4MK)`I_!^H`NaSuA"
+!!'ccs4I>Q!!&Xirr[`N!8mPN!2K8g!'K-<!87;N!JT\5rr>pq!!%,Prr?R.!!C"9
+s31HB"Asl,;'l/@!'KWJ!%%UE"2Fm9L&M&Pbk1o8L&M&PU\aul!!#[dQ2p$trrgXR
+!"cnss-!BbpK.Cq=OI-M!!%M#s1A:45QF'jrr_-Y!5HSS!d$Q0p\t<"4JVfR!d$Q"
+qu6bn,s9lYrr[?h4QaEY!WW4mW;csL!!(pOrrAhl!!4H/-2mlE4Pp)<Pl:X_A,6-,
+fhj%m\c2aX!!#.\rrC:B!!%`Orr@cO!!&e]rr]Mg-$9.d!/:CP!6k*8!/:CP!6k<>
+!WW3npQbg@fDc!:+92DNK)^r4"SY.]!/K#&!WW4MK)`I_!^H`NaSuA"!!'dTrrBh5
+!!%`KrrAhn!!(^Nrr[rT!%%OB"!mpI;>gFr,ldq!^]+?8!2$4i"+L:Nhtd9P^\n-<
+-*dLMo-FA:;;V<QA,ZH.bc^sGL&M&PPlC[_bl.SBL&CrNL&M&P;<IlYL&M&Pbk1o8
+L&M&Pbkh>@!!#[dQ2p$urr[3?!0;a3NrK7N+92]1e,KIL!.TV#]Dhpt!'nX*"5a(Y
+^W?ETg&1mNU\k&kZ2O_'-2dcC-2mlEU](2mbl.SB-2dcF,ldq!^]+?8!2$4i"+L:N
+htm?Ro-OA9!@>tgrr]#B4PB6(!p533rVlo\g%bRL49,@-XoAJL!!">DrrC:B!!%`N
+rrC:B!!#.Drr@cP!!(7<rrhKHs8Psq!!(7>rrN0#9D=_Pjk0S8cN!rAK)^f0"4$rI
+:t,FG!!%M#s1A:45QEA1YlO+<rr_-Y!5HSS!2KMn!@?FtrrM7.rVur5rVllNr;Zh-
+rVlkOr;ZiArVlsG!!%_frrN0#T;_blIfKK+qYpP*rVusFbk(i<k*0@<A#&r$$7,ZP
+U]6#o,lf6FrVm8fb`jCR!$u_L4AiB^rr^"u4O!X$"jE3bKqmf/rr_CG-"HlQ"6M]l
+;?$S&Yu-bcs1`Y<,pe9BrrM8Hr]C6ZPih]>!2KMn!+Z!-!6kEB!/:@N!5JL5!'L8\
+"6M]lA,Q?/juaqerVlqQ4Al(W!/:CP!6k??!M_dU,m@..!!">-qYpTs!)*'P!9Ml5
+"&Jstc[u1TrrZ't!700p!WW4MK)`I_!^H`4pm(pAdf0F,!!'dRrrAhn!!#.[rr>1\
+!!&8]rrA;^!!#.[rr>1[!!&8^rrXPI!/82f!WW4mW;csL!!(pRrrBh4!!&ecrrI3f
+qu?a[bl7VBbl.SC4AktU"GQmUUF#U6!87AO"!mpI4T#-ZKdHWs!@<I!rr@0?!!(7A
+rr@cP!!gaJjs:!-PYq;X!2KMm!JMis!!+Bfp\t@Y!!">-rVllArVuqPrVlo\4T5<\
+PlC[_FT)7?bl.PAL&M&Sbl@^rrVuq?rr2tPrVurBr;QaZpAb1>q>UKr!)*'P!9Mo6
+"4mMQBS-8Arr_-a!*IbN!WW4MK)`I_!^H`4pm(pAdf0F,!!'dQrr?R.!!>@`s)e5?
+!+Yp+!+Ys-!%%UD!%%RD!/:CO"!mpIKtmWh!!&Xirr[`N!8m\R!)`^q!+YX#!'L&W
+"=<[>s310:"""!I4S8[Sg&D!R,ldokrVloB-27HB-/&;\rVurBrVljprW!#Ds310:
+!'L8\!+Ya'!/:7K!2KMn!+Ys,!6kEB"_5d#P[c$=!!">Drr>1\!!(7Arr>pq!!CIF
+s31HB!'L8\!/:CP!6kEA!'KrT!%%I@!WW3npQbg@g&D/(!!(>ss,$aX:]Ldqec,[N
+!.TV#]Dhpt!%.K,!9MZ/"5a(Y^Vp-P4T5<]A$Q"5!'L,X!'L/Z"53_S^\e'34T59^
+,ldq!^]+?8!2$4i"+L:Nhu*KSg&:sP-0Fk"!+Yp,!%%RD"(VB2bk_;?;*=gX!mL[u
+q>gL@!Bc)7rrXPI!'L8\!SJdt!!4H/4T,6]L&WIu!!(^Nrr>1\!!:CEbkhA@,s;/,
+"$HV`Z2FY),s4:9rVupEq>URD!!">-r;Qc@o`+usrVljDrVurOrVlj[rW!&Es8U=B
+!!%-?rr@cP!!(7Brr?R.!!FTXKnWD&!!">@rrN0#9D=_Pjk9Y8-ibBAs+p[WT)\kh
+ec,[N!.TV#]Dhpt!%.K,!9MZ/"5a(Y^Vp-Qo-OA9"=4$J--Z5c!%%OC"/GnrA,H<,
+-2miG,ldq!^]+?8!2$4i"+L:Nhu*KSFT)7?A+]d$^\n-7A(gmHrW!$Hs8U=?!!8qq
+bl.SKU]:A/PftER!'L&V"!mpI4T>?\;>pOr4MUmq!0mH_"blt&!!">Crr>1\!!:CE
+bkqGIFQWTL!!#.]s#g8\!0mK_!0mH_!%%LA!/:CP!+Yp+!6k-:!@>MZrrXPI!%%RC
+!'L5\"3gfFbl.SBL&V)PL&M&Xbl@_*,ldokbl.PAPl:X_-2IQB!!#[dQ2p%#rr^jQ
+!-j+qM#RSG#QRuWrrN0#ItI^4rrPFc-MWl,jjO/2hZ*Yk_uBb]-2[`CPktC[bkhAH
+A,lQT!!";F!%%UD"!mpIbeO/Z!!&Xirr[`N!8m_S!'L5\!5J1+!+Z!.!)`^p!+Z!.
+!l+cZqu?hQs8U=B!!%`NrrXPI!'L)W!6kEB"$HV`^]"354T,3ZL&M&UL&WG!!%%RC
+!'L5\!mL\gr;Zhmrr3-J!!#mr^]"39A,lS(4T,6[A,H90o-FA:-1h$6!6k'8!2KPn
+"!mpI-2dcC4T5<_bl@]srVuqPrr2tPrW!&Es8S>_!!&ekrrXPI!'L)W!WW3npQbg@
+gA_8a!!(&ks+gUU:]NK*rrN0#ItI^4rrPFc-MWl,jjO/2hZ*Yk_Z'V#r;Zh-q>UbT
+!!"<-!!#.]^]"35L&M&Pbl7VE,ldqh^]+?8!2$4i"+L:Nhu*KV,ldokoD\e:rVurO
+rVll4rW!"Rs31EA!'L8\!5JL5!/:@N"!mpI4Sf!Wbl.SE4TGFkrVuqnr;Qb=rW!,:
+s!7XF-2dcI49,@-k5W[)!!$O-rro/D4PBaVrW!#)KdHWs!'L,X!+Z!.!/::L!6kEB
+!)``L!FmGS!!ah's8OAF!%%RC#<Vtd-0G7-L&M&PL&V)PL&M&Vbl@]?!!">ArrXPI
+!'L)W!WW3npQbg@gA_8I!!)K;rrJ@Ko`#!-L$"Qu!p53$qYpWgKp;E5"5.0]k0O&/
+BE01*rrN0#IuaO0ft[N?!L2:&rr^"u-)8lf!^H`4pm(pAdf0F,!!'dNrr>1[!!$O)
+rt.?n!'Gr8!%%YT!!">:,ldq0rr3'H!!(6XrrN0#T;_blIfKK+r;QjF!!">:rrXPI
+!%%RC!6kEB!epZur;Zh^rr2tPrVuqPr;QjF!!#.WrrC:B!!YRcs#^8]-2[]B4T5<a
+g&E>u!%%RC#!;kc-3+"hrVuqPq#:=VrVupEqu?a[U\aunjs:!--2IQ@xxxxxx&CrO
+^HDJq##YF#,ldokr;Qj]!!">Err@cP!!%`Prr@cP!!^[Is#^8]4So'[,ldp-q>UKr
+!)*'P!9Mr7!e11UeGfYK!!#.Dp\t>j!!"=ErrSrAFRoG3L&<4u!!&ekrrXPI!+Ym*
+"$?P`4O=$/IfKK!rrN0#J+EU>g&B1sKfjIRrr@cL!!,3Wm/I/M!!">BrrJ@Zg&D+=
+!%.K,!9MZ/"5a(Y^Vg'O;>U=nU\aun,ldpebl.SNUEom?A,eXk!+Z'/bl.SBbeO/Z
+!!&Xirr[`N!8m_S"!mpI-2@KCg!'Krbl.SB4T,3Zbl.SDL&[D:!!+D.rr2tPrVuqP
+r;QjF!!#.WrrC:B!!YRcs!7XF-2[]K,ldoks8OAF!%%RC#!;kc-3+"hrVuqPq#:=V
+q>^OYU\OihA,ZH.U\Xoibl.SBL&1fU,ldokk5Q_-!%%RC"$?P`-3!oEL&M&PL&V)P
+L&M&Vbl@]*!!#.XrrXPI!'L)W!WW3npQbg@gA_4f!$Kek!%%UE!@@@5rrAhm!!(6D
+rrgOl!!&eerrKANq#CClr;QbNrVupEqu6Ykr;Zi4d/O37!!)35rrN0#J+WaAUHJAQ
+!847L!%%C?!)`.`"$?P`-2dcF49,@DgA_4>!%.K,!9MZ/"5a(Y^Vp-PA,ZH34='t-
+-0G.*!2KMn"i('`!!#.\!!p@>@fQKTs8U=B!!(6XrrN0#T;_blIfKK+r;QaCrVuqn
+qu7#p@fQL+s8OAF!'L2Z!5JL5!gN_=rVupErVlkOrVuqPr;QjF!!#.WrrC:B!!YRc
+s!7XF-2dcC^]"3;-3+!-!!">CrrtRc!%%[Fbl.SBL%tZJ4T,6],uMGOrrBh5!!#.V
+rrC:B!!%`Lrr>1\!!UUH49,@-r;Qj]!!">Err@cP!!%`Prr@cP!!^[Is#^8]-2RWD
+,ldp-q>UKr!)*'P!9Mr7!al!neGfMjr;Zg[qYpQ1r;Zg[WrE&]rVuq?pAY,fpAb1U
+r;QaCr;Zhmr;Qb,r;Zh>d/O3?!!(p-rrN0#J+`gA;>:+kL!K]#ffUR&h>[I$pAb1U
+mf*AO!!">DrrC:A!!(^,rrPFc-MWl,jjO/2hZ*Yk`W#pJrW!!Gk-=mc!'L2Z##P@#
+-3+!Bqu@0Ps8S;`!%$e-bQ%Vhk.got!!&Xirr[`N!8m_S!-J2?!@>tgrrJl@rW!0L
+s8OAF!%$e+rr>pq!!:jRL&M&P4T59[^]"35A,Q?/,ldp-q>UH=rW!-bs8OAF!%%RC
+!)`^q"$HV`4T5<\bl.PG49,@-s8U=B!!%`Jrr>pq!!,sZqu6]Zbl.PA;>pOqU\Oih
+bl.SBL&CrOUJ_!j"""!I4T5<\bl.PD49,@-rr2tPrVuqPrr2tPrW!&Es8R3?!!$O,
+rrgOl!!">@rrN0#9D=_PjkB_9?iWI@rr?R-!!%-=rrM^;rVusFo;hlkA,QB-4SSjU
+U\k)n,s3LQ!!#.[rrM7.r;Zh>r;QaCr;Zg[d/O3?!!(p-rrN0#J+imB4SJgUL!K]$
+;#gSBk2-+C,ldp-bfmh!r;Zh>n,EJP!!">DrrhI1!!">!rrPFc-MWl,jjO/2hZ*Yk
+`r?%'rW!'Ibl@]brVuq?rVm'J!!#.]s-3E]"(VB2g&:sTPlJr-!%#AZ!WW4mW;csL
+!!(pSrrM7.rW!'I@teD=qu?g]s8QU.!!GFHs8QU.!!>@`s+UFP!'L5[!6kEB!'L2Z
+"!mpI4Sf!Wbl.SE4TGFkrVuqPrr2t.r;Zp^s8RfP!"5%ks5qNO!!">Fs31HB!/:4J
+!2KMn!@=N>rs.4e,liZ!s4RAO!'L#U!6kEB"a%tQF?ClI!!B"rs+UFP#aGAhk0,+O
+!%%XE!/:CP!/:FP!/:CP"O-oGjsC!,"_6]ps-+i/!!">@rrN0#9D=_PjkB_9?iWI?
+rr?R-!!&emrr>pq!!+CiX8`1)qu?^Cq#:?/r;[*LZ2ajq,ldpBrVll4qu?^ZrVlo\
+-2dfD-.)YoT)\lKf)GdO!.XbC!'L2["!r&C4T5<\L!K\u4T5<\bhi@%,ldp-rVlkm
+rVupEn,EJP!!">Crr^#5;;'\'!^H`4pm(pAdf0F,!!'dSrrAhn!!+CirVlj[rW!>$
+s8V4-!!%-@s5kX+!!'e5rs0nN!)`c\!!">Crr^#G,uM__!WW4mW;csL!!(pRrrAhe
+!!#mqrrM7.rW)pDr;Zr)s8RfP!!#.ZrrXPI!%%RC"!mpI4Sf!Wbl.SE4TGGrr;Zm]
+@jV$Q"$HV`U\t2l-2dfG-0G6OrVuqPp\t4Ur;ZpG4?Oqg!!?a2s'u$.!2K;g!6k'8
+!2KPn!2KJmr[%LC"=<41s+UFP!/:FP!/:CP!6kHB!-J/>r[%IB!%%I@!WW3npQbg@
+gA_4^!'ns3!'L5\"=;:ls)e2>!2Jo\!p533rVlo\fua6po-O86!875K!V7W:!!+Ci
+rVltp,s9lZrr@cN!!">DrrAhl!!"=lrr\kn!8lB-!WW4Mq#:>(r;Zh-rr3,`,ldq?
+cMmlSrVuqPhu<]0rVup\r;Qb=rVurBnG`SQ!!"=mrrPFc-MWl,jjO/2hZ*YkaSu78
+r;Zhmr;Qc3rW!$Hbl>od!!&8_rr>1\!!">Drs_g*!%%Z!!!"=!Ki'-Br;ZhOaSu;A
+!2$4i"+L:Nhtm?QU\Ffi-'\?-!0m6Y!+Z$.!0mH_!/:@N"!mpI-2miHjs:!-4Sf!W
+bl.SB4T>?\FS5\7L&V)P-2%<?bl>od!!%`IrrL=ipAbFEg&L1\!!">=rrC::!!,3s
+r;QaCp&G3=s8RfP!!%`Prr@cP!!(7Arr>1S!!(^KrrN0#9D=_PjkB_9?iWI>rrLe!
+rW!!Gk-=jb!+Yg(!SMSo498requ7!L!!&eoKdA#F-&(Xa!d$PYjo5<jrVupErVuqn
+qYpP*rVusFbk1o84So*Yg&D!O;>U=nbgHFmT)\lKf)GdO!.XhE!0mE^!+Ys,!jPUe
+p\t9VbhW4#UP6I)rW!%BKnZ;]rrC:B!!%-=rr@cP!!(74rrY@`!%%.7!mJmAjo5BI
+!%.K,!9MZ/"5a(Y^W?ET-2mlEU\aujL&M&R4TEY)!!(7Brr@0?!!%`Orr@cP!!1;t
+o`+usaSu;A!2$4i"+L:Nhtd9R^JQ<V!!4GmL&(`LUF#g<!@;jdrrC:B!!%`NrrY@`
+!%%UD!6kEB!)`Ok"$?P`L&M#PKdHWs"Ci_X!/:FP!R)ka!!:CEbl.SBU\=]ho4'*D
+!!OZGk5YJ*rVuqPp&>"<q>^RC;5=!f!R)ka!!gaJs5kU-!5JO5"-`cc-2[]CF=$ea
+"!mpI-2IQB!!#[dQ2p%#rrQR.5g]N2Z2FY'4=0t,!'L&V!+Yj*!@=N?rrC:B!!,2Z
+qZ$VMm/I'\rVurOkPkOerVusFA,ZH.FSl(<^\n-4U\"Kc-2RZB^]+65-2RZB^X<&`
+T)\lKf)GdO!.XkF!Tk^-!!$O&rsRLB-):LT;'dLg-):D<!TnM&,m$2Nk4nrWUJ_":
+!BcVFrr?R&!!#.ZrrJllr?VJAU[\9`bl.SBL&CrNA,ZH.bl%JEPWU6<4GE\4"$?P`
+-2miGo/n<]qYpSM-2mlG-"H*:rrR9g;>L4ojuar3qYpU^!%.K,!9MZ/"5a(Y^W?EW
+,ldq?q#:V0!!">Ff`2!urVlu^,lg(*rrqO2!!(6Xq#CLC-"F^1rrN0#T;_blIfKK+
+p\t6UrlbB)pAY0UFT+B'FQWK#!b3NRqu6c',pf>brrC:B!!%`IrrJA!qu6l_PYjPQ
+^Y/Sd!/:@N$):um4ER@',pcFfrrQ[V;=jemk+dW-4GBQmrVlu^,lf7`rs.[r4?S=O
+UWiE2$):um4ER@',pcFerrV>:g&1jOP_HmJrs>HB4Ca)[s--Bqq>UKr!)*'P!9Mr7
+!al!nci4!?q>^OBbk_8=4SJgX^]4>Xp&G(=m/I'>rVurBkPkNErVutQbl.SB4T#-Y
+;>pOqA+T^$jsBm)"*FSC^\Rp1L!fo&T)\lKf)GdO!.XkF!+Z!.!'KrS"Ao.!,uOO>
+!%%UD!M^t;!!+C@qu6]@4Sf$\-):M?-1q6<k5PA\;>C1l4RrFObl.SBL&M#OZ2O_'
+-2miEYpK8I!@>tgrrY@`!%%UD!/:CP!2KJl!+Yj*"!s`BU](5nFSc";;>pOqg&(dN
+5QE/+Q2p$prr_-Y!5HVT!ni:4pAYAO4L+qdZ%^m/rrM9+qYq#04GEh8Yrj<p4AggI
+k/@9$!!&Xirr[`N!8klt"!mpnk3;mGU](5n^\%O+k2-+<bh)jpk1BV7!!#[dQ2p%#
+rrQR.5gKB0A,?6+U\XoiFSu4=49-],!!?a2s31<>!DtuY!!(71rr@cP!!(7,rr@0?
+!!YRcs!7XF-2dcCg&:sP-0Fh!!2KAj"$HV`A,ZH.4T5<\;:5CGT)\lKf)GdO!.XnG
+!Tk^-!!'e,rr>1T!!CIFs0;:u!@?n,rrJl@p](CBs8R37!!#.\rr>1U!!$O"rrC:B
+!!J#Us5o%6!!%`PrrB>!!!#.[rrY@`!%%UD!/:CP!/:CO!-Iu9![[l]r;Zi4r;Qc3
+rVusFk55/[5QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:NhoG`tbi\-h!)`^q!82u(
+q>UKr!)*'P!9Mr7!al!nc2Rbir;Zh-q>UW\,ldok^]+65A,ZH1;?-[?qZ$\ms31HB
+!2K)a"L2H!4=0t,rB((bmJd4?-2mlH^]4<[rVurBrVlk>rVuq.o)A]"rW!15,ldok
+s8ODE!!KPQ!!"=mrr\kn!8lB-!WW4Mqu6Y<rVupqo`"nRqu?dE;,R;m"3gfF-2mlE
+4T:$7-2mlEPlC[`fd6Ut#:3lTKd?^!-3!oHftW5<rVuq.rlkBA!/:CP"=7Q3Kk()^
+!%%49!/:CP"!p&U-2dfD4T>?]jsBs+!@9l,!!%`PrrY@`!%%UD!/:CP!6kHB!5JI4
+$&-U<@fQKTs8P4\!!#.Zrr>pq!!$O*rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL
+!!(oYrrAhn!!"<ss7lTq!!#[dQ2p%#rrQR.5gKB0A,H<,4Sf!WFT)7CPlKm"-2dfG
+U]:A<qu?hQs8U=B!!%`Crr=A<!!(^?rr>pq!!H1!bfi3K!!%`Orr>1\!!'e)rr=AE
+!!0>NrVuuC^]"3:-3#7k!%$%m".oPnhq%f/!!%NGrr=AE!!'e+rr>1[!!?a&s+UFP
+!mL[urVuq.rr3"o-2mlEU]18n;>pOu--ZDhbl.SBA,H9+L&M&PL&:lU,ldokbl@_*
+A,ZH.-1_'9L%bQJ4PB`6!+Z!."=:h_s.fPn!%%XE"$?P`-2miDFT)7?bl7VB;>pOq
+L&M#TZ%_??s1eL4!/:FP!5JI4!875K!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N
+!8k3a"/@.g4T:$7;>gIpKnB@"rrN0#9D=_PjkB_9?iWI<rr@0;!!%-;rrtRc!%#j!
+-2[`CA,cK.bl%MA4T>?\^]"35L%50C-2%<>-0F[r!0mE^!@9&h!!#mprrXPI!%%49
+!87>O![[kVrVutQA,ZH0FT4K&!!'d^rr\kn!8lB-!WW4Mr;Qo^,ldokoD\eQrVuq.
+rr3G&!!">-s!7XF-1h/$4T,6[-3!oEg&:sP--ZAg!6kEB!/:=M!2KMn!/:@N!2KMn
+"GQlj@jV'R!/:"D!/:4K!@;jcrr=AE!!';&rsCjg!%$e-s#^8]-2miD4T5<_bl@^X
+rVup\pAY,&rVupErr2sqrVupqq>UL]!%.K,!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+
+[Jp4QpAb1UK)bTF!WW3npQbg@gA_4^!'np2!2KJm!%%RD!3uG$!%%C?!E$W1rrC:A
+!!&8_rr@cP!!%`CrrM89r]L/["E]?O;6fTi!)`@g!%%UD"!mpI-1_'9L&M&R4TD2U
+!!,2.rW!#Qs+UFP!-HZh".oPnhq%f/!!%NHrrC:B!!#.QrrbFa!%%78rsFHBZ2`r4
+!!#l<-2[`D4O!g)!/:CP!-J2>!6kEB!/:=M!6kEB!/:@N"_.N4-o!!+Bfnc&TC
+rW)p[!E#*YrrC:B!!">Crr@cP!!^[Is#^8]-2miD4T5<_bl@]QrVur5pAY0U-2mlG
+L&\pd!!'e0rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL!!(oarr>1V!!#lJs7ZHo
+!!#[dQ2p%#rrQR.5gfT3U\t/o4TA:X!!+D;r;QaCqZ$[D;8<#.!0mH_!@?n-rr@cP
+!!%`?rr@cP!!(7/rr>1W!!+Alr;ZiNrr3'H!!">?rrLfsrVlj[rW!%Ss5kX)!!>@`
+s1eO5!'J^0".oPnhq%f/!!%NHrrC:B!!#.QrrY@`!%%F?!6k3<!Bd.Trr>1\!!(7A
+rrC:B!!%`MrrC:B!!%-=rr>1W!!4HVk4&BNFT)7?g%YLHU](5nA,Q?,L&M&Vbl@]*
+!!">Drr>1\!!^[Is!7XF-1q3;L&M&R-0A_:!!#mkrrPFc-MWl,jjO/2hZ*YkK)aL'
+!WW4mW;csL!!(o`rrJ?Hr?VM-A&!Wqp&>'n!)*'P!9Mr7!al!ndf0<^r;ZsHbl?fO
+rVupqr;QaCr;ZmFA*3Ue!/:CP!%%UD!/:CP!/9h?!/:CP!6jg0!Tk^-!!dV"^Wapa
+s&&aq!0mK_!%%UE!2KGk"S6+'!)`aq!%%UE"3gfF-2RZBPlC[b,ldokdf0EA!!(p-
+rrN0#J,K<Hbl.SB4Sf!Yk(T'!rrY@`!%%F?!6k9>!Bd.Rrr>1\!!(7ArrC:B!!%`M
+rrC:B!!#.Zrr>1Y!!4HVk3i6O49,@-pAY,HrVuqPr;QbNrW!/Hs8P1]!%%UD!'L5\
+#0d,I,ldp-oD\e:rVusr-2mlE^\Ig15QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:N
+hh(m#rrN0#9D=_PjkB_9?iWI@rrL=irVusFbl7VBZ2FY&L&M#O-2mlEL&1fPg"HE*
+L&M&P4T59[^]"35A*s9uPQ1\0li-rprVupEqYpPjrVupqrr2t?rVusFbl.PBUF#m>
+"""!I^]"35-3!oEFSl+>-0G4,!'L5\!2J$C".oPnhq%f/!!%NGrr=AE!!'e2rsFu:
+!!$O/s#^8]-2@K?bl%MC,uMGPrr>pq!!(7@rrXPI!/:=M!6kEB!'L2Z!'L2[!@<Hc
+rrY@`!%%@=!6kEB!+Ys,$=a&9-0G7-49,@-rVlj[rW!/Hs8OAF!'KlQ!2KAj!)`Lj
+!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N!8iD.TDnrm!)*'P!9Mr7!al!neGfQn
+-2dfD^\n*3A,QB-Z2Xb'A,ZH/4MUjp#/<8#!5JPfrVup\rVllArVup\m/I-@4L+5P
+!%%UE!/:7K#UKHN-0G7-jsC!,"=7Q3@jV$Q"$HV`L&M&P4T>?\bkqG@4T59[A,ZH.
+A(1G[T)\lKf)GdO!.XnG!)`^q!@>M[rrKl3r;[$as8P1]!%%F?"m.*2!%$=qrrq)0
+Z2aiXrVuq?r;QjF!!#.YrrC:B!!#.Zrr?R.!!%-;rrJmKo)AeS!!">=rrqO2!!">:
+rr3,F,ldokrr3'_!!">Drr>1\!!gaJs#^8]-0G+)!R0^'rr>1Y!!'e.rrPFc-MWl,
+jjO/2hZ*YkK)aL'!WW4mW;csL!!(o.s.B;m!!#[dQ2p%5rrDf_rrQR.5h5l8fd6Rs
+!2KDj!'L5\"XVCms5kX+!!=N04=0q+!i,dLrVup\r;QjF!!"=prrA;_!!">?rr?R.
+!!&8_rrAhe!!#mqrr>pq!!#mprr=AD!!&8^rrAhn!!"=orr\kn!8m&@!;Gs^!WW4M
+qu6]M-2dfF4?Oqe!!]4us#^8]-27E>;>pP(4JV'=s1`%D!%$e-g&:sT-,9K[k&gS&
+!@?n+rrC:B!!#.ZrrBh4!"!/Zs8Uc:49,@koD\nT!!"><rr>pq!!GF!bbHK`!!%`P
+rrY@`!%%UD!'L5\"3gfFL&M&Q4L+nc"GJ-%-0G.*!2KGl!)`Ii!^H`4pm(pAir9#Q
+o)AgL!!'dtrrqQ/UP4EGmJd:N;*<(Mrs7ces3/63KqllarrRm:FP6Zq!!&Xirr[`N
+!8iD.TDnrm!)*'P!9NSI!a(NXo)Ac!!'o*7!)`[p!2KAi!5JI4!'L8\!M^t8!!>@`
+s-3K_!/:@N"!mpI-.Mqp;>pOqL%tZJ^]"354T59[U\Ffi-'\B.!'L5\!/:CO!+Z!.
+!@?n,rrM7.rVurOeGfWC!!(p@rrVpSYOVVo!!%NFrrAhf!!+CNrr3'_!!">>rrBh3
+!<+;C!!">Err>1[!<+;B!!%`NrrC:B!!#.Yrr>po!!+Alqu?_=oD\nT!!"><rrBh.
+!!#.[rrY@`!%%UD!'L5\!6kHB!%%RDr[%LC!6k??!)`[p!2K8f!^H`4pm(pAir9(P
+@,LVV"5a(Y^Zkb!jsBp*![V@JnG`TE!!#.[rrTrh^Y/VeL&NCq!!4HDZ2O\(UP7k0
+rrXPI!6j0s!WW4mW;csL!!(o0rrQ%DKqSGI!!#[dQ2p%5rreqo(m"F`rrQR.5h5l7
+4T5<\U\FcgU](5n-2miEfhqSG!@;jerrC:B!!%`NrrY@`!%$.p"0j-P4SJdWF8u<*
+r;Qi5;'l2A![T.Hqu6Y+rVur5rVll4rVuqPqu6XYrVurBeGfWC!!(p?rrZX/0X(*J
+!WW4Mq>UJj-2ITC-"HQFrrY@`!%%@=!M^t9!!+C@rr3#C-2%<=-2dcCbl.SB;>U:m
+;>1%j4S&LS@fQKTo`"oFq#CFAbl.PD49,@-rVljprVurBrr3#C-27H?4So'XFT)7?
+4SA^U5QE/+Q2p%+rri'%!+=^Xrr_-Y!5Idu!0m9Z!@>t[rr[rT!'L8\!87>O!5I7f
+!'KoS#*f/fPQ1\0rr3'H!!(6srrN0#T;_blIfKK+e,KJH-"HWJ!i%&=`W$$^!!">$
+rrTrhZ24J%fnH^,rrTH&FPQlt!!#[dQ2p%5rs%ot!!!jsp\+Ug?iWIBrr^J--&)$l
+"-b)XFSl(Bfp%1Q;2)d^rrQ[V;>^@qYpC]ke,KI2bk1o9UVHX)!9X:)!9X+W"6NH,
+L&:lOZ"'$prr^Ik!)_5F".oPnhrt(?\,H@.0X(0L!WW4Mq#:BWA,R\T4ET`_rrZ*u
+!'KrS!p3u=qu?dEA(ge[!SL?J!!O[&@fQKkr;QcMrVuqnq>UMk4=0q+![Tsnnc&^E
+,pd[)rrJl@qu?apg&1jPF8u;NrVlu7,lg(*rrV=[-2[`D4JV`P!%%UE!2K5e!^H`4
+pm(pAiVrm[rVut,ht[3RhZ*Ykl2LsA!!"<-4=0t,!@?n!rr[rT!'L8\!2KMn!0l4;
+!'L5\q^)4A"/GnrA,ZH4g&M'u!!(6srrN0#T;_blIfKK+eGfN5rVurBp\tBY,ldq!
+a8Z;),ldoko`"u7-):)3!Tmnj,m+,I-0G.*"MZ5_!2KGk"PG($!-I&s!WW3npQbg@
+li-rer;Zm9O8&GL!al!n`;]l#k(<X+rrCa#rr\kn!8lu>!#YY7!AL_OrrN0#J*Ht8
+k$qoSo)Aj:^P/H,p\tBLP_Fh+rr3&)L$&:4!jPUepAY<Yb`mh*k1fn9U],rIg%kXK
+bfoq`!872J"m2&';2*]urrAhn!!#.RrrPFc-MWl,jl-4>\,64,@,Lh\"5a(Y^Zkb#
+K`D*8rr2tPrVuq.o)AfG!!#.[rrQ%D4PB`;49,A'k5>5\fp&92rr^q:-"HrS"!mpI
+bhE'u!!&Xirr[`N!8l<+!/:CP!6k3;!0mH_!0kP(!/:CP!/:+G"JYqs-0Fn#!JMiq
+!!&8]rr>pq!!#.Yrr?R.!!">$rrN0#9D=_Pjm2pHYPS;$(m"FfrrQR.5_B#jrr\kn
+!8lu>!-%f8!AL_QrrN0#ItI^Frr>1\!!&8UrrPFc-MWl,jl$.=&GlG.@,Ln^"5a(Y
+^Zkb#K`D*8rVlta!!">9rr[rT!'J^0"$?P`L$nsC,ldqhgA_3S!2$4i"+L:NhphZ+
+L&M&PbkM,;4T5<\bfB_c,ldokp&>':-2mlE^\7[-A+os'L&M#PjsC!,!@?n+rr=AD
+!!'djrrN0#9D=_Pjm2pHfD,CJ(m"FhrrQR.5_B#jrr\kn!8lu>!13K]!AL_SrrN0#
+ItI^GrrBh5!!">:rrPFc-MWl,jl$.=3;EOT@,Lt`"5a(Y^Zkb#F8u;'rVluD!!">9
+rr[rT!'KlQ!SP]VrrY@`!/9k@"!mpIbhE'u!!&Xirr[`N!8l<+!/:CP!6k3;!'L5\
+!6iOa!5JL5!+Y^%!'L2[!/:1I!+Ys-"!p&l-2mlEL&M#OU\k)l^]"05jsBs+!/9;0
+!WW3npQbg@li-tZpAb73O8&YR!al!nK)^T*".oPnhrk">\+]k'0X(HT!WW4MK)a-r
+!+Z!.!+YX#!^H`4pm(pAi;WdZpAbD*huDR6!5Idu"$?P`FT)4AUAt9?rVm)a@lu&"
+A+T[!",-^T4T>?_fd.r>r;Qu+49,@-4JVoU!`:8=qYpUo-&)$l#Wr(eL&_1sbi\d%
+"/@.gg&D!R,ldqhr;QeO4T6W-;5<:R!WW4mW;csL!!(p+rr@cP!!(7;rraVJ!%$dK
+rr>pq!!(^Grr@0=!!#.Vrr@cO!!GF;s8Tk5!!&8^rr@0=!!%`OrrAhl!!#mQrrN0#
+'DEgR3U/j0"SMg"(m"Fk?iWHDs+^OUT)\jNk<K#(o`,1MYQ+V&!.TV#cMmkjrVurO
+oD\kW!"/KJ!'/t&!$(Y3"CT+I!5Idu"$?P`L&V)TbU!5hA,cK/KdHWs!@?Furr[rT
+!'L8\",-^T4T59[U\Xrp4TCWG!%$=rrr\Jc!%%=<!^$G_rZqRF!<+8EFT)4A49,A8
+rr3'H!!(7BrrLe8q>^M*kPkS`!2$4i"+L:NhphZ+L&M&PbkM,>,ldokmJd3OL#2h4
+js:!-4SJdT^\\!2-2IQ@^\n-44T,3\F<sf^rr>1Z!!#.[rr?R,!!#.<s3:TI(lqr&
+5_B#jrrA\A!!G!Z!!%M#s3L]F^]"354S&LP5f3R%^Zkb.49,A'beIX6!!"=us8S>Z
+!!#.\rr[rT!'L8\",-^T4T>?bfd-Uu,s3LQ!!1<srVup\r;QjF!!#.Srr>1T!!(^O
+rrY@`!/:FP"!mpIbl7VB4T5?[-2mlE^Zb\!!!&Xirr[`N!8lc8!p4Ser$;A+g&D!O
+L&M&PbkM,C,ldoks8UbLA,-'6Kfk(hs'l$/;?+Cb4Cb/]rrM8Hr]C6ZPih]>!+Z!.
+!2K8f!'L,Y!@?n)rr>1\!!#.Qrr=AC!!">Drr=AC!!">%s3(HE#lm5Bs+^ORT@!W=
+ItI^HrrAhn!!&8Srr>=%!!'durr>1V!",M$s5kU-!%!?CA,ZH4U]:@J!!#.\rrZa2
+!'L8\$p4Li--ZDhPU03,s'u$.!2KPn!/:CP!2K5e!'KuU!%%UD"!mpIL&V)V,ldqh
+s8RfP!!ebgs03jM!/9Y:!WW4mW;csL!!(p9rrJl@q#CClrr2t?rVurBp\tOG!!">F
+s!7XFA,?3*Z2O_)U]2Y>!!">C!!+Ciqu6\N-2RZC-$8q^"Qh!1!'KuT!-J2?!B`LD
+!!'e2rr@cP!!+D!o`"pEqZ$UBrr2uOqZ$UBhZ(h#"(5(.5_B#jrrA\A!!Ej_!!%M#
+s3CWGF<sfSrr>=%!!'durr=AA!!+CNrr2t?rVur5rr39e!!$O/s+LFQ4T>?b49,@D
+s8Skn!!'e0rrhp>!!">ErrXPI!'KoR"?ZYa-&)6?r;QjF!!%`Prs^7S!6kKC,ldq!
+s5mf;rVurOkl1\a!2$4i"+L:NhrF_:^\7^.4T>?`49,@-k55/cbeJjc,ldoks5kX,
+!!';$rr>1\!!8Db-2.B?-0G1+!+Ya'!/:7K!+Z!.!2K;g!SJdu!!0igrVuq?qu6XB
+rVuq_oD\fcq>^W4s8R3;!!(7#rrN0#'DEgR3U/j0#5%s"@,Lul!'l/9LAq@J!!#"A
+5QE_8!!X!an,E@fItI^4rrPFc$MYqJ3T*.&*q]L95c4S^^Zkb",ldrE,lpl<r;Qj]
+!!#mprs=AZ!'L;]K`D*8rr39e!!%-@s%rar;>:(jL&M&RL&[D:!!&edrrY@`!/:+G
+"!mpI^]+6@,ldqhs3(HC-*^;nrVusFUZ_XY!!&Xirr[`N!8li:!/:CP#<[^)b]Egb
+A,cK849,@-s4O0$4=)<M!!=PIs&&aq!%%RC!2KMn"""!I-2%<=A,cK.Z2FY),s4:9
+rVupEqYpQ1rVup\pAY+TrW!"0s1eO5!'L2Z!0mH_!'KiP!+Yj*",6dT-2mlE4T5<\
+Pi)KB!!#[dQ2p%3s7QEn@,Lt`!al!nK)^T*".oPnhrk">^\7^0&:a0JrrN0#ItI^4
+rrPFc-MWl,jl$.=@.sX*5em?V!!'durrXPI!6k6<"!mpIL&M#XK`D*8s8RcQ!'L8\
+#s81fL&_0!!!'e-rs1^e!%%5!!!#.QrrY@`!/:+G"!mpIbl7VG,ldqhs.fDj![V@=
+k5PJ_!2$4i"+L:NhrF_:;>pOqZ2O\(P[ikTrr>1\!!">;!!FVJs5kX,!!%->rr>1\
+!!@?Cs!@UD#>r7[YpBAM-3!oE4T5<\PlC[_Pl:X_-2RWA;>pOqU\FcgPl:Xf-1h0!
+,ldokr;QaZrVuqno)A\9rVuq.rW!!^s4RAO!@>#M!!$NdrrN0#9D=_Pjm2pHhtR0P
+@,Ln^!al!nK)^T*".oPnhrk">TD8Hg&:a0HrrN0#ItI^4rrPFc-MWl,jl$.=5ktB\
+5em<u"5a(Y^Zkb#,ldqhq#:FB!!%`Ors=AZ!'L;]K`D*8rr39e!!%`Qs!7Xkk4\fT
+U](5n4T5<\U\"Kf49,A8p&>+?!!(7Brrj\K!6kIsqu?dEFQVZa!WW4mW;csL!!(p:
+rrA;_!!4Hgk5##W4R`=N4T>?\L&M&T-0G7-U](5r-0G7--2mlEPl:U^A,ZH0^]2(J
+!!Hg3s._^T!!$O+rrBh5!!#mjrrM^;rW!(Cs3/\5rVurBrVlsG!!">9rrCaO!!ah'
+,ldoks)e5?!Fsg^!!#.=rrN0#9D=_Pjm2pH\,$(*@,Lh\!al!nK)bWG!i%l3r;Qhn
+4GDbo!L/;Nrr\kn!8lu>!-nA@!YBkMqYpTs!.TV#]Dhpt!%.K,!9N/=!#YS5!AM:d
+rr_-Y!5Idu"!mpIbkV2?,ldperVm1$!!$O/s+LFQ4T>?e49,A8s8OAF!6k-9!'L/Z
+!%%49"$?P`L%YHJ,ldqhrr3-J!!(7CU](5o4I"h)!WW4mW;csL!!(p9rr>1[!!4HV
+k55/Y4Sf$b,pcEBUWgq.!!#.[rr=AE!!?a2s#g8\!+Z$."$?P`-2dcCPl:XaL&Z8o
+!!9EZ-2[`C4So'X4T5<\^\@a.A,QB.,piEg!0mK_!6kEB!'KiP!0mH_!^-K/rVuuC
+-2mlJ^],S[!%$P&!WW3npQbg@li-ruqu?b*ht[3Q?iWI(rrC9ZrrCaO!!&8_rrCaO
+!!&8DrrZa2!)^H0".oPnhrk">./a,I&:a0DrrN0#ItI^4rrPFc-MWl,jl-4>a8>o<
+0X(?Q"5a(Y^Zkb#,ldqhq#:S/!!"=hs8Skn!!^4<s+LFQ4T>?f49,A's8P1]!'KlP
+rrTr4A,Q?,^\e'3L%>6G49,A8p&>+?!!'e5rs9tO!6kK*,ldper;QhP,uNn+!WW4m
+W;csL!!(p8rr>1Z!!+C"r;QaZrW!$_FHk#GrrXPI!'L5[!2KJm!PcDK!!+D.rr2s\
+rVurOrVllArW!"Rs#g8\!%%OC!Bd.RrrAhn!!#mjrr=A;!!#mqrrC:B!!#.Prr>1\
+!!7lSA,ZH.;>pOt-3+!-rVur5i;WiY!)*'P!9NSI!V[0)!!-KbpAY2%!'n6t"S4_U
+-)8BX!6kEB!/:FP!6kEB!/9J5"$?P`-,'<\T)\lKkl1Y'rW!!2J+*+2!WW4MK)`I_
+!^H`4pm(pAiVrmkrVusQYPA,"hZ*Ykl2Li3!!(7<rrBh5!!4H/4T5<\4T>?_K`D*8
+rr30b!!#.]s.fPn"!qH24T5<\Pl1O];>pOq-1V!;49,A8p&>+?!!%`PrrsbL!6kKC
+A,ZH.-2p"/,ldokkl1\a!2$4i"+L:Nhr+M8UHJGS!'L5["$?P`-2.?@,ldp-r;QaZ
+rVusr;>pOqA,ZE-4T5<\bl.PAbl.SDL&X:3!!,3Wq#:IZ!!">-p\t4>q#CFA-2mlE
+-3!oEbl.SB4S\pWbh;sp!%%UE!mL\>q>^V-s8R3?!!%-!rrN0#9D=_Pjm<!MY5eQ1
+ht6pM?iWI*rr@cP!!">$rrQ[mZ0M>hbl.SBL&V)Pbl.SBL#`18,ldok^&J2,!!(p?
+rrd9@&:a0@rrN0#ItI^4rrPFc-MWl,jl6:CpD<laYP.tuhZ*Ykl2Li3!!(7;rr@cL
+!!+D!rr3(S!!#.\rrY@`!)`aq!+Yg)!@?FsrrAhn!!%`CrrY@`!/:+G"!mpIPlC[b
+,ldqhrr2s\p](;9kl1\a!2$4i"+L:NhqnA6^JXq0!+Z$."!mpI-2.?@,ldp-r;Qc3
+q>^OBk5G;[4T5<\bl.PAU](5pL&X:6!!4HD^\@a.L&M&PA,$!'U](5p-&%'PbQ@hE
+-2mlMg&M*7,ldokk55/`ffT67L&_1frW!'Is8V4-qZ$`Os8Tk5!!#.>rrN0#9D=_P
+jm<!K:gi2OrrQR.5e[0tPl:X_4Pp)?@fQKTlMgk.rVuqPrr2uBrVuqPj8T3-!!"=Y
+rr\kn!8m&@"8=3nn+-J[!!%M#s1A:45QE/+Q2p%+rrTAXYOqhshZ*Ykl2Lfp,uO@8
+!L+o/!!,48rVlu)!!&8_rr]MP-*dFK!JMiu!!4HVk55/\;#gSBnG`SQ!!%`Grr[?h
+-0G4,!^$H/r;QhP,piNj![Tt(kPkS`!2$4i"+L:Nhq\53U](5n-3!oH,ldp-pAY4@
+!!">Brr>pn!!$O,rr>1\!!(7Arr>pq!!8qq;>pOr;<IcU!TqW)rraVJ!%$e%rr>1\
+!!$O*rr?R.!!&8_rr>1\!!,4RrVlnP-2mlH4TGG'rVup\rr2s\qu?^CrVm!H!!">-
+iVrrZ!)*'P!9NSI!9`kO!al!n]`/(D,s9E.rr>1\!!(7/rrC:B!!%`PrrC:B!!%`5
+rrXPI!'Isp".oPnhs(.Ap[@VO!WW4MK)`I_!^H`4pm(pAir9#Ao)AgL!!'ddrr^#i
+L"Z>&!SQ/trr^#iKqnJD"Qh!1!/9qB",/$`k3`0Kbk_8=k5NTcrrN0#T;_blIfKK+
+j8T1cKtmTd"S3o>!%%XE"!mpI4SJdW,ldokqu6Z2qu?aDk5>5Z4T5<\U]18nL&M&S
+-0G6&rVusFU](2tfjc<.L&_1;rVuq.p\t6.r;Zi4qYpQ1rVup\rr2u'r;ZsHFG3R<
+qu?h@s8P4\!!%-?rr@cN!!%->rr=AE!!&eQrrN0#9D=_PjkB_9?iWHWrr>pq!!&8L
+rrC:B!!%`PrrC:B!!%`5rrXPI!'Isp".oPnhq%f/!!%M#s1A:45QE/+Q2p$prr_-Y
+!5Gf="ChE3-0DB1!WW4mW;csL!!(p;rrCaO!!">E49-],!!#.\rrXPI!'KuT"!mpI
+-2RWAA,QB-;>^@n4T,9Z-2dfDA,cK.4T,6^,s4:9r;[(4s8P1]!%$e%rr>pq!!#mk
+rr=AE!!(^Orr?R%!!%-?rr=AE!!&8_rrCaM!!(^Nrr?R.!!#mTrrN0#9D=_PjkB_9
+?iWI"rrTrh^]"05g#h]%"6Ri-L&M&SUWgsEmf*:2rVuqPrr2uBrVuqPkPkY.s8UdO
+!!#-prr\kn!8lB-!WW4MhZ!bS@lukNPi2QBP_Iom!JU.Arr\L>Ktm9[!5JMe!87&F
+!87@*!5I@i!^H`4pm(pAdf0F,!!'d=rrXPI!+W/2!WW4mW;csL!!(p;rrCaG!!BM+
+s31HB!'KuT"!mpI-2RWAbl%MA^\e$24SJgU4T59\bU)u`"!uY#U](5nA+op&-2mlE
+^\Ig/L&M&PL&M#OA,$$)4MUjp!%%UE!6kEA!%%UE!'L2Z!2KMn!%$V(!WW3npQbg@
+gA_4^!'n6t"6NHCU]19$^An6[k5Sp;!$sb4qu6\l;>VXEFT;Ap,lf5;rW!'I!!"<B
+qu6]ZPl<cGFP6Tl!6kEB!/:FP!6kEB!/::L!M`Nk49:/hq>U]^@jNE$,pd[4!!$NB
+rr\kn!8lB-!WW4Mhu<^>!<"2F!%#DCrrI4qrr3!]-/JS&@fXaNrs$[n!$rokA,$!)
+ffT96,ln!Up\t7k!<+8F!'K-<!^H`4pm(pAdf0F,!!'d>rrAhn!!'d9rrN0#T;_bl
+IfKK+j8T.6-2ITB-):G="!mpIL%bNK;#gSBqYpP*rVupqqYpOXp](:Vqu6`h@jV!P
+"XR%.s8RfP!!'e-rr[?C!+Ya&"$?Q0g&1jNUHJJT![Tt(qu6a\!!">Crr@cP!!'e3
+rrhI1!!">(rrN0#9D=_PjkB_9?iWI*rrZ*u!%%XE!/:CP!Fn7h!!'e4rr>1V!!:jR
+-2%<>-0G1+!FmGQ!!,sMrr2uBrVuqPrr2uBrVuqPr;Qf&-2ITA;>^@oUF#X7!/8,d
+".oPnhq%f/!!%N,rsDU'A*3gkk(Nd]k3;mIbQ*@rrrJ@<hZ![f!!(7@rs'hr^]4=D
+!/:4J#Wr*@s8V4D!/:7K#]p&Vk5YHk!)_YR!^H`4pm(pAdf0F,!!'d>rrZ*u!%"`H
+!WW4mW;csL!!(p9rrM8HrB(*jU\k&mfnG[_rrRn.g%t^K-2mlE^\[s14T5<\;>rZY
+A&%g=#Nhe8;*9Q-k5G;^YpBBIo`"sFbk1o9PihfA!87@qq#:H24?TnGrrSEpZ24J&
+UEq4.iVrrZ!)*'P!9Mr7!al!n^&J'prW!&Es8RfH!!#mqrr>pj!!:CE;>'ti-3!oF
+bWPY#!%%XE!6kEB!/:FP!6kEB!/:CO!2K8g!)`^p!2K2e!/8,d".oPnhq%f/!!%N-
+rrV=/-2[]D@fV5IrrUCEL"lV2ffT6\!6kEA!gE\=rVlmE-2IQB^AqdBrrVd<-2IQA
+,piKh!^$J9i;WjD!%.K,!9MZ/"5a(Y^U!kA49,A'XT&>%!2$4i"+L:Nhn/mgL&M&P
+4Sf!W4T5<\bi\p+k01@8!TrP&rrN0#9D=_PjkB_9?iWI*rrY@`!%%XE!/::M"XRY)
+!!">Err=AE!"EFl^S<mk-0G7-P]T#6rVup\re1@*rr2s\r;ZmF@o<4*!%%XE!6kEB
+!/:FP!6kEB!/:FP!Tk^-!!">E4T5<a-0G7-jsC!,"?_BlF=$kc!/8,d".oPnhq%f/
+!!%N-rrUCE4T#-[ffWdCrrhJ<@s"LBrsuku;2)dbs-.U*;2)dbP_K&8"J^'9L"ZG)
+#JYumk(QZdg%YLNfd.quK`K?qrrP;/k5G;]F9')PrrSEIL&CrO4=0k(!nf\5r;Qh?
+!6jC$!^H`4pm(pAdf0F,!!'d>rrUD,;60]u!!&Xirr[`N!8kEg!%%UE!2KAi!'L5\
+!6g&pp\t9p!)*'P!9Mr7!al!n^&J0s!!">Err@cN!!ssqs+LFQ-0G6\rVup\rVlrP
+A!Hlj!/:CP!/:=M!+Ys-"-iicbl.SB;?$Rqbl.SBL&V)Pbl.SBL&V)PA,ZH.A,cK/
+^ErjZ"53_SA,ZH.A,ZE.o0!!P!2I7-".oPnhq%f/!!%N,rrOJm^\7[-U\uJ?!'JL(
+rrHU0rZqpPA,fCP!$rqFs#_V,rrUD,!<+8F!-J5?!ehqbrZqUG!2K>h#0^T>s+LHs
+rVlmE-2dcEUB$#=rrFDlo)AbR!86<1!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N
+!8kHh!5JL5!%%F?!'L5\!6g&pp\t9p!)*'P!9Mr7!al!n^&J0\!!">Err@cN!!C"9
+s+UFP"3gfF-2mlF4L+V[!0mH_!/:@N!Tk^-!!&enrrC:B!!%`PrrC:B!!%`PrrC:B
+!!%`Prs'hM!'L;]^JXq0!'L8\"!mpI4T#-YL&M&Pbe=#YT)\lKf)GdO!.Wr,"bcpV
+-$6ours5k04PBc7PQ3iFrsWuLA+T`l;#lj\bQ*@rrrG5.rr3Wo!/:IQju`Wts8RcQ
+!0mN`PQ3$%rrRlSbl.PB,s;,*!mCXSoD\lG!+YX#!l"^thu<aC!%.K,!9MZ/"5a(Y
+^OlL<rrN0#T;_blIfKK+]`.t/rVuq?q#:=VrVurBK)bTF!WW3npQbg@gA_4^!'n6t
+"!mpI-3!oEL&CuOA,cK.FT)7Bbl@^<qu?a[U\Oihbl.SBL&CrNPl:X_A,ZE-bl.SB
+L&V)Pbl.SBL&V)Pbl.SEL&_1frW!"RUHJGS"=;:ls4RAO!/:=M!/:CP!6i.V".oPn
+hq%f/!!%N+rrJlWrW!!G4I#gE!^%d^rVm(U!2KSo,piNi#3I4/s3(Isrr30b-3+"?
+!+Z!-#P05fs8RcQFT)4@xxxxxxxxxxxxxxx,s;,*!mCX,o`##g!%%7/rr^Ik!5IFk
+!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N!8kHh!%%UE!87/I!'L5\!6g&pp\t9p
+!)*'P!9Mr7!al!n^&J0\!!">Err@cO!!(^Orr>1\!!(7BrrJl@qu?a[g%t^Kbl.SB
+L&CrN;>pOq^]"04bl.SBL&V)Pbl.SBL&V)Pbl.SEL&_1,rVupEqu?aDL&M#Obl.SB
+^\e$2L&M&Pbe=#YT)\lKf)GdO!.Wi)$e^4r,ldp-k5YH-4T,3`bQ(N?bQ)/KrrUCE
+L&V)V4=1%-;#ni<rru=#bl<@sbl.PCF9'PXrrRlSbl.PB,s;,*!mCX,p&>,h!%#k]
+rr^Ik!2JEN!^H`4pm(pAdf0F,!!'dns8L5os8)`s!!&Xirr[`N!8kKi!87>O!'L#U
+!'L5\!82u(p\t9p!)*'P!9Mr7!al!n^&J0\!!">Err>pq!!">Drr>1\!!(7ArrV=m
+-2dfE-):A;!6kEB!'L2Z!'L5\!6kEA!6kEB!/:FP!6kEB!/:FP!6kEB",6dTL&(cM
+-&)6r!6kEB!6k??!/:CP!6i.V".oPnhq%f/!!%N%rs-;$!)`d?!!)mB"TU[bK`Hi&
+rrUCEL&V)U4=1%-4=0n)#)*&As+LHsrVlqQ!6k-9!egWurVlmE4T,3\bQ)/Hrr[rT
+--Z#]"0j-PUYYqO5QE/+Q2p$prr_-Y!5IUp!FmGT!!4HDg#i;7U](2n,uNLu!Du_k
+rrLeMrZqPup&>#%rZqSBg#W/7!!&Xirr[`N!8kHh"(M<WZ1n8#YpBBIK)bQE!WW3n
+pQbg@gA_4^!'n6t"!mpI-3!oE4T5<\;>pLp4T5<\bkqDAk(P,\!!+D.r;Qc@rVup\
+r;QaZrVurBrVm#_,ldq!rr2uBrVuqPrr2uBrW!%Ss8RfN!!,3Wq>UH=rVuq?qu6YM
+rVurB^&J2,!!(p-rrN0#J)UD.^P2Oa#4j,es3(HhqLo':s+LH,q>UN?!/:FP"["+2
+s#_V)rs"/WPlHF;bl.PCK`K?irrRlSbl.PB,piKh!l"_hp\t>*!'Js,rr]"r-*c8*
+!^H`4pm(pAdf0F,!!'dqrrP:_4T:$:49-\Okl1Zn-2miE,uNP!!b23mr;R#T,pdYe
+;#k,#rs(Xd@tf"N-/%D[!WW4mW;csL!!(ogrrLg8p&>'Tb_#lfrrN0#9D=_PjkB_9
+?iWI*rrXPI!%%XE!'L5\!/:CO!-J2?!2KAi!V8GQ!!%`NrrC:B!!#.Zrr@cP!!&8]
+rrXPI!)`aq!6kEB!/:FP!6kEB",6dTPl:X`4MUam!6kHB"=4$J--Z;e!+Z!.!2I7-
+".oPnhq%f/!!%N-rrP:_^\[s6494's,s:u&!mCXdr;Qqqbl>leL&V)V4=1%-;#ni<
+rrus5bl<@sbl.PCK`K?irrRlSbl.PB4=0q*!egWLq#:CX!'KlQ"*=MhbhN.!5QE/+
+Q2p$prr_-Y!5I[r!gE[pr;Qh_!'KKF!B_[^rrhq'!!#.ZrrQ$t^]+67@fX:>rrRlS
+L&V)R^Aq-mrrN0#T;_blIfKK+K)_JC!WW3npQbg@gA_4^!'n6t"!mpI-3!oE4T5<\
+L&M#OL&M&UL&_1,PhH$8!-J2?!/:@N!6kEB!'L2Z!5JL5!BfuQrrfSQ!!">ErrC:B
+!!%`PrrC:B!!n;Ys5kU-!%!?trs.\?,lggBs'u$."XTrDs5m2W!!%_drr\kn!8lB-
+!WW4MiVrtD!'L/Y#Nd<Ys8OAkk5G;aUEt$^js;>Orrj\ps3(Isrr30b-3+"0!-J/=
+"skSqs+LHsrVlqQ!6k-9!egWurVlq@!2KMm!^%dkq>UM+!+YX#"/>iYo@j3G5QE/+
+Q2p$prr_-Y!5I[r!^$J,qu6^D-0G+)!87,H!TrPBrrG5.p&>$Fp&>$Fp&>3#,lhF$
+4T59]js<.grrUjR;>L4m;'l/?!@9&RrrN0#T;_blIfKK+K)_JC!WW3npQbg@gA_4^
+!'n6t"!mpI-3!oE4T5<\L&M#O^]"374TA:X!!">E4T,6[U\t,lbl.SB4T#-Y-2mlH
+-"CF2qu?hos8U=B!!%`PrrC:B!!%`Prr?R-!!FT14=)<Q!!FVJs5kX+!<+;B!!%_d
+rr\kn!8lB-!WW4Mi;X`Y!'I%=s8SiV!/:IQPQ3i.s8U:h!5JR6@fU$<rsN<:L&]?s
+;?-7f4=1",![RiArr345!-J8@K`K?qrrRlSbk:u;K`K?qrs7a5--ZDh@fU$<rs/.L
+PlLcg!%%Kcrr34WL&_28,pfhnbhrF%5QE/+Q2p$prr_-Y!5I[r!`8rmqu6]Mbl.PG
+Yrj<4,uNh&rr@cO,n#G,bU!5h,piTk,uO[A#3KDA!$rqUrVm+";;"em!$ua]rrkMI
+Z2Z+4rVlqo!/:@N!@9&_rrFDljo5A^!2$4i"+L:Nhh(m#rrN0#9D=_PjkB_9?iWI*
+rrXPI!%%XE!)`^q!6kEA!6kEB!^-K[pAb1Uqu6Z?rVup\qu6Yko`,(Vs8U=B!!%`P
+rrC:B!!%`Orr>1T!!&enrrJl@p&G(i^&J2,!!(p-rrN0#J)C8-49,B\,m"&mFT)4E
+@fRf;4=(!&rVm'a!$s`R!+Z$."sj6qL&X7]rr35I,lf5R,lhHSrrRlSbl.PCK`K?i
+rrRlSbl%JFUEq3K,lg(+rrpUH4TGFYq#CC@rr3*I-3+"0p](<<i;WjD!%.K,!9MZ/
+"5a(Y^ZPP!YlH(lg%bRQUAuToKjt*/k5PB#;#i_4Kff?Fo7\J:Kn]R,,s;5-js:";
+KnVVhA,cK64=):NKleU@L%tZJ^]+66,s;/+!egWhr;Qd[-1h-<@fV5ErrN0#T;_bl
+IfKK+dJj70L&O18FMHc6!JQcorrKBhqYpQXre1@7p&>0WP_Fgdnc&WDo?[F<!!#[d
+Q2p%#rrQR.5e[1"@fQL+rr2tPrVurBr;QsI!!#.]juiG>!)`Um!6kEB!0m?[!M^t<
+!!c@`!!">Fs4RAO!5JO5!87>O!5JI3!JMir!!,3sr;QfA4So*],p`NkKt[KgT)\lK
+f)GdO!.Wl*!P`aU49:/uqu6i7F?D[-g&(dPUJX-NU](2sflU)ds-/68rreQK4Cc/)
+rrTrhoDS[j^P2:PrrTrhoDAOjfjd-,Pl1Obo7`G/s-3;4rr3+TL&_1fpk8_>i;WjD
+!%.K,!9MZ/"5a(Y^ZGJ#F<pne,uKohrVlu^,pi0^rs,;!;?-Zk!)`^p"["*ns#_V+
+rrsc3s8PprPl:Ue493.rs#^9krr3&D,pi3`!@9l,rrRlSbl%JB493V"rrh";,li&J
+rrN0#T;_blIfKK+df0BD,lmoj!WW41kPkVG;9]%>!@9kbrrUCj4T#-YU\lD<L%kTP
+F<po5,lf78o`"u&!6idh!WW3npQbg@gA_4^!'n3s!McFgrr_CG-$9%a"*>hObl7VC
+^LR4)!JT5%rrR9g;>:(tPYjP*FP6]oF?Hi-rrTHZU\t,nZ%\tKrs$5l@m"jtg%bRR
+fnE9cKp:`Q@thSq".oPnhq%f/!!%M#s1A:45QE/+Q2p$prr_-Y!5IUp%H_aY,ldok
+;=jhfPQ6sGrrtS3s8Pprbl.PF^P2^f4=0t+"XQ;2s!8uhrs-:=;?-YY-0G1+!@9&a
+rrFE.rVlqQ!6kB@!^$J,p\tDl4?Oo9UZMLW!!&Xirr[`N!8l9*"2=g^U]18q^H;L<
+kl1^<!6kHB!JQcqrr^Ik!'L2Z#ep@%k5XR+!5J@0#dF@l^]4=u!%%=<"(M<2bg6:j
+!!#[dQ2p%#rrQR.5_B#jrr\kn!8lB-!WW4MK)`I_!^H`4pm(pAdf0F,!!'dmrsIn`
+@jM+;s8PprFSpgr,ll0h,pi?d!B_\,rrj]2s3(I?qu6gG4TGFD-2dcD4=0Y"!@9l,
+rrRlSbl%JB493Utrr^Ik!5I[r!WW4mW;csL!!(p*rrQ[1U\t,njs;>;rrRlSbhN.#
+KdA#F4T,3\;#nB1rrV=/;>L4n4=0.grrR9BPkb7^ffT6\!6idh!WW3npQbg@gA_4^
+!%<I!LAq@J!!(p-rrN0#ItI^4rrPFc-MWl,jjO/2hZ*YkhZ!fO491WG4951'"3gck
+-2@K@4=0t+"XQ;2bQ*@orrj\ps8P2-r;Qd[-1q3<,s;/+!egWur;Qd[-1_';UB"fd
+rrN0#T;_blIfKK+e,KJ3!6k??!b4@GrVm#8Ki*Q=qYpY^@q1c&rs4<U!-Eqds+Q^8
+rreQrA!H-Srs+dQs1`YQPih`?"]57^bU#CLrrFDlr;Qd[-2IQA;'l/?!mCXuq>UZP
+,pe8!!6idh!WW3npQbg@gA_4n!"ab^LAq=9!!(RL!WW4MK)`I_!^H`4pm(pAdf0F,
+!!'dsrrUk"A,?30^Aq.2493V#rrFDlq#:@W-2miI,s;4O!)`Xn"XQ;2s#_V*rrG5.
+o`"q<4T59]PQ6F8rrFDlq#:?Ir;QiB!'KED!WW4mW;csL!!(p*rrR9BA+fj&@fZKS
+!<?!qrt2L^!$rok--ZB8,lf5;bl8tOrr34u,lf5;!%"E>rs1_L@fRf$!%$=nrrlo-
+s8OB-rVlrC!)`[o!b25SoD\l6!0m<Z#0^T>s+LHsci4%H!)*'P!9Mr7"-3E^pO`F#
+rrREF(tJWf!!%M#s1A:45QE/+Q2p$prr_-Y!5I^s"6LmUoDAOlYlJnGK`IA8rs"_&
+s8P1]g&:pSUEu]84=0t+"XQ;2s!8uhrs$4<;?-YY-2dcD4=0Y"!@9l,rrUjR;>pLr
+js<.crrFDlr;Qhn!+Y0k!WW4mW;csL!!(p*rs&'@!$tL,g%t^cF9#hBs8QR/A,lSk
+,pfhrs03jrs8RcQbl7VZ,s;5-fd.rLs8Th[!5JR649-\Bs8QR/;=skh,s;/+!mCXu
+r;QhP!2K2d"7mfbk4S`UK`K?CrrN0#9D=_PjkB_:VZ6_KK)^W+!al!^ec,[N!.TV#
+]Dhpt!%.K,!9MZ/"5a(Y^ZPOu;#i`@rVm,b493.rf`4/5rs-ao-3+"?!+Z!-"]59Q
+s#_V+rrsc3s8PprU](2s;#mBks#_V*rrG5.o`"q<4T,3\4=/5NrrQ[1U\Xok;#ljZ
+rrP:_^ZPOt!!&Xirr[`N!8l6)!p3u=rW!!GA&&!B!@9&irru=Hk5TN'Pl:Ud@jTh.
+K`K?rrrsc3s8QR/U](2t^Aq.2s#^:drVlmE-1q3<,s;/+!mCXur;QhP!/:(F!^$I:
+o`"uH!6idh!WW3npQbg@gA_8q!!&@;s+gUU(][+WrrN0#ItI^4rrPFc-MWl,jjO/2
+hZ*Ykjo5WL!$sa]Ki',rA,cK6F9"Fub`jCRU]19549/m+^LI7Rs8Ppr;0;j<,s;5-
+fd-W?beI!T;?$Rr4=0q*!B_\#rrFE.r;R#,!%"Da@fSXirs_gObl@^r,liYCUHANd
+jo5A^!2$4i"+L:Nhp;<1ULPSr!!%`Qs1\PUr;QtT!0mLG-0G%'!egWurr3-J4TGF-
+-2[]G,piTk4=0q*!B_\#rrFE.rVlrC!/:@N!egW.p&>(U!+YX#!egWuci4%H!)*'P
+!9Mr7"8<?,5_B#lrr^"9!/K,)!WW4MK)`I_!^H`4pm(pAdf0F,!!'dprrHUUrW!!G
+4JViS!JMj!!!+C@r;Qq1,ldokFT2:Ffd-VEk5Q`)rr32U;'c2B-&)<t!Dt0@rrGtC
+o`"q<;>^@sYpBAM,uOU?!`:8frr32H4='t--&(F[!WW4mW;csL!!(p#rs.\?!!'e6
+K`Lrq"9=/U,pi?d!egWurr3-J4TGF-4T#-^494(74=0q*!B_\#rrFE.rVlrC!/:@N
+!egWLp\t?K49/m^rrRlSbg6:j!!#[dQ2p%"rrZX/!9\t6M>mZk!!(p,rrN0#ItI^4
+rrPFc-MWl,jjO/2hZ*Ykir9,6bfo5ErrUltg%bRJbfoq`!87,H!p7_Ng]%?!bi\Ns
+!p7_Nir9&[!2$4i"+L:Nhp_T+Pe[(p#)*&!s+LGMqLo$ds!8udrrRlSbl7VG,s;5-
+,s;))"Zue<s#_V*rrG5.o`"q<4T59]bQ)/NrrR9BbkV2?bU!7Cnc&ZE!6idh!WW3n
+pQbg@g&D/`!!&(3s,-gYpD<lieGfRM!.TV#]Dhpt!%.K,!9MZ/"5a(Y^OlL<rrN0#
+T;_blIfKK+eGfTo!'L,X#0['Es.]R9q#:@W-2dcIk+hPJK`K?rrrj]2s8OAkqu6gG
+-3+!--2dcD4=0Y"!@9l+rrFE.r;Qg\-0G%'"0j-uU[\9bK`K?CrrN0#9D=_Pjk9Y:
+pFlRapO`F'rr\;^!2n?H!WW4MK)`I_!^H`4pm(pAdf0F,!!'ccs4I>Q!!&Xirr[`N
+!8l9*![RiAqu6kB!0mNG,piKh#%Jsas'l&(rVm(D!2KRJ!6kHB"slD3s%rd$rVm):
+!'L;]4=0q*!B_\#rrFE.r;Qg\-0G4,!qR^#q>UQM,pge(rrRlSbg6:j!!#[dQ2p%!
+rr]G)!0;a3N;j"S(]Z8=rrN0#ItI^4rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL
+!!(p*rsGM$!+X7Qs4Ll^-3!oG@fU$<rt;(,-3+#-,pge8s3)c8s8RcQFT2:P,s;5-
+^AoS(s8V4D!3uS(4=0q*!B_\#rrFE.r;R%t!'KlQo/m#Jrr34fL%G?E490L#bQ[V<
+s7:r/qYpVN!6idh!WW3npQbg@fDbq,!"db6s,I$\BE/%9e,KIL!.TV#]Dhpt!%.K,
+!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+df0WK,ldok,ldp-bl.PH49-Zi,lf78rr3S*
+,pbZ9,pge8s1\O6--ZB84T>?cUEq3K4=);-rr3!]-2dcD4=0Y"!@9l*rrus5,s3IR
+A,ZE1493V*g%YONL&_1s!'L,X!egWuci4%H!)*'P!9Mi4"Le@2+Qn@VO8f<;!!#:4
+rrN0#ItI^4rrPFc-MWl,jjO/2hZ*YkK)aL'!WW4mW;csL!!(p(rs%VM;*6sNU\auo
+ULQDKPihoD"m0nh4ET`ars#`<A&&%tPl:Uck&`^JFQWQ%!L/<9rrJ@<o`"rGPktC_
+Yu*V\U\t,pP_J`/oD""C^]4?*Kp;H6!l'H\ci4%H!)*'P!9Mf3"HNN_3;8%)OoGQf
+!!"/1df0@K!.TV#]Dhpt!%.K,!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+K)_JC!WW3n
+pQbg@ec,bc!!"_1K)_&7"HNN_&D,>0!WW4MK)`I_!^H`4pm(pAdf0F,!!'ccs4I>Q
+!!&Xirr[`N!8iD.TDnrm!)*'P!9Mc2"ntOf!#X%6s-<TeBE/#<\'Y-V!!%M#s1A:4
+5QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:Nhh(m#rrN0#9D=_PjjX50E;fh<@,HS9
+RK!G_+92Bacd2Um!!%M#s1A:45QE/+Q2p$prr_-Y!5F-cf`)!Q!2$4i"+L:Nhh(m#
+rrN0#9D=_PjjO//Qi6sd#\^Dns.95lhiBJj!!,(BcMmqG!$HkY]0HE/!%.K,!9MZ/
+"5a(Y^OlL<rrN0#T;_blIfKK+K)_JC!WW3npQbg@dJj7);#L@q&7C9F^SJUGQ[^^f
+!!*q'bl7YKJcN7[!%.K,!9MZ/"5a(Y^OlL<rrN0#T;_blIfKK+K)_JC!WW3npQbg@
+ci4$l:kA\9!!4!upWNR:QhE[r-Gh)0BD@bmjjO/2hZ*YkK)aL'!WW4mW;csL!!(o.
+s.B;m!!#[dQ2p$krrVAM5_9!/!!4!N^V'SuQFN4\jjO/2hZ*YkK)aL'!WW4mW;csL
+!!(o.s.B;m!!#[dQ2p$frrCZ&^SS[FpUL6TQFN4\jjO/2k5YLSK)aO("5a(YT;_bl
+IfKK+K)_JC!WW3npQbg@K)^H&T`9V0\<[-VdJj7J!.TV#g&D0+!!'L,rr[`N!8iD.
+TDnrm!)*'P!9Jh4K)_MDJsNp4!9MW.![%IkK)aO("+L:Nc`$jGIfKK+K)_JC!WW3n
+pQbg@K)^H&T`9V0\<[-VdJj;n!!'ccs4dPUpD<lQVuHjK!!(o.s.B;m!!#[dQ2p#u
+s+:9Ds+6QHQ2p$orrgpZ!$L`^s4mVVBE/%)VuHjK!!(o.s.B;m!!#[dQ2p#us+:9D
+s+6QHQ2p$nrr\Sf!*FjQh>[Sd!!#Qerr[`N!2kF`T>(F-!)*'P!9Jh4K)_MDJsNp4
+!9MQ,"@)qe37ic^iVs)UGQ7^TkGJ7ZIt@Zh!!#[dQ2p#us+:9Ds+6QHQ2p$mrs%@/
+!!!:<f7O%ars%YI+92BQ\#'*)^OcHS!!$L&Q2p#us+:9&s+:9FrrMk=JcOU,!D)CK
+rrC[E^AtZnE2[^UHM3X)jb!Mas+:9&s.KAma%1d^i;`lqT9]EVnq*0tQ2p#us+:9&
+s+:9BrrM;t]70fVr;Zh9Z@;nYa-6N'nq*0tQ2p#us+:9&s+:9&s4.,LTD\`ihh(mE
+rrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.s2"^8nq*0tQ2p#us+:9&s+:9&s4.,L
+TD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.s2"^8nq*0tQ2p#us+:9&
+s+:9&s4.,LTD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.s2"^8nq*0t
+Q2p#us+:9&s+:9&s4.,LTD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$rrA\i!!(o.
+s2"^8nq*0tQ2p#us+:9&s+:9&s4.,LTD\`ihh(mErrDVAQCO6@jb!Mas+:9&s+::$
+rrA\i!!(o.s2"^8nq*0tQ2p#us+:9&s+:9&s4.,LTD\`ihh(mErrDtKjdbE4pk&Nt
+s+:9&s+::$rrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&
+s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9Q
+rrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i
+!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.
+s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&
+s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&
+s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&
+s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9Q
+rrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i
+!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.s+:9&s+:9&s+:9&s+:9QrrA\i!!(o.
+s+:9&s+:9&s+:9&s+:9XrrC+:rrA\i!!(pSrrMT?K)^H&K)^H&K)^H&K)^H&]Dhto
+(hhP#rrA\i!!(pUrr]H,#g\,&K)^H&K)^H&K)^H&K)`I_#PT&8!%;N1?Msj.G(3U2
+!!#iIs+:9&s+:9&s+:9&s+:9]rrA,M!!(>ss+:9&s+:9&s+:9&s+:9]rrMj2o)Jbe
+K)^H&K)^H&K)^H&K)^H&\,QGho)Jd:K)^H&K)^H&K)^H&K)^H&\,QL')"dk/:kJ_!
+s+:9&s+:9&s+:9&s0_k,O7`JQc[u1Ks+:9&s+:9&s+:9&s0_k-pDEW)!)S:IK)^H&
+K)^H&K)^H&K)`1W!0?jS!7-8sK)^H&K)^H&K)^H&K)`1W!V[H,!!#iIs+:9&s+:9&
+s+:9&s+:9UrrA,U!!(>ss+:9&s+:9&s+:9&s+:9UrrMj2qZ$UmK)^H&K)^H&K)^H&
+K)^H&YQ"T`qZ$WBK)^H&K)^H&K)^H&K)^H&YQ"Xt)#XF7:kJ_!s+:9&s+:9&s+:9&
+s/l;$O8T%Yc[u1Ks+:9&s+:9&s+:9&s/l;(pD<l1:kJ_!s+:9&s+:9&s+:9&s/Z/%
+NrT1+K)^H&K)^H&K)^H&K)^H&X8`7q(f5haK)^H&K)^H&K)^H&K)_hM!KYQYs+:9&
+s+:9&s+:9&s+:9&s+:9&s+:9&s+:9&s+:9ds+8"U^AuT3s+:9&s+:9&s+:93rr>$1
+!1NrgBS-89s+:9&s+:9&s,m<]hgtis!!"-ns+:9&s+:9&s+:95rr_-Y!-j+1T>(Fu
+!$HmnK)^H&K)^H&K)^u5"5a(YT7[*8rrQR.+G0WFs+:9&s+:9&s,m<`hZ*YKK)_JC
+!al!NK)^H&K)^H&K)^H&OoGO@!!&XCs.B;m?iV=$s+:9&s+:9&s+:95rr_-Y!2"lC
+TDnt#!$HmnK)^H&K)^H&K)^u5"5a(YT7[*8rrQR.+G0WFs+:9&s+:9&s,m<`hZ*YK
+K)_JC!al!NK)^H&K)^H&K)^H&OoGO@!!&XCs.B;m?iV=$s+:9&s+:9&s+:95rr_-Y
+!2"lCTDnt#!$HmnK)^H&K)^H&K)^u5"5a(YT7[*8rrQR.+G0WFs+:9&s+:9&s,m<`
+hZ*YKK)_JC!al!NK)^H&K)^H&K)^H&OoGO@!!&XCs.B;m?iUu:YlN%#s+:9&s+:9&
+s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm
+^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XC
+s.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&
+K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfn
+K)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lC
+TDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&
+s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXN
+s+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8
+rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YK[Jp8lUTjb!UQiUp!al!ApQbfnK)^H&
+K)^H&K)^H&SGr]K!!&YVrr[s;L$$e_"$?P`FOC*hYrqq1!Frn1rrZa2!'J-u!al!A
+pQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrr@cP!!4HVk0s>4,ldp-dJj1mq#CFmk3`0N
+49,@-r;QkQ,pf>0rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKli-rIqu?dE;5;\A
+"!mpI4OX60bkD)<--YfW"$?P`-2miDg&:sO--Q;i?iUl7Q2nXNs+:9&s+:9&s+:9@
+rr_-Y!2&TW!'L&W!@<HOrrXPI!'J^0!6kEB"!p&l-2dfE-1gU*"$?P`-2miDbl.SC
+-0EGO!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrr>1U!!,3sg&D.#!!#.0rrC:B
+!!%`PrrJl@xxxxxx,EJP!!">CrrZ*u!+X4P!al!ApQbfnK)^H&K)^H&K)^H&SGr]K
+!!&YWrrtRc!%"mI-2RZBL"cP/,ldp-df0<^rVuqPrVm#E,ldokn,EJP!!">BrrLg+
+b5VNN!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlL_49,@-s8V4k-2[`CA*X'pbh;Xg
+"!mpI4OX60L&M&PPl1O`49,@-n,EJP!!"=^rrQR.'DIdm^4QB:s+:9&s+:9&s.')k
+hZ*YKli.&L!!">CrrI3fr;Zh>q#:?/re1BJk55/a;#gU$s5q(M^\[s4,ldp-q>UQ@
+P_HmLrrV>:^\Ig1UP7k%rr@cP!!(7@rrY@`!%%LA"3cIQbkh>A49,@-r;QhnKsCLS
+"m0nh4Cb/arrTrhk4nrWPa(J5!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrrY@`
+!%%OB!R*\)!!';$rrJ?1qu?dE;;(sK!87>O!^'=+rVusFFSu.@,ldp-qu6\N-2dfE
+-&)?u"Qh!1!5JC1"-`cc-1h-:L&M&Pbl.PEfd-Uu-2miFo4'*F!!,3er;Qj]!!">D
+rrB>'!!(^MrrJl@qu@!KL&_1X!!">:qYpY-!!#m^rrQR.'DIdm^4QB:s+:9&s+:9&
+s.')khZ*YKli.&L!!">@rr>1\!!#.Zrr?R(!!FV1s8U=:!!$O-rrXPI!'L2Z!'L&W
+"*FSCPl:X_4So'X-2mlEbk1o8L&M&Pbl7VCbU*5g!/:FP!R)kc!!';&rrY@`!%%UD
+!/:CP!/:CO!2K;h!d+H>rVuq.qu6Z2rVupEli.#o!#,*m!5='bK)^H&K)^H&K)_A@
+"5a(YTBlLZ49,@-q>UKX-2mlEU]18nPl1U]-2dfGFT;Bbo`,!,rr3'H!!#.[rr?R'
+!!C"9jsC!,!-J/=!/:CP!'KlQ!+Z!."Ja2*;'l2A!%%UD!'L#V!%%UD"$?P`-2miD
+L&M&PU]18ofd6Ut![TrTrW!!^s.fMm!3uJ%!)`^q!+Y?p!al!ApQbfnK)^H&K)^H&
+K)^H&SGr]K!!&YWrrY@`!%%F?!/:CP!'L8\!%%UE!/:FP!-J2?"$HV`bkqGC4GAK!
+rVupqrr3'H!!#.\rrAhm!!?)n^HDJq"&]*uL&M&Q-/&7s!%%UE!2K/c!'KuU!@>M[
+rr?R-!!?`GUF#m>!0mK_"$?P`-2miDL&M&Pbl7VB;>pOqA,cK4YpC]ks8Psq!!#.[
+rrBh5!!+D.li.#o!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLZ49,@-q#:T],ldok
+s8S>_!!IEDs1_G0!!AJcs31EA!/:CO"!mpI-3!oH,ldp-rr2s\rVuq.rr3,m,ldok
+rr2s\rVupqrr2tPrVupEo)A\Pp](=Wbl.PA-2mlEPlC[_^]"354T>?_49,@-rVljp
+rW!&Es8Tk5!!#.UrrLe!rVuqPrr2sqrVupqlMgon!#,*m!5='bK)^H&K)^H&K)_A@
+"5a(YTBlLZ49,@-p\tXJ!!">Fs#^8]-1dloqu?^ZrVlsG!!#.Zrr>1\!"R6Qs!7XF
+4TGHD,ldokoDS[hA,ZH1bl@^<r;Zr7s8ODE!!%`Drr>1Y!!4H/Pl1O]U](5n4T,3]
+,ldokrr3'_!!">Drr>1\!!CIFs&&aq!5J7-!+Z!."""!I^\n-4^Zth#?iUl7Q2nXN
+s+:9&s+:9&s+:9@rr_-Y!2&TW"$?P`-27EH,ldoks8OAF!$rrh!!+C"r;QjF!!">C
+rr@cP!"$mLs!7XF4TGH*rVup\r;QbNrVurBrr2sqrW!!^s-3K_!%%18"$?P`-2u*g
+k5,)XL&M&PL&CrQ49,@-rr3'_!!">Drr>1\!!^[Is!7XF-2%9=o-OA9!d+H>rVupq
+l2Lfm!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLZ49,@-q#:T],ldoks8ODA!!+C"
+qYpXD!!">Crr@cP!"$mLs!7XF4TGG8rVuqPr;QbNrVurBrr2u5r;Zkn4T5<\L%50F
+,ldp-pAY+TrVurBr;Qj]!!">ErrY@`!%%UD!'L5\!mL\grVuq?o`"oFrW!!G^ErjZ
+!5Idu!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrrY@`!%%F?!/:CP"&]*u-2[`D
+4JV]O"!mpI-2dcCFT)7Hbl@\h!!#.]s.fPn!/:@N!/:CP!6kEA!+Z!.!%%UE!%%.7
+"!mpI4SJdTA,ZH.bl%JC49,@-rr3'_!!">Drr>1\!!:CEbl.SBL%G<E4T5<\-2mlE
+;<\#]?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2&TW"!mpI-2IQAbU*5g"/Gnr-2mlF
+;8;i)"!mpI-2dcC-2mlNg&M'u!!#.]s31HB!'L2Z"$?P`-2dcDjsBm)!/9qB"!mpI
+4SJdTL&M&PFT)4Bjs:!-4T>?_49,@-rVlj[rW!#Ds4RAO!+YX#!2KAj!5Iat!al!A
+pQbfnK)^H&K)^H&K)^H&SGr]K!!&YWrrXPI!%%LA!R)kh!!#.\rr>pq!!%-<rs<cn
+-0G7-,ldokrVlk^rVupErr3'H!!#.\rr=AE!!&enrr?R.!!#mnrr?R,!!">6rrXPI
+!'KuT!87>O"XVCms78AP!!&8_rrY@`!%%UD!'L5\#L*5J,ldok^]"07k$pNKqu6XY
+qu?^okPkTk!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLW-2mlFA&&#e!i'6Or;Zi4
+rr2u5r;[!I;2']d-2mlHPlLb0rW!$H4?Oqg!!%`PrrXPI!'L8\!/:@O!^&Rkr;Zi4
+qu6]Z-2dfDFRT53,ldp-p&>"hrW!$H4?Oqh!!">DrrY@`!%%UD!'L5\"3gfFL&CuV
+;2'^6,ldokqu6Z$qu?`3kPkTk!#,*m!5='bK)^H&K)^H&K)_A@"5a(YTBlLW-1_*:
+U\t,lA+fm*-0G7--2.B>4T59^,ldp-rVlj[p](;9q>UG:rVusFk3r<P,ldp-p&>'G
+-27H?Z2O\)49,@-rVlj[rVurBrr2s\pAb1>qYpOXrVup\k5PKj!#,*m!5='bK)^H&
+K)^H&K)_A@"5a(YTBlLWFS,V7-):>:!L+o+!!,48rr2sEp](:Vr;QjF!!$O-rrM7E
+q>^M*q#:=krVuq.mf*Ad!!$O$rrKk\qZ$XCU\t,o49,@DrVm"S!!">-rVljpq#CFm
+g%t^K-2mlEUZVRX?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2&QV!l&4kq>^RC;;(^D
+#F&(J,pbZq^\n*3-2moC,lp,mqu6bn4Ak8<rr@cO,lplXq#:N[,ldokk3`0LKn]*t
+!Tmnj,lqN<qu6cB4?UCVrrRmOZ2=P%UJ^t9!Frn?rrAhn!!#.CrrQR.'DIdm^4QB:
+s+:9&s+:9&s.')khZ*YKkPkb$Ki'sdKtlgN"!mpI-/8G"A,ZH.A%2I<k4\fT4T5<\
+UZMLW?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%:2"!mpI-/8G"-2mlE^T@G8^]"35
+-05(-?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%:2"!mpI-/AM#Pl:X_4KJJ^;>pOq
+FQEH'?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%:2"!mpI-/AM#4T5<\UTFJ!js:!-
+-0F:g!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y2rrXPI!%$J$!87>O!%"]G!0mH_
+!'K<A!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y2rrXPI!%$J$!0mH_!+W)0!)`^q
+!2JTS!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y2rrZ*u!+Xjb"Qh!1!5GT7"0hh+
+-0"q+?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%71!L/i'rrV>:^T%57^P1h0rrQR.
+'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K
+!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&
+K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!A
+pQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y
+!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&
+s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y;rr^rubiXNW
+ec,\Y!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT@*Z>KdH]u![Tt6k5PJE^]+66;'k&u
+!l$&*qu6YMrZqSBg%PFHUHJN%!E%PErrLeMrZqPSci4&S!#,*m!5='bK)^H&K)^H&
+K)_A@"5a(YT@3`G@fRfsKnWAM!0l^I!nelRrr3!r-/SY(bU!85r;R"3!)\Gl,ph7>
+rs4;Y-$4iN!%$=ors.4'-$4iN!'JX.!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y?
+rr^pS4S/OO"3`&;k3;mIbQ*@NrrfSQ!!(7ArrTq8;?$RsbU$-^rr_C04S/RP!i#`m
+q>ULn!5JO5!egW=dJj8U!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT@<fAK`Hi(rrQ[1
+U\k&kk4\fTbl%JBbQ*@irrCaGrrC:8rrlm4-"?r!rVlq/!5JL4!`8sNqYpV]!/:@N
+!@9&grrVd<4T59]bQ'cQrrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKe,KK6!+Yp+
+!qXY-rVlk-r?VH.r;R>];'c2g;;(tH,lf5;L&Y!rrVm(s4='tR;<IlX#DFJq@jM+$
+;>:(pbU$cjK`K?qrrFDlr;QhP!0m?[!qX1Ar;QdD-1h-<^Aq-YrrQR.'DIdm^4QB:
+s+:9&s+:9&s.')khZ*YKe,KR5,lhGip\tI\!+U_:490L&rt3!l-$4i_,ph6/F9#0l
+^]-DBrr3XR!%!>Q@xxxxxxxx!4?S=O49/7Rrs&)Ws8RcQbl.PB,s;,*!mCXuoD\m,
+!'KoR"6M]G^X<&_?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%^>#GWRF!$sa]g&1jO
+@fV5]rs(Xdg&M(7!5JO5#,;0.s3(Isrr33c-3+"u!'KlPrs,;!;?-ZM!'L5[![T/T
+p&>)I!6kEA!@9l+rrUCE4S/RS492Y[rreQK,pf>5rrQR.'DIdm^4QB:s+:9&s+:9&
+s.')khZ*YKd/O034=0t,!BeU*rrFDlr;Qu9!-J7o!'L2Z"bj5]bQ*@rrrtS3s8R0@
+U\t,r494(7K`InHrrQ$tbk:u;K`K?qrrFE.r;QiB!'KoR!^$Hmp&>2*4?NU+bgHFl
+?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%O9$,:R.!%$=uf`3>rKa)W!4TD/VL&(`M
+bQ*@rrrtS3s8P1]g&1jSF9')UK`K?qrrRlSbk:u;K`K?qrrFE.r;QiB!'KuT"7nVT
+A+BR#UAuUfrrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKb5VZU!)`d?!!)jA"B#2Q
+!/:7K!mCXurr3-a-3+!--2[]HK`Hi,K`K?qrrRlSbk:u;K`K?qrrFE.r;QiB!/:1I
+"3`%kA+0F!@fW:PrrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKe,KG24Sf!\,piT8
+!'L&V!i#aLq>UN?!/:FP#!=43s#^;7r;QtT!5JPf!6kEA!egWup&>)I!6kEA!@9&i
+rrSDbL%tZMYpBCFo`"p_r;QhP!/8l$!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&Y?
+rrOJH^\e$8o-HO!s!8uhrs%VMg&K7r;>gFt4Al.&!/:FP#!=43s)\79r;Qs`!87C+
+!6kEA!egWup&>)I!6kEA!`8sNrVlq/!6k9="3`&;Z1\+ubU$-arrQ[1UXK/D?iUl7
+Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%a?",-_$^\n*:@fV5_s%rc\rVm+4!/:IQ4=/5N
+rs$4<;?+i?FT2:E4=1%-^ApCprs-:=4TGG8!6kEA!egWup&>)I!6kEA!i#a*rr3&D
+,s;#'"7mfbbk(i9,pge7rrUCj-.2_o?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2%^>
+$"Er84EQ9e,lg(,rs7a5!+X6f@fSXjrt2L9-'ZW<,ph7Ef`3=?Z2Zp4rr3F;!'I%#
+KdA%[s8RcQbl.PCK`K?irrRlSbl%JG49/m8UEooFrr35I,uO^BF9!Wa49/7XrrFDl
+rr38!!%"DaPU-=)dJj8U!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT@*Z?KdA&E!!+C"
+r;QuS;'c2B,uOU?!O4cd!!,4+rr314,lhHT;'l2@#)+?'!$tLqrr3%R--Z>f!ehrE
+p&>)I--Z8d"_/hY!%"E=rrpUm;?-Ynpa,q>!@9&jrrJl@rVus]Z-`LP?iUl7Q2nXN
+s+:9&s+:9&s+:9@rr_-Y!2%U;"6RhOg%YLIbfok^!nkfNqYpQKp\t<=bi[^\!p7_N
+iVru4bh:;A!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&
+s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.
+'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K
+!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&
+K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!A
+pQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y
+!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&
+s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7
+Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(Y
+T7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&
+K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m
+!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YK
+K)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XCs.B;m?iUl7Q2nXNs+:9&s+:9&
+s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&K)_A@"5a(YT7[*8rrQR.'DIdm
+^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfnK)^H&K)^H&K)^H&SGr]K!!&XC
+s.B;m?iUl7Q2nXNs+:9&s+:9&s+:9@rr_-Y!2"lCTDnt#!#,*m!5='bK)^H&K)^H&
+K)_A@"5a(YT7[*8rrQR.'DIdm^4QB:s+:9&s+:9&s.')khZ*YKK)_JC!al!ApQbfn
+K)^H&K)^H&K)^H&SGr]K!!%7q^Rr7B8,s=tQ2nXNs+:9&s+:9&s+:9@rrCr.!1Elf
+'DIdm^4QB:s+:9&s+:9&s-s#g."VGg!!"\HQ2nXNs+:9&s+:9&s+:9?rrDfd^Aru%
+E!0#@!"rnaDua@LDub%SQ2nXNs+:9&s+:9&s+:92rrB=<Q2hp(!!#g:Q32(9!%O_/
+!5='bK)^H&K)^H&K)^l2!3s8(r;Zgjad)oHrVuq2UQtnoK)^H&K)^H&K)^H&NrK*a
+^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&
+K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"
+r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&
+NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtno
+K)^H&K)^H&K)^H&NrK*a^6\]t!)(G"r;ZgjUQtnoK)^H&K)^H&K)^H&NrK+F^?,:n
+!-63Cr;Zh<UZDLDK)^H&K)^H&K)^H&K)`smr;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&
+K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&
+K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&
+K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#
+K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>
+!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhI
+aoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8
+r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&
+K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&
+K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&K)^H&K)^H&K)b*8r;ZhIaoD;>!.TV#K)^H&
+K)^H&K)^H&W;cn9Xi8'R!!%Mjs8;otItI]Ps+:9&s+:9&s+:9Mrr=dg!!%5bs8;ot
+?cBb[Y(H\*s+:9&s+:9&s+::6rrBsN!!#C.s1\O7"Ik#CK)^H&K)^H&K)^H&l2LaF
+^&S.0aoB'T!#^CgK)^H&K)^H&K)^H&l2LaU^An9Kn&bS0$,6H?$A/;0s+:9&s+:9&
+s+::8rrA\i!!&q9^AuEsrrI?F^]4?NK)^H&K)^H&K)^H&K)b*8!2'2i!8iY5!Ul`$
+^Aph(!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&
+s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-n
+s+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`i
+hh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&
+s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+
+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`
+TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&
+s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mN
+rr?I+!!"-ns+:9&s+:9&s+:9&s69O`TD\`ihh(mNrr?I+!!"-ns+:9&s+:9&s+:9Z
+rrC[9^B"#RrrA\i!!(oAs6@?!a3Xbc@/^-++G0WFs+:9&s+:9&s1/.1Va0DF!D)D#
+rrA\i!!(oErrVqM.-LX4#^H*lrr?I+!!"-ns+:9&s+:9&s+:9_rrM:Rj8]3'n'V.8
+TD\`ihjXQGa!g!K!*I\L!+>d+!$HmnK)^H&K)^H&K)`L`#,`"4!"`PAlG!F/!!$uc
+rrA\i!!(oGrr@<C!!+L/lG!J*-ia7Ve,KDUrVup@K)^H&NW0&i;<EK1K)^H&[JpEV
+#QOj4n)s]P5QDqSrrA\i!!(oHrreYg!!nACrr_Ei!-$Ee!+>d+!$HmnK)aX+!b4@-
+p&>)g4L)m*"(M<2;?$Rqbk(i8g#dndK)^H&b5VV=0E;Bfjo5F<!!)K9rrA\i!!(oI
+rrh3b!%?I\rrP.[8CRS=@/^-++G0WFs5!\W@fQKTpAY9K,ldqua8Z.SrW!-bs5kU-
+--Z)_"(M<WZ%E"-s+:9orr[`N!/KY8"1J71T@3`>TD\`ihjscL5QCf)jSo<q!!qK3
+rr?I+!!"-ns+::,rrY@`!%%@=!+Z!.!6iL`!+Z!.!i,dLrVusFZ2">!A,ZH.4G*Tb
+s+:9prr_]q!''$="SW`5!-$D:!)NOn!,oDt!f+P2l2Ljp!!%9(rr]_1!#X48!&4BP
+!"cSg!gg[RK)_qP"$?P`-2.?@,ldok`r?5h!!">Fs1eL4!@?Fqrr@0>!!%_)s+:9&
+s31KFT)\khir9"fJcPcM!Z5nFm/I/q!!)3Arr?_a!<)s!.%c+kY5\Sd!!">=rrXPI
+!%#\c!0mH_!/:FP!2KJm!'L/Y!3uJ&!+UW\K)^H&bPqZh!!r>XrrL/2JcPcM!>rlE
+rrP.[5iDYCT.kisrVusikCW`<rrY@`!%%C>!6kEB!%#\c"$?P`-2dcCU\t/mA,ZE.
+jsC!,!'Gl5K)^H&b5VNF!&0$)hu<bmO!su-!-mr3!Z1oVK)ad/#OfEW(]XOI[t=Xb
+rrY@`!%%C>!6kEB!'KZK!R06RrrBh5!!$O+rr?R-!!%`Prr>1\!!+D.m/I+>fn06U
+s+::0rrPFc5_B$krre)_!!&ASrrN0#ItI^Vrrqk!!!!;^K)`Rb!Mac7491*6rrY@`
+!%%C>!6kEB"[)hbk(USFrsb`Wk5YHY!!';(k.cVbpAY--re1BJk4S`S;>pOq^\[s1
+4T,6]U]4j&!!';!rrCaOK`RFkqu7"F!!%`Qk&`^34JRN.K)^H&l2LfM!'l/9g]%E.
++92])nG`Oi!.TV#g]%AZ!!#99s1nX8UF#^9!2KPn"$?P`-27E>bl.SH4TFOi!!'e1
+rrnVe!%%ZurW!!^;'l2A!@;jarrJ?1qu?dE;;(aE!5JL5!)`Rl!V7W:!!+C"r;Zh-
+q>UK14So*Z4L+kb"XO-K-)2da!!%+ms+:9&s6BUc5QF'$s4[JT^An7!nG`Oi!.TV#
+gA_8"!!&@;s2+d9Z1e4uL&V)S,ldokq>UNYbbP.;!^-LIrVup\qYpOArVuuCbk;#:
+A,Q?,A,$$)-0G%'!)`^q!5J=/!R)kd!!#.WrrAhg!!';'rr=A>!!+D.K)^H&K)b0:
+!^H`NK)aO(")%Z7fCAkB!!%M#s4[JTpF$"aK)`^f!'L5\#:2KBF<pnePlC[h,ldp-
+s8UceKfo>\qu?g]s5kX,!!%-=rr@cP!!5:_bk1r9^]+65Pl1U]-2dfDFSc";Z2O_'
+;>1"iZ24M%-/&.p!SJdu!<"5C!!#.\rr=AB!!+AlrVuq_K)^H&K)b0:!^H`NK)aO(
+"5a(YJ+<O?!!%M#s4RDSLB%=pK)`ag"=4$J-1h-9!p2U-rVm$I!!"<--1q6?;?-ZM
+rVusFg&:pN-2mlGU]8R9!!>?;Kk()^!)`aq!%%UE!/:FP!-J2?!'L,X!'L5\!5J4,
+!/:=N!3uA"!)`^q#\3#ss03jM!%%XE!%%OC#!DMK,ldpeK)^H&K)b0:!^H`NK)aL'
+!\aU>nc&Xj!.TV#g&D0C!!&@;s24j:4T5<];;(aE!%%+7!/:FP!'L5\!)`aq!/:CP
+"""!Ibl%MAL&M#U,ldoks8S>_!!IEDs1_G0!!&8\rrAhn!!$O$rr>1[!!+CiqYpQK
+rW!*as8V4k-2mlE;?$Rq-2dfD4T>?_,ldp-K)^H&K)b0:!^H`NK)aL'!al!Vnc&Xj
+!.TV#f`)!a!.TV#_uB_Ar;ZmF;8;u-!%%F@"XPHWFG4i9!!%`PrrAhm!!C"9s!@XE
+!/:FP"!mpI4T,3Z4T5<dbl9d*!%%634T#0Z4So'\,ldokk4S`S4So*Y4So'XL&M&S
+Z+j-^r;ZjEg&D!O-2dfD^]+68,ldp-K)^H&K)b0:!^H`NK)aL'!al!Nnc&Xj!.TV#
+f`)!q!.TV#_Z'V2qZ$Xok5>5Z-2mlI,s5\%bl%J@xxxxxx&M#O;>pOs4TCZF!!">D
+rrXPI!%%RC!/:CP#0d)n!!";kqu?aDL&1fLL&M&PA+fj%A,-*)A,H9+4T5<\-2[`E
+-"H*9rr=AE!!#.\rrC:B!!#-5s+:9&s6K[d5QF'$s4I>Q?iV>>rrN0#J'7iqg!#/(
+UY1q4![%JmK)`[e!P_M0!!+C@rVlsG!!#.UrrC:B!!%`OrrBh4!!/iWrVuqPrVlsG
+!!">Crr@cP!!:CE-2ITB-&)0p"nO#?!%%71rr?R-!!-Sor;Zi&r;QaZq>^RCA*3^h
+!Tk^-!!&8_rrC:B!!#-5s+:9&s6K[d5QF'crrR:)U\k&nUEr%UVZ-^*!$Lh3!WW4M
+c2Rgt4So*Z4L+b_!l'H(U&P0:!.TV#^]+AM@jV'R#J^<=js:!-4SSjUbl.SBL&CrN
+A,ZH.-2mlE-2dcF,ldokr;Qb=rW!#Ds!@RC!Bd.Orr?R.!!%`Hrr@0>!!>@`s&&aq
+!@?n,rr>1Z!!4I#k5,)Xbl%MAbl7VBbl.SB4G*Tbs+:::rrPFc5f3O'K`D*!qu6aE
+!!#lnrrQR.+S#I5!!%Mnrr@cJ!!$O,rrCaO!!'d.rrO;CItI^6rrM7ErW!$ts8U=B
+!!$O'rrC:B!!#.ZrrM7.qZ$VMr;QjF!!">Crr=AE!!:jR-2mlF;8;i)"Qh!1!%%@=
+!2KJm!'L8\!V7W:!!#.[rr>1\!!,3Wp\t6;rVupErVm#_,ldp-K)^H&K)b0:!^H`N
+_Z'T^rVuqnrVllArVupEVZ-^*!$Lh3!WW4Mc2RctrW)pDr;Zh>rVlkmrVuq_UAk9;
+!.TV#_uBbjbl%J@xxxxxxxxx*rVuqPp\t6;rVup\qu6Y+qu?^Cqu6aE!!">DrrA;_
+!!=PIs&&aq!-J,<#';.;k5YHkrVuqPp\t5gr;Zg[r;Qc%r;Zh-rr2t_rVusrk5>5_
+PU.W\s31HB!%%RC"!mpI-%c/Ks+:::rrPFc5f<U%g&1mNA,ZE-L&CuObbtIB?iV>>
+rrN0#J'IuqK`D*8rr3"o-2mlEg&:pP;'e>urrO;CItI^=rrfS,!$tMAK`F77!!?*u
+s31HB!/:1I!6kEB!'L/Y!Tk^,!!%-<rr=AE!!=N04=0q+",6dT^\n-9,uKAM4=0t,
+#*f/f,ldokp\t5gr;ZjEbkqD?A,QB-U]18n-2mlJ,s6m8;'l2A!`B!ArVupEr;QaC
+rVurOK)^H&K)b3;!^H`N_uB_$r;Zg[rVlj[r;Zh^VuHg+!$Lh3!WW4Mc2Rm"!!#.[
+rrgOl!!%_ArrO;CItI^=rr@cH!!C"9s+UFP!/:1I!6kEB!'L,X!-J2?!@?n*rr=A>
+!!#.[rr?R&!!=P0s+UFP!/:4J!Tk^-!!+Ciq>UFWr;Zr7s8Ske!!9G*bl.SB4T,3Z
+4T5<\b_#kHs+::;rrPFc5f<U%A,QB--2miD-2dfDL%#$Cfho#errQR.+S#I5!!%Mn
+rr[rT!'L2Z"$?P`L%kTPUP7D$s5qPLXT&>E!.TV#`;]l04S\sX-):J>!2KMn!2K8f
+"!mpI4So'X;>pOqA,?3*-27H?4T#-ZPU6,*#X$f?s#^8]-0G"&!6kEB!@>tbrrL=i
+rVuqPrr3#64S\sX-*dIL"!mpI4T,3ZFT)7?b_#kHs+::;rrPFc5f<U%4T#0]g&M)e
+qu?^ZqYpT2A,[bT;5=*i#UKHs^N;Ra4GCZP!al!Nnc&Xj!.W8n",-^T4T59_o-FA:
+L&V)`fd.r>s8Th6!'Kj_,ldokbkqD@^LR6h!E#Wjrrc1]^]0#d,m;Hl;'i"6rrQ%D
+L"H>++96nCs2+d:PW\mj!^(Ser;Qh?4Ce'a"/@t@bkqDDjs:!--0G((!%%UEr?VJ,
+Pkb7`PYjOh,s6:arVlss!!$O&rrY@`-,90R"MZ5_-,9BX#GYck,pbZ`U\t,o;#ho;
+r;Ql6,lg&Zs+:9&s6K[d5QF'err=AC!!B"rs'ts,!%%OB!+Yj*"$HV`bl.SB-2[`C
+4N%1#?iV>>rrN0#J'IuqK`D*8rr3#64T5<\g&D!UK`D*8s8RfP!!">C!!#.Zrr?R*
+!!bXds-*K`,piHh"[&"L!%$=rrr\Jc!%$7s![%JmK)_>?!+Z!.!+Yj)"!mpI-0>.-
+Pa(h?!6k'7!p54!mJd42k5,)Yk0/GWK)^H&lMgoN!'nL&!6k<?$"O#8,ldok!!">C
+rr>1[!!+AlrW!#Ds313;!-H0Z!al!Nnc&Xj!.W8n!/:CP![TrTr;Zh>rVm(U!!#.]
+s31??!%%UE!6kHB!'L2[!@9&k!!:CEL&1iQ,ldokg&:sO4T,3],ldp-fDbmp!.TV#
+S,WI7rVur5q>UOC!!"<ss+:9&s,R*\5QF'frs=AZ!$s`-!'L:rrVuqPrVurBrr2tP
+rW!6e^]1P=!%%[Fbl%MG-$4i'!!"=`rrQR.+S#I5!!%Mnrr@cJ!!+D.rVm(3!!#.]
+s31B@#aG?O!!%`Qs+UFP#s?!&YlFbMs8RfO!!bX$bQ%Vhs'u$.!2KPn!/:CP!2J0G
+![%JmK)_A@!0mH_!'L&V"!mpI-%c/Ks+:92rrPFc5fE[749,@DK`D*!s'l$/-1`D_
+!0mK_"!mpI4T>?_K`D*!rr3'H!!$O.rrhp>!!(6^rrQR.+S#I5!!%Mnrr@cI!!+Ci
+rr30b!!#.]s1eL4%!;OL49,A8s8OAF!'L8\#)*$W-3+"!rW!@:s8U:C!%%[:,ldok
+rr3'H!!#.4rrO;CItI]jrr>1\!!&ehrrXPI!%!6sK)^H&NrK/G!'nL&"=4$JFNj^a
+&>LNO!+Z$k!!$O/s.]Po-0G4,",-^T4T>?_,ldqhrVlsG!!%_lrrQR.+S#I5!!%Mn
+rr[rT!%%Vu!H]Xe!"(%Ds8P1]!-J8@L&M&P-3!oN49,A8s.]Po-0G4,$&&?Z4TGG8
+!!">DrrlmpU]:@JrW!"Rs-3K_!2J-F![%JmK)_DA!87>O!%%C>"!mpI-%c/Ks+:92
+rrPFc5fNa'U](5s^],S[!'L5\$bu^O!!">Fs+LFQ-2miGK`D*8rr3'H!!%`OrrY@`
+!/8Dl!al!Nnc&Xj!.W8n",-^T4T,3ZPl:XhFT;A'!!%`Qs+UFP!-J5?#Wr(eL&Zi,
+!%%UD$&&?Z4TGG8!!#.Urs1^e!%%5!!!#.3rrO;CItI]krrA;_!!$O'rrXPI!%!6s
+K)^H&NrK/G!'nO'##P@#-3+!Bqu@-Os8S;`!%$e-K`D*8rVlu7!!#.\rrXPI!/:CO
+"$?P`KuO&n?iV>>rrN0#J'IuqK`D*8qu7(7!!#.]s#^8]L&_1,rVurBrr36d!!%`Q
+K`D*8rVm2=!!#.]s+LFQ4SSjUU](5n4T5<\UXfAG+96nCs.0/mjs:!-^\@a1;#gT+
+K)^H&K)^l2!^H`N`W$,g!!#.]s-3E]"(VB2g&:sTPlHF;!%%UD"3^`F-3!oH,ldq!
+rVlsG!!&8&rrQR.+S#I5!!%Mnrr[rT!'L2Z&\gF.!)`dr49,A8s8QR/!%$e,rs1^e
+!+Z%_!!">Drs?mL!%%[FK`D*8pAY+Tqu?^CeGfRm!.TV#SGrZQKtm<\!L/h#s+:9&
+s,I$[5QF'hrs7a5!!%-@s5kX+!!'e5rrj\K!)`d2rVur5rr3>1!!">-s8OAF!/:FP
+!+Z!.!85?k!al!Nnc&Xj!.W8n#_`6Y4TEX#@jV'R%);iB49,A's8P1]!%%UD"]57"
+4TE1q!!'e5rs>q1!%$e-K`D*8pAY--qu?_NeGfRm!.TV#K)^H&K)^H&QN%"O!'nR(
+!6kEB!0mK_!'L5\!%%UD%8d**-3*uk!!"<eKi'/q!"!08s!7XF,pbZ"rVupq`;]mH
+!$Lh3!WW4Mc2RctrVupEq>^Mjrr39e!!#.]s'l$/-2miQK`D*!s8OAF!$u`@;'l2A
+"_7Rd!!#.Srr>pq!!"=orrO;CItI]Ps+:9&s+:9:rrPFc5fWg(bl.SBbl7VBFT)7?
+L&M#OL&M&Rbl=I4!!=PIs!@I@!@?mHrrQR.+S#I5!!%Mnrr@cJ!!,3srVm0d!!#mr
+s+LFQ-2miJPQ1\0s8Skg!!O\KK`D*8p&>#erVuqPe,KIl!.TV#K)^H&K)^H&QN%"O
+!'nR("5*YS-2miGjs:!ir;R&b,ldqhs8T>Mr;['bF?BOLs8ODA!!,sM_uBdG!$Lh3
+!WW4Mc2Rgt-2dfG,pd'9qu6u-,pfhrs-*K`;>pLsf`2!urr3#(-2dfM4EN[c-3'_?
+!)`Fh"&T$u-.;ep+96nCs8;ltPb[jM!L0A,rrL@+K)^H&K)^H&hu<aC!'nO'!jRI4
+r;Qf[bkh>@Yrma<rr^K0PhH'9$^BfRs!7XFFHhKDftm[i?iV>>rrN0#J'@omk5ENn
+rrSF=k5>5\P_Ifgrr^K0PhH'9"dJ0Ls-/61rrhI1!!%`$rrO;CJ%GX\g!&a]!R/dG
+rrY@`!-Io6"$?P`FOU6l,lf7Ro)A`q4T$K+A&!WqK)^H&K)bWG!^H`NU&P3@!!%_d
+rrQR.+S#I5!!%M.rrcg3!%$dUrrO;CJ%P^_K`D*8q#:DL,uOI;"(M<2;;qNW,ldp-
+p&>+?!!#.2rrC:B!!%`Drr=A@!!,sZU]1F+,s9DmrrIgqg]%B<;'f(ks+:9grrPFc
+5b\2[,ldq!^&J.A!$Lh3!WW4MNW0),!!$NVrrO;CJ%P^\4T5<\PktC[Z2O_'A,?3*
+^]"35-/nk+,ldp-p&>+?!!#.2rrAhn!!%`ErrC:;!!+Cih>[Q=Kqm9"!p533q>UGZ
+rVup\ao;I-!!#mZrrTrh^\Rm0;>pOqFFsOEs2=p=5QF'CrrXPI!/8,d!al!Nnc&Xj
+!.U%/!2KMn!5Hq]![%Jm]DhkQrVup\qYpOXrVupEqYpP*rVup\iVs!+!!"><rrXPI
+!'Jd2!/:CP!0m*T!6kEB"!p&l-2dfE-1g!n"!mpIPh?!<,ldq0qYpPLrVupEb5VIV
+rVupEkl1XtrVurOqYpOXrVuq.K)^H&`;]m(!'m7X"!mpIKt[Kf?iV>>rrN0#IuaO2
+;#gSBd/O.i!.VW\!87;N!87;M!2KGl!878L!%%UE!2JNQ"!mpI-2%9?,ldp-eGfN&
+rVurBoD\g7rVuqPrr3"o-2mlEA)I:dbl.SB4PB`7bl.SB4So'\ju`ViUW`Z<o-O>8
+!6j^-!/:CP!/::L"L06Q-/!nMK)`dh!^H`NU&P3@!!&e-rrQR.+S#I5!!%M/rrY@`
+!-HTf![%Jm])MaVrVuq_r;QaZqu?`3r;Qo^,ldoki;Wm*!!"><rrXPI!'Jd2!/:CP
+!6k'7!5JL5!/:CO"O&.l!%$P&!6kEB!%$=u!6kEB!%%F?!R0]Krr?R,!!&8Jrr@cP
+!!$O(rrC8ps+:9frrPFc5b\2ZUHE&!rrQR.+S#I5!!%M/rrUD,;:#7D+96o&rr@cP
+!!#.[rrM7.qu?_Nr;Qb]rVupqi;Wm*!!">BrrQ\-g&D!R,ldp-eGfMYrVurBoD\fE
+rVuq_r;Qj]!!">%rrXPI!%$:t"!mpI-0"q*g"G?a!3uD$!+Y9n!6kEB!+UW\K)`@\
+!^H`NK)aL'!al!Nnc&Xj!.TV#f`)!q!.VT["Qh!1!%%UD!0m?\!-J/=!'L5\!2KAi
+"3cIQbkh>H^Qdm\s5p(u4ET`brrXPI!%%RC"$?P`-3!oH,ldp-q>UQ@P_HmFrrBh5
+K`Kg$rs.\.4=):9PW\pF!86uD!/:CP!6kB@"$?P`-3!oFUSIhg"PK#L4I#[A"3d!`
+^\e$5@jNE`rW)mC!E&"VrrAhnK`Jm^rrqP,4?R,Kr;Qk/,pb\Q!<"2E;<IlX!gJDl
+q>UTNUP5K*qu7"F!!%`Qk&`^34JV3A!V7W7!!#.Urrp/I4?R`#rVm#_;'dMNrW)mC
+!+Z$.!p52jrVlq/;;(gG!el?jqu6Ykre1?eK)^H&hZ!XB!'l/9f`)"\!$Lh3!WW4M
+K)aL'![%Jm\c2XlrVur5rr2s\qZ$UYrVllNrVupEqu6`h@jV'R!BdXcrs$4<!%$<.
+-2dfD-3!oH,ldokrVlj[rVupErr3'H!!#.YrrIg"r;ZjEL&(`LKdHWs!Bd.SrrI3f
+p](:?o)A]DrVurBrVm;Z,ldoks8RcQ!)^L.qu?^or;QeO-2dfE-&)?u!5J1,!-J2>
+!H]Xc!!+BUqYpSk-2[`G-&)C!^\%R2FT;A_!!">BrrKAer;ZjEA,Q?1,ldokUF#g<
+!-IQ,!+Z!."ApHF!%%F?!+Ym+"?`shs)do6%);iB49,@Ys8Ppr!'L/Y"&T$u4T59\
+F=$hb!@;6-s+::/rrPFc5_B$grrQR.+S#I5!!%M#s4I>Q+96o%rr@cP!!IEDs5kX)
+!!">Drr?R.!!$O,rrL=iq#CE"rr2tPrVupEq>^kes8OAF!'L;]ff]35!/:FP"!mpI
+4T,3Z4S\sWFSu.>ff]$0!-J2>!+Y^&!%%49!/:CP!6kHB!R)kh!!@rTs#fuT!87AO
+!'L&W"*FSC^\%R,FT2:?4SSmV4T,3ZU\FfjFT9,K!!@?Cs#g8\!6kEA!+Yg)!'L5[
+!%%@>!@?mqrrBh5!!4J/4T5<\bkh>>A,$$*Z2\q=!"$F?s!7XF-3*ukrVur5rVm#_
+,ldokrr2s\p](:VK)^H&iVrsE!'l/9f`)"\!$Lh3!WW4MK)aL'![%Jm\c2Z_rW!$_
+s8S>_!!FT1!!">DrraVJ!%$e*rr>1V!!">Err@cL!!">E!""AZs!7XF4TEVOr;Zh-
+rVlsG!!#.[rr?R'!!'e5rrM^;r;ZmF4=0t,!'L8\!/:@O"!p&l-2dfD-1_'9A,ZH2
+UWes"-2mlE-3!oE4Sf$X-2mlHbl@]QpAbE4s8Rd8,piKir]C0Xrr2t.r;cgCr;Zi4
+rr3#P-2mlG,s3LQ!!YRcs+NQ]-2diC49/7XrrbFa!%$e,rrA;X!!%`Prr=AB!!+Al
+rVuq_mJd/KrW!"Rs'u$.!/:=M!0mE^!^&RkrW!.Vs8QRk,piKir]C1&rr30K!!">F
+s+UFP!)`^p!-J2?"(VB2A,QE,-2dfD^OlK;s5O%[5QF'$s4I>Q?iV>>rrN0#ItI^Q
+rrO;CJ%5L_,ldoks8P4\!!-S>rW!&Es8Skn!!#morr?R-!!?`GUF#m>"-iicL&:oP
+A&$7e!!n;Ys!7XF4MN3@!!$O,rrXPI!'L8\!2KJm"&Yi.4T5<\;?$Rq;>gIsL&_1,
+rVuqPrr2sErVuq_rVlk-rVupEo)A\PpAb4?^]+654T,6^-$7gorW!#Ds.fMm"&Yi.
+4T5<\;>^@q,ldokqu6Z2rVusFU]18n4T5<\L&V)P;>pOqA,cK1YpC]kqu6aE!!">A
+rrY@`!%%XE!Tk^-!!>?Jb[^VP!%%XE!%%OC#!DMK,ldpemf*9@rW!$_s8S>_!!#mn
+rr=AE!!&enrr[s$4PBZ4!6kEB!'L,X$RGcQ4TGHD,ldokk5PA\-2mlGg&Jhd!!+C@
+rr2s\rVuqPK)^H&ir9'F!'l/9f`)"\!$Lh3!WW4MK)aL'![%Jm\GlPNrW!#7jsC!,
+!Palu!!@rTs&&aq!5JI3!%%UE!0mK_!5JL5"$HV`L&CuRU]:A<rW!.Vs8OAF!%%OC
+!-J,<"!mpI4T>?\4T5<\A,cK5o-FA:-3+"[r;Zhmrr2tPrW!&Es8Skn!!%`MrrXPI
+!'KiP!'L#V!BeU)rr>1\!!FUls8RfP!!:CE4T5<\A,cK2o-FA:-2[]E,ldokqu6Xn
+rW!)+s8SiVr;ZrQs8Tk5!!#.QrrXPI!%%LA"!mpI-3!oEFT)7?4T59[;>pOtbl@\h
+r;Zg[rr3'H!!#.MrrM7.rW!%qs8U=B!!">Crr@cP!!$O$rrC:B!!#.YrrCaO!!#.\
+rr>pq!!@xxxxxxx"&]*u;>pOuZ2aj!4T,6[fn06Us5O%[5QF'$s4I>Q?iV>>rrN0#
+ItI^QrrO;CJ%5LY^]"36FG9\o!^-M,rW!."s5kU-!'L2Z!2KMn!'L2Z"sj6L-3+"!
+rVuq?rVm'a!%$e-s!@LA!)`Um$RGcQ4TGHD,ldokoDS[hA,ZH0bl;2P!!%->rr@cP
+!!^[Is'l$/-2RWD,ldp-o)A\PqZ$[D4I#aC!'L5\!3uP'$K`W74TFOi!!">:rVlk-
+rVurBr;Qj]!!">BrrsbL!'L:8-2[`CA,cK.;>pOq^[qI-49,@-qYpXD!!">Err=AE
+!!';&rrAhn!!@rTs!@UD!5JO5"!mpI4R`:M;>gIp4T6Z+!!+D.rVm!H!!">:oD\n=
+!!#.YrrC:B!!#.\rrBh5!!=PIs&&aq$)@P#,ldp-s+Mcs!!$M\s+::0rrPFc5_B$g
+rrQR.+S#I5!!%M#s4I>Q+96o$rrqO2!!#,-rW!4gs8OAF!%%YerVuq_r;QbNrVuqP
+r;Qs`!!">Fs+UFP!6kB@!6kEA!%%F@!0mB\"sj6L4TGH*rVup\r;QbNrW!/Hs!7XF
+-0G1+!/:CP#0d,I49,@-qYpXD!!#.PrrY@`!%%Wg!9X+W"$?P`-2[]Ebl@^erVup\
+r;QbNrVurBr;Qj]!!">CrrC:B!!+Alqu?a[U](2p,ldoko)AeS!!">ArrXPI!%%XE
+"!mpI-2dcCbl.SEL&_0!rVup\rr2uBrVup\nc&XP4S/URU]18nbl.SBA+KX%,ldp-
+qu6Z?rVup\rVlj[rW!5=js:!--3+"hrVusF-2[`D4JRN.K)ad/!^H`NK)aL'!al!N
+nc&Xj!.TV#f`)!q!.VKX!%%LB!%%XE#UKHN-.sRE!%%OB!'L5\!6kB@#!;kc-3+"!
+rVurBq#:?<qu?^CrVusFbl%JF,ldp-s8RfP!!%`Nrr@cP!!UUH,ldokr;QbNrW!/H
+s8P1]!'L,X"!mpI4S&LS,ldp-p&>+V!!">?rr@cP!!%`Nrr@cP!!(7@rr>1\!!(^N
+rrC:=!!,3Wr;Qc@rVuq?o)A\PrVurOqu6jH!!">Fs31HB!'L2Z!6kEB",6d;-2mlE
+PlC[_bl.SB4RrFObjtf7A,cK.L&M&P^[hC,,ldokqu6Z?rVup\rVlk^rVut/A,ZH1
+L&_1sq#CFXUOrMts5*bW5QF'$s4I>Q?iV>>rrN0#ItI^QrrO;CJ%,FXA,?6+FT2:?
+;>pOq;>pOqFSl(<A,ZH.bl%JF49,@-s8RfP!!(7<rrC:A!!7964T5<]-1h*8"sj6L
+4TGGVrVuqPr;QbNrW!,Gs!7XF-2dcCPl:Xebl@]*!!">ArrXPI!'KiP"!mpI4SA^V
+49,@-q#:>hrVuqPr;QbNrVurBr;QaZrVurBrVllAqZ$Xo^\[s1bl.SBL%>6D4T5<\
+bkqDI,ldoks8V4-!!#.ZrrC:B!!7lSbl%MAbl7VBbl.SB4RrFOL&M&R,s5'(K`TDm
+rVupErr2tPrVurBo)Ae<!!">BrrC:B!!#.ZrrXPI!%%UE!%%XE!6k<?!E$U`s+::+
+rrPFc5j&(Jg!&.9rrV>:Pg'./k02'?rrSsLg"HB,?iV>>rrN0#J*-b4bfo59rrTrh
+Z-<4Lg!%\2rrJ@<f`)!q!.VKX!2KGl!@?n-rr@cM!!+D.qu6YMrVuq?rVm,b,ldp-
+s8RfP!!(7<rrC:B!!H1!s4J^t!!#mprrsbL!'L;]bl.SB4T,3d49,@-s8P1]!%$e+
+rrC:B!!B"rs'u$.!0mE]"S3o>!'KiP"!mpI4SA^V49,@-q#:?<rVup\r;Qj]!!">B
+rr>1\!!(7ArrC:A!!-T_q#:?IrVuq.o)A\PrVurBqu6aE!!">ErrXPI!%%RC!+Z!.
+!mL\grVupErVm#_,ldp-nc&S8rVuqPqYpdH!!">-s8S>_!!&ebrrXPI!%%OB!6kEB
+!'L2Z!+Ym+!/:FP!6kBA!Fsf7s+::)rrPFc5jA:Mfd.sD!!4HD^[M1);#gT\rVlo\
+bh2psKdAk\,m=8K,pcE`r;QfNg&D!Rf`2!ug&D+]!$Lh3!WW4Ml2M$a,p`Nk,pd'`
+n,EJ9!!(^NrrLg+f`)(a,s3J"rW!$H-"F^frrL@+rr3(b!!#mLrrO;CJ%,FXg&(gM
+;>pLpbkhA?;>U:mg&:sT--ZDho0!!P"-iicL&M&PbkV2<^]"35L&V)PU\t/mPlC[b
+,ldp-rr2sErVuqnrr2t.rW!$ts8QU.!!%`OrrAhn!!?a2s1eL4!0mK_!SKU7!!">9
+rrXPI!'KrS"$?P`-27E>-2mlEU]18nA,ZH.;>^@n4T5<\bl%JD,ldokPl1Ogk#!Ee
+s8OAF!%#DYrr_Cn4JVfR!'L5\!6k??"!mpI-3!oE;>pOqA,cK.U](5q-3+"hrVupE
+r;QjF!!">9rrA;_!!+D.qYpP*rW!%Ss8UdO!!,4ErVlu7;*<)"rrXPI!%%OB!6kEB
+!'L2Z!878M!@?n,rraVJ!%!m-rr_C\,s6eZK)aj1!^H`Nl2L`nq#CD:nG`SQ!!%`P
+rr]MP!'Js7!%%==%6WeQs)\5@FT;Bb!!"=urrQR.+S#I5!!%N5rr=AA!!+C@nG`S:
+!!(7Brr[?C!-Hrp!6k*9!)`aq#s826Z2aiX!!#.7rrO;CJ%#@W-2dfDU\t,l-2[`C
+^\Rm0;>pOt,s4:9rVupErr2tPrVurBq#:>JrVuqPrVlk>rW!0Lk5YH-!!#.\rr@cO
+!!58F-2dfG^]4>Kr;Zq0^Q_Uo!!">Err>pp!!=N04=0q+!%%49"!mpI4SA^V49,@-
+p\t5Ir;Zm]4=0q+!5JF2!'L5\!6kB@!/:@O"XRZ4F?ClK!!:jRL&CuV;2'^6,ldok
+qu6XYrVurBqu6aE!!">ErrBh4!!4H/4T,6^L&_1srVupEr;QaCrVurOoD\eQrVuq.
+q>UH0rVupErr2sqrW!'I@tfV6rVup\qu6aE!!">BrrC:B!!#.Yrr>1[!!$O,rr@cO
+!!OZYKlfF'rVurOK)^H&j8T0G!'ofK!^$G_r[%LC!+YR!"$?P`L&V)PA,ZH.bhE's
+-1q6Hg&M'u!!">Fs3(HC-/&;"?iV>>rrN0#J*Ht7,ldrE-2dfDU[e?d,ldqhrr3'H
+!!">!rrC:9!!=PIs5s:\##YF#K`D*8g&D*r!.VHW!)`^q!@@@8rr>1[!!">?rrLe!
+p](<!rr2tPrVurBq#:>JrVuqPr;QaZrW!.Es8OAF!'L5[!'L#V!-J2>!'KoS"GQmU
+jsB^$!@?n"rrXPI!'KrS"$?P`-2.?=4SSmVFSc";4T5<\bkqD?4SAaT4T>?\4SJgU
+-2[]B4T5<\bkqDB,ldokrVlk-p](:Vrr2uBrVup\r;QaZrVurBo`"pErVusFk4nrV
+4T5<`g&M**-2.B>;>^@q,ldokqu6Z?rVup\qu6YkrVusFk55/Y4SAaT4G*Tbs5O%[
+5QF(6rs(Xd!/:IQUHJMU!5J+)"$?P`L&V)SYpBB4g&D1$!!%,Ur6,4r4GEe7$$6.I
+FT;Bb!!"=urrQR.+S#I5!!%N5rsC%P!6kKCKd?^!-1V!;,ldqhrr3(B!!%,prrgOG
+!%!?sbQGV%4L+nc#s81fZ2aiX!!#.7rrO;CJ%#@WPl1R^g&1jMPl1R^L%kTJ^EraW
+!@=N>rr@cP!!(^IrrCaO!!&8]rrBh5!!\/Ws!7XFA,ZE.juiJ?!+Yp+!'L)X!%%UE
+!'L8\!TlN@!!FSJ!%$e!rrZ*u!+Y^%"$?P`-2.?>juiJ?!+Yj)"$?P`-2IQAF=$b`
+!@;7Rrr>pl!!,sMqu6a\!!">ArrZ*u!'L2Z!+Yj*!'L2Z"!mpI4T,3ZFT)7?bk(i:
+,ldpep\tB2!!">-rr3#C4Sf$Y-"HfO"!mpI4So'[,ldpTqYpXD!!#mlrrI3fq>^OB
+@tO`4s5EtZ5QF(6rrY@`!/:CO"$?P`A+KX%49,A8rVlo\bh2pt,ldqho`"sFbl7VE
+bQ%Vhg&D+]!$Lh3!WW4Ml2Li3!!(7BrrgOl!!&ebrrXPI!6kEA!SP]Mrr^IF!%%7:
+!R06rrr[rT!'Js7![%Jm[Jp>+,pd[1rrhI1!!#.SrrM7lr?VJSk5>5]^EikBpAY2J
+4GEY3!i%kfrr3(q4Ak8<rr@cO,lplXq>UJj4T6W2;5=/r,pfhorsHMN4=):9FP0M;
+L%50DKn]1!",/$IFS,S5L&E:u;8;o+"/@.gFSPkAk(Po[,pb[-k5,)YUJ^t9!Frn?
+rr]#B-$9"`"6O*'g&(dMUHJN%!Bd.SrrZ*u-):D<"2?,^4S&LRk(T&mrrTH&^\e$3
+PW\mj!HdK"rrZaW-*d=H!l%TSq>UQ@4Ajf,rs7b@4?Oo94GDpLs+::/rrPFc5jA:N
+49,A8rVltR!!#.PrrY@`!/8l$"!mpIbjYQ6bQ%Vhg&D+]!$Lh3!WW4Ml2Li3!!(7A
+rrY@`!/:"D"!mpIbgZRobQ%Vhmf*BC!!#.7rrO;CJ#`MNfnG.Bk5PG7OT,@Dk2H=?
+k2ZIAk4JZRk2H=@bi\d%!TqVWrrD3RrrD25s+:9ZrrPFc5jA:N,ldq?rVltA!!#.Z
+rreR.4GCQJrrY@`!/:FP!mEc(qu6i7;'dMNPl:U_FCY.H!b5a&p&>+?!!(79rrSrX
+FT2:BbQ%Vhqu6l8F?DZ_Pih-.!al!Nnc&Xj!.X;6"O$iG-0G1+"$?P`L&M#Tk(R;B
+L$&=5"!mpIbl7VDUHEYqrro/[,pcE`rr3&Q@tjdZ!ngG)p&>-<!!">;rrR:)U]18q
+K`D*8qu6hp@luk`UZMLW+96nCs+:9&s+:9&s-EZd5QF(6rrXPI!6kHB"O&.l!0mK_
+!L+o.!!%->rrY@`!/:FP"$?P`L&M#OU\b#q-):KM!!#mnrr[rT!)`Fh"=4$J@m'`:
+"$A\Cg&:pW,ldqhs8U:C!%%RC!+Ym+!@=N(rrQR.+S#I5!!%N6rr^IF!%%UD!2KMn
+!87AO!H]Xd!!+C@rVlsG!!(7BrrXPI!6kEA!+Ym+#!CT=49,A8qu6aq!!&8WrrpUH
+!$u_LrZqV.4Ce?i"3^`F-3!oHK`D*8rVloO4So*Z--YQP![%JmK)^H&K)^H&K)_/:
+!^H`Nl2M5>!!(7Ck(P)]!%$e-s+U7K!0mK_"$?P`L&V)S49,A8rr2u5r;ZgDrW!!G
+s)e5?!0mH^"Qh!1!)`Fh!%%@>!'L5[#pfQObl@^e!!">Drr?R(!!(^9rrQR.+S#I5
+!!%N6rs-aJ!%%[Ffjk!]!'L8\!)`Rm!@?FurrXPI!6kHB"!mpIbl7VBL&M&Q,piNj
+##YC_!!"=urVlkmrVuq_pAY-:p&G)&rr3)E!!">Err[rT!'L5[!'L&W!%$h.![%Jm
+K)^H&K)^H&K)_/:!^H`Nl2Lf2!!*!Er;[;%s8Uau!!"<TF<pne-3!oH49,A8rr3'_
+!!%`Prsq3l!%#D[^H;Kns77N:!%%UD!+Z!.!5J4,!%%@>!'L5[#pfQObl@^e!!">E
+rrAhn!!d#Xb`jCR!/9Y:!al!Nnc&Xj!.X;6!6kEB!@9&j!!FV$s8S>_!!4HgA,ZH.
+;?$Rt,ldqhrr3TW!!(7Cs4J[u!'KE+UEonos1eO5!)`^p"$?P`-2%9<bk;#:FT2:B
+^An6[rr3(S!!#.\rr?R.!!e5%b]G-2!6j[,![%JmK)^H&K)^H&K)_/:!^H`NlMgnI
+-2ITB-):J>&Q&N.--ZDhbU!5h^]4<r!!%`PrsC%P!/:IQK`D*!bl.PAbl7VBPl:Xf
+FT;C',ldpBo`#%?!!"<Bqh5%4rr2uBrW!/Hs8U:C!%%XE#<VtdA,lS(4T5<\^Zb\!
+?iV>>rrN0#J*R%6U\Olj4O!g)$7,ZP4S/UQPQ1\0rr30K!!(7Cs31HB#0d,I;#gSY
+r;QcMrr2t.rW!&*s8Skn!!%`GrrC:B!!+BUr.P-8rVltR!!">Ert0qb!'L;]js:!-
+PlLc;,ldokkPkT+!.TV#K)^H&K)^H&QN%"O!'oiL!6k?@"!o78k5G;^,ldpTrVm0d
+!!%`Qs#^8]L&V)Y,ldq?s8OAF!+Yd'#!;kc-0G5;rVur5o`#">!!(7:rtETV!%$e-
+s3(HC-3+"u!!"=hKdHZt!+Y3l!al!Nnc&Xj!.X;6!/:=N![TsnrVllArVuqnrVmWZ
+!!(7Cs!7XFbl@^e!!">-s5kU-!2K>h$K`W7!'L;]49,@-o`#$;!!"><rr[rT!%%XE
+%#"Z]4TGGG!!#.D@jV'R!2J`W![%JmK)^H&K)^H&K)_/:!^H`NlMh%3!!"=hbkh>>
+bl.SBbl.PJ49,A8s8P1]!/:FP#pfQObl?>r!%$e%rrB>'!!Qm4,ldpBoD\n=!!(7:
+rr^IF!%%XE$HrJM-3+"[!!";kr;Zj\UZVRX?iV>>rrN0#J*R%;K`D*8bfoq`",-^T
+-2dcX,ldqhs8OAF!6kKCbQ%Vhs8S;`!%%@=!-J2?!MdF/!!%`Frr^IF!%%=<",-^T
+4T>?fK`D*8s8R0@!$rri!!,s3k5PK*!.TV#K)^H&K)^H&QN%"O!'oiL"3^`F-2@K?
+bl.SBbl.PJ49,A8s8P1]!/:FP#UKHNbl>le!%%=<"Ao.!-"HoS!5J.*"!mpIbkD&=
+bQ%Vhrr32H!!">Fs+U=M!Bd.<rrQR.+S#I5!!%N6rr[rT!'L&V",-^T-2dcX,ldqh
+s8OAF!6kKCbQ%Vhs8RcQ!)`Fh#:0?M4Ac(Y-1h-=bQ%Vhp&>,J!!#.\rs"/W!'L;]
+4T#0\,uMG<rrO;CItI]Ps+:9&s+:9:rrPFc5jJ@ObQ%Vhq#:?IrVurBrVm0M!!&8`
+s#^8]L&V)X,ldqhs3(HC-2%9<^\\!24S&LS,ldqhpAY6=!!">Ers$[I!%%[FPl:Xa
+,uMG:rrQR.+S#I5!!%N6rr[rT!'L&V"-`cc-2miZjs:!-g&M'u!!(7Cs3(HC-3+"!
+!!#mhrr@cM!!$O#rr^IF!%%=<",-^T4T>?bK`D*8s8Psq!!4HVk2QCB+96nCs+:9&
+s+:9&s-EZd5QF(7rr^IF!%%C>"!mpIA,cK8UAt9?k5YHD!!%`Prs9tO!6kK*,ldq?
+rVlr]KtmQc!+Yp,!2K,b"!mpIbkD&=bQ%Vhrr3>L!!">Fs4IAP-'\?-!l&6!kl1]l
+!$Lh3!WW4MlMgs?!!#.VrrCaO!!&8_rrZa2!%%XE&1%;Vbl@^e!!">Fs.]Po--Z>f
+!l'HOr;QaZr;ZjEk4ATTbQ%Vhp&>,J!!#.\rsFG[!'L;]PQ1\0^\n*5UJ\;[rrO;C
+ItI]Ps+:9&s+:9:rrPFc5jJ@ObQ%Vhp\t5'rW!!sKk()^!)`aq"$?P`L&V)V,ldq!
+s8Psq!!d#K^LJPi-0G1+!Tk^-!!#.OrrXPI!6k0:!6kEB#0d,IbQ%Vhrr2s\rVupq
+re1G:!!">/rrQR.+S#I5!!%N6rr[rT!'L#U!'L5\!b6p]rVuqPrr30K!!(7Cs31HB
+%F"kP,ldokFNgLW!!#.ZrrAhm!!$O"rr^IF!%%=<",-^T-3!oWK`D*8s8V4-!!"<T
+KnXUp!!#.FrrO;CItI]Ps+:9&s+:9:rrPFc5jJ@ObQ%VhpAY+Tq>^OBk5PA_49,A8
+rr33L!!%`Qs4J^o!!+D.r;Qb,rVuqnnc&\;!!(7:rrC:B!!^[Is3(HC-3!oFfd6Cn
+!)_t[!al!Nnc&Xj!.X;6",-^T4SSjVbU*)c!'L5["sj6Lbl@^erW!&Es8Skh!!#.Y
+rraVJ!%$durr^IF!%%=<",-^T-3!oHK`D*8rr2tnpAb2Ikl1],!.TV#K)^H&K)^H&
+QN%"O!'oiL"6Lm0;>1"jff]04!BeU)rrZ*u!5JO5"&T$ug&D!PbWPb&!E%PIrrY@`
+!'KcN"!mpIbk:u;,lf7jrr^pS!'L5[!p3?+qu?aDA*<jn?iV>>rrN0#J*R%9YlFcX
+pAY/u-2[`C;>gFq,lf7irrOJH-2miEUF#g<!@;7QrrhI1!!$O!rr^IF!%%=<"2=g9
+;?$RtPQ1]*rVlo54So*Z-&(O^![%JmK)^H&K)^H&K)_/:!^H`Nl2LeHbk(i;ULQD`
+U\aukKqnSG!R06orro0-4?R`=qYpQ1rVuqnnG`PP!%%:;!p7_hrVlr(L$&:4!Tp0V
+K`JmLrrQR.+S#I5!!%N5rrLg+oD\rX;*8@'qu6`NKtmTd!p7_hqu6ha;*6t*k5,)\
+K`D*!k4/HRjs:")o`"sFbl%JAPa)%E!SN_:K`K?YrrO;CItI]Ps+:9&s+:9:rrPFc
+5dC=k;#gSBmf*:2_>aRE!$Lh3!WW4MZ2XnP!!#mbrrM9+_>aQZ!.TV#K)^H&K)^H&
+QN%"O!'mji"Qh!1!/7QT!al!Nnc&Xj!.V<S!2KMn!5GZ9![%JmK)^H&K)^H&K)_/:
+!^H`NZMt&L!!">-XoAH1!$Lh3!WW4MZMt"h!!"=HrrO;CItI]Ps+:9&s+:9:rrPFc
+5dLCl,ldpBXT&?0!$Lh3!WW4MZi:0j,ldq!XT&>E!.TV#K)^H&K)^H&QN%"O!'mji
+"!mpIUTFIs?iV>>rrN0#J$].XbQ%Vhk,eRa+96nCs+:9&s+:9&s-EZd5QF'TrrQ[V
+4KJJ`?iV>>rrN0#J$T(U4=+L<rrO;CItI]Ps+:9&s+:9:rrPFc5_B$grrQR.+S#I5
+!!%M#s4I>Q+96nCs+:9&s+:9&s-EZd5QF'$s4I>Q?iV>>rrN0#ItI^QrrO;CItI]P
+s+:9&s+:9:rrPFc5_B$grrQR.+S#I5!!%M#s4I>Q+96nCs+:9&s+:9&s-EZd5QF'$
+s4I>Q?iV>>rrN0#ItI^QrrO;CItI^crr>R2!!"*ms+:9&s+::6rrPFc5_B$grrQR.
++S#I5!!%M#s4I>Q+96nCs6BUb*>6OK!>kfgs+:9&s+::6rrPFc5_B$grrQR.+S#I5
+!!%M#s4I>Q+96nCs6BUb*@/g8!A=G)s+:9&s+::6rrQ!s5_B$grrQR.+S#I5&-.33
+s4I>Q#QT@+s6BUb*@/g8!A=G)s+:9&s+::6rrQj6+G0XGrrP^k5k4jU-idY,s4I>Q
+!!%e+s6BUb*@/g8!A=G)s+:9&s+::6rr[`N!9\t6gA_9L&--,.rrPFc."_KPrr]_1
+!2kGKlMgl*,g0Nq0*$V(K)^H&K)b$6"2=g9LP#Q[rr]G)!2oAe"+L:Na+F?FrrZ@'
+#k*BFlMgl*,g0Nq0*$V(K)^H&K)b!5""4-Tf7O%Xrrhd-!#YJ#rrh3b!%@Sns4mVV
+^An71K)b*8!?EH/?NDe[K)^H&K)^H&k5PP0#QQi9s4mVV?iU2!n,EKV!!%7qs5!\X
+pE0GIkCW`urrF,cb?k9'!.t6&s+:9&s5j7`IfKI>kCW`lrrhdu!!#RWrrbRe!-n6i
+s5<n[a!^ofT7[+,rrF,cb?k9'!0[?^LWMd]T7[)ps,d6bpG`-Q&=;R3s5a1apSSi.
+!$LIlrrq9k!!"FNK)am2!T//$!!#iIs6'C_*@/g8!A=G9rrE*,b7am]*J4<Cs,[0\
+mpQ(o!'#QqjZieOrVusikNi-Kf/Wa0!"a`IjZif"rVus)LP#QgrrF,cb?k9'!0[?_
+!%,l`!?E24s+:91rrKSGJcO^/!>qHlrrIl\JcO^/!BA\_s5j7]*@/g8!A=G9rrE*H
+b=r!X*J4<Cs,6mXYAgO-r;Zg?^d%s7TC:nA!r&TpY<W(!rVup0]KcLBc[u2WrrF,c
+b?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_
+!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24
+s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'
+!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB
+5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+
+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'
+!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`
+!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&
+s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#
+s3(EB5lL``5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``
+5_B$+rrF,cb?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,c
+b?k9'!0[?_!%,l`!?E24s+:9&s0D\'!!%M#s3(EB5lL``5_B$+rrF,cb?k9'!0[?_
+!%,l`!?E24s+:9&s0D\'!!$BF^Aum*rrC*Y^Aote!!#99s.')i*@/g8!A=GrrrM:)
+aT);fb=r!X*J4<Cs+:9Vs1\O7%&h>K!J:Nj!!#'3s.')i*@/g8!A=GrrrTq8;p0%Z
+!%,l`!?E24s+:9&s0D[=!!!nZrr<A?!!"-ns.')i*@/g8!A=GrrrTq8VT[cr!%,l`
+!?E24s+:9&s0DY)$,6H?#L!,IfY.=c.Y@\jrrF,cb?k9'!6bBD^At.Sh#RL&b=r!X
+*J4<Cs+:9Vrr@\d!!!bWrrCrk!!*,!K)_A@!?EH/?NDe[bPqXY!2drq!<=Ii9`Z7T
+K)^H&K)`+U!RZtI^Aph(!!".brrCsT!!%5_^B1s,mt1S/rrF,cb?k9'!6bBD^At.S
+h#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT*@/g8!A=GrrrTq8
+VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+rrF,cb?k9'!6bBD
+^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT*@/g8!A=Gr
+rrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+rrF,cb?k9'
+!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT*@/g8
+!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+rrF,c
+b?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)ps4mVT
+*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XCs+::+
+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NTT7[)p
+s4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT!!&XC
+s+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscbhu*NT
+T7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".brrCsT
+!!&XCs+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-++Nscb
+hu*NTT7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+!!".b
+rrCsT!!&XCs+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i@/^-+
++Nscbhu*NTT7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::Arr?I+
+!!".brrCsT!!&XCs+::+rrF,cb?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s760i
+@/^-++Nscbhu*NTT7[)ps4mVT*@/g8!A=GrrrTq8VT[cr!%,l`!?E24s+:9&s+::H
+rrDNbrr?I+!!"/<rrDNArrD6ZrrCsT!!&YgrrDM>s+::2rrF,cb?k9'!6bBD^At.S
+h#RL&b=r!X*J4<Cs+:9&s7uZr:fsq"rr?I+!!"/?rr^kl+QqJY"0X,.hu<WUhu*NT
+TDnimpRauqK)^H&j8T-#,g0Nq0*'2q!l"`4bM<1!-Hf*a*?Bb3K)^H&K)bZH#L<AM
+(hf8N;>pP#*P\M%0E;)lf`).0!!#96\#90)#CO:A?jH`<kCW_cs5X+[*@/g8!A=Gr
+rrTq8VT[cr!%,l`!?E24s+:9&s+::Grr>md!!*Agf`(rTnGiQ.K)^H&ir9$",g0Nq
+0*'2q!l"`4bM<1!-Hf*a*?Bb3K)^H&K)bWG!7139!-$Nh!&4!E!=7k?s+::1rrF,c
+b?k9'!6bBD^At.Sh#RL&b=r!X*J4<Cs+:9&s7cNn;"O_g#j9e=!3bto!-!PiK)ag0
+!?EH/?NDGQb<Q+_!1_6g!<=Ii9`Z7TK)^H&K)^H&p\t6>oDel1eGfM&o`,!ukCW_c
+s5EtY*@/g8!>baZ0ENL"I*:=H!%,l`!?E2KrrBfcJ"1ug[t=Y#rr>mh!!*AgeGfNP
+o`+u2K)^H&i;Wfu,g0Nq(BDXo!g!D0bM<1!-Hf*a*?CUK!3^tSRK*>kK)`pl!71?=
+!-$Bd!&4-I!=7k?s+::/rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*Ld!.It@Zh!!%M#
+s2Y->;"t"k#j9Y9!3c+s!-!PiK)aa.!?EH/?NCrCbJ41@!.;uG!<=Ii9`Z7TRf<G=
+!!%WNT)Sil!.TV#a8Z.cp](;5d/O)"q#CF$kCW_cs53hW*@/g8!>ba\^]r$0X?`?=
+j3?B\!%,l`!?E2LrrRZM!.t6BrrN0#ItI^?rr>ml!!*Agd/O*Lq#CD6K)^H&hZ!Ts
+,g0Nq(BDt#"O>ren+l\W"T7uamc;mR!<=Ii9`Z7TRf<G=!!%WNT)Sil!.TV#`r?%b
+q>^M7cMmkuqZ$X&kCW_cs5*bV*@/g8!>bag^]VO-l20iI"9%iVhq6`c!%,l`!?E2L
+rrRZM!.t6BrrN0#ItI^>rr>mn!!*AgcMmmJqZ$V8K)^H&h>[Kr,g0Nq(BE4*!lEOQ
+jo5D]oB=oa!<=Ii9`Z7TRf<G=!!%WNT)Sil!.TV#`W#qaqu?_9bl7Ysr;Zj(kCW_c
+s5!\U*@/g8!>bal^]MC0qr%JTr9E(n!<=Ii9`Z7TRf<G=!!%WNT)Sil!.TV#`;]g6
+rVus)kKNr+YPeG$E.\+As4mVT*@/g8!>bam^]E$\pAY9I[srm8r'1BmIt+rZpAY0h
+k2+np!%,l`!?E2LrrRZM!.t6BrrN0#ItI^=rrCCE!!$u\rrb"U!!qb>s+::+rrF,c
+b?k8d!8tWn`pNR$!lodMn,NMTLX5bq!V5.+h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M#
+s24j=:]Ldab5VRI!!$tis+::*rrF,cb?k8d!9(]of_bOF!nV)kl2Ul&Gh;fl!W;->
+h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M#s24j<cN%q*rrOk[kCW_cs4dPS*@/g8!>baq
+^]<QorrKSgj8]3?\,-+)mc*%'!%,l`!?E2LrrRZM!.t6BrrN0#ItI^;rrH6baSu:E
+E.\+As4[JR*@/g8!>bar^]<QprrL_BhuEdKhu!ESo%rH`!<=Ii9`Z7TRf<G=!!%WN
+T)Sil!.Tq,\\A-T`kMM[Y.ju"K)`%S!?EH/?NCrCjhLo6lhg\^GkV1B)eEf*TqT-u
+f*8m]TlOpM'_hY/#`&<W!VP=2h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M2rr^l&5VRci
+U]:N'5Y.7!K)`7Y!?EH/?NCrCk.h#9mJQtbh`1E3!ZPIKnCI`8<ttH1!BA^/rrMfL
+k1p%<-Hf*a*?CUK!e11Mdf0B`L"YMd"6NH,FRK/0biX`]!WW4MPlCgZLF@`SRfEIC
+YCce`rrF,cb?k8d!9_,u_Xm^*!RD>S!!3@2Y3OU>Ti(Xd!>*TTrrD`Sh#RL&b=r!X
+*Ld!0IfKK?rr^q#-"H':"2=g94QHGAL&M&PbjbW849-[)^UjFHUQjojrrN0#J!L$7
+T-4(4"!D9,LP!:>^BD#qIom9\!!+dgK)`C]!?EH/?NCrCkJ.)\r;Qf4&GlG.0=Bro
+!N74>!!*YWr;QcbkM6.=-Hf*a*?CUK!e11MoD\efrVurOk5PO;!!">*rr@cP!!(75
+rrA;]!!,s3^&J4F!!">-ec,[N!.U@8!T,=)!!49^c[u1hrrTZC)#aL98FM01]DhmP
+,g0Nq(BE[7!8.5L!P\p<!!*:Ej4==YAbuH.+Q*+s!9WM$!<=Ii9`Z7TRf<G=!!)Wj
+!'L5\!6jU*"$?P`4QHGAL&M&Pbjk]5L&(cN-$8:brr=AE!!&86rrN0#J!g6>^CUAF
+(nZE[Rf<TdIh2S[.+a(N]`/!Q,g0Nq(BE^8!QtB>rrL^_qu?aT[G]X;W$;->!?gk0
+rrN&Ul.l@?-Hf*a*?CUK!e11MoD\eQrVurBk5PNG!!#.Arr@cP!!(75rr@cJ!!+Bf
+_>aKtrVurOec,[N!.UF:!13Zb!Isiqs-N`hmoTPi&@[8k^&J*R,g0Nq(BE^8!:Tmd
+!Uh0/!!,4/p"'8fTn`J\!f`o#p"'5e./X&G3;<CO!:oC1!<=Ii9`Z7TRf<G=!!)Wj
+!'L5\!6jU*"$?P`4QHGAL&M&Pbjk]5L&M&Q4=0k)!BeTDrr_Cn4L*E9!WW4MRf<Mo
+!!!;&K)_&7"GZsW#g\,&^Ae3S,g0Nq(BEa9!8.5L!+>^)!Bea(f)s0?6Oi_h!uk*l
+d.l2nasd/f!.XqH!9WS&!<=Ii9`Z7TRf<G=!!)Wj!'L5\!6jU*"$?P`4QHGAL&M&P
+bjk]5L&M&SbiXU*qu?aDUQb]Z!!%M<rrg@J!"dJ.s,m<aY5ePFkCW`KrrF,cb?k8d
+!:.E$_YO01!2'/h!Bea)f)j*+%Ia?!%;!]Xf)a#Br;Zj(ci*kDq<Hc:!%,l`!?E2L
+rrRZM!;$3j4T5<\bi\p349,@Ds8TifL!8f]!/:CP!6k!5!/:CP!6kHB!M_dT!!&e]
+rr^q:4O!g)!R/dBrr^qO;;(sK!l'H5p](08!9WhO!WW4MSGr`T(]XiVK)^o3"HNN_
+3;8%)_#FEU,g0Nq(BEd:!8RPQ!V[H0!!+%cq:>Y:'^Pf#)lWSa!Q,BF!!#RfrrD9K
+h#RL&b=r!X*Ld!0IfKK?rr>1\!!(76rrKlEr?VJdk5G;`49,@D@jV'R!@=!*rrJ?H
+r?VJS^\n*3L&M&Pbjk]5L&M&Pbl%J@L&CuP--Z5c!M`Nk,lqN<r;R1&!!#.]YpBAM
+-):Kor?VGtq#:AZ4T6W-;5=$g"&U?jg&D!U49,@Ys)]Rd!!,4+r;Qhn4=0n*!@>#A
+rrN0#J"6N@Du]m)K)^i1")%Z7O+RDIrrF,cb?k8d!:7K%_YO01!0@$X!0m<2!++jh
+!-n=k!-nDA!3cA$!;Ys:!<=Ii9`Z7TRf<G=!!)Wj!'L5\!6k*8!V91b!!+Bfrr2s\
+p&G)&qu6]@4S\sWA,ZE-L&M&Pbjk]5L&M&PbkqD@^ErjZ!'L2Z!SKU4!!+C@rVm!H
+!!"=0qu?aD4So*YL&:lNUF#a:!BeU*rrC:B!!$O.rraVJ!$sc)!!#.[rr?R(!!#.P
+rrN0#J"?TAhZs3YK)^f0"SW`5)#&X^_>aNV,g0Nq(BEg;!8.8M!V[H0!!#C_f)a5c
+q>^U/:k,,8^B:*X:^Hmt!*B!J!%@dG!&4?N!9WY(!<=Ii9`Z7TRf<G=!!)Wj"$?P`
+-1q3<fd6@m"3gfF4S8[SL&M#PjsBa%!2KPn!/:CP!6k!5!/:CP!6k<>!R)kh!!&8_
+rrM7.q#CFAg&D!R,ldoko)Jb:r;Qb,pAb1Urr2uBrVup\rr2sEp&G30s8Skk!!">E
+!!#.PrrN0#J"?TA:]LLAK)^c/"0V\)O+RDJrrF,cb?k8d!:7K$n,<7dO8T%Z#/'ib
+!RNt+!!,'Wp&>*fT-4"2!)`UE!3#eq!5JL4!:oL4!<=Ii9`Z7TRf<G=!!)Wj"!mpI
+-1q3;4T,6e;3[h%!!">-s8P4[!!GEZbfjSr!!+D.rr2sqrW!'IFG5EGrVupqrr2tP
+rVurBnc&TCrVurBq>UGKrVup\rr2s\r;ZmF4=0t,!)`aq!%%LB!'L/Z![V>&rVurB
+rr2tnr;ZpGFKo?T!!$O.rrC:B!!%`Prr=AB!!.2+rW!%Ss8R3?!!d#Xg&J<'!/:"D
+!WW4MT)SoM!!#iIs,$aW0E;rAs2"^9*@/g8!>bb'^];IRrr=bO!!$@%f)T.T!!+4W
+nG`N]&GuM.Er+Af6i?ub;#UCprnd%u!<=Ii9`Z7TRf<G=!!)Wj"!mpI-2%9<L&CuO
+U]18q,ldokrr3*`!!"=0r;Qb,rW!%Bs8Tk5!!PLVs8ThrrVuq.rr2tPrVurBnc&TC
+rVurBq#:OE!!">-s.fMm$^C\kbU!5h-0G7--2[`DL!9Jq"&\4\FT)7?PlC[_-2mlI
+4S/UQL&M&PU]18n^]"35L&V)P-2[`LU]:??!!#mrs'u$.!0mH^!SO7<rrN0#J"HZB
+LB%=hK)^]-",?jV^OlL&rrF,cb?k8d!:@Q%hYmHS^\e'3[JSPUY5A8#+Q)Ve!RD>U
+!!*;,qpth;r;Zj(kPbD\l0[:-!%,l`!?E2LrrRZM!;$3m,ldokp&>"<rVuq_rVlsG
+!!#.\rrY@`!'L,X"sj6L4TGFkrW!&8s.`Hh!!'e5rr@cP!!(75rr@cP!!(7<rr>1\
+!!:CE;>pOqFT)4>FT)7BU]:??r;Zn`s31HB!'L8\!6kEB",6dTPl:X_4T59[L&M&P
+bl7VBL&M&PL&V)P-2dfDFT2:E,ldp-s8Skm!!,3WmJd4f!.UU?!^H_sK)^Z,"5a(Y
+BS-9$rrF,cb?k8d!:@Q%n,<7d@/U'*0Da9#0DtkO&D-dY#5R`J^Y\\_qYpT2#lO`'
+./MNq'`A"3L].5Qo'P66!%,l`!?E2LrrRZM!;$3m,ldokpAY-:rVup\r;QjF!!#.\
+rrY@`!'L,X$TnCh-3*uk!!"=!4T#0[-):G=!/:CP!6k!5!/:CP!6k6<!'L5\#0d)n
+!!">-rVllArW!%Ss8ODE!!?a2s4RAO!'L8\!87>O"$HV`4T5<\Z2O\&L&M&Pbl7VB
+L&M&PL&V)P-2mlE-3!oIjs:!-4T>?\A,H<-4JVBF!WW4MTDo#^!!$DYs+gUU2uk@Y
+s2+d:*@/g8!>bb(^];=Nrr<W/!!%cNf)VuO!!'5#rs\_YaM>TQ!.<VYipZjDrrA,X
+!!'2!f)TUb!!"_OrrE#bh#RL&b=r!X*Ld!0IfKK?rrXPI!%%@=!/:CP!/:@N"!mpI
+4T>?_49,@DqYpa^!!">Fs!@I@!@<Hsrr@cP!!(75rr@cP!!(7<rr>1\!!UU/,ldok
+r;Qc@rW!.Vs8OAF!%%UD"!mpI4T59d,ldp-s8OAF!%%RC!/:CP!6kHB!/:CP!/:FP
+!%%UE!+Z$.!6kEB!'L5[!H]Xc!!,sZnc&Xj!.UX@"4$rIYCce0rrRZM!.t6frrF,c
+b?k8d!:IW&eG]CI^\n-5#138!!(6\b!*K1!!U%>u^]KStI/Vk%i:[$J!&4?O!(6Y8
+!5/40!8mbT!93G&!<=Ii9`Z7TRf<G=!!)Wj"!mpI4SJdTL&M&PL&CrQ,ldp-rr3'_
+!!#.XrrtRc!%%[F-2RZC-&)0p!/:CP!6k!5!/:CP!6k6<"XO-K-3)3g!!#.ZrrC:B
+!!\/Ws!7XF-2miG,ldp-rVm0M!!">Fs!7XF-2dcCL&M&Pbl7VBL&M&SL&_1sr;Zi4
+rr2uBrVup\r;Qi\@jV'R!@?FirrN0#J"Q`C[f?ESeGfS[4L+SZ!jOkAW;ck[n,NC2
+"2@\qg&(dOk#"7UqYpZN4=,^-rr\kn!9\t6_uB`X,g0Nq(BEm=!9!hU!/LLQ!&+6$
+!Q,-?!!(@DrrMZ,r4iAq!.=_#!T*\OrrB8#!!'G(f)QN`!!&qqrrD<Oh#RL&b=r!X
+*Ld!0IfKK@rrC:B!!#.TrrA;_!!%`NrrY@`!'L8\"$?P`4T#-`fd-Uu4TGF-r;Zj\
+U\FcgL&M&Pbjk]5A,ZH.bk_8=L&M&V4TGF-!!">CrrAhn!!]4us!7XF-2miG,ldok
+rVm0d!!">-s!7XF-2dcC^]"35bl7VBL&M&SL&_1srVusFk5PA\bl.SB4Sf!XKdH]u
+!)`=e!WW4MTDo"c!!)34rr?R.!!%`IrrAhn!!&dorrR9B4S/RSk$o_7!!#mnrrY@`
+!%%LA!'L5\!5Hn\"1J71c[u27rrF,cb?k8d!:IW&li$h`=T&4"?Mi=SGl7UB;#L=n
+bko0WO8s\*h#Q[:rr=bO!!%9@f)S2:!!%9BrrDQVh#RL&b=r!X*Ld!0IfKK@rrC:B
+!!#.Xrrh#/U]8R;!!#.ZrrY@`!%%XE"$?P`4T,3[o0!!P#F,8g,ldokU\k&mk*2,0
+rr@cP!!(75rr>1\!!(7>rrAhm!!B"rs!@XE!5JL4$9S:g-0G7-,ldokrVls^!!">D
+rr>1\!!:CE4T5<\^]"04bl.SBL&V)PL&M&SL&_1srVupEr;QjF!!">?rrgOl!!">9
+rrN0#J"Q`BIfKJurr>pp!!&8ZrrAhm!!&7arrAhn!!&8VrrJl@q#CC@r;Qblr;Zhm
+r;QcMr;Zh-d/O3g!!'ccs24j;*@/g8!>bb(^]=!)rr=bO!!&#Uf)Rr3!!'5$rrDB]
+^]KStI/;Y!q>L<nO8T%Y;>\rFEr>t<;#UCoo^:N9!%,l`!?E2LrrRZM!;-9kbl.SB
+FT2:Bb`ksNrW!"Rs!@XE!0mK_!L+o0!!B"rs#g8\"XS9*b]G01!!#.\rr@cP!"C6.
+g&M)rF<pneU]:@JrVurBnc&SOrVuqnqu6YMr;Zg[rr2tPrW!'IUWgJ8rVupqrr3'H
+!!">Drr>1\!!(7Brr@0?!!8qqPl:Xd4Qc\Dfhq_K!'L8\!/:CP",6dTbl.SB-2dcL
+,ldoks8R1'FMIhT"MZ5_!%%49!WW4MTDntB!$Kek!SJdt!!'e2rrL=irVup\X8`4R
+-2mlEA+op&U\=`g-2dcC;>gIp;>gFoPl1R^-.)YohZ*YkK)`ag!?EH/?NCrCm_Ai"
+rVlj'r;Zi*r7:tr#5nN%hu3QTde^`\O8s\)h#Qd>rrBh4!!"5?f)V<=!!"GGrrDl_
+h#RL&b=r!X*Ld!0IfKK@rrBh5!!=N0,piBf!^-Kmr;ZmF4=0n*"&]*u4S8[S^]"04
+-2[`D,piHh"2Fm9L&M&Pbjk]54T,6[-2fq+-2dfE-/&7s!%%C?!@?FurrXPI!%%UD
+!-J2?!6kHB!/:CP",6d;-2mlG,s3LN!!C"9s+UFP",6dTbl.SB-2dcC4T5<]bfp"c
+r[%LC!)`=e!WW4MTDntB!$Kbj!R)kh!!+D;r;QaZrVusFk,\L^4T,6[4SSjUU\k)n
+;2',k!!">Crr=AD!!">Crr>pp!!"=lrr_-Y!5F-c_uB`X,g0Nq(BEp>!65!;!8%,K
+!7:Yq!3#hr!#YY6!6"`L!g!D0qV;/1rVlllqu?`Dr7:qVqu?`krr2usmbImD-Hf*a
+*?CUK!e11Mo`"odo)Jlts8P4S!!:jR4SJgV-*dCJ!R*\#!!$O.rr@cP!!(75rr?R$
+!!+Cir;Qf4-2@N@U](2p49,@-rVlkOrVuqnrr2u5rW!%1s8Ske!!?*us-3K_#DN3X
+js:!-4T,3Z;>pOsbiU5H!!+D!o)Aak!.UX@!e11mdf0<^r;Zg[rVlk-rVusFbcCaD
+L&:oN-2@K@bU*5g!@>M[rrZa2!'L5[!Tk^,!!">Crr=AC!!(6jrr_-Y!5F-c_uB`X
+,g0Nq(BEp>!6G-=!5JI4!#5=^!0-pW!(d(g!;60'!g!D0q:u&JrVljGr;Zi#r7:qq
+qu?`SrVu<A!<=Ii9`Z7TRf<G=!!)Zk!Tk^'!!=MnA(gh\!FmGS!":/`PU-;Uk5V\4
+,s3LP!!4HVk5##XKdHWs![U^KrVlu)!!#.MrrGtCpAb4Vg%t^LbWPe'!BdXbrr[rT
+!)`^p!/:CP!/:FP!87>O!)`aq!O4cb!!PK[49,@krr3'_!%$e,rrXPI!)`[o!0mH_
+"53^h4So*[,uN@crrN0#J"Q`BIfLV=rrA;^!!?a2s+UCO!0ljM"5-OKg&D!Q^P0nS
+rrLe!qZ$W?q>UFWrVusFbl%JBFCX#&rrBh2!!(7BrrCaL!!'d]rr_-Y!5F-c_uB`X
+,g0Nq(BEp>!7(QC!5JI4!%@`r!-8#<!-nJB!9a0n!g!D0q:u&ErVlj_r;ZhkqptfW
+r;ZiTrVu<A!<=Ii9`Z7TRf<G=!!)Wj!O4cc,m6>-KtldGrrhJZKnZ<$rrUl-^]"06
+k5YJ[bk1o<g!#/7bk_8>g!&g_"I)"p,lmoj!Frn<rrBh5K`Jm`rrLfsr;Qc3rVurO
+rVltA,s9lYrrC:BK`Kg*rrJ@Kr;Qc@r;Qi54Ce6f!b4?trVllNrIk9Ik3r<O!!%M@
+rrRZM+OL,gA,QB.KtmQd!)`Ok!L,_F,lqMjr;Qs`!!#mrF=$nd!BeTlrrP;/;<@fX
+4T5<\-2mlEPktC[FT)7@--Z#]!/::M!/:FP!/::M!/8i#"5a(Y^OlL'rrF,cb?k8d
+!:R]'d/EtE^\n-42>bu*C]+55J,TBIi;(.iO8s\(h#R0Irr>=_!!&_if)Qcg!!(pT
+s6e\D!%,l`!?E2LrrRZM!1*Wck02W\!l'H([/U1-!.UX@!e11mci3u-r;ZgDrVusF
+oD8IfbWP\$!+Z!-"=4$J,s;&)!'KWJ!0mH_!6jX+!/:CP!Bc)8!!$O+rrM7.rVuq_
+oD\eQqZ$V+rr2s\qZ$V+dJj=+!!'ccs24j;*@/g8!>bb)^];a[rrBh4!!"nRf)TUb
+!!%NIrrD!Q^]KStI/2RupAP!k5lCZ_U&3FA)uTa:hu3TCh#RL&b=r!X*Ld!0IfKJ#
+s.95l!!%M@rrRZM+O9ue4Sf$X^\[s2jsBa%!2KPn!%%==!5Iq$!/:CP!6j[,!Tk^-
+!!0@KrVupEqu6Y+rVupqo)A\9qZ$aFs8V4-qZ$UYdJj=+!!'ccs24j;*@/g8!>bb)
+^];a[rrBh4!!"nRf)TUb!!%NIrrD!Q^]KStI/2RupAP!k5lCZ_U&3FA)uTa:hu3TC
+h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+O9ufbU*/e!0m<Z!)`^q"=8/DKi.gL
+!)`aq!%%LB!HaS*!!%`?rr@cP!!(7,rr>pq!!Z=#s!7XF-2[]B-2mlE^[qI*g%k[N
+-3+"0rW!'`,ldokdJj=+!!'ccs24j;*@/g8!>bb,^]W$Cn+6MX!5JI4!&aZ*!,MN5
+!.XtI!;H<X!oq&Pq=XgerVlj_r;Zhkqptfer;ZiTrVlunoBYE,h#RL&b=r!X*Ld!0
+IfKJ#s.95l!!%M@rrRZM+O0od;>gIp4Sf!W^]"3:4S/UQ^HDJq!+Z$.!%%OC#,D4u
+,ldpBnc&T2r?_FCr?VGcmJd0krW!'Ik5YHDrVur5rVlkmrVup\o)A]SrVus]4T5<^
+^]-Fq!!/<HrVurOdf0F,!!'ccs24j;*@/g8!>bb.^]DaRq>UH0r;ZgTqptg`r;ZhI
+jSo3Fr;Zhkqptfer;ZiTq>UKfj7M..!%,l`!?E2LrrRZM!.t6BrrN0#J"Q`BIfLV:
+rr?R+!!';#rr?R.!!C"9UJ^ph!5JO5!%%RD!-J5?"!mpI4S&LQjsB[#!6jm2!'L5\
+"B!BsKdH]u!/:CO!+Z!.!0m'S!'L5\!L.^*!!dW.,ldoks'u$.!2J!B"5a(Y^OlL'
+rrF,cb?k8d!;=2/_WU[n!5JI4!&aZ*!,MN5!.X)0!'pJ_!29;A!#tk:!8mPN!:BI8
+!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@!e11mci4!!q>^OBoDAOk,ldokKfo85!@=N>
+rr=AE!!">ErrhI1!!#.Orr>1T!!">6rrM7lo`+tSrVlj[rVurBo)A\9rVuuP^]"36
+4I#gF!`Au^rVuq.df0F,!!'ccs24j;*@/g8!>bb0^]<]orrBh4!!"nRf)TUb!!%N0
+rr>=_!!&_if)Qcg!!(pMrrM`JpY>iM-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$KYg
+!2KJm!B_\-!!#mnrr=A@!!+C"qu6XBrVuq.rr2uBrVup\nG`U7KnX%9!!K(@b_>3J
+rr>1R!!">Drr>1\!!(77rrBh5!!ahMs!7XF,piNj!i,e>rVupEdf0F,!!'ccs24j;
+*@/g8!>bb1^]<*]rrBh4!!"nRf)TUb!!%N0rr>=_!!&_if)Qcg!!(pLrrDZbh#RL&
+b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+OU2hU\t/o-1eD?!!&8]rr=AB!!+C"qYpQ>
+r;Zi4rr2uBrVup\mJd0?rVurBli-rIquH[A!B_\-!!(7Brr>1\!!'e0rrSsL^]+65
+A,ZH1;?-YYqZ$UBrr3*I!!">-e,KO-!!'ccs24j;*@/g8!>bb2^]DIRr;QeQ+LV7O
+5aV6CrrD-Th#RL&b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+O^8jbU*5g"=;:ls'u$.
+!@>tgrr=AD!!,3Wq#:?<rVusFk5PA\bl.SB4RN.KL&M&Pg$J_=^\n-5UWiZ9!+Z!.
+!/:FP!-J2?!)`Xn#j+ta!%$e-s!@XE"-iicFSc%<A,cK.4T5<\UXT5FhZ*YkK)`ag
+!?EH/?NCrCpqQmirVlom33iMb0^nu?!;6-C!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@
+!e11me,KHm-2mlF--Z>f!'L5\!'L5["=4$J-):A;"m2&6s8U=B!!">CrrXPI!%%%4
+"0hh+-0tR2;>pOq4So'X^]"354T>?\g&1mNA,ZE.KdHZt"3gf--2mlHbl@^rqZ$W2
+rr2tPrVupqe,KO-!!'ccs24j;*@/g8!>bb2^]=91rr?H2!!#:_rrN,Vq:u&O-Hf*a
+*?FVK!8"@Q!e11MK)_GB!WW4MnG`L?Z2XlT!$Kek!R)kg!!';%rrBh4!!#mqrr@cP
+!":0-g&M)rF<pneU]8R;!!">CrrXPI!%%"3!l'HOm/I+K-2mlEU\Xoi-2mlEg&D!O
+A,QB0,s4:9qu?g]s8U=B!!">Drr=AD!!">DrrBh5!!"=orr_-Y!5F-c_uB`X,g0Nq
+(BF9H!6kEA!8"@R!8mbT!9a16!<=Ii9`Z7Tnc&Z_+LeKQ!e11MK)_GB!WW4Mo)Acp
+0UK'E!e11mec,[4-2dfDU\aujL&CuOA,cK.-2[`D,piHh!l+cZrVupEr;QaZrVurB
+ec,VkrVup\q#:>9rVuq?rVlj[p&G)&rr2tPrVupErVlk-r;Zh-r;QaCrVurBeGfX.
+!!'ccs24j;*@/g8!>bb3^]<$crr@<B!!#!gIfL>a!!'5$rrD?[h#RL&b=r!X*V9:5
+T-++NXT&?O!!("<!-J2d"$A\f^OlLFrrN0#J+WaDY:oq^n$2loIfLVArr@cO!!&eh
+rr>1[!!M!Ts3*V"!!d$6s5kU-!'L2Z!)`^q!6j!n!)`^q!2K>h"Qh!1!'L2Z!'L&W
+!BdXcrr@cP!!#.[rrBh4!!'e3rr>1\!!%`&rr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M
+!+>a*!2$e$!+>a*!2'5i!:'C9!<=Ii9`Z7Tp&>&b+T;?@E30'@IfKJgrrAhi!!+C1
+K)ap3!WW4MpAY/s0`D%P:pBs$IfLVArrA;_!!&efrr>1\!!(^NrrIg"qu?dE;6g*"
+"!mpI;>gFoPl:X_g"$*)ffUQjpAY5i,pg>'rrJlWr?VJAU\k&k^]"35U\t,o49,A'
+qu6YMrVuq_eGfX.!!'ccs24j;*@/g8!>bb3^]<$crr?I*!!&YjrrMB.]u9tDr;Zhi
+rVll_q:u&O-Hf*a*?FnS!M:M4!!(?HrrRZM!65$=L%bQJ4P>>dk5PJ_!.XeD!O"3T
+!!'4,rrRZM+OpDmKfl.'rr_ji-&)3q"PM"QPg'"(!l$j-qYpV,4L)j)!9WSH!i&Vf
+qYpSkbk_8?F<tGGrr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M!+>a*"/#Vn`Oh'/2#RCS
+TDecilM96:!%,l`!?E3VrrJ`7qZ$U5X8`6N!!(%=!/:CP!@9&h!!+C@K)b$6!WW4M
+qYpT"0_tbLpTXZ!IfLUCs+^OUhZ*YkK)`ag!?EH/?NCrCq7m!_rVlk*r;Zqls7_Sd
+MuY^5!!&YirrD?[h#RL&b=r!X*W,j;T-3q0!'mUb!e11M`r?$mrW!)Fs3-]iqu?`3
+K)b'7!WW4Mr;Qf$0_k\K+KteHIfLUCs+^OUhZ*YkK)`ag!?EH/?NCrCq7m!_rVlk*
+r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7TrVlnj+SPj9@&s;/IfKJgrr@cP!!(7A
+rrJ?1rVupEK)b'7!WW4Mrr3#&0_YPI5d11hIfLUCs+^OUhZ*YkK)`ag!?EH/?NCrC
+q7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9a)OXs8S]6RfLJ.!/:CP!6kB@
+!R)kh!!&8Js8:(@k3`0Lbi\d%!R0^"rrLg+q#:EKbfo2Kr6,0'ir9/^!.Y$P0Ve[O
+0W0C#+G0WJrr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M!+>a*!h]M^\r6VGr;ZhirVll_
+q:u&O-Hf*c*?CapR/l+D!^%c+m/I'>rVurBqu6Y\rVup\qu6]3A,R\S4I#^B!i%k(
+qu?aDZ2=P%UJ_":!Ft9irrXPI-/&4r&L@E'Z2aj!,s9l\UHBh&!'Js4rrKAerW!!G
+;8;u-!P`.C,lp,mqYpVl4=0n*!@>#2rrW6$="p9I!cn>aK)^T*"5a(Y^OlL'rrF,c
+b?k8d!;XD1f_tgM@/U',TE"DlMuY^5!!&YirrD?[h#RL&b=r$Y&eLE1hu<\@rVurB
+mJd/`rVurBqYpXD!!#.Zrr@0:!!+CirVlk-p](:VrVloO4So*Z-):J>!2KMn!/:CO
+!6kEB#DN3X,ldpB4So*Y;>pLpU\OliA,Q?,FSPn;--Z>f!+Yd(!'K<A!WW3/T)\pk
+!$HmnLAqA5!!'ccs24j;*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:
+!%,l`"<ANOIh8%Khu<\1rVurBmJd/KrVurBqu6Y+rVup\rVlk>pAb1Urr2tnqZ$UB
+rVup\rr3#]-2@ND-/&=uL&M&PL&M#OL&M&SL&_0!pAb1>rr2u'pAb3;rr2t?pAb1U
+rr2tnqZ$UBrVup\j8T5^!.0bDU&Y9,HN51?s+^OUhZ*YkK)`ag!?EH/?NCrCq7m!_
+rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9a2UYs8VP;&G?)(33.N156(]@rr@cP
+!!(71rr>1\!!(7ArrM7lr;Zh>rr2u5r;ZstKnXUprW!&Rs8R3?!!d#Xg&J<'!/:FP
+!'L2[![TrTrW!$ts8Psq!!&emrr@cP!!@rTs!@RC"XRY)!!">Err=AE!"*5[b]G-2
+!87DP^\n-8;2'^G-2mlHg&M(orW!15bh<$$,liYZrrrH'J,f8()"mq0.'\7)Qfihu
++G0WJrr_-Y!5F-c_uB`X,g0Nq(BF9H!8.8M!+>a*!h]M^\r6VGr;ZhirVll_q:u&O
+-Hf*a*?G+Y!q1UMp](:rX8`6N!!)'Z!-J/crW)mC!-Ic2!'L5\"a#HP@lu(9!!+D;
+rr2sqrVuq_rr2tPrW!'Ik5YHkrVuq_rVloOU]18nU\t0"PlLd-,ldokk5RRC!!(7A
+rr@cP!!@rTs!@UD$&/EZ49,@-s8RfP!!#mprrUl-^]+65;>pOqPlC[_L&M&T-0G7-
+A,ZH.Pl:U_fq[R,!WW4Mrr3&oNu7Wl!'%1^!e11mK)^T*"5a(Y^OlL'rrF,cb?k8d
+!;XD1f_tgM@/U',TE"DlMuY^5!!&YirrD?[h#RL&b=r!X*W,j<msboF!!#!ZrrRZM
+!9F.\jsB[#!6k$6!'KoS!@>thrs7a5!!#mrk&_pJ!!#mqrrAhm!!,3WqYpOmrVuq?
+rVlk>rW!"ps#g8\!6kEA!/:CP",6dT-2mlEPlC[i@fQKks8OAF!%$e&rs7a5!!#mr
+k&_pJ!!#mqrrAhm!!,3WhZ!WW!.XqH!r%`mq>^L4YQ"ZR!$HmnLAqA5!!'ccs24j;
+*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E3VrrVY=&GuM/
+&GN:+!e11Mj8T*Ap&G(=nc&SOpAb7@A*3ai!2KMn!d%ouqu?^or;Qb,qu?a[U\t,p
+,ldokk5G;[bl.SDL&X:7!!(7Arr@cP!!^4<s!7XF4T,3^@o:qZU](5nFSGe8U](5p
+FCQWp!!#morr?R,!!,3Wi;WiY!.XkF!r%`mqZ$WZYl=cS!$HmnLAqA5!!'ccs24j;
+*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E3TrrVY=&H)S/
+YH7a*IfKK.rr^K!Kk()^"Ja2bL$%q*!'L#V!@>#Jrr@cJ!!,s3qYpS<-2[`K;<IoY
+js:!--2dcCbl.SDL&X:7!!(7Arr@cP!!^[Is!7XF4S\pVA,ZH.g%YLHL%kWK;8;u-
+!H]Xc!!,sZir9&[!.XeD!r%`mr;ZhYYl=cS!$K\h!R.><K`Rt2lMgs?,s9D's4I>R
+hZ*YkK)`ag!?EH/?NCrCq7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7T
+p&>3aIh2S[:osZuIfKK+rr@cP!!(71rr>1\!!">B!!+Bfr;QbNqZ$[D;8;l*!p3u=
+r;ZpGg&K:q!!#.ZrrC:B!!7lSFT)7?bl.PAL&M&Vbl@\h!!#.VrrY@`!%%@=!/::M
+![U^Yp\t<W@jV'R!@?FZrrN0#J+imGpQ$-k!&1YW!e11mdf0;EqZ$[D;8;Jt"!mpI
+4T,3\k(UR7rrTrhg!Tg%hZ*YkK)`ag!?EH/?NCrCq7m!_rVlkBr;Zmq^U1Rc!$D.>
+!2oeq!:'C9!<=Ii9`Z7ToD\s^Ih2nSXoAHP!!(pV!/:CP!86c>!'L5\"52@;-2[`D
+4PB`6!/:@O![V@=o)A`E-2mlK;?-YB!!">CrrAhn!!8qqL&M&P^]"04L&M&Vbl@\h
+!!#.VrrY@`!%%@=!/:@O![V@=o)A`E-2mlE;<.ZX!!%N@rri(W(]`0mrrRZM+Og>k
+jsBd&!-IW."!mpI4T59_fd-UuFI)q,Pl:X_Z-rXShZ*YkK)`ag!?EH/?NCrCq7m!Y
+rVllDXoJIJrVllYq:u&O-Hf*a*?F\M!q1W:XoAHP!!(pV"0hh+-1(X34T5<abl@_*
+@jV'R"=:>Qs.fPn!'L,X!l'HBq#:TC,ldoks8ODE!!'e4rrtRc!%$e-Pl:X_L&M#O
+L&M&Vbl@\h!!#.Vrr@0?!!&ekrrgR!s8Skn!!#.XrrTrhg%bRMbU!5h-0,",!!%N>
+rrVqUO0S]dIfLV?rrC::!!$NsrrXPI!'L5[!/:CP!%!s2!'L5\!)_2E"5a(Y^OlL'
+rrF,cb?k8d!;XD2_YsH5!'mag!$M4>!9!\/!<=Ii9`Z7TRf<G=!!(mU!l'HOm/I&J
+rVurBrVloO4T#0]^]4<[rW!I+^]4>rUJV!k4TGG'4ES@;rs-:b!!">Fs+UFP"=9he
+^HDJq"&]*ubl.SG4MT+TKfo>7#0d,I,ldp-q#:?/rVusFPlC[fUHAMVZ2ahMrW!I+
+^]4>rUJV!k4TGG'4ES@;rrg(_!!">*rrN0#J"Q`BIfLV?rrC:B!!IDfbbI<!!!':m
+rrXPI!'L5[!2KMn!)]'^!+Z!.!0kq3"5a(Y^OlL'rrF,cb?k8d!;O>0j8JuYh[$Lf
+!>+/errD]dh#RL&b=r!X*Ld!0IfKJgrr>1\!!(7?rr?R-!!>@`s+U@Nr[%LC!^-M,
+r;cgCr;Zgprr2sEp](=@g&D!O-2%<CPlLb0!!#.Urr>pp!<+;C!!@rTs+U@Nr[%LC
+!^-M,r;cgCr;Zgpj8T/\!.UX@!e11me,KElrVuqPrVlk-rVup\n,EJ9!!#.ZrrSrX
+A!HupKfk(:rr_-Y!5F-c_uB`X,g0Nq(BF6G!6kB@!S9<=!!3F.fDPXKj7qF2!%,l`
+!?E2LrrRZM!65$=4T5<\bkh>>U](5n4T>?\FS>b<--ZDO-27H@-/&:t!P]rV!!&em
+rr@07!!\/Ws!7XF4SJdT4SSmW-/&:t!-Ir8"=;:ljsBd&!@?FZrrN0#J"Q`BIfLV?
+rrA;_!!%`NrrY@`!%%+6"!mpI4G*Ucrr_-Y!5F-c_uB`X,g0Nq(BF3F!9O+X!T-HH
+!!@G[^UM1U!+c$.!I+#0rrDQ_h#RL&b=r!X*Ld!0IfKJgrr]MP!'L&V"0jsNbl.PC
+^JQ<T!!4HgoD\aj^HDAn![U^sr;QfA4T#0[4L+e`!H]Xc!!">E!!\\fs!7XFFS5Y7
+F=$hb!@<HsrrTr4-2[`E-$8bXrrKksqZ$[D;;'t/!WW4MTDntB!$Kbj!/:CP!5JI3
+"$?P`-1Cj9,ldp-nG`R6bi[LV!TqW(rrLfsqYpTLbl.PCKfk(grr^r=UZVLS!jOjt
+rr3)_UQjI'rrQ[mZ2Xb)b_<ggrr_-Y!5F-c_uB`X,g0Nq(BF3F!Q+O,rr?I*!!Akn
+s7F:^!/CFP!2'/g!;-!@!<=Ii9`Z7TRf<G=!!("<!TqVmrrgQ@Ktl=:rrCaNK`Rt2
+q#:?/re1?ep\tN6KnZ;Ts)]Psrr3&7;0;C/"J^ZJKtm?]"O*Wp^Y/G_!87=)!Mef8
+rrN0#J"Q`BIfLVWrrZaW4Qc&2!/:CP!6kB@"!mpI-2dcIk&`^3,s7t"rrXPI!'L5[
+"2?-.A,?30@jM*T,pe9DrrQ%DFSYq=YpC]koD]EU4=-d&^JQ:'!%"E?s+LFQA,Q?2
+K`D*8s8Skn!!9pZ4T5<]-$9.d#Nd<4!/:#A-2mlE;>gFrKdA%?rr314!!">FUF#m>
+!@=N:rrJm:r]C48k3r<PhZ*YkK)`ag!?EH/?NCrCp:p^Op&+gi@/U'-TE"r``Rb*E
+r;Zhir;Qcdp"]WK-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$LY.!87>O!/9h?!/:CP
+!6kEA!-J2?!)`^p!JMis!!#.ZrrXPI!'L5["?ZYa-0G.*!'L)X"!u1kA,ZH.Z24J&
+,ldokoD\qj!!"<BqZ$gHs8OAF!%%RC#!;kc-3+"!rVus]-2RZEU]:A<rVusF-2RZB
+A,ZE0,ldokrr2s\rVup\qZ$XCk5>5[KdHTr!@<Hhrr_-Y!5F-c_uB`X,g0Nq(BF*C
+!:0U`!+>a*"/#VnoYoD^LA_)PTDecimI]38!%,l`!?E2LrrRZM!.t6BrrN0#J"Q`B
+IfLVXrrC:B!!%`?rr@cP!!LOGs4Lo\!!'e5rr@09!!$O-rrXPI!'L5[!'L5\!6kEA
+!'L#V!^-L)rVusFoDJUgL&M&P4S/RQ4SAaYbl8sh!%%RC"sj6L-3+"!p&G1Ws8U=:
+!!">DrrXPI!%%XE!'KrT!-J2>!'KuU!'KfO"5a(Y^OlL'rrF,cb?k8d!;+&,kPbD\
+@/U'-TE"r``Rb*Er;ZhirVll_o\BNJ-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$LY.
+!6kEB!/9h?!'L5\!^&Rkqu?_,rr2u'r;ZmF4=0q+!5JO5"!mpI4T59^49,@-rVlkO
+rW!9OUWfJq!!#mrjsC!,!+Ys,!%%UE!2K/c!'L/Z![U]@rVuuCg&:sO-2dcI,ldok
+s8RfM!!k]^49,@-s8U=?!!4I2A,ZH.bl7VE,ldp-rr2s\qZ$e0UEom?4T>?\4T,6^
+4GAJdrVupEnc&^K!!'ccs24j;*@/g8!>bb.^]<Qrrr?I*!!@G[^UM1U!+l*/!2'5i
+!:'44!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@!e11mnG`Na4T6Z+!<"2D;=XYd4SJgU
+A,ZE-4T5<`4Qc\DA,ZH.A,cK1,ldp-rVls^!!">Drr=AE!!'e4rrJ@Krr2tPr;Zi4
+rr2tPrVupEo)A\Pr;Zq0oDaOD!!1<frVup\r;QsI!!">Fs+U@N"$HV`L&M&Rg&K:o
+!!=Oks31HB!0mK_"!mpI4T>?\4T#0cA,lQk!!">Fs-3K_!@>MZrrXPI!%%18"5a(Y
+^OlL'rrF,cb?k8d!;+&,kPbD\@(61:TDecilL`m5!%,l`!?E2LrrRZM!.t6BrrN0#
+J"Q`BIfLV\rr=A<!!%`Drr>1W!!+C1rVllNrVusFk5G;^,ldokrr3'H!!#.[rrXPI
+!%%XE!/:CP!-Ir7!'L5\!)`aq!%%UE!/:"D!'L5\!+Z$."eu%t-0EGN!!#.ZrrsbL
+!%%[FL&CuS-0G7-L&M&Rbl>ob!!BM+s31HB",6dTbl.SB4T>?\4T,6[4T>?b49,@-
+s8ODE!!'e3rrXPI!%%18"5a(Y^OlL'rrF,cb?k8d!;+&,kPbD\@(61:TDecilL`m5
+!%,l`!?E2LrrRZM!.t6BrrN0#J"Q`BIfLV\rr@06!!'e)rr>1\!<,(]A#&r$!/:CP
+!+Ys,"$?P`-3!oH,ldp-rVlsG!!">ErrXPI!%%=<!3uJ&!l+bhrVupEnc&_S!!">:
+rVm"S4L+q1rVup\r;QsI!!#.]s+UCO!/:FP!+Z!.!mL\gr;Zgprr2tnrW!%Ss8U=B
+!!#.\rr>1[!!'e5rrj\K!%%ZurVup\r;Qo^,ldp-nc&^K!!'ccs24j;*@/g8!>bb.
+^]<Qrrr?I*!!Akns7F:^!/CFP!2'5i!:'44!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@
+!e11mn,ELCP_Fhj!!IDfb`om4rrY@`!%%@=!+Z!.!2KJl"$?P`-3!oH,ldp-rVm3N
+!!">Fs5kU-!)`Cg!)`^q!^-K/rVuqPnc&\R!!">?rrC:B!!#.ZrrsbL!'L;]L&M&Q
+-0G4,!'L5\!mL\gr;Zhmrr2tPrW!%Ss8U=B!!#.\rr>1\!!">Drrj\K!%%Z?rVuqP
+r;Qc@xxxxxxx&^K!!'ccs24j;*@/g8!>bb.^]<Qrrr?I*!!Akns7F:^!/CFP!2'5i
+!:'44!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UX@!e11mm/I(0rVuqPmJd87!!#.Trr>1\
+!!(7@rrY@`!%%XE"!mpI4T59a,ldoks8U=B!!%`FrrBh4!!#mq!!">7rrY@`!%%C>
+"!mpI4T,3`,ldp-s8P4\!!#.[rr>1\!!:CEL&M&P-2miDL&M&SL&_1srVup\rr2sE
+rVuq?rVm$I!!">FL&M&PL&CrNL&M&PL%50FhZ*YkK)`ag!?EH/?NCrCoY:IirVlk*
+r;Zqls8V`1f)UR(!!&YirrD?Vh#RL&b=r!X*Ld!0IfKJ#s.95l!!%M@rrRZM+RK+.
+bl.SBPjSJQ,ldp-pAY,HrVuqnr;QjF!!">ErrXPI!'L5["sj6L-3+"hrVuqPoD\f#
+q>^MLnG`SQ!!">>rrXPI!'L2Z"sj6L4TGFDrVuq.rVlj[rW!#Ds+UFP!%%UD!/:CP
+",6dTbl.SB4T>?\-2mlEU](2r,ldoks+UFP!/:@N!'L5\!2K)a"5a(Y^OlL'rrF,c
+b?k8d!;+&,kPbD\@/U'-TE"r``Rb*Er;ZhirVll_o\BNJ-Hf*a*?CUK!e11MK)_GB
+!WW4MTDntB!$LY."Qh!1!86c>"!mpI4SJdTU](5n;>pLpPl:X_A,cK1,ldp-rVlsG
+!!">ErrXPI!'L/Y!TqW'rrM7.qu?^Cn,EJP!!">>rrXPI!%%RC"sj6L4TGFDrVuqP
+rVlkOrW!"as+UFP!'L5[!6kEB"&]*ubl.SB4T>?\-2mlEbl.PA4T5<]ft[Ld!+Z!-
+!0mE^!6k!5"5a(Y^OlL'rrF,cb?k8d!;+&,kPbD\@/U'-TE"r``Rb*Er;ZhirVll_
+o\BNJ-Hf*a*?CUK!e11MK)_GB!WW4MTDntB!$LV-!p53Om/I/6!!#.Srr=AE!!?`T
+b_>uq!5JO5"!mpI4T59^,ldokrr2sqrW!4$g&M*7@jM+;qu6Y+qu?_Nn,EJP!!">>
+rr>1\!!J#"b`m5K!!>@`s#g8\!/:CO!/:CP!d+HrrVup\rVllArW!$_s8U=B!!#.\
+rr=AE!!(7Arr>1\!"$F?,ldok^]4=uqu?`@nc&^K!!'ccs24j;*@/g8!>bb.^]<Qr
+rr?I*!!Akns7F:^!/CFP!2'5i!:'44!<=Ii9`Z7TRf<G=!!(^P!P_M1,lqN<jo5>P
+rr3"/;;M6Rjuh>orrg)64?S>jrrM8(r]C1Fo)Acr4I#aC"MZ89s7?)@!5I7f!WW4M
+TDntB!$Kbj"!mpI4SA^SL%bQIA,ZE0,ldp-rVlsG!!">ErrBh3!<+;D!!">BrrM^;
+rVusFk3r<P49,@-p\t58p&G1@s8P4\!!&8^rrC:B!!5:_L&M&P;>gFu,ldoks8U=B
+!!#.\rr=AE!!(^Nrr@cP!!7lSFSu1?,piEg!86oB"5a(Y^OlL'rrF,cb?k8d!;+&,
+kPbD\@/U'-:Odk?`G5H@r;ZhirVll_o\BNJ-Hf*a*?CUK!e11MgA_5L!!*!\"!mpn
+^Zb\!o/qa+rrG5.h>[O=!6kB@#GV8F4?NU+oD&=jYpBB44='tio`#$b,liYrrrdEi
+s8U=>!!%`,rrN0#J"Q`BIfLV?rrXPI!'KoR!)`Ol!'L2Z"!mpI4T59^,ldokrVlkm
+pAb2'qYpOXrVuq.mf*AO!!">>rrM7.pAb:As8QU.!!(7ArrCaO!!5:_U](5nL&CrT
+,ldoks8UdO!!#.\rrXPI!%%RC!0mH_",6dT4Sf$[,ldoknG`UJ!!'ccs24j;*@/g8
+!>bb.^]<Qrrr?H:!!&YirrD?Vh#RL&b=r!X*Ld!0IfKK'rr_C0-,9EY!gE[2kl1_.
+!/:FP!SP]SrrhIH!!(7Ars7a54S/UQUB"g!rrOJm^]+67@fU$3rrZ*u!/:=M"smdZ
+s+LHJr6,04gA_3S!.UX@!e11me,KNF,pfhfrrI3fr;ZjEA,H9.49,AVrVltR,pd[2
+rrKksqu?dE;8;u-!87>O!@?mrrrZ*u!'KuT!R*\(!!aer!!">Fs-3K_!87;M"XO-K
+;?,>K!!&8]rrZ*u!%%XE"&T%EZ2Xb*;#gSBr;QcMrVuq_rr3"@-2dfH;02d<-1Lp:
+hZ*YkK)`ag!?EH/?NCrCoY:IirVlk*\,ZN$rVll_o\BNJ-Hf*a*?CUK!e11Mg]%>>
+!-J,<!`8s4l2Lh/!/92-"dC;5493V(rrR9BU](2o4=0.drrSqqFSu.>,pi9b"I&mK
+!/:@N#Nd>-s8PqBk1'D4!!%M@rrRZM+Me!\k*1RRPihfA!R06orrM9Eq>UWOKlggh
+k4nrVA,ZH.A*s9uk$qoSo`#6NP_Fh8s3*Sf^]+67F?Hi*rrTGfA,cK0PWXZsrr^qO
+;;(pJ!87;M"6NHXg&(dNKfk(drs6AnL"ZJg!!">7rr_-Y!5F-c_uB`X,g0Nq(BF*C
+!9a=\!+>a*"/#VnoYoD^LA_)PTDecilL`m5!%,l`!?E2LrrRZM!8IMTK`H5lrrTrh
+^]"09UHBhbA(ge[&E[Ib,s7t&s'n.k,s7Fl@o<4)"m0;W,s7Fjrs+ccs._\&4I#U?
+#0['0^P)[3rVlm\-2dcEK`InErrTrWPl1O^4=0b%"kb23K`Hi)rrJ?1rr3!F-.Dkq
+!!%M@rrRZM+Hla*jsC!,!83M7"!mpI4Ri@QhZ*YkK)`ag!?EH/?NCrCoY:IirVlk*
+r;Zqls8V`1f)UR(!!&YirrD?Vh#RL&b=r!X*Ld!0IfKK'rr^pS-):26#@d`[4?Oo9
+U]19*YpBB44='u;s'n.k,s7Fl4=1",#GWRF4?Oni4T>?dKdC4T4?OniFSPk?fq\TI
+K`K?qrrFDlr;Qi5!/:%E!p1dTp\tCZ4TC*8L&CrO;*=jX"slCH@m"89f`)!Q!.UX@
+!dF\NP5bN9rVupqOoGEVrVuq.nG`U:!!'ccs24j;*@/g8!>bb/^]DaTrVlk*r;Zql
+s8V`1f)UR(!!&YirrMiOp"]WK-Hf*a*?CUK!e11MgA_A!!!"<-L!9Go!egVarr38J
+,ph^Rs!8u+rr31"!5JQX!/:FP#<X=4s5kUR^]+6B@fU$=s+LG!bl@^e,pi3`!egWu
+rVlmE4T,3\bQ(N3rrQ[1L%tZPF9')UK`Hi)rsU3-s8U:C,lf5;!!%,orrN0#J"Q`C
+QN.$KPQ(V/rVuqnR/[01r;Qf4-2mlE^[V7*[f?ESK)`ag!?EH/?NCrCp:p[\qu6Y(
+r;Zqls8V`1f)UR(!!&YhrrN&[p>#`L-Hf*a*?CUK!e11Mg&D,g;'l2A!@;7SrrOJm
+oDS[nUB$PYUB#E7rs$5#Z2`#JL&V)V4=1%-PQ6F8rrsbqk5U,8Pl:U`493UurrRlS
+bl.PB,s;,*!mCX,o`"u&!'L&V#JU7ms8RcQL&M#]bQ->rs-*LG^]4>K,lj^orrN0#
+J"Q`C[f?ESPlC`urVupERK!EC,lf5;r]L,Z!'K`M".oPnkCW`OrrF,cb?k8d!;F80
+b5M5;!+>a*"/#VnoYoD^LA_)PTDSWhrSdM,!<=Ii9`Z7TRf<G=!!(UM$GU[F,lg(!
+s5kUir6,A?!'L:'!5J@0!mCXurr30b-3+!-!6kB@#%IYWs+LHsrVlqQ!6k-9!egWu
+rVlmE4T,3\bQ'currQ[14SSjV4?WWC!egW.rVln?-3!oFo?@.4!l"^tgA_3S!.UX@
+"4$rIYE]%eFT)7?A"!>sL%bQJ--YiX!dF\FK)`^f!?EH/?NCrCpV6e%r;QiULEZTr
+""6E"4iK8Y,5hKC18!b-rrMuQptYrN-Hf*a*?CUK!e11Me,KU649/mkbkM/@4T@MD
+bk_8?bQ*@rrrkM2s8P2-qu6kS!/:H,!6kEA!egWup&>)I!6kEA!@9l+rrUCEFS>_9
+;#i`QrrQ[Vbl7VDK`Hi*rrG5ZpAY.>-//A#!!%M@rr_]i!+;&k!+Z!.!83e?!SJdp
+!!,48mf*>:!%<I!_Z'WW,g0Nq(BF6G!7^rH!M9q1!!*@\r;Qc`ptYrN-Hf*a*?CUK
+!e11Mg]%:aA,?30js;>RbQ'd%bQQW!;#ni9rrUCEL&V)V4=1%-4=0.frs"/WU]6#J
+bl.PCK`K?irrRlSbl.PB,piKh!i#aLq#:HY49/mbrrFDGr$;RJ,pe9Fjs?errrFDl
+gA_3S!.UU?"$chtpQY[Z;'g=MrrJm:r]C6ZL"Ykn"5a(YG_5t4rrF,cb?k8d!;O>0
+oDS[hVm$.$TDeciqY8kI!%,l`!?E2LrrRZM!8IMT,ph^Mrrj\ps8OAkqu6iQs8RcQ
+U\t,q;3_+)!/:FP#!=43s'l&Dr;Qsu!6kIs!6kEA!egWup&>)I!6kEA!^%dkrVlq@
+!5J@0"7mf=FS5Y6;>`N^,lf5RPlIL)k5PA^@m&oOrrFDlgA_3S!.UU?".&uf[t=X:
+rr\#V!5F-c_Z'WW,g0Nq(BF9H!6G-=!V[G8!!*AorVllWq:u&O-Hf*a*?CUK!e11M
+g]%@c!'KlNrs+5XA,lQk!5JL4#)*%es1\P2rVm(s!-J7b!/:FP#!=43s.]R(rVm,b
+,piTkK`K?qrrRlSbk:u;K`K?qrrSDbL&M#P,pi?d!^$IXmf*?B!/:FP!Fn7jrrQ[1
+L&M#QPQ54IrrN0#J"HZBk5YKYK)^`."8=JL(kVe(rrF,cb?k8d!;XD1f)>UKVlg""
+\,H=,kP<p7!%,l`!?E2LrrRZM!8@H&49-[L^W`HM!%$e-s1\O[U]:@Y!%$e-s%rc+
+k5V\4-0G6O!%#D5s#_V,rs_'jA*3g+491WGs+LHsrVlqQ!6k-9!egWur;R!J!0mNG
+491*7rs+cNPlLcJ!%%Jqrr3!r;>L4nK`Hi+rrFEfrVm2d,lj20s-*L0k1]h:!!%M>
+rr[3?!7-8sMuNm?!!&(3s2"^9*@/g8!>bb3^]<$crr?I*!!8Men@FPY2#RCSTDeci
+lM96:!%,l`!?E2LrrRZM!87AQ;'l,?!E%PKrs,;F!$rok--Z>f##P@H,lf78rr30b
+!!%-@4=0t+##P@H,lf6Urr3%R!6kEA!egWup&>)I!6kB@#0]10,p`P$rVm%T!/:IQ
+4S\sW-3!oF,piBe#DE/3s8UaPbl%JG^Eik+,lg'Og&D*R!.UR>"6Tpi:kJ_+rri'5
+!#YH^s2"^9*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E2L
+rrRZM!8.;Tk+dWaPhGm4"2BPD^\[s4fnG-Tqu6i7PhH)ibl%JCfnG-Tr;Qfhbl%JA
+o??k,!V=P2rr]$ML"ZD("nTt0s8UdIbl7VCbfon_#4p(1s8Tifq>UQ3Kn[:nrrN0#
+J"6N@Du]m!K)^i1"(2*/YCceirrF,cb?k8d!;XD1f_tgM@/U',TE"DlMuY^5!!&Yi
+rrD?[h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M=rrhL-!!'K[s,[0^NrT/FK)`Uc!?EH/
+?NCrCq7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WNT)Sil
+!.UL<"O@>R&C5t.OoGQf!!"/1K)`Uc!?EH/?NCrCq7m!_rVlk*r;Znks7!UY!&XWS
+!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WNT)Sil!.UI;"Kqe*#cE:SPQ(c@!!!;VK)`Rb
+!?EH/?NCrCq7m!_rVlk*r;Znks7!UY!&XWS!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WN
+T)Sil!.UF:!13Zb!Isiqs-N`hmoTPi&@[8k^&J*R,g0Nq(BF9H!8.8M!+>a*!h]M^
+\r6VGr;ZhirVll_q:u&O-Hf*a*?CUK!e11MK)_GB!WW4MR/[?)&-)\IT7[*3rs&4I
+&-)\Yf7O%8rrF,cb?k8d!;XD1f_tgM@/U',TE"DlMuY^5!!&YirrD?[h#RL&b=r!X
+*Ld!0IfKJ#s.95l!!%M8rrM"*rW!!BE6j.9TDnu%BGg^K!D)[2s1A:3*@/g8!>bb3
+^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E2LrrRZM!.t6BrrN0#J!L$7
+T-4(4"!D!$ItGG6^BBUIIo$^T!!+dgK)`C]!?EH/?NCrCq7m!_rVlk*r;Znks7!UY
+!&XWS!2'5i!:'C9!<=Ii9`Z7TRf<G=!!%WNT)Sil!.U75!r%HuJcM8?!AL^/s0r"/
+*@/g8!>bb3^]<$crr?I*!!8emn@FPY2#RCSTDecilM96:!%,l`!?E2LrrRZM!.t6B
+rrN0#J!'a5f7-%FJcMSH":.7`Qf!Dp[Jp7J,g0Nq(BF9H!8.8M!+>a*!h]M^\r6VG
+r;ZhirVll_q:u&O-Hf*a*?CUK!e11MK)_GB!WW4MK)^H&K)^H&h>[Kr,g0Nq(BF9H
+!8.8M!+>a*"/#VnV7VZd2#RCSTDecilM96:!%,l`!?E2LrrRZM!.t6BrrN0#ItI]P
+s+:9&s5!\U*@/g8!>bb3^]<$crr?I*!!Jqos81$QW;o0]!!&YirrD?[h#RL&b=r!X
+*Ld!0IfKJ#s.95l!!%M#s+:9&s+::,rrF,cb?k8d!;XD1f_tgM@/U'*T=Fn$@/U'*
+TDecilM96:!%,l`!?E2LrrRZM!.t6BrrN0#ItI]Ps+:9&s5!\U*@/g8!>bb3^]<$c
+rr?I*!!&(irr?I*!!&YirrD?[h#RL&b=r!X*Ld!0IfKJ#s.95l!!%M#s+:9&s+::,
+rrF,cb?k8d!;XD1f)>UKVlg""\,H=,l1s-9!%,l`!?E2LrrRZM!.o]lIf]TMItI]P
+s+:9&s5!\U*@/g8!>bb3^];ISrrMj2YQ+\0n,<7djS@U4!%,l`!?E2Lrr@h+!1Elf
+ItI]Ps+:9&s5!\U*@/g8!>bb2^]=!)rrA[q!!&YirrDulh#RL&b=r!X*Ld!/f,0)>
+S,`R,c[u1Ks+:9&s5!\U*@/g8!>bb2^];m^rrJ/dZiC+4L]%/PnG(f?!%,l`!?E24
+s+:9&s+:9&s+:90rrF,cb?k8d!;F8/p&+gkhg\2,5QXKKkPY>\r87;*!<=Ii9`Z7T
+K)^H&K)^H&K)^H&N;io!,g0Nq(BF3F!QtA@rrN,^pY>iM-Hf*a*?Bb3K)^H&K)^H&
+K)^f0!?EH/?NCrCp:p[\X8`5"kP!^4!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d
+!;4,.deBpE!Vk[Ih#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>bb.^]MC0pTjf"
+p?;,(!<=Ii9`Z7TK)^H&K)^H&K)^H&N;io!,g0Nq(BF!@!QrpJhu^uM^>A8Zl/pjm
+h#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&
+s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8
+!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&
+b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&
+s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ
+^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X
+*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90
+rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KSt
+I*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,cb?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<C
+s+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H!%,l`!?E24s+:9&s+:9&s+:90rrF,c
+b?k8d!6`.ZO8s[Oh#RL&b=r!X*J4<Cs+:9&s+:9&s,?sY*@/g8!>baZ^]KStI*:=H
+!%,l`!?E24s+:9&s+:9&s+:90rr=Bt!1s5k*eOEDs+:9&s+:9&s,?sXYKD=qDbnQ+
+!ddFabC9OkB?G](YCce+s+:9&s+:9Grr
+~>
+grestore
+currentdict /inputf undef
+currentdict /pstr undef
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,109 @@
+D/audio////
+D/hw////
+D/linux-user////
+D/pc-bios////
+D/slirp////
+D/target-arm////
+D/target-i386////
+D/target-ppc////
+D/target-sparc////
+D/tests////
+D/fpu////
+D/keymaps////
+D/target-mips////
+/.cvsignore/1.13/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/COPYING/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/COPYING.LIB/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/Changelog/1.116/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/LICENSE/1.2/Sat Feb 12 14:45:23 2005//Trelease_0_8_1
+/Makefile/1.99/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/Makefile.target/1.107/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/README/1.12/Wed May 24 10:40:08 2006//Trelease_0_8_1
+/README.distrib/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/TODO/1.38/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/VERSION/1.28/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/a.out.h/1.2/Wed May 24 10:40:08 2006//Trelease_0_8_1
+/aes.c/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/aes.h/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/alpha-dis.c/1.3/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/alpha.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/arm-dis.c/1.3/Wed May 24 10:40:08 2006//Trelease_0_8_1
+/arm.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/block-bochs.c/1.1/Tue Apr 26 21:34:00 2005//Trelease_0_8_1
+/block-cloop.c/1.3/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/block-cow.c/1.5/Thu May 25 12:38:49 2006//Trelease_0_8_1
+/block-dmg.c/1.4/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/block-qcow.c/1.6/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/block-vmdk.c/1.7/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/block-vpc.c/1.2/Thu May 25 12:38:49 2006//Trelease_0_8_1
+/block-vvfat.c/1.5/Thu May 25 18:22:25 2006//Trelease_0_8_1
+/block.c/1.26/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/block_int.h/1.4/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/bswap.h/1.5/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/cocoa.m/1.8/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/configure/1.100/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/console.c/1.5/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/cpu-all.h/1.54/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/cpu-defs.h/1.15/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/cpu-exec.c/1.78/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/dis-asm.h/1.11/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/disas.c/1.30/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/disas.h/1.7/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/dyngen-exec.h/1.27/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/dyngen-op.h/1.1/Mon Jan 3 23:40:55 2005//Trelease_0_8_1
+/dyngen.c/1.42/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/dyngen.h/1.10/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/elf.h/1.6/Thu May 25 12:38:50 2006//Trelease_0_8_1
+/elf_ops.h/1.3/Tue May 2 20:54:12 2006//Trelease_0_8_1
+/exec-all.h/1.47/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/exec.c/1.79/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/gdbstub.c/1.36/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/gdbstub.h/1.2/Tue Apr 26 20:42:36 2005//Trelease_0_8_1
+/i386-dis.c/1.5/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/i386-vl.ld/1.3/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/i386.ld/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/ia64.ld/1.1/Thu Apr 7 22:20:28 2005//Trelease_0_8_1
+/keymaps.c/1.2/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/kqemu.c/1.10/Thu May 25 18:22:26 2006//Trelease_0_8_1
+/kqemu.h/1.1/Wed Feb 8 22:39:17 2006//Trelease_0_8_1
+/linux-2.6.9-qemu-fast.patch/1.1/Wed Dec 8 23:48:11 2004//Trelease_0_8_1
+/loader.c/1.2/Wed Apr 26 22:05:26 2006//Trelease_0_8_1
+/m68k-dis.c/1.1/Sun Nov 6 16:52:11 2005//Trelease_0_8_1
+/m68k.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/mips-dis.c/1.3/Thu May 25 18:22:28 2006//Trelease_0_8_1
+/monitor.c/1.48/Thu May 25 18:22:28 2006//Trelease_0_8_1
+/osdep.c/1.10/Wed May 24 10:40:10 2006//Trelease_0_8_1
+/osdep.h/1.5/Wed May 24 10:40:10 2006//Trelease_0_8_1
+/ppc-dis.c/1.7/Thu May 25 12:38:51 2006//Trelease_0_8_1
+/ppc.ld/1.2/Thu May 25 12:38:51 2006//Trelease_0_8_1
+/qemu-binfmt-conf.sh/1.4/Thu May 25 18:22:28 2006//Trelease_0_8_1
+/qemu-doc.texi/1.87/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/qemu-img.c/1.8/Thu May 25 12:38:51 2006//Trelease_0_8_1
+/qemu-img.texi/1.2/Thu May 25 12:38:51 2006//Trelease_0_8_1
+/qemu-tech.texi/1.9/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/qemu_socket.h/1.1/Sun Apr 30 22:53:25 2006//Trelease_0_8_1
+/readline.c/1.1/Tue May 23 19:16:56 2006//Trelease_0_8_1
+/s390.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/sdl.c/1.26/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/sdl_keysym.h/1.3/Tue Mar 1 21:43:41 2005//Trelease_0_8_1
+/sh4-dis.c/1.1/Thu Apr 27 21:05:14 2006//Trelease_0_8_1
+/softmmu_exec.h/1.1/Sun Oct 30 18:16:26 2005//Trelease_0_8_1
+/softmmu_header.h/1.13/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/softmmu_template.h/1.16/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/sparc-dis.c/1.2/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/sparc.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/tap-win32.c/1.2/Sun Feb 19 12:40:00 2006//Trelease_0_8_1
+/texi2pod.pl/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/thunk.c/1.6/Wed May 24 10:40:10 2006//Trelease_0_8_1
+/thunk.h/1.13/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/translate-all.c/1.14/Thu May 25 18:22:29 2006//Trelease_0_8_1
+/translate-op.c/1.1/Sun Mar 13 16:53:06 2005//Trelease_0_8_1
+/usb-linux.c/1.4/Sat Mar 11 18:03:38 2006//Trelease_0_8_1
+/vgafont.h/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/vl.c/1.184/Thu May 25 18:22:30 2006//Trelease_0_8_1
+/vl.h/1.116/Thu May 25 18:22:30 2006//Trelease_0_8_1
+/vnc.c/1.4/Mon May 1 21:44:22 2006//Trelease_0_8_1
+/vnc_keysym.h/1.1/Sun Apr 30 21:28:36 2006//Trelease_0_8_1
+/vnchextile.h/1.1/Sun Apr 30 21:28:36 2006//Trelease_0_8_1
+/x86_64.ld/1.1/Thu Jan 6 20:50:00 2005//Trelease_0_8_1
+D/target-sh4////
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/audio/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/audio/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,19 @@
+/alsaaudio.c/1.5/Sun Nov 20 18:53:05 2005//Trelease_0_8_1
+/audio.c/1.9/Thu May 25 18:22:31 2006//Trelease_0_8_1
+/audio.h/1.5/Thu May 25 18:22:31 2006//Trelease_0_8_1
+/audio_int.h/1.7/Thu May 25 18:22:31 2006//Trelease_0_8_1
+/audio_template.h/1.4/Sun Nov 20 16:24:34 2005//Trelease_0_8_1
+/coreaudio.c/1.5/Sun Nov 20 18:53:42 2005//Trelease_0_8_1
+/dsound_template.h/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1
+/dsoundaudio.c/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1
+/fmodaudio.c/1.5/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/mixeng.c/1.4/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/mixeng.h/1.2/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/mixeng_template.h/1.2/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/noaudio.c/1.4/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/ossaudio.c/1.9/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/rate_template.h/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1
+/sdlaudio.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/sys-queue.h/1.1/Sun Oct 30 18:58:22 2005//Trelease_0_8_1
+/wavaudio.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/audio/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/audio/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/audio
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/audio/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/audio/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/audio/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/audio/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/fpu/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/fpu/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,7 @@
+/softfloat-macros.h/1.1/Sun Mar 13 16:54:06 2005//Trelease_0_8_1
+/softfloat-native.c/1.3/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/softfloat-native.h/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/softfloat-specialize.h/1.1/Sun Mar 13 16:54:06 2005//Trelease_0_8_1
+/softfloat.c/1.2/Sun Mar 13 18:52:28 2005//Trelease_0_8_1
+/softfloat.h/1.3/Thu May 25 18:22:32 2006//Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/fpu/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/fpu/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/fpu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/fpu/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/fpu/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/fpu/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/fpu/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/hw/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,72 @@
+/adb.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/adlib.c/1.5/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/apic.c/1.8/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/arm_boot.c/1.1/Thu Apr 27 23:15:07 2006//Trelease_0_8_1
+/arm_pic.c/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/arm_pic.h/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/arm_timer.c/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/cirrus_vga.c/1.21/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/cirrus_vga_rop.h/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/cirrus_vga_rop2.h/1.7/Thu May 25 12:52:49 2006//Trelease_0_8_1
+/cuda.c/1.10/Thu May 25 12:38:51 2006//Trelease_0_8_1
+/dma.c/1.14/Thu May 25 18:22:32 2006//Trelease_0_8_1
+/es1370.c/1.4/Sun Nov 20 16:20:39 2005//Trelease_0_8_1
+/esp.c/1.6/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/fdc.c/1.18/Wed May 24 10:40:13 2006//Trelease_0_8_1
+/fmopl.c/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/fmopl.h/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/heathrow_pic.c/1.2/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/i8254.c/1.8/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/i8259.c/1.18/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/ide.c/1.42/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/integratorcp.c/1.9/Thu Apr 27 23:15:07 2006//Trelease_0_8_1
+/iommu.c/1.6/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/lance.c/1.7/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/m48t59.c/1.7/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/m48t59.h/1.5/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/mc146818rtc.c/1.6/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/mips_r4k.c/1.16/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/ne2000.c/1.19/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/openpic.c/1.9/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/parallel.c/1.4/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/pc.c/1.53/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/pci.c/1.24/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/pckbd.c/1.15/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/pcspk.c/1.1/Mon Apr 24 21:58:30 2006//Trelease_0_8_1
+/pl011.c/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/pl050.c/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/pl080.c/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/pl110.c/1.6/Tue Apr 18 19:02:59 2006//Trelease_0_8_1
+/pl110_template.h/1.2/Sun Feb 19 12:31:32 2006//Trelease_0_8_1
+/pl190.c/1.1/Sun Apr 9 01:32:52 2006//Trelease_0_8_1
+/ppc.c/1.9/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/ppc_chrp.c/1.21/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/ppc_prep.c/1.26/Thu May 25 18:22:33 2006//Trelease_0_8_1
+/ps2.c/1.4/Wed Apr 12 21:09:07 2006//Trelease_0_8_1
+/rtl8139.c/1.1/Sun Feb 5 04:14:41 2006//Trelease_0_8_1
+/sb16.c/1.19/Thu May 25 18:22:34 2006//Trelease_0_8_1
+/serial.c/1.12/Thu May 25 18:22:34 2006//Trelease_0_8_1
+/sh7750.c/1.1/Thu Apr 27 21:32:09 2006//Trelease_0_8_1
+/sh7750_regnames.c/1.1/Thu Apr 27 21:32:09 2006//Trelease_0_8_1
+/sh7750_regnames.h/1.1/Thu Apr 27 21:32:09 2006//Trelease_0_8_1
+/sh7750_regs.h/1.1/Thu Apr 27 21:32:09 2006//Trelease_0_8_1
+/shix.c/1.1/Thu Apr 27 21:32:09 2006//Trelease_0_8_1
+/slavio_intctl.c/1.6/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/slavio_misc.c/1.3/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/slavio_serial.c/1.6/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/slavio_timer.c/1.3/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/smc91c111.c/1.3/Sat Feb 4 22:15:28 2006//Trelease_0_8_1
+/sun4m.c/1.16/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/sun4u.c/1.8/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/tc58128.c/1.1/Thu Apr 27 21:32:09 2006//Trelease_0_8_1
+/tcx.c/1.7/Thu May 25 18:22:35 2006//Trelease_0_8_1
+/usb-hid.c/1.2/Wed Apr 12 21:09:07 2006//Trelease_0_8_1
+/usb-hub.c/1.3/Sun Apr 30 21:53:59 2006//Trelease_0_8_1
+/usb-uhci.c/1.8/Tue Apr 25 21:01:19 2006//Trelease_0_8_1
+/usb.c/1.6/Mon Apr 24 21:18:20 2006//Trelease_0_8_1
+/usb.h/1.4/Wed Apr 12 21:09:07 2006//Trelease_0_8_1
+/versatilepb.c/1.2/Thu Apr 27 23:15:07 2006//Trelease_0_8_1
+/vga.c/1.42/Thu May 25 18:22:36 2006//Trelease_0_8_1
+/vga_int.h/1.6/Thu May 25 18:20:53 2006//Trelease_0_8_1
+/vga_template.h/1.11/Wed May 17 14:47:01 2006//Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/hw/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/hw
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/hw/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/hw/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/keymaps/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/keymaps/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,36 @@
+/ar/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/common/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/da/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/de/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/de-ch/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/en-gb/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/en-us/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/es/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/et/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/fi/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/fo/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/fr/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/fr-be/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/fr-ca/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/fr-ch/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/hr/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/hu/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/is/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/it/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/ja/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/lt/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/lv/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/mk/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/modifiers/1.2/Tue Mar 1 21:43:42 2005//Trelease_0_8_1
+/nl/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/nl-be/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/no/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/pl/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/pt/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/pt-br/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/ru/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/sl/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/sv/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/th/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+/tr/1.1/Sun Dec 12 16:56:30 2004//Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/keymaps/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/keymaps/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/keymaps
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/keymaps/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/keymaps/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/keymaps/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/keymaps/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/pc-bios/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/pc-bios/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,15 @@
+/Makefile/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/README/1.7/Thu May 25 12:38:52 2006//Trelease_0_8_1
+/bios.bin/1.13/Thu May 25 18:22:37 2006/-kb/Trelease_0_8_1
+/bios.diff/1.11/Thu May 25 18:22:37 2006//Trelease_0_8_1
+/linux_boot.S/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
+/linux_boot.bin/1.1/Wed May 17 14:47:01 2006/-kb/Trelease_0_8_1
+/ohw.diff/1.2/Thu Jul 7 22:38:00 2005//Trelease_0_8_1
+/ppc_rom.bin/1.6/Thu May 25 12:39:00 2006/-kb/Trelease_0_8_1
+/proll.elf/1.5/Thu May 25 18:22:38 2006/-kb/Trelease_0_8_1
+/proll.patch/1.6/Thu May 25 18:22:38 2006//Trelease_0_8_1
+/vgabios-cirrus.bin/1.6/Thu May 25 18:22:38 2006/-kb/Trelease_0_8_1
+/vgabios.bin/1.5/Thu May 25 18:22:39 2006/-kb/Trelease_0_8_1
+/vgabios.diff/1.2/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/video.x/1.1/Sun Jul 3 14:00:51 2005/-kb/Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/pc-bios/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/pc-bios/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/pc-bios
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/pc-bios/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/pc-bios/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/pc-bios/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/pc-bios/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/target-i386/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/target-i386/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,13 @@
+/cpu.h/1.36/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/exec.h/1.29/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/helper.c/1.65/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/helper2.c/1.41/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/op.c/1.44/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/opreg_template.h/1.3/Wed May 24 10:40:25 2006//Trelease_0_8_1
+/ops_mem.h/1.7/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/ops_sse.h/1.6/Tue Apr 26 20:38:17 2005//Trelease_0_8_1
+/ops_template.h/1.10/Wed May 24 10:40:25 2006//Trelease_0_8_1
+/ops_template_mem.h/1.6/Thu May 25 18:22:39 2006//Trelease_0_8_1
+/translate-copy.c/1.7/Wed May 24 10:40:25 2006//Trelease_0_8_1
+/translate.c/1.56/Thu May 25 18:22:39 2006//Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/target-i386/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/target-i386/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/target-i386
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/target-i386/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/target-i386/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/target-i386/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/target-i386/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/tests/.CVS/Entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/tests/.CVS/Entries Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,18 @@
+/.cvsignore/1.4/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/Makefile/1.36/Thu May 25 18:22:40 2006//Trelease_0_8_1
+/hello-arm.c/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/hello-i386.c/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/linux-test.c/1.3/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/pi_10.com/1.1/Wed May 17 14:47:02 2006/-kb/Trelease_0_8_1
+/qruncom.c/1.4/Thu May 25 18:22:41 2006//Trelease_0_8_1
+/runcom.c/1.3/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/sha1.c/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/test-i386-code16.S/1.3/Wed May 24 10:40:26 2006//Trelease_0_8_1
+/test-i386-muldiv.h/1.2/Wed May 24 10:40:26 2006//Trelease_0_8_1
+/test-i386-shift.h/1.5/Thu May 25 18:22:41 2006//Trelease_0_8_1
+/test-i386-vm86.S/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/test-i386.c/1.49/Wed May 24 10:40:26 2006//Trelease_0_8_1
+/test-i386.h/1.2/Wed May 24 10:40:26 2006//Trelease_0_8_1
+/test_path.c/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
+/testthread.c/1.2/Wed May 17 14:47:02 2006//Trelease_0_8_1
+D
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/tests/.CVS/Repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/tests/.CVS/Repository Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+qemu/tests
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/tests/.CVS/Root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/tests/.CVS/Root Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+:pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/qemu
diff -r 4acc6d51f389 -r b76e86966e7e tools/ioemu/tests/.CVS/Tag
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/tests/.CVS/Tag Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1 @@
+Nrelease_0_8_1
diff -r 4acc6d51f389 -r b76e86966e7e tools/security/xensec_ezpolicy
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/security/xensec_ezpolicy Wed Aug 02 13:39:47 2006 -0600
@@ -0,0 +1,1628 @@
+#!/usr/bin/env python
+#===========================================================================
+# This program 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.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006 International Business Machines Corp.
+# Author: Reiner Sailer
+#============================================================================
+# use 'yum install wxPython' to get wx or download from www.wxpython.org
+import sys, time, string
+import wx
+import wx.lib.buttons as buttons
+"""
+This program creates a default policy based on names of organizations and
departments.
+The resulting policy can be refined using the policy generation tool
(xensec_gen).
+"""
+
+helpprovider = wx.SimpleHelpProvider()
+wx.HelpProvider_Set(helpprovider)
+
+ID_CS_START=1000
+
+realm_bmp = None
+workload_bmp = None
+conflict_bmp = None
+realm_icon = None
+workload_icon = None
+
+class orgTreeCtrl(wx.TreeCtrl):
+
+ event = None
+
+ def __init__(self, parent, id, pos, size, style, validator, name):
+ wx.TreeCtrl.__init__(self, parent, id, pos, size, style,
+ validator, name)
+ self.parent = parent
+ orgs_root = self.AddRoot(text="Organization / Department")
+ rootfont = wx.Font(pointSize=12, family=wx.FONTFAMILY_DEFAULT,
+ style=wx.FONTSTYLE_NORMAL,
weight=wx.FONTWEIGHT_LIGHT)
+ self.SetItemFont(orgs_root, rootfont)
+ self.SetItemBackgroundColour(orgs_root, wx.LIGHT_GREY)
+
+
+ def LabelExists(self, label, item):
+ for i in iterchildren(self.GetItemParent(item)):
+ if (self.GetItemText(i) == label) and (i != item):
+ return True
+ return False
+
+
+ def _OrgEdt(self, event):
+ item = self.event.GetItem()
+ self.OrgEdt(item)
+
+
+ def OrgEdt(self, item):
+ oldlabel= self.GetItemText(item)
+ #get new name
+ dlg = wx.TextEntryDialog(self, "Please enter org/dept name:",
+ "Naming a Workload",
+ style=wx.CANCEL | wx.OK | wx.CENTRE |
wx.TE_NOHIDESEL)
+ dlg.SetValue(oldlabel)
+ ret = dlg.ShowModal()
+ newlabel = dlg.GetValue()
+ dlg.Destroy()
+ if (ret == wx.ID_CANCEL) or (newlabel == ''):
+ return False
+
+ #now check if the new name is permissible
+ if self.LabelExists(newlabel, item):
+ dlg = wx.MessageDialog(self, 'Item with name ' + newlabel + '
already exists!',
+ 'Rename', style=wx.OK)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return False
+
+ #all checkspassed, change item and adapt runtime exclusion rules
+ self.SetItemText(item, newlabel)
+ app.win.LabelReplaceInConflictsets(item, oldlabel, newlabel)
+ return True
+
+
+ def _OrgRAdd(self, event):
+ self.OrgRAdd()
+
+
+ def OrgRAdd(self):
+ new = self.AppendItem(self.GetRootItem(), text="")
+ self.SetItemBold(new, True)
+ self.SetItemImage(new, realm_icon, wx.TreeItemIcon_Normal)
+ self.EnsureVisible(new)
+ if not self.OrgEdt(new):
+ self.Delete(new)
+
+
+ def _OrgWAdd(self, event):
+ item = self.event.GetItem()
+ self.OrgWAdd(item)
+
+
+ def OrgWAdd(self, item):
+ new = self.AppendItem(item, text="")
+ self.Expand(item)
+ self.SetItemImage(new, workload_icon, wx.TreeItemIcon_Normal)
+ self.EnsureVisible(new)
+ if not self.OrgEdt(new):
+ self.Delete(new)
+
+
+class OrgsPanel(wx.Panel):
+ ID_CONSADDBTN = 145
+ ID_REALMADDBTN = 144
+
+ def __init__(self, parent, ID):
+ global realm_icon, workload_icon
+
+ wx.Panel.__init__(self, parent, -1)
+
+ #create image list
+ imagelist = wx.ImageList(16, 17, True)
+ #define generic function and use it for all input
+ realm_icon = imagelist.Add(realm_bmp)
+ workload_icon = imagelist.Add(workload_bmp)
+
+ #left tree control for organizations / workload definitions
+ orgshdrbox = wx.StaticBox(self, -1, "")
+ orgshdrboxsizer = wx.StaticBoxSizer(orgshdrbox, wx.HORIZONTAL)
+ orgshdr = wx.StaticText(self, -1, "Organization / Department
Definition",
+ style=wx.ALIGN_CENTER)
+ orgshdr.SetHelpText(RealmWorkloadPanelHelp)
+ points = orgshdr.GetFont().GetPointSize() # get the current size
+ hdrfont = wx.Font(points + 2, family=wx.DEFAULT,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
+ orgshdr.SetFont(hdrfont)
+ orgshdr.SetForegroundColour('MEDIUMBLUE')
+ orgshdr.SetBackgroundColour('SNOW')
+ orgshdrboxsizer.Add(orgshdr, proportion=1, flag=wx.EXPAND | wx.ALL |
wx.ALIGN_LEFT, border=5)
+ addorgsbutton = wx.Button(self, self.ID_REALMADDBTN, "New Org",
style=wx.BU_EXACTFIT)
+ addorgsbutton.SetToolTipString("Add A New Organization")
+ addorgsbutton.SetHelpText(NewRealmButtonHelp)
+ addorgsbutton.SetForegroundColour('MEDIUMBLUE')
+ addfont = wx.Font(points, family=wx.DEFAULT,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
+ addorgsbutton.SetFont(addfont)
+ orgshdrboxsizer.Add(addorgsbutton, proportion=0, flag=wx.EXPAND |
wx.ALL | wx.ALIGN_RIGHT, border=0)
+
+ self.orgs = orgTreeCtrl(self, -1,
+ pos=wx.DefaultPosition,
+ size=wx.DefaultSize,
+ style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT |
wx.TR_NO_LINES
+ | wx.TR_MULTIPLE,
+ validator=wx.DefaultValidator,
+ name="orgs")
+ self.orgs.AssignImageList(imagelist)
+ self.orgs.SetHelpText(RealmWorkloadPanelHelp)
+
+ self.addconsbutton = wx.Button(self, self.ID_CONSADDBTN,
+ "Create run-time exclusion rule from
selection -->",
+ style=wx.BU_EXACTFIT)
+ self.addconsbutton.SetToolTipString("Create New Exclusion rule From
Above Workload Selection")
+ self.addconsbutton.SetHelpText(CreateRunTimeButtonHelp)
+ self.addconsbutton.SetForegroundColour('MEDIUMBLUE')
+ addfont = wx.Font(points, family=wx.DEFAULT,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
+ self.addconsbutton.SetFont(addfont)
+ self.addconsbutton.Bind(wx.EVT_BUTTON, self._AddConflict,
id=self.ID_CONSADDBTN)
+
+ orgsvbox = wx.BoxSizer(wx.VERTICAL)
+ orgsvbox.Add(orgshdrboxsizer, proportion=0, flag=wx.EXPAND | wx.ALL,
border=5)
+ orgsvbox.Add(self.orgs, proportion=1, flag=wx.EXPAND | wx.ALL,
border=5)
+ orgsvbox.Add(self.addconsbutton, proportion=0, flag=wx.EXPAND |
wx.ALL, border=5)
+ self.SetSizer(orgsvbox)
+ addorgsbutton.Bind(wx.EVT_BUTTON, self.orgs._OrgRAdd, id=
self.ID_REALMADDBTN)
+
+
+ def _AddConflict(self, event):
+ app.win.conspanel._AddNewConflict(event)
+
+
+class ConsPanel(wx.Panel):
+ ID_CONSSELECT = 151
+ ID_CONSADD = 152
+ ID_CONSRENAME = 153
+ ID_CONSDEL = 154
+ ID_CONSSELECTSUB= 155
+
+ conflictMAX = ID_CS_START
+
+ def __init__(self, parent, ID):
+ self.conflictsets = []
+ self.parent = parent
+ wx.Panel.__init__(self, parent, -1)
+ #header
+ conshdrbox = wx.StaticBox(self, -1, "")
+ conshdrboxsizer = wx.StaticBoxSizer(conshdrbox, wx.HORIZONTAL)
+ conshdr = wx.StaticText(self, -1, "Run-time Exclusion Rules",
style=wx.ALIGN_CENTER)
+ conshdr.SetHelpText(RunTimeExclusionPanelHelp)
+ points = conshdr.GetFont().GetPointSize() # get the current size
+ hdrfont = wx.Font(points + 2, family=wx.DEFAULT,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
+ conshdr.SetFont(hdrfont)
+ conshdr.SetForegroundColour('ORANGERED')
+
+ #context help button
+ ctxHelp = wx.ContextHelpButton(self)
+ ctxHelp.SetHelpText("Context Help Button.")
+ ctxHelp.SetToolTipString("Context Help: Press this button, then press
any other button or panel to get help.")
+
+
+ conshdrboxsizer.Add(conshdr, proportion=1, flag=wx.EXPAND | wx.ALL |
wx.ALIGN_LEFT, border=5)
+ conshdrboxsizer.Add(ctxHelp, proportion=0, flag=wx.EXPAND | wx.ALL |
wx.ALIGN_RIGHT, border=0)
+ #scrolledwindow for all the run-time exclusion rules
+ conflictspanel = wx.ScrolledWindow(self, -1, (0,0),
+ style = wx.FULL_REPAINT_ON_RESIZE |
+ wx.VSCROLL )
+ conflictspanel.SetVirtualSize((1000, 1000))
+ conflictspanel.SetScrollRate(5,5)
+ self.conflictsboxsizer = wx.BoxSizer(wx.VERTICAL)
+
+ #self.conflictsboxsizer.Fit(self)
+ conflictspanel.SetSizer(self.conflictsboxsizer)
+ consvbox = wx.BoxSizer(wx.VERTICAL)
+ consvbox.Add(conshdrboxsizer, proportion=0, flag=wx.EXPAND | wx.ALL,
border=5)
+ consvbox.Add(conflictspanel, proportion=1, flag=wx.EXPAND | wx.ALL,
border=5)
+ self.SetSizer(consvbox)
+ self.consvbox = consvbox
+ self.conflictspanel=conflictspanel
+
+ self.cmenu = wx.Menu()
+ self.cmenu.Append(self.ID_CONSRENAME, "Rename Run-time Exclusion
Rule", "Rename Run-time Exclusion Rule")
+ self.cmenu.AppendSeparator()
+ self.cmenu.Append(self.ID_CONSDEL, "Delete Run-time Exclusion
Rule", "Delete Run-time Exclusion Rule")
+ self.Bind(wx.EVT_MENU, self._CSRename, id=self.ID_CONSRENAME)
+ self.Bind(wx.EVT_MENU, self._CSDelete, id=self.ID_CONSDEL)
+
+
+ #Helper methods called from anywhere
+ def New(self):
+ #delete all run-time exclusion rules
+ for i in self.conflictsets:
+ i.Disable()
+ i.Destroy()
+ self.conflictsets = []
+ self.conflictsboxsizer.Layout()
+ size=self.GetSize()
+ self.Fit()
+ self.SetSize(size)
+
+
+ def DelCSById(self, delid):
+ #delete CS representation
+ delpos, item = self.GetCSBox(delid)
+ if item:
+ self.DelCSByItem(item)
+
+
+ def DelCSByItem(self, item):
+ #delete CS representation
+ self.conflictsets.remove(item)
+ exists = self.conflictsboxsizer.Detach(item)
+ if exists:
+ item.Destroy()
+ self.RefreshMe()
+
+
+ def RefreshMe(self):
+ size=self.parent.GetSize()
+ self.parent.Fit()
+ self.parent.SetSize(size)
+
+
+ def GetOrgSelection(self):
+ (tree, selection) = GetOrgsSelection()
+ if not len(selection):
+ dlg = wx.MessageDialog(self, 'You must select first at least one
Organization/Department workload!',
+ 'Creating A New Run-time Rule', wx.OK |
wx.ICON_ERROR)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return None,None
+ # now rewrite selection (realm.workload extension, check consistency)
+ alist = []
+ for i in selection:
+ if isRealm(i):
+ alist.append(tree.GetItemText(i))
+ else:
+ alist.append(tree.GetItemText(tree.GetItemParent(i))
+ + "." + tree.GetItemText(i))
+
+ if isRealm(i):
+ for j in selection:
+ if tree.GetItemParent(j) == i:
+ violation = ("[ " + tree.GetItemText(i) + ", " +
+ tree.GetItemText(i) + "." +
tree.GetItemText(j) + " ]")
+ dlg = wx.MessageDialog(self,
+ 'Invalid Selection ' +
violation + '.\n\n' +
+ 'You can only select EITHER an
Organization OR specific Department!',
+ 'Creating A New Run-time Exclusion Rule',
wx.OK | wx.ICON_ERROR)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return None,None
+ return (alist, selection)
+
+
+ def AddConflict(self, name, types):
+ csbox = myCSPanel(self, self.conflictMAX, name, types)
+ self.conflictsboxsizer.Add(csbox, proportion=0, flag=wx.EXPAND |
wx.ALL, border=5)
+ self.conflictsets.append(csbox)
+ self.conflictMAX = self.conflictMAX+3
+ self.RefreshMe()
+ csbox.RefreshMe()
+
+
+ def GetCSBox(self, id):
+ pos = -1
+ i = 0
+ while self.conflictsboxsizer.GetItem(i):
+ item = self.conflictsboxsizer.GetItem(i).GetWindow()
+ if ((item.cbmp.GetId() == id) or
+ (item.add_selection.GetId() == id) or
+ (item.del_selection.GetId() == id)):
+ pos = i
+ box = item
+ break
+ i = i + 1
+ if pos < 0:
+ print "Run-time Exclusion Rule Not Found ERROR!"
+ return (None, None)
+ else:
+ return (pos, box)
+
+
+ #bind methods
+ def _AddNewConflict(self, event):
+ # first get the conflicting workload types with current selection
+ types, items = self.GetOrgSelection()
+ if not types:
+ return
+ #get name for conflict set
+ dlg = wx.TextEntryDialog(
+ self, 'Please enter a name for the Run-time Exclusion Rule:',
'Creating A New Run-time Exclusion Rule')
+ dlg.SetValue("")
+ ret = dlg.ShowModal()
+ name = dlg.GetValue()
+ dlg.Destroy()
+ if ret != wx.ID_OK:
+ return
+ self.AddConflict(name, types)
+
+
+ def _OnClick(self, event):
+ self.event = event
+ app.win.SetStatusText("")
+ self.PopupMenu(self.cmenu)
+
+
+ def _CSRename(self, event):
+ delpos, item = self.GetCSBox(self.event.GetId())
+ if not item:
+ return
+ #allow to name the conflict set
+ dlg = wx.TextEntryDialog(
+ self, 'Please enter a new name for the Conflict Set:', 'Renaming A
Run-time Exclusion Rule')
+ dlg.SetValue(item.box.GetLabel())
+ ret = dlg.ShowModal()
+ name = dlg.GetValue()
+ dlg.Destroy()
+ if ret != wx.ID_OK:
+ return
+ item.box.SetLabel(name)
+ item.box.SetFont(wx.Font(item.GetFont().GetPointSize(),
family=wx.DEFAULT,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD))
+
+
+ def _CSDelete(self, event):
+ delid = self.event.GetId()
+ self.DelCSById(delid)
+
+
+ def _AddOrgSelection(self, event):
+ addid = event.GetId()
+ addpos, item = self.GetCSBox(addid)
+ alist, items = self.GetOrgSelection()
+ if not alist:
+ return
+ existing = []
+ for i in range(0, item.clb.GetCount()):
+ existing.append(item.clb.GetString(i))
+
+ #now make sure that we don't get realm + workload into the same CS
+ for i in items:
+ if isRealm(i):
+ #ensure no workload of this realm is already in CS
+ realm = app.win.orgs.GetItemText(i)
+ for j in iterchildren(i):
+ workload = app.win.orgs.GetItemText(j)
+ try:
+ idx = existing.index (realm + "." + workload)
+ except:
+ #ok, does not exist
+ continue
+ #nok, exists already
+ violation = ("[ " + realm + ", " +
+ realm + "." + workload + " ]")
+ dlg = wx.MessageDialog(self,
+ 'Invalid Selection ' + violation + '.\n\n' +
+ 'You can only have EITHER an Organization OR a
specific Department workload\n' +
+ 'in a single Run-time Exclusion Rule',
+ 'Adding Orgs/Depts workloads to a Run-time
Exclusion Rule',
+ wx.OK | wx.ICON_ERROR)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ else:
+ #ensure realm of this workload is not in CS
+ realm = app.win.orgs.GetItemText(app.win.orgs.GetItemParent(i))
+ try:
+ idx = existing.index(realm)
+ except:
+ #ok, does not exist
+ continue
+ #nok, exists already
+ violation = ("[ " + realm + "." + app.win.orgs.GetItemText(i) +
+ ", " + realm + " ]")
+ dlg = wx.MessageDialog(self,
+ 'Invalid Selection ' + violation + '.\n\n' +
+ 'You can only have EITHER an Organization OR a
specific Department workload\n' +
+ 'in a single Run-time Exclusion Rule',
+ 'Adding Orgs/Depts workloads to a Run-time
Exclusion Rule',
+ wx.OK | wx.ICON_ERROR)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+ #check if any of the selections are already in the conflict set
+ overlap=[]
+ for l in alist:
+ for e in existing:
+ if l == e:
+ overlap.append(str(l))
+ if len(overlap):
+ if len(overlap) == 1:
+ message = "Selected item " + str(overlap) +\
+ " is already in the Run-time Exclusion rule and will be
ignored.\n\n Continue?"
+ else:
+ message = "Selected items " + str(overlap) +\
+ " are already in the Run-time Exclusion rule and will be
ignored.\n\n Continue?"
+ dlg = wx.MessageDialog(self,
+ message, 'Adding Orgs/Depts workloads to a
Run-time Exclusion rule',
+ wx.YES | wx.NO | wx.ICON_EXCLAMATION)
+ ret = dlg.ShowModal()
+ dlg.Destroy()
+ if ret != wx.ID_YES:
+ return
+
+ for s in alist:
+ try:
+ existing.index(s)
+ except Exception:
+ # s not yet in list box, add it
+ item.AddTypes([s])
+ self.RefreshMe()
+
+
+ def _DelConSelection(self, event):
+ eventid = event.GetId()
+ pos, item = self.GetCSBox(eventid)
+ idtuple = item.clb.GetSelections()
+ idlist = []
+ for i in idtuple:
+ idlist.append(i)
+ #delete reverse, otherwise item mubers get messed up while deleting
+ idlist.reverse()
+ for i in idlist:
+ item.clb.Delete(i)
+ item.RefreshMe()
+ if item.clb.GetCount() < 2:
+ dlg = wx.MessageDialog(self,
+ """Run-time exclusion set has less than two types.\n\n
+ Do you want to delete this rule?""",
+ 'Deleting Orgs/Depts workloads from a Run-time Exclusion
rule',
+ wx.YES| wx.NO | wx.ICON_QUESTION)
+ ret = dlg.ShowModal()
+ dlg.Destroy()
+ if ret == wx.ID_YES:
+ self.DelCSById(eventid)
+ return
+ else:
+ for i in item.clb.GetSelections():
+ item.clb.Deselect(i)
+ self.RefreshMe()
+
+
+class myCSPanel(wx.Panel):
+ def __init__(self, parent, ID, title, list=[]):
+ wx.Panel.__init__(self, parent.conflictspanel, -1)
+ self.parent = parent
+ cspansizer = wx.BoxSizer(wx.VERTICAL)
+ self.box = wx.StaticBox(self, -1, title)
+ csboxsizer = wx.StaticBoxSizer(self.box, wx.HORIZONTAL)
+ #left: type add/del
+ typesizer = wx.BoxSizer(wx.VERTICAL)
+ self.add_selection = wx.Button(self, ID+1, "--> Add",
style=wx.BU_EXACTFIT)
+ self.add_selection.SetToolTipString("Add Workload Selection To
Run-time Exclusion rule")
+ self.add_selection.SetHelpText(AddToExclusionButtonHelp)
+ self.add_selection.SetForegroundColour('MEDIUMBLUE')
+ points = self.add_selection.GetFont().GetPointSize()
+ addfont = wx.Font(points, family=wx.DEFAULT,
+ style=wx.FONTSTYLE_NORMAL, weight=wx.BOLD)
+ self.add_selection.SetFont(addfont)
+ self.box.SetFont(addfont)
+ typesizer.Add(self.add_selection, proportion = 0, flag = wx.EXPAND |
wx.ALL,border=0)
+ typesizer.Add((5,5))
+ self.del_selection = wx.Button(self, ID+2, "<-- Del",
style=wx.BU_EXACTFIT)
+ self.del_selection.SetToolTipString("Delete Workload Selection From
Run-time Exclusion Rule")
+ self.del_selection.SetHelpText(DelFromExclusionButtonHelp)
+ self.del_selection.SetForegroundColour('ORANGERED')
+ self.del_selection.SetFont(addfont)
+ typesizer.Add(self.del_selection, proportion = 0, flag = wx.EXPAND |
wx.ALL, border=0)
+ csboxsizer.Add(typesizer, proportion = 0, border=0)
+ csboxsizer.Add((5,5))
+ #middle: types
+ self.clb = wx.ListBox(self, id=-1, choices=list,
+ style= wx.LB_MULTIPLE | wx.LB_SORT )
+ self.clb.SetHelpText(ExclusionSetHelp)
+ csboxsizer.Add(self.clb, proportion=1, flag=wx.EXPAND | wx.ALL,
border=0)
+ csboxsizer.Add((5,5))
+ #right: Conflictset-global ops button
+ bmpsizer = wx.BoxSizer(wx.VERTICAL)
+ self.cbmp = buttons.GenBitmapButton(self, ID, conflict_bmp,
style=wx.BU_EXACTFIT)
+ self.cbmp.SetHelpText(ManageExclusionButtonHelp)
+ self.cbmp.SetToolTipString("Rename/Delete\nAssociated Run-time
Exclusion Rule")
+ bmpsizer.Add(self.cbmp, proportion = 0, flag = wx.EXPAND | wx.ALL,
border=0)
+ csboxsizer.Add(bmpsizer, proportion=0, border=5)
+ cspansizer.Add(csboxsizer, proportion=0, flag=wx.EXPAND | wx.ALL,
border=0)
+ self.csboxsizer=csboxsizer
+ self.cspansizer=cspansizer
+ self.SetSizer(cspansizer)
+ self.cbmp.Bind(wx.EVT_LEFT_DOWN, parent._OnClick, id=ID)
+ self.add_selection.Bind(wx.EVT_BUTTON, parent._AddOrgSelection, id=ID
+ 1)
+ self.del_selection.Bind(wx.EVT_BUTTON, parent._DelConSelection, id=ID
+ 2)
+
+ # append and delete an item to get rid of
+ # the ugly vertical scroll bar on the Listbox on Linux
+ def RefreshMe(self):
+ x = self.clb.Append(" ")
+ app.win.conspanel.RefreshMe()
+ self.clb.Delete(x)
+ self.Layout()
+ app.win.conspanel.Layout()
+
+
+ def AddTypes(self, list):
+ for i in list:
+ self.clb.Append(i)
+ self.RefreshMe()
+
+
+ def GetTypes(self):
+ alist = []
+ for i in range(0, self.clb.GetCount()):
+ alist.append(self.clb.GetString(i))
+ return alist
+
+
+ def GetBoxName(self):
+ return self.box.GetLabel()
+
+
+ def Replace(self, oldlabel, newlabel):
+ index = self.clb.FindString(oldlabel)
+ if index != wx.NOT_FOUND:
+ self.clb.SetString(index, newlabel)
+
+
+ def Delete(self, label):
+ index = self.clb.FindString(label)
+ if index != wx.NOT_FOUND:
+ self.clb.Delete(index)
+
+
+class myHelpPanel(wx.Panel):
+ def __init__(self, parent, ID):
+ wx.Panel.__init__(self, parent, -1)
+
+
+class ezFrame(wx.Frame):
+
+ ID_ABOUT = 101
+ ID_NEW = 102
+ ID_OPEN = 103
+ ID_SAVE = 104
+ ID_SAVEAS = 105
+ ID_EXIT = 106
+ ID_HELP = 107
+
+ ID_ITRENAME = 111
+ ID_ITADD = 112
+ ID_ITDEL = 113
+
+ ID_COLLAPSEALL = 121
+ ID_EXPANDALL = 122
+ ID_SORTALL = 123
+
+ ID_TRANSLATE = 131
+
+ ID_ORGEDT = 141
+ ID_ORGADD = 142
+ ID_ORGDEL = 143
+
+ def __init__(self, parent, ID, title):
+ global realm_bmp, workload_bmp, conflict_bmp
+
+ wx.Frame.__init__(self, parent, ID, title,
+ wx.DefaultPosition,
+ wx.Size(700,450)
+ )
+
+ realm_bmp = GetIconBitmap('Organization')
+ workload_bmp = GetIconBitmap('Department')
+ conflict_bmp = GetIconBitmap('Conflict')
+ self.SetHelpText(GetHelp)
+ self.orgfilename = None
+ self.CreateStatusBar()
+ self.SetStatusText("")
+ self.bkg = wx.Panel(self)
+
+ self.orgswin = wx.SashLayoutWindow(
+ self.bkg, -1, wx.DefaultPosition, (300, 150),wx.SW_3DSASH |
wx.SW_BORDER)
+
+ self.orgswin.SetDefaultSize((300,150))
+ self.orgswin.SetOrientation(wx.LAYOUT_VERTICAL)
+ self.orgswin.SetAlignment(wx.LAYOUT_LEFT)
+ self.orgspanel = OrgsPanel(self.orgswin, -1)
+ self.orgs = self.orgspanel.orgs
+
+ self.realm_menu = wx.Menu()
+ self.realm_menu.Append(self.ID_ORGADD, "Add Department\tctrl-a", "Add
Department Workload")
+ self.realm_menu.AppendSeparator()
+ self.realm_menu.AppendSeparator()
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|