WARNING - OLD ARCHIVES

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

xen-changelog

[Xen-changelog] [xen-unstable] Merge.

# HG changeset patch
# User Steven Smith <ssmith@xxxxxxxxxxxxx>
# Node ID cdd03c7ec8d33df2f382015b781b2d1e5f095b6e
# Parent  08a582a98471da30fb86bca620495f3d91d55800
# Parent  92bfc59726a4ebfff76994bce9445cb93fce9f76
Merge.
---
 tools/python/xen/xm/sysrq.py            |   32 -
 tools/firmware/vmxassist/machine.h      |    1 
 tools/firmware/vmxassist/vm86.c         |   87 +++-
 tools/python/xen/xend/XendDomainInfo.py |   34 +
 tools/python/xen/xm/addlabel.py         |   37 -
 tools/python/xen/xm/cfgbootpolicy.py    |   25 -
 tools/python/xen/xm/console.py          |    2 
 tools/python/xen/xm/create.py           |   81 +--
 tools/python/xen/xm/dry-run.py          |   20 
 tools/python/xen/xm/dumppolicy.py       |   11 
 tools/python/xen/xm/getlabel.py         |   36 -
 tools/python/xen/xm/labels.py           |   77 +--
 tools/python/xen/xm/loadpolicy.py       |   19 
 tools/python/xen/xm/main.py             |  666 ++++++++++++++++++--------------
 tools/python/xen/xm/makepolicy.py       |   10 
 tools/python/xen/xm/migrate.py          |   16 
 tools/python/xen/xm/opts.py             |   92 +++-
 tools/python/xen/xm/resources.py        |   25 -
 tools/python/xen/xm/rmlabel.py          |   32 -
 tools/python/xen/xm/shutdown.py         |    1 
 xen/arch/x86/hvm/platform.c             |   10 
 xen/arch/x86/hvm/svm/svm.c              |   16 
 xen/arch/x86/hvm/vmx/io.c               |    8 
 xen/arch/x86/hvm/vmx/vmx.c              |  139 ++++--
 xen/arch/x86/mm/shadow/common.c         |    2 
 xen/include/asm-x86/hvm/hvm.h           |    7 
 xen/include/asm-x86/hvm/svm/emulate.h   |   32 -
 xen/include/asm-x86/hvm/vmx/vmcs.h      |    3 
 xen/include/asm-x86/hvm/vmx/vmx.h       |   44 --
 xen/include/asm-x86/mm.h                |    3 
 30 files changed, 892 insertions(+), 676 deletions(-)

diff -r 08a582a98471 -r cdd03c7ec8d3 tools/firmware/vmxassist/machine.h
--- a/tools/firmware/vmxassist/machine.h        Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/firmware/vmxassist/machine.h        Fri Sep 22 17:22:18 2006 +0100
@@ -36,6 +36,7 @@
 #define CR4_VME                (1 << 0)
 #define CR4_PVI                (1 << 1)
 #define CR4_PSE                (1 << 4)
+#define CR4_PAE                (1 << 5)
 
 #define EFLAGS_ZF      (1 << 6)
 #define EFLAGS_TF      (1 << 8)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c   Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/firmware/vmxassist/vm86.c   Fri Sep 22 17:22:18 2006 +0100
@@ -52,29 +52,74 @@ static char *rnames[] = { "ax", "cx", "d
 static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
 #endif /* DEBUG */
 
+#define PDE_PS           (1 << 7)
 #define PT_ENTRY_PRESENT 0x1
 
+/* We only support access to <=4G physical memory due to 1:1 mapping */
 static unsigned
-guest_linear_to_real(unsigned long base, unsigned off)
-{
-       unsigned int gcr3 = oldctx.cr3;
-       unsigned int l1_mfn;
-       unsigned int l0_mfn;
+guest_linear_to_real(uint32_t base)
+{
+       uint32_t gcr3 = oldctx.cr3;
+       uint64_t l2_mfn;
+       uint64_t l1_mfn;
+       uint64_t 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);
+               return base;
+
+       if (!(oldctx.cr4 & CR4_PAE)) {
+               l1_mfn = ((uint32_t *)gcr3)[(base >> 22) & 0x3ff];
+
+               if (oldctx.cr4 & CR4_PSE || l1_mfn & PDE_PS) {
+                        /* 1 level page table */
+                       l0_mfn = l1_mfn;
+                       if (!(l0_mfn & PT_ENTRY_PRESENT))
+                               panic("l1 entry not present\n");
+
+                       l0_mfn &= 0xffc00000;
+                       return l0_mfn + (base & 0x3fffff);
+               }
+
+               if (!(l1_mfn & PT_ENTRY_PRESENT))
+                       panic("l2 entry not present\n");
+
+               l1_mfn &= 0xfffff000;
+               l0_mfn = ((uint32_t *)l1_mfn)[(base >> 12) & 0x3ff];
+               if (!(l0_mfn & PT_ENTRY_PRESENT))
+                       panic("l1 entry not present\n");
+               l0_mfn &= 0xfffff000;
+
+               return l0_mfn + (base & 0xfff);
+       } else if (oldctx.cr4 & CR4_PAE && !(oldctx.cr4 & CR4_PSE)) {
+               l2_mfn = ((uint64_t *)gcr3)[(base >> 30) & 0x3];
+               if (!(l2_mfn & PT_ENTRY_PRESENT))
+                       panic("l3 entry not present\n");
+               l2_mfn &= 0x3fffff000ULL;
+
+               l1_mfn = ((uint64_t *)l2_mfn)[(base >> 21) & 0x1ff];
+               if (!(l1_mfn & PT_ENTRY_PRESENT))
+                       panic("l2 entry not present\n");
+               l1_mfn &= 0x3fffff000ULL;
+
+               l0_mfn = ((uint64_t *)l1_mfn)[(base >> 12) & 0x1ff];
+               if (!(l0_mfn & PT_ENTRY_PRESENT))
+                       panic("l1 entry not present\n");
+               l0_mfn &= 0x3fffff000ULL;
+
+               return l0_mfn + (base & 0xfff);
+       } else { /* oldctx.cr4 & CR4_PAE && oldctx.cr4 & CR4_PSE */
+               l1_mfn = ((uint64_t *)gcr3)[(base >> 30) & 0x3];
+               if (!(l1_mfn & PT_ENTRY_PRESENT))
+                       panic("l2 entry not present\n");
+               l1_mfn &= 0x3fffff000ULL;
+
+               l0_mfn = ((uint64_t *)l1_mfn)[(base >> 21) & 0x1ff];
+               if (!(l0_mfn & PT_ENTRY_PRESENT))
+                       panic("l1 entry not present\n");
+               l0_mfn &= 0x3ffe00000ULL;
+
+               return l0_mfn + (base & 0x1fffff);
+       }
 }
 
 static unsigned
@@ -95,7 +140,8 @@ address(struct regs *regs, unsigned seg,
            (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg))
                return ((seg & 0xFFFF) << 4) + off;
 
-       entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base, 
0))[seg >> 3];
+       entry = ((unsigned long long *)
+                 guest_linear_to_real(oldctx.gdtr_base))[seg >> 3];
        entry_high = entry >> 32;
        entry_low = entry & 0xFFFFFFFF;
 
@@ -780,7 +826,8 @@ load_seg(unsigned long sel, uint32_t *ba
                return 1;
        }
 
-       entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base, 
0))[sel >> 3];
+       entry = ((unsigned long long *)
+                 guest_linear_to_real(oldctx.gdtr_base))[sel >> 3];
 
        /* Check the P bit first */
        if (!((entry >> (15+32)) & 0x1) && sel != 0)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Sep 22 17:22:18 2006 +0100
@@ -596,6 +596,8 @@ class XendDomainInfo:
             if self.info['memory'] == 0:
                 if self.infoIsSet('mem_kb'):
                     self.info['memory'] = (self.info['mem_kb'] + 1023) / 1024
+            if self.info['memory'] <= 0:
+                raise VmError('Invalid memory size')
 
             if self.info['maxmem'] < self.info['memory']:
                 self.info['maxmem'] = self.info['memory']
@@ -986,14 +988,18 @@ class XendDomainInfo:
                 this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime())
                 corefile = "/var/xen/dump/%s-%s.%s.core" % (this_time,
                                   self.info['name'], self.domid)
+                
+            if os.path.isdir(corefile):
+                raise XendError("Cannot dump core in a directory: %s" %
+                                corefile)
+            
             xc.domain_dumpcore(self.domid, corefile)
-
-        except:
+        except RuntimeError, ex:
             corefile_incomp = corefile+'-incomplete'
             os.rename(corefile, corefile_incomp)
             log.exception("XendDomainInfo.dumpCore failed: id = %s name = %s",
                           self.domid, self.info['name'])
-
+            raise XendError("Failed to dump core: %s" %  str(ex))
 
     ## public:
 
@@ -1001,6 +1007,9 @@ class XendDomainInfo:
         """Set the memory target of this domain.
         @param target In MiB.
         """
+        if target <= 0:
+            raise XendError('Invalid memory size')
+        
         log.debug("Setting memory target of domain %s (%d) to %d MiB.",
                   self.info['name'], self.domid, target)
         
@@ -1093,15 +1102,16 @@ class XendDomainInfo:
     ## public:
 
     def destroyDevice(self, deviceClass, devid):
-       if type(devid) is str:
-           devicePath = '%s/device/%s' % (self.dompath, deviceClass)
-           for entry in xstransact.List(devicePath):
-               backend = xstransact.Read('%s/%s' % (devicePath, entry), 
"backend")
-               devName = xstransact.Read(backend, "dev")
-               if devName == devid:
-                   # We found the integer matching our devid, use it instead
-                   devid = entry
-                   break
+        if type(devid) is str:
+            devicePath = '%s/device/%s' % (self.dompath, deviceClass)
+            for entry in xstransact.List(devicePath):
+                backend = xstransact.Read('%s/%s' % (devicePath, entry),
+                                          "backend")
+                devName = xstransact.Read(backend, "dev")
+                if devName == devid:
+                    # We found the integer matching our devid, use it instead
+                    devid = entry
+                    break
         return self.getDeviceController(deviceClass).destroyDevice(devid)
 
 
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/addlabel.py
--- a/tools/python/xen/xm/addlabel.py   Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/addlabel.py   Fri Sep 22 17:22:18 2006 +0100
@@ -19,19 +19,23 @@
 
 """Labeling a domain configuration file or a resoruce.
 """
-import sys, os
+import os
+import sys
+
 from xen.util import dictio
 from xen.util import security
+from xen.xm.opts import OptionError
 
-def usage():
-    print "\nUsage: xm addlabel <label> dom <configfile> [<policy>]"
-    print "       xm addlabel <label> res <resource> [<policy>]\n"
-    print "  This program adds an acm_label entry into the 'configfile'"
-    print "  for a domain or to the global resource label file for a"
-    print "  resource. It derives the policy from the running hypervisor"
-    print "  if it is not given (optional parameter). If a label already"
-    print "  exists for the given domain or resource, then addlabel fails.\n"
-    security.err("Usage")
+def help():
+    return """
+    Format: xm addlabel <label> dom <configfile> [<policy>]
+            xm addlabel <label> res <resource> [<policy>]
+    
+    This program adds an acm_label entry into the 'configfile'
+    for a domain or to the global resource label file for a
+    resource. It derives the policy from the running hypervisor
+    if it is not given (optional parameter). If a label already
+    exists for the given domain or resource, then addlabel fails."""
 
 
 def validate_config_file(configfile):
@@ -114,9 +118,8 @@ def main (argv):
 def main (argv):
     try:
         policyref = None
-        if len(argv) not in [4,5]:
-            usage()
-            return
+        if len(argv) not in (4, 5):
+            raise OptionError('Needs either 2 or 3 arguments')
 
         label = argv[1]
 
@@ -135,20 +138,20 @@ def main (argv):
                     if os.path.isfile(configfile):
                         break
             if not validate_config_file(configfile):
-                usage()
+                raise OptionError('Invalid config file')
             else:
                 add_domain_label(label, configfile, policyref)
         elif argv[2].lower() == "res":
             resource = argv[3]
             add_resource_label(label, resource, policyref)
         else:
-            usage()
-
+            raise OptionError('Need to specify either "dom" or "res" as object 
to add label to.')
+            
     except security.ACMError:
         sys.exit(-1)
 
-
 if __name__ == '__main__':
     main(sys.argv)
+    
 
 
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/cfgbootpolicy.py
--- a/tools/python/xen/xm/cfgbootpolicy.py      Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/cfgbootpolicy.py      Fri Sep 22 17:22:18 2006 +0100
@@ -28,20 +28,17 @@ from xen.util.security import policy_dir
 from xen.util.security import policy_dir_prefix, boot_filename, xen_title_re
 from xen.util.security import any_title_re, xen_kernel_re, kernel_ver_re, 
any_module_re
 from xen.util.security import empty_line_re, binary_name_re, policy_name_re
+from xen.xm.opts import OptionError
 
-
-def usage():
-    print "\nUsage: xm cfgbootpolicy <policy> [<kernelversion>]\n"
-    print "  Adds a 'module' line to the Xen grub.conf entry"
-    print "  so that xen boots into a specific access control"
-    print "  policy. If kernelversion is not given, then this"
-    print "  script tries to determine it by looking for a grub"
-    print "  entry with a line kernel xen.* If there are multiple"
-    print "  Xen entries, then it must be called with an explicit"
-    print "  version (it will fail otherwise).\n"
-    err("Usage")
-
-
+def help():
+    return """
+    Adds a 'module' line to the Xen grub.conf entry
+    so that xen boots into a specific access control
+    policy. If kernelversion is not given, then this
+    script tries to determine it by looking for a grub
+    entry with a line kernel xen.* If there are multiple
+    Xen entries, then it must be called with an explicit
+    version (it will fail otherwise).\n"""
 
 def determine_kernelversion(user_specified):
     within_xen_title = 0
@@ -152,7 +149,7 @@ def main(argv):
             policy = argv[1]
             user_kver = argv[2]
         else:
-            usage()
+            raise OptionError('Invalid number of arguments')
 
         if not policy_name_re.match(policy):
             err("Illegal policy name \'" + policy + "\'")
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/console.py
--- a/tools/python/xen/xm/console.py    Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/console.py    Fri Sep 22 17:22:18 2006 +0100
@@ -18,9 +18,7 @@
 
 XENCONSOLE = "xenconsole"
 
-
 import xen.util.auxbin
-
 
 def execConsole(domid):
     xen.util.auxbin.execute(XENCONSOLE, [str(domid)])
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/create.py     Fri Sep 22 17:22:18 2006 +0100
@@ -25,7 +25,6 @@ import socket
 import socket
 import re
 import xmlrpclib
-import traceback
 
 from xen.xend import sxp
 from xen.xend import PrettyPrint
@@ -57,7 +56,8 @@ gopts.opt('help', short='h',
 
 gopts.opt('help_config',
           fn=set_true, default=0,
-          use="Print help for the configuration script.")
+          use="Print the available configuration variables (vars) for the "
+          "configuration script.")
 
 gopts.opt('quiet', short='q',
           fn=set_true, default=0,
@@ -65,35 +65,36 @@ gopts.opt('quiet', short='q',
 
 gopts.opt('path', val='PATH',
           fn=set_value, default='.:/etc/xen',
-          use="""Search path for configuration scripts.
-         The value of PATH is a colon-separated directory list.""")
+          use="Search path for configuration scripts. "
+          "The value of PATH is a colon-separated directory list.")
 
 gopts.opt('defconfig', short='f', val='FILE',
           fn=set_value, default='xmdefconfig',
-          use="""Use the given Python configuration script.
-          The configuration script is loaded after arguments have been 
processed.
-          Each command-line option sets a configuration variable named after
-          its long option name, and these variables are placed in the
-          environment of the script before it is loaded.
-          Variables for options that may be repeated have list values.
-          Other variables can be set using VAR=VAL on the command line.
-        
-          After the script is loaded, option values that were not set on the
-          command line are replaced by the values set in the script.""")
+          use="Use the given Python configuration script."
+          "The configuration script is loaded after arguments have been "
+          "processed. Each command-line option sets a configuration "
+          "variable named after its long option name, and these "
+          "variables are placed in the environment of the script before "
+          "it is loaded. Variables for options that may be repeated have "
+          "list values. Other variables can be set using VAR=VAL on the "
+          "command line. "     
+          "After the script is loaded, option values that were not set "
+          "on the command line are replaced by the values set in the script.")
 
 gopts.default('defconfig')
 
 gopts.opt('config', short='F', val='FILE',
           fn=set_value, default=None,
-          use="""Domain configuration to use (SXP).
-          SXP is the underlying configuration format used by Xen.
-          SXP configurations can be hand-written or generated from Python 
configuration
-          scripts, using the -n (dryrun) option to print the configuration.""")
+          use="Domain configuration to use (SXP).\n"
+          "SXP is the underlying configuration format used by Xen.\n"
+          "SXP configurations can be hand-written or generated from Python "
+          "configuration scripts, using the -n (dryrun) option to print "
+          "the configuration.")
 
 gopts.opt('dryrun', short='n',
           fn=set_true, default=0,
-          use="""Dry run - print the configuration but don't create the domain.
-          Loads the configuration script, creates the SXP configuration and 
prints it.""")
+          use="Dry run - prints the resulting configuration in SXP but "
+          "does not create the domain.")
 
 gopts.opt('paused', short='p',
           fn=set_true, default=0,
@@ -105,18 +106,16 @@ gopts.opt('console_autoconnect', short='
 
 gopts.var('vncviewer', val='no|yes',
           fn=set_bool, default=None,
-          use="""Spawn a vncviewer listening for a vnc server in the domain.
-          The address of the vncviewer is passed to the domain on the kernel 
command
-          line using 'VNC_SERVER=<host>:<port>'. The port used by vnc is 5500 
+ DISPLAY.
-          A display value with a free port is chosen if possible.
-          Only valid when vnc=1.
-          """)
+           use="Spawn a vncviewer listening for a vnc server in the domain.\n"
+           "The address of the vncviewer is passed to the domain on the "
+           "kernel command line using 'VNC_SERVER=<host>:<port>'. The port "
+           "used by vnc is 5500 + DISPLAY. A display value with a free port "
+           "is chosen if possible.\nOnly valid when vnc=1.")
 
 gopts.var('vncconsole', val='no|yes',
           fn=set_bool, default=None,
-          use="""Spawn a vncviewer process for the domain's graphical console.
-          Only valid when vnc=1.
-          """)
+          use="Spawn a vncviewer process for the domain's graphical console.\n"
+          "Only valid when vnc=1.")
 
 gopts.var('name', val='NAME',
           fn=set_value, default=None,
@@ -439,7 +438,6 @@ gopts.var('uuid', val='',
           will be randomly generated if this option is not set, just like MAC 
           addresses for virtual network interfaces.  This must be a unique 
           value across the entire cluster.""")
-
 
 def err(msg):
     """Print an error to stderr and exit.
@@ -490,7 +488,6 @@ def configure_disks(config_devs, vals):
     """Create the config for disks (virtual block devices).
     """
     for (uname, dev, mode, backend) in vals.disk:
-
         if uname.startswith('tap:'):
             cls = 'tap'
         else:
@@ -851,7 +848,6 @@ def choose_vnc_display():
         if port in ports: continue
         return d
     return None
-
 vncpid = None
 
 def daemonize(prog, args):
@@ -885,7 +881,6 @@ def daemonize(prog, args):
             w.write(str(pid2 or 0))
             w.close()
             os._exit(0)
-
     os.close(w)
     r = os.fdopen(r)
     daemon_pid = int(r.read())
@@ -904,6 +899,7 @@ def spawn_vnc(display):
     vncpid = daemonize("vncviewer", vncargs)
     if vncpid == 0:
         return 0
+
     return VNC_BASE_PORT + display
 
 def preprocess_vnc(vals):
@@ -1019,11 +1015,10 @@ def parseCommandLine(argv):
 def parseCommandLine(argv):
     gopts.reset()
     args = gopts.parse(argv)
-    if gopts.vals.help:
-        gopts.usage()
+
     if gopts.vals.help or gopts.vals.help_config:
-        gopts.load_defconfig(help=1)
-    if gopts.vals.help or gopts.vals.help_config:
+        if gopts.vals.help_config:
+            print gopts.val_usage()
         return (None, None)
 
     if not gopts.vals.display:
@@ -1091,7 +1086,6 @@ def check_domain_label(config, verbose):
 
     return answer
 
-
 def config_security_check(config, verbose):
     """Checks each resource listed in the config to see if the active
        policy will permit creation of a new domain using the config.
@@ -1145,7 +1139,6 @@ def config_security_check(config, verbos
 
     return answer
 
-
 def create_security_check(config):
     passed = 0
     try:
@@ -1158,7 +1151,9 @@ def create_security_check(config):
         sys.exit(-1)
 
     return passed
-
+  
+def help():
+    return str(gopts)
 
 def main(argv):
     try:
@@ -1176,11 +1171,11 @@ def main(argv):
         PrettyPrint.prettyprint(config)
     else:
         if not create_security_check(config):
-            err("Security configuration prevents domain from starting.")
+            raise OptionError('Security Configuration prevents domain from 
starting')
         else:
             dom = make_domain(opts, config)
             if opts.vals.console_autoconnect:
-                console.execConsole(dom)
-        
+                console.execConsole(dom)        
+             
 if __name__ == '__main__':
     main(sys.argv)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/dry-run.py
--- a/tools/python/xen/xm/dry-run.py    Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/dry-run.py    Fri Sep 22 17:22:18 2006 +0100
@@ -22,20 +22,18 @@ from xen.util import security
 from xen.util import security
 from xen.xm import create
 from xen.xend import sxp
+from xen.xm.opts import OptionError
 
-def usage():
-    print "\nUsage: xm dry-run <configfile>\n"
-    print "This program checks each resource listed in the configfile"
-    print "to see if the domain created by the configfile can access"
-    print "the resources.  The status of each resource is listed"
-    print "individually along with the final security decision.\n"
-    security.err("Usage")
-
+def help():
+    return """
+    This program checks each resource listed in the configfile
+    to see if the domain created by the configfile can access
+    the resources.  The status of each resource is listed
+    individually along with the final security decision."""
 
 def main (argv):
-    try:
-        if len(argv) != 2:
-            usage()
+    if len(argv) != 2:
+        raise OptionError('Invalid number of arguments')
 
         passed = 0
         (opts, config) = create.parseCommandLine(argv)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/dumppolicy.py
--- a/tools/python/xen/xm/dumppolicy.py Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/dumppolicy.py Fri Sep 22 17:22:18 2006 +0100
@@ -21,12 +21,10 @@ from xen.util.security import ACMError, 
 from xen.util.security import ACMError, err, dump_policy
 
 
-def usage():
-    print "\nUsage: xm dumppolicy\n"
-    print " Retrieve and print currently enforced"
-    print " hypervisor policy information (low-level).\n"
-    err("Usage")
-
+def help():
+    return """
+    Retrieve and print currently enforced hypervisor policy information
+    (low-level)."""
 
 def main(argv):
     try:
@@ -34,7 +32,6 @@ def main(argv):
             usage()
 
         dump_policy()
-
     except ACMError:
         sys.exit(-1)
 
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/getlabel.py
--- a/tools/python/xen/xm/getlabel.py   Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/getlabel.py   Fri Sep 22 17:22:18 2006 +0100
@@ -21,13 +21,13 @@ import sys, os, re
 import sys, os, re
 from xen.util import dictio
 from xen.util import security
+from xen.xm.opts import OptionError
 
-def usage():
-    print "\nUsage: xm getlabel dom <configfile>"
-    print "       xm getlabel res <resource>\n"
-    print "  This program shows the label for a domain or resource.\n"
-    security.err("Usage")
-
+def help():
+    return """
+    Usage: xm getlabel dom <configfile>"
+           xm getlabel res <resource>\n"
+    This program shows the label for a domain or resource."""
 
 def get_resource_label(resource):
     """Gets the resource label
@@ -90,21 +90,17 @@ def get_domain_label(configfile):
 
 
 def main (argv):
-    try:
-        if len(argv) != 3:
-            usage()
+    if len(argv) != 3:
+        raise OptionError('Requires 2 arguments')
 
-        if argv[1].lower() == "dom":
-            configfile = argv[2]
-            get_domain_label(configfile)
-        elif argv[1].lower() == "res":
-            resource = argv[2]
-            get_resource_label(resource)
-        else:
-            usage()
-
-    except security.ACMError:
-        sys.exit(-1)
+    if argv[1].lower() == "dom":
+        configfile = argv[2]
+        get_domain_label(configfile)
+    elif argv[1].lower() == "res":
+        resource = argv[2]
+        get_resource_label(resource)
+    else:
+        raise OptionError('First subcommand argument must be "dom" or "res"')
 
 if __name__ == '__main__':
     main(sys.argv)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/labels.py
--- a/tools/python/xen/xm/labels.py     Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/labels.py     Fri Sep 22 17:22:18 2006 +0100
@@ -23,49 +23,46 @@ import string
 import string
 from xen.util.security import ACMError, err, list_labels, active_policy
 from xen.util.security import vm_label_re, res_label_re, all_label_re
+from xen.xm.opts import OptionError
 
-def usage():
-    print "\nUsage: xm labels [<policy>] [<type=dom|res|any>]\n"
-    print " Prints labels of the specified type (default is dom)"
-    print " that are defined in policy (default is current"
-    print " hypervisor policy).\n"
-    err("Usage")
 
+def help():
+    return """
+    Prints labels of the specified type (default is dom)
+    that are defined in policy (default is current hypervisor policy)."""
 
 def main(argv):
+    policy = None
+    ptype = None
+    for arg in argv[1:]:
+        key_val = arg.split('=')
+        if len(key_val) == 2 and key_val[0] == 'type':
+            if ptype:
+                raise OptionError('type is definied twice')
+            ptype = key_val[1].lower()
+
+        elif len(key_val) == 1:
+            if policy:
+                raise OptionError('policy is defined twice')
+            policy = arg
+        else:
+            raise OptionError('Unrecognised option: %s' % arg)
+
+    if not policy:
+        policy = active_policy
+        if active_policy in ['NULL', 'INACTIVE', 'DEFAULT']:
+            raise OptionError('No policy active, you must specify a <policy>')
+
+    if not ptype or ptype == 'dom':
+        condition = vm_label_re
+    elif ptype == 'res':
+        condition = res_label_re
+    elif ptype == 'any':
+        condition = all_label_re
+    else:
+        err("Unknown label type \'" + ptype + "\'")
+
     try:
-        policy = None
-        type = None
-        for i in argv[1:]:
-            i_s = string.split(i, '=')
-            if len(i_s) > 1:
-                if (i_s[0] == 'type') and (len(i_s) == 2):
-                    if not type:
-                        type = i_s[1]
-                    else:
-                        usage()
-                else:
-                    usage()
-            else:
-                if not policy:
-                    policy = i
-                else:
-                    usage()
-
-        if not policy:
-            policy = active_policy
-            if active_policy in ['NULL', 'INACTIVE', 'DEFAULT']:
-                err("No policy active. Please specify the <policy> parameter.")
-
-        if not type or (type in ['DOM', 'dom']):
-            condition = vm_label_re
-        elif type in ['RES', 'res']:
-            condition = res_label_re
-        elif type in ['ANY', 'any']:
-            condition = all_label_re
-        else:
-            err("Unknown label type \'" + type + "\'")
-
         labels = list_labels(policy, condition)
         labels.sort()
         for label in labels:
@@ -74,9 +71,7 @@ def main(argv):
     except ACMError:
         sys.exit(-1)
     except:
-        traceback.print_exc(limit=1)
-        sys.exit(-1)
-
+        traceback.print_exc(limit = 1)
 
 if __name__ == '__main__':
     main(sys.argv)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/loadpolicy.py
--- a/tools/python/xen/xm/loadpolicy.py Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/loadpolicy.py Fri Sep 22 17:22:18 2006 +0100
@@ -21,26 +21,23 @@ import sys
 import sys
 import traceback
 from xen.util.security import ACMError, err, load_policy
+from xen.xm.opts import OptionError
 
-
-def usage():
-    print "\nUsage: xm loadpolicy <policy>\n"
-    print " Load the compiled binary (.bin) policy"
-    print " into the running hypervisor.\n"
-    err("Usage")
+def help():
+    return """Load the compiled binary (.bin) policy into the running
+    hypervisor."""
 
 def main(argv):
+    if len(argv) != 2:
+        raise OptionError('No policy defined')
+    
     try:
-        if len(argv) != 2:
-            usage()
         load_policy(argv[1])
 
     except ACMError:
         sys.exit(-1)
     except:
-        traceback.print_exc(limit=1)
-        sys.exit(-1)
-
+        traceback.print_exc(limit = 1)
 
 if __name__ == '__main__':
     main(sys.argv)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/main.py       Fri Sep 22 17:22:18 2006 +0100
@@ -22,28 +22,27 @@
 """Grand unified management application for Xen.
 """
 import os
-import os.path
 import sys
 import re
 import getopt
 import socket
-import warnings
-warnings.filterwarnings('ignore', category=FutureWarning)
+import traceback
 import xmlrpclib
 import traceback
 import datetime
-
-import xen.xend.XendProtocol
+from select import select
+
+import warnings
+warnings.filterwarnings('ignore', category=FutureWarning)
 
 from xen.xend import PrettyPrint
 from xen.xend import sxp
-from xen.xm.opts import *
-
-import console
-import xen.xend.XendClient
+from xen.xend import XendClient
 from xen.xend.XendClient import server
+
+from xen.xm.opts import OptionError, Opts, wrap, set_true
+from xen.xm import console
 from xen.util import security
-from select import select
 
 # getopt.gnu_getopt is better, but only exists in Python 2.3+.  Use
 # getopt.getopt if gnu_getopt is not available.  This will mean that options
@@ -51,93 +50,148 @@ if not hasattr(getopt, 'gnu_getopt'):
 if not hasattr(getopt, 'gnu_getopt'):
     getopt.gnu_getopt = getopt.getopt
 
-
-# Strings for shorthelp
-console_help = "console <DomId>                  Attach to domain DomId's 
console."
-create_help =  """create [-c] <ConfigFile>
-               [Name=Value]..       Create a domain based on Config File"""
-destroy_help = "destroy <DomId>                  Terminate a domain 
immediately"
-dump_core_help =   """dump-core [-L|--live][-C|--crash]
-            <DomId> [FileName]      Dump core of the specified domain"""
-
-help_help =    "help                             Display this message"
-list_help =    "list [--long] [DomId, ...]       List information about 
domains"
-list_label_help = "list [--label] [DomId, ...]      List information about 
domains including their labels"
-
-mem_max_help = "mem-max <DomId> <Mem>            Set maximum memory 
reservation for a domain"
-mem_set_help = "mem-set <DomId> <Mem>            Adjust the current memory 
usage for a domain"
-migrate_help = "migrate <DomId> <Host>           Migrate a domain to another 
machine"
-pause_help =   "pause <DomId>                    Pause execution of a domain"
-reboot_help =  "reboot <DomId> [-w][-a]          Reboot a domain"
-restore_help = "restore <File>                   Create a domain from a saved 
state file"
-save_help =    "save <DomId> <File>              Save domain state (and 
config) to file"
-shutdown_help ="shutdown <DomId> [-w][-a][-R|-H] Shutdown a domain"
-top_help =     "top                              Monitor system and domains in 
real-time"
-unpause_help = "unpause <DomId>                  Unpause a paused domain"
-uptime_help  = "uptime [-s|--short] [DomId, ...] List uptime for domains"
-
-help_spacer = """
-   """
-
-# Strings for longhelp
-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 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"
-info_help =    "info                             Get information about the xen 
host"
-rename_help =  "rename <DomId> <New Name>        Rename a domain"
-log_help =     "log                              Print the xend log"
-sched_sedf_help = "sched-sedf [DOM] [OPTIONS]       Show|Set simple EDF 
parameters\n" + \
-"              -p, --period          Relative deadline(ms).\n\
-              -s, --slice           Worst-case execution time(ms)\n\
-                                    (slice < period).\n\
-              -l, --latency         scaled period(ms) in case the domain\n\
-                                    is doing heavy I/O.\n\
-              -e, --extra           flag (0/1) which controls whether the\n\
-                                    domain can run in extra-time\n\
-              -w, --weight          mutually exclusive with period/slice and\n\
-                                    specifies another way of setting a 
domain's\n\
-                                    cpu period/slice."
-
-sched_credit_help = "sched-credit                           Set or get credit 
scheduler parameters"
-block_attach_help = """block-attach <DomId> <BackDev> <FrontDev> <Mode>
-                [BackDomId]         Create a new virtual block device"""
-block_detach_help = """block-detach  <DomId> <DevId>    Destroy a domain's 
virtual block device,
-                                    where <DevId> may either be the device ID
-                                    or the device name as mounted in the 
guest"""
-
-block_list_help = "block-list <DomId> [--long]      List virtual block devices 
for a domain"
-block_configure_help = """block-configure <DomId> <BackDev> <FrontDev> <Mode>
-                   [BackDomId] Change block device configuration"""
-network_attach_help = """network-attach  <DomID> [script=<script>] [ip=<ip>] 
[mac=<mac>]
-                           [bridge=<bridge>] [backend=<backDomID>]
-                                    Create a new virtual network device """
-network_detach_help = """network-detach  <DomId> <DevId>  Destroy a domain's 
virtual network
-                                    device, where <DevId> is the device ID."""
-
-network_list_help = "network-list <DomId> [--long]    List virtual network 
interfaces for a domain"
-vnet_list_help = "vnet-list [-l|--long]            list vnets"
-vnet_create_help = "vnet-create <config>             create a vnet from a 
config file"
-vnet_delete_help = "vnet-delete <vnetid>             delete a vnet"
-vtpm_list_help = "vtpm-list <DomId> [--long]       list virtual TPM devices"
-addlabel_help =  "addlabel <label> dom <configfile> Add security label to 
domain\n            <label> res <resource>   or resource"
-rmlabel_help =  "rmlabel dom <configfile>         Remove security label from 
domain\n           res <resource>           or resource"
-getlabel_help =  "getlabel dom <configfile>        Show security label for 
domain\n            res <resource>          or resource"
-dry_run_help =  "dry-run <configfile>             Tests if domain can access 
its resources"
-resources_help =  "resources                        Show info for each labeled 
resource"
-cfgbootpolicy_help = "cfgbootpolicy <policy>           Add policy to boot 
configuration "
-dumppolicy_help = "dumppolicy                       Print hypervisor ACM state 
information"
-loadpolicy_help = "loadpolicy <policy>              Load binary policy into 
hypervisor"
-makepolicy_help = "makepolicy <policy>              Build policy and create 
.bin/.map files"
-labels_help     = "labels [policy] [type=DOM|..]    List <type> labels for 
(active) policy."
-serve_help      = "serve                            Proxy Xend XML-RPC over 
stdio"
-
-short_command_list = [
+# General help message
+
+USAGE_HELP = "Usage: xm <subcommand> [args]\n\n" \
+             "Control, list, and manipulate Xen guest instances.\n"
+
+USAGE_FOOTER = '<Domain> can either be the Domain Name or Id.\n' \
+               'For more help on \'xm\' see the xm(1) man page.\n' \
+               'For more help on \'xm create\' see the xmdomain.cfg(5) '\
+               ' man page.\n'
+
+# Help strings are indexed by subcommand name in this way:
+# 'subcommand': (argstring, description)
+
+SUBCOMMAND_HELP = {
+    # common commands
+    
+    'console'     : ('<Domain>',
+                     'Attach to <Domain>\'s console.'),
+    'create'      : ('<ConfigFile> [options] [vars]',
+                     'Create a domain based on <ConfigFile>.'),
+    'destroy'     : ('<Domain>',
+                     'Terminate a domain immediately.'),
+    'help'        : ('', 'Display this message.'),
+    'list'        : ('[options] [Domain, ...]',
+                     'List information about all/some domains.'),
+    'mem-max'     : ('<Domain> <Mem>',
+                     'Set the maximum amount reservation for a domain.'),
+    'mem-set'     : ('<Domain> <Mem>',
+                     'Set the current memory usage for a domain.'),
+    'migrate'     : ('<Domain> <Host>',
+                     'Migrate a domain to another machine.'),
+    'pause'       : ('<Domain>', 'Pause execution of a domain.'),
+    'reboot'      : ('<Domain> [-wa]', 'Reboot a domain.'),
+    'restore'     : ('<CheckpointFile>',
+                     'Restore a domain from a saved state.'),
+    'save'        : ('<Domain> <CheckpointFile>',
+                     'Save a domain state to restore later.'),
+    'shutdown'    : ('<Domain> [-waRH]', 'Shutdown a domain.'),
+    'top'         : ('', 'Monitor a host and the domains in real time.'),
+    'unpause'     : ('<Domain>', 'Unpause a paused domain.'),
+    'uptime'      : ('[-s] <Domain>', 'Print uptime for a domain.'),
+
+    # less used commands
+
+    'dmesg'       : ('[-c|--clear]',
+                     'Read and/or clear Xend\'s message buffer.'),
+    'domid'       : ('<DomainName>', 'Convert a domain name to domain id.'),
+    'domname'     : ('<DomId>', 'Convert a domain id to domain name.'),
+    'dump-core'   : ('[-L|--live] [-C|--crash] <Domain> [Filename]',
+                     'Dump core for a specific domain.'),
+    'info'        : ('', 'Get information about Xen host.'),
+    'log'         : ('', 'Print Xend log'),
+    'rename'      : ('<Domain> <NewDomainName>', 'Rename a domain.'),
+    'sched-sedf'  : ('<Domain> [options]', 'Get/set EDF parameters.'),
+    'sched-credit': ('-d <Domain> [-w[=WEIGHT]|-c[=CAP]]',
+                     'Get/set credit scheduler parameters.'),
+    'sysrq'       : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
+    'vcpu-list'   : ('[<Domain>]',
+                     'List the VCPUs for a domain or all domains.'),
+    'vcpu-pin'    : ('<Domain> <VCPU> <CPUs>',
+                     'Set which CPUs a VCPU can use.'),
+    'vcpu-set'    : ('<Domain> <vCPUs>',
+                     'Set the number of active VCPUs for allowed for the'
+                     ' domain.'),
+
+    # device commands
+
+    'block-attach'  :  ('<Domain> <BackDev> <FrontDev> <Mode>',
+                        'Create a new virtual block device.'),
+    'block-configure': ('<Domain> <BackDev> <FrontDev> <Mode> [BackDomId]',
+                        'Change block device configuration'),
+    'block-detach'  :  ('<Domain> <DevId>',
+                        'Destroy a domain\'s virtual block device.'),
+    'block-list'    :  ('<Domain> [--long]',
+                        'List virtual block devices for a domain.'),
+    'network-attach':  ('<Domain> [--script=<script>] [--ip=<ip>] '
+                        '[--mac=<mac>]',
+                        'Create a new virtual network device.'),
+    'network-detach':  ('<Domain> <DevId>',
+                        'Destroy a domain\'s virtual network device.'),
+    'network-list'  :  ('<Domain> [--long]',
+                        'List virtual network interfaces for a domain.'),
+    'vnet-create'   :  ('<ConfigFile>','Create a vnet from ConfigFile.'),
+    'vnet-delete'   :  ('<VnetId>', 'Delete a Vnet.'),
+    'vnet-list'     :  ('[-l|--long]', 'List Vnets.'),
+    'vtpm-list'     :  ('<Domain> [--long]', 'List virtual TPM devices.'),
+
+    # security
+
+    'addlabel'      :  ('<label> {dom <ConfigFile>|res <resource>} [<policy>]',
+                        'Add security label to domain.'),
+    'rmlabel'       :  ('{dom <ConfigFile>|res <Resource>}',
+                        'Remove a security label from domain.'),
+    'getlabel'      :  ('{dom <ConfigFile>|res <Resource>}',
+                        'Show security label for domain or resource.'),
+    'dry-run'       :  ('<ConfigFile>',
+                        'Test if a domain can access its resources.'),
+    'resources'     :  ('', 'Show info for each labeled resource.'),
+    'cfgbootpolicy' :  ('<policy> [kernelversion]',
+                        'Add policy to boot configuration.'),
+    'dumppolicy'    :  ('', 'Print hypervisor ACM state information.'),
+    'loadpolicy'    :  ('<policy.bin>', 'Load binary policy into hypervisor.'),
+    'makepolicy'    :  ('<policy>', 'Build policy and create .bin/.map '
+                        'files.'),
+    'labels'        :  ('[policy] [type=dom|res|any]',
+                        'List <type> labels for (active) policy.'),
+    'serve'         :  ('', 'Proxy Xend XMLRPC over stdio.'),
+}
+
+SUBCOMMAND_OPTIONS = {
+    'sched-sedf': (
+       ('-p [MS]', '--period[=MS]', 'Relative deadline(ms)'),
+       ('-s [MS]', '--slice[=MS]' ,
+        'Worst-case execution time(ms). (slice < period)'),
+       ('-l [MS]', '--latency[=MS]',
+        'Scaled period (ms) when domain performs heavy I/O'),
+       ('-e [FLAG]', '--extra[=FLAG]',
+        'Flag (0 or 1) controls if domain can run in extra time.'),
+       ('-w [FLOAT]', '--weight[=FLOAT]',
+        'CPU Period/slice (do not set with --period/--slice)'),
+    ),
+    'sched-credit': (
+       ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
+       ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
+       ('-c CAP',    '--cap=CAP',       'Cap (int)'),
+    ),
+    'list': (
+       ('-l', '--long', 'Output all VM details in SXP'),
+       ('', '--label',  'Include security labels'),
+    ),
+    'dmesg': (
+       ('-c', '--clear', 'Clear dmesg buffer'),
+    ),
+    'vnet-list': (
+       ('-l', '--long', 'List Vnets as SXP'),
+    ),
+    'network-list': (
+       ('-l', '--long', 'List resources as SXP'),
+    ),
+}
+
+common_commands = [
     "console",
     "create",
     "destroy",
@@ -165,7 +219,6 @@ domain_commands = [
     "domname",
     "dump-core",
     "list",
-    "list_label",
     "mem-max",
     "mem-set",
     "migrate",
@@ -223,67 +276,105 @@ acm_commands = [
     "makepolicy",
     "loadpolicy",
     "cfgbootpolicy",
-    "dumppolicy"
+    "dumppolicy",
     ]
 
 all_commands = (domain_commands + host_commands + scheduler_commands +
                 device_commands + vnet_commands + acm_commands)
 
-
-def commandToHelp(cmd):
-    return eval(cmd.replace("-", "_") + "_help")
-
-
-shorthelp = """Usage: xm <subcommand> [args]
-    Control, list, and manipulate Xen guest instances
-
-xm common subcommands:
-   """  + help_spacer.join(map(commandToHelp, short_command_list))  + """
-
-<DomName> can be substituted for <DomId> in xm subcommands.
-
-For a complete list of subcommands run 'xm help --long'
-For more help on xm see the xm(1) man page
-For more help on xm create, see the xmdomain.cfg(5) man page"""
-
-longhelp = """Usage: xm <subcommand> [args]
-    Control, list, and manipulate Xen guest instances
-
-xm full list of subcommands:
-
-  Domain Commands:
-   """ + help_spacer.join(map(commandToHelp,  domain_commands)) + """
-
-  Xen Host Commands:
-   """ + help_spacer.join(map(commandToHelp,  host_commands)) + """
-
-  Scheduler Commands:
-   """ + help_spacer.join(map(commandToHelp,  scheduler_commands)) + """
-
-  Virtual Device Commands:
-   """  + help_spacer.join(map(commandToHelp, device_commands)) + """
-
-  Vnet commands:
-   """ + help_spacer.join(map(commandToHelp,  vnet_commands)) + """
-
-  Access Control commands:
-   """ + help_spacer.join(map(commandToHelp,  acm_commands)) + """
-
-<DomName> can be substituted for <DomId> in xm subcommands.
-
-For a short list of subcommands run 'xm help'
-For more help on xm see the xm(1) man page
-For more help on xm create, see the xmdomain.cfg(5) man page"""
-
-# array for xm help <command>
-help = {
-    "--long": longhelp
-    }
-
-for command in all_commands:
-    # create is handled specially
-    if (command != 'create'):
-        help[command] = commandToHelp(command)
+####################################################################
+#
+#  Help/usage printing functions
+#
+####################################################################
+
+def cmdHelp(cmd):
+    """Print help for a specific subcommand."""
+    
+    try:
+        args, desc = SUBCOMMAND_HELP[cmd]
+    except KeyError:
+        shortHelp()
+        return
+    
+    print 'Usage: xm %s %s' % (cmd, args)
+    print
+    print desc
+    
+    try:
+        # If options help message is defined, print this.
+        for shortopt, longopt, desc in SUBCOMMAND_OPTIONS[cmd]:
+            if shortopt and longopt:
+                optdesc = '%s, %s' % (shortopt, longopt)
+            elif shortopt:
+                optdesc = shortopt
+            elif longopt:
+                optdesc = longopt
+
+            wrapped_desc = wrap(desc, 43)   
+            print '  %-30s %-43s' % (optdesc, wrapped_desc[0])
+            for line in wrapped_desc[1:]:
+                print ' ' * 33 + line
+        print
+    except KeyError:
+        # if the command is an external module, we grab usage help
+        # from the module itself.
+        if cmd in IMPORTED_COMMANDS:
+            try:
+                cmd_module =  __import__(cmd, globals(), locals(), 'xen.xm')
+                cmd_usage = getattr(cmd_module, "help", None)
+                if cmd_usage:
+                    print cmd_usage()
+            except ImportError:
+                pass
+        
+def shortHelp():
+    """Print out generic help when xm is called without subcommand."""
+    
+    print USAGE_HELP
+    print 'Common \'xm\' commands:\n'
+    
+    for command in common_commands:
+        try:
+            args, desc = SUBCOMMAND_HELP[command]
+        except KeyError:
+            continue
+        wrapped_desc = wrap(desc, 50)
+        print ' %-20s %-50s' % (command, wrapped_desc[0])
+        for line in wrapped_desc[1:]:
+            print ' ' * 22 + line
+
+    print
+    print USAGE_FOOTER
+    print 'For a complete list of subcommands run \'xm help\'.'
+    
+def longHelp():
+    """Print out full help when xm is called with xm --help or xm help"""
+    
+    print USAGE_HELP
+    print 'xm full list of subcommands:\n'
+    
+    for command in all_commands:
+        try:
+            args, desc = SUBCOMMAND_HELP[command]
+        except KeyError:
+            continue
+
+        wrapped_desc = wrap(desc, 50)
+        print ' %-20s %-50s' % (command, wrapped_desc[0])
+        for line in wrapped_desc[1:]:
+            print ' ' * 22 + line        
+
+    print
+    print USAGE_FOOTER        
+
+def usage(cmd = None):
+    """ Print help usage information and exits """
+    if cmd:
+        cmdHelp(cmd)
+    else:
+        shortHelp()
+    sys.exit(1)
 
 
 ####################################################################
@@ -298,7 +389,7 @@ def arg_check(args, name, lo, hi = -1):
     if hi == -1:
         if n != lo:
             err("'xm %s' requires %d argument%s.\n" % (name, lo,
-                                                       lo > 1 and 's' or ''))
+                                                       lo == 1 and '' or 's'))
             usage(name)
     else:
         if n < lo or n > hi:
@@ -345,14 +436,19 @@ def xm_save(args):
 def xm_save(args):
     arg_check(args, "save", 2)
 
-    dom = args[0] # TODO: should check if this exists
+    try:
+        dominfo = parse_doms_info(server.xend.domain(args[0]))
+    except xmlrpclib.Fault, ex:
+        raise ex
+    
+    domid = dominfo['domid']
     savefile = os.path.abspath(args[1])
 
     if not os.access(os.path.dirname(savefile), os.W_OK):
         err("xm save: Unable to create file %s" % savefile)
         sys.exit(1)
     
-    server.xend.domain.save(dom, savefile)
+    server.xend.domain.save(domid, savefile)
     
 def xm_restore(args):
     arg_check(args, "restore", 1)
@@ -366,9 +462,9 @@ def xm_restore(args):
     server.xend.domain.restore(savefile)
 
 
-def getDomains(domain_names):
+def getDomains(domain_names, full = 0):
     if domain_names:
-        return map(server.xend.domain, domain_names)
+        return [server.xend.domain(dom) for dom in domain_names]
     else:
         return server.xend.domains(1)
 
@@ -378,9 +474,11 @@ def xm_list(args):
     show_vcpus = 0
     show_labels = 0
     try:
-        (options, params) = getopt.gnu_getopt(args, 'lv', 
['long','vcpus','label'])
+        (options, params) = getopt.gnu_getopt(args, 'lv',
+                                              ['long','vcpus','label'])
     except getopt.GetoptError, opterr:
         err(opterr)
+        usage('list')
         sys.exit(1)
     
     for (k, v) in options:
@@ -397,7 +495,7 @@ def xm_list(args):
         xm_vcpu_list(params)
         return
 
-    doms = getDomains(params)
+    doms = getDomains(params, use_long)
 
     if use_long:
         map(PrettyPrint.prettyprint, doms)
@@ -412,7 +510,7 @@ def parse_doms_info(info):
         return t(sxp.child_value(info, n, d))
     
     return {
-        'dom'      : get_info('domid',        int,   -1),
+        'domid'    : get_info('domid',        int,   -1),
         'name'     : get_info('name',         str,   '??'),
         'mem'      : get_info('memory',       int,   0),
         'vcpus'    : get_info('online_vcpus', int,   0),
@@ -428,7 +526,7 @@ def parse_sedf_info(info):
         return t(sxp.child_value(info, n, d))
 
     return {
-        'dom'      : get_info('domain',        int,   -1),
+        'domid'    : get_info('domid',         int,   -1),
         'period'   : get_info('period',        int,   -1),
         'slice'    : get_info('slice',         int,   -1),
         'latency'  : get_info('latency',       int,   -1),
@@ -436,34 +534,40 @@ def parse_sedf_info(info):
         'weight'   : get_info('weight',        int,   -1),
         }
 
-
 def xm_brief_list(doms):
-    print 'Name                              ID Mem(MiB) VCPUs State  Time(s)'
+    print '%-40s %3s %8s %5s %5s %9s' % \
+          ('Name', 'ID', 'Mem(MiB)', 'VCPUs', 'State', 'Time(s)')
+    
+    format = "%(name)-40s %(domid)3d %(mem)8d %(vcpus)5d %(state)5s " \
+             "%(cpu_time)8.1f"
+    
     for dom in doms:
         d = parse_doms_info(dom)
-        print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s 
%(cpu_time)7.1f" % d)
-
+        print format % d
 
 def xm_label_list(doms):
+    print '%-32s %3s %8s %5s %5s %9s %-8s' % \
+          ('Name', 'ID', 'Mem(MiB)', 'VCPUs', 'State', 'Time(s)', 'Label')
+    
     output = []
-    print 'Name                              ID Mem(MiB) VCPUs State  Time(s)  
Label'
+    format = '%(name)-32s %(domid)3d %(mem)8d %(vcpus)5d %(state)5s ' \
+             '%(cpu_time)8.1f %(seclabel)9s'
+    
     for dom in doms:
         d = parse_doms_info(dom)
-        l = "%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s 
%(cpu_time)7.1f  " % d
         if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
-            if d['seclabel']:
-                line = (l, d['seclabel'])
-            else:
-                line = (l, "ERROR")
+            if not d['seclabel']:
+                d['seclabel'] = 'ERROR'
         elif security.active_policy in ['DEFAULT']:
-            line = (l, "DEFAULT")
+            d['seclabel'] = 'DEFAULT'
         else:
-            line = (l, "INACTIVE")
-        output.append(line)
+            d['seclabel'] = 'INACTIVE'
+        output.append((format % d, d['seclabel']))
+        
     #sort by labels
     output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
-    for l in output:
-        print l[0] + l[1]
+    for line, label in output:
+        print line
 
 
 def xm_vcpu_list(args):
@@ -474,7 +578,11 @@ def xm_vcpu_list(args):
         doms = server.xend.domains(False)
         dominfo = map(server.xend.domain.getVCPUInfo, doms)
 
-    print 'Name                              ID  VCPU  CPU  State  Time(s)  
CPU Affinity'
+    print '%-32s %3s %5s %5s %5s %9s %s' % \
+          ('Name', 'ID', 'VCPUs', 'CPU', 'State', 'Time(s)', 'CPU Affinity')
+
+    format = '%(name)-32s %(domid)3d %(number)5d %(c)5s %(s)5s ' \
+             ' %(cpu_time)8.1f %(cpumap)s'
 
     for dom in dominfo:
         def get_info(n):
@@ -568,10 +676,7 @@ def xm_vcpu_list(args):
                 c = "-"
                 s = "--p"
 
-            print (
-                "%(name)-32s %(domid)3d  %(number)4d  %(c)3s   %(s)-3s   
%(cpu_time)7.1f  %(cpumap)s" %
-                locals())
-
+            print format % locals()
 
 def xm_reboot(args):
     arg_check(args, "reboot", 1, 3)
@@ -634,30 +739,30 @@ def xm_dump_core(args):
 
 def xm_rename(args):
     arg_check(args, "rename", 2)
-
+        
     server.xend.domain.setName(args[0], args[1])
 
-def xm_subcommand(command, args):
+def xm_importcommand(command, args):
     cmd = __import__(command, globals(), locals(), 'xen.xm')
     cmd.main([command] + args)
 
 
 #############################################################
 
-def cpu_make_map(cpulist):
-    cpus = []
-    for c in cpulist.split(','):
-        if c.find('-') != -1:
-            (x,y) = c.split('-')
-            for i in range(int(x),int(y)+1):
-                cpus.append(int(i))
-        else:
-            cpus.append(int(c))
-    cpus.sort()
-    return cpus
-
 def xm_vcpu_pin(args):
     arg_check(args, "vcpu-pin", 3)
+
+    def cpu_make_map(cpulist):
+        cpus = []
+        for c in cpulist.split(','):
+            if c.find('-') != -1:
+                (x,y) = c.split('-')
+                for i in range(int(x),int(y)+1):
+                    cpus.append(int(i))
+            else:
+                cpus.append(int(c))
+        cpus.sort()
+        return cpus
 
     dom  = args[0]
     vcpu = int(args[1])
@@ -719,11 +824,12 @@ def xm_sched_sedf(args):
         info['period']  = ns_to_ms(info['period'])
         info['slice']   = ns_to_ms(info['slice'])
         info['latency'] = ns_to_ms(info['latency'])
-        print( ("%(name)-32s %(dom)3d %(period)9.1f %(slice)9.1f" +
+        print( ("%(name)-32s %(domid)3d %(period)9.1f %(slice)9.1f" +
                 " %(latency)7.1f %(extratime)6d %(weight)6d") % info)
 
     def domid_match(domid, info):
-        return domid is None or domid == info['name'] or domid == 
str(info['dom'])
+        return domid is None or domid == info['name'] or \
+               domid == str(info['domid'])
 
     # we want to just display current info if no parameters are passed
     if len(args) == 0:
@@ -757,20 +863,25 @@ def xm_sched_sedf(args):
         elif k in ['-w', '--weight']:
             opts['weight'] = v
 
+    doms = filter(lambda x : domid_match(domid, x),
+                        [parse_doms_info(dom) for dom in getDomains("")])
+
     # print header if we aren't setting any parameters
     if len(opts.keys()) == 0:
-        print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s'%('Name','ID','Period(ms)',
-                                                     'Slice(ms)', 'Lat(ms)',
-                                                     'Extra','Weight')
-
-    doms = filter(lambda x : domid_match(domid, x),
-                        [parse_doms_info(dom) for dom in getDomains("")])
+        print '%-33s %-2s %-4s %-4s %-7s %-5s %-6s' % \
+              ('Name','ID','Period(ms)', 'Slice(ms)', 'Lat(ms)',
+               'Extra','Weight')
+    
     for d in doms:
         # fetch current values so as not to clobber them
-        sedf_info = \
-            parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom']))
+        try:
+            sedf_raw = server.xend.domain.cpu_sedf_get(d['domid'])
+        except xmlrpclib.Fault:
+            # domain does not support sched-sedf?
+            sedf_raw = {}
+
+        sedf_info = parse_sedf_info(sedf_raw)
         sedf_info['name'] = d['name']
-
         # update values in case of call to set
         if len(opts.keys()) > 0:
             for k in opts.keys():
@@ -780,7 +891,7 @@ def xm_sched_sedf(args):
             v = map(int, [sedf_info['period'], sedf_info['slice'],
                           sedf_info['latency'],sedf_info['extratime'], 
                           sedf_info['weight']])
-            rv = server.xend.domain.cpu_sedf_set(d['dom'], *v)
+            rv = server.xend.domain.cpu_sedf_set(d['domid'], *v)
             if int(rv) != 0:
                 err("Failed to set sedf parameters (rv=%d)."%(rv))
 
@@ -789,17 +900,14 @@ def xm_sched_sedf(args):
             print_sedf(sedf_info)
 
 def xm_sched_credit(args):
-    usage_msg = """sched-credit:     Set or get credit scheduler parameters
- Usage:
-
-        sched-credit -d domain [-w weight] [-c cap]
-    """
+    """Get/Set options for Credit Scheduler."""
+    
     try:
-        opts, args = getopt.getopt(args[0:], "d:w:c:",
+        opts, params = getopt.getopt(args, "d:w:c:",
             ["domain=", "weight=", "cap="])
-    except getopt.GetoptError:
-        # print help information and exit:
-        print usage_msg
+    except getopt.GetoptError, opterr:
+        err(opterr)
+        usage('sched-credit')
         sys.exit(1)
 
     domain = None
@@ -816,15 +924,16 @@ def xm_sched_credit(args):
 
     if domain is None:
         # place holder for system-wide scheduler parameters
-        print usage_msg
+        err("No domain given.")
+        usage('sched-credit')
         sys.exit(1)
 
     if weight is None and cap is None:
         print server.xend.domain.sched_credit_get(domain)
     else:
-        err = server.xend.domain.sched_credit_set(domain, weight, cap)
-        if err != 0:
-            print err
+        result = server.xend.domain.sched_credit_set(domain, weight, cap)
+        if result != 0:
+            err(str(result))
 
 def xm_info(args):
     arg_check(args, "info", 0)
@@ -843,6 +952,8 @@ def xm_console(args):
     dom = args[0]
     info = server.xend.domain(dom)
     domid = int(sxp.child_value(info, 'domid', '-1'))
+    if domid == -1:
+        raise Exception("Domain is not started")
     console.execConsole(domid)
 
 def xm_uptime(args):
@@ -899,6 +1010,12 @@ def xm_uptime(args):
 
         print upstring
 
+def xm_sysrq(args):
+    arg_check(args, "sysrq", 2)
+    dom = args[0]
+    req = args[1]
+    server.xend.domain.send_sysrq(dom, req)    
+
 def xm_top(args):
     arg_check(args, "top", 0)
 
@@ -920,8 +1037,11 @@ its contents if the [-c|--clear] flag is
     myargs = args
     myargs.insert(0, 'dmesg')
     gopts.parse(myargs)
-    if not (1 <= len(myargs) <= 2):
+    
+    if len(myargs) not in (1, 2):
         err('Invalid arguments: ' + str(myargs))
+        usage('dmesg')
+        sys.exit(1)
 
     if not gopts.vals.clear:
         print server.xend.node.dmesg.info()
@@ -939,7 +1059,7 @@ def xm_serve(args):
     from fcntl import fcntl, F_SETFL
     
     s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    s.connect(xen.xend.XendClient.XML_RPC_SOCKET)
+    s.connect(XendClient.XML_RPC_SOCKET)
     fcntl(sys.stdin, F_SETFL, os.O_NONBLOCK)
 
     while True:
@@ -1085,7 +1205,7 @@ def parse_block_configuration(args):
         cls = 'tap'
     else:
         cls = 'vbd'
-        
+
     vbd = [cls,
            ['uname', args[1]],
            ['dev',   args[2]],
@@ -1094,19 +1214,12 @@ def parse_block_configuration(args):
         vbd.append(['backend', args[4]])
 
     # verify that policy permits attaching this resource
-    try:
-        if security.on():
-            dominfo = server.xend.domain(dom)
-            label = security.get_security_printlabel(dominfo)
-        else:
-            label = None
+    if security.on():
+        dominfo = server.xend.domain(dom)
+        label = security.get_security_printlabel(dominfo)
+    else:
+        label = None
         security.res_security_check(args[1], label)
-    except security.ACMError, e:
-        print e.value
-        sys.exit(1)
-    except:
-        traceback.print_exc(limit=1)
-        sys.exit(1)
 
     return (dom, vbd)
 
@@ -1206,11 +1319,12 @@ commands = {
     "domid": xm_domid,
     "domname": xm_domname,
     "dump-core": xm_dump_core,
+    "reboot": xm_reboot,    
     "rename": xm_rename,
     "restore": xm_restore,
     "save": xm_save,
-    "reboot": xm_reboot,
     "shutdown": xm_shutdown,
+    "sysrq": xm_sysrq,
     "uptime": xm_uptime,
     "list": xm_list,
     # memory commands
@@ -1249,24 +1363,23 @@ commands = {
     }
 
 ## The commands supported by a separate argument parser in xend.xm.
-subcommands = [
+IMPORTED_COMMANDS = [
     'create',
     'migrate',
-    'sysrq',
     'labels',
     'addlabel',
+    'cfgbootpolicy',
+    'makepolicy',
+    'loadpolicy',
+    'dumppolicy'
     'rmlabel',
     'getlabel',
     'dry-run',
     'resources',
-    'cfgbootpolicy',
-    'makepolicy',
-    'loadpolicy',
-    'dumppolicy'
     ]
 
-for c in subcommands:
-    commands[c] = eval('lambda args: xm_subcommand("%s", args)' % c)
+for c in IMPORTED_COMMANDS:
+    commands[c] = eval('lambda args: xm_importcommand("%s", args)' % c)
 
 aliases = {
     "balloon": "mem-set",
@@ -1284,11 +1397,18 @@ def xm_lookup_cmd(cmd):
     elif aliases.has_key(cmd):
         deprecated(cmd,aliases[cmd])
         return commands[aliases[cmd]]
-    else:
-        if len( cmd ) > 1:
-            matched_commands = filter( lambda (command, func): command[ 
0:len(cmd) ] == cmd, commands.iteritems() )
-            if len( matched_commands ) == 1:
-                       return matched_commands[0][1]
+    elif cmd == 'help':
+        longHelp()
+        sys.exit(0)
+    else:
+        # simulate getopt's prefix matching behaviour
+        if len(cmd) > 1:
+            same_prefix_cmds = [commands[c] for c in commands.keys() \
+                                if c[:len(cmd)] == cmd]
+            # only execute if there is only 1 match
+            if len(same_prefix_cmds) == 1:
+                return same_prefix_cmds[0]
+            
         err('Sub Command %s not found!' % cmd)
         usage()
 
@@ -1296,27 +1416,17 @@ def deprecated(old,new):
     print >>sys.stderr, (
         "Command %s is deprecated.  Please use xm %s instead." % (old, new))
 
-def usage(cmd=None):
-    if cmd == 'create':
-        mycmd = xm_lookup_cmd(cmd)
-        mycmd( ['--help'] )
-        sys.exit(1)
-    if help.has_key(cmd):
-        print "   " + help[cmd]
-    else:
-        print shorthelp
-    sys.exit(1)
-
 def main(argv=sys.argv):
     if len(argv) < 2:
         usage()
-    
-    if re.compile('-*help').match(argv[1]):
-       if len(argv) > 2:
-           usage(argv[2])
-       else:
-           usage()
-       sys.exit(0)
+
+    # intercept --help and output our own help
+    if '--help' in argv[1:]:
+        if '--help' == argv[1]:
+            longHelp()
+        else:
+            usage(argv[1])
+        sys.exit(0)
 
     cmd = xm_lookup_cmd(argv[1])
 
@@ -1329,9 +1439,9 @@ def main(argv=sys.argv):
                 usage()
         except socket.error, ex:
             if os.geteuid() != 0:
-                err("Most commands need root access.  Please try again as 
root.")
+                err("Most commands need root access. Please try again as 
root.")
             else:
-                err("Error connecting to xend: %s.  Is xend running?" % ex[1])
+                err("Unable to connect to xend: %s. Is xend running?" % ex[1])
             sys.exit(1)
         except KeyboardInterrupt:
             print "Interrupted."
@@ -1340,16 +1450,16 @@ def main(argv=sys.argv):
             if os.geteuid() != 0:
                 err("Most commands need root access.  Please try again as 
root.")
             else:
-                err("Error connecting to xend: %s." % ex[1])
+                err("Unable to connect to xend: %s." % ex[1])
             sys.exit(1)
         except SystemExit:
             sys.exit(1)
         except xmlrpclib.Fault, ex:
-            if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
-                print  >>sys.stderr, (
-                    "Error: the domain '%s' does not exist." % ex.faultString)
+            if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN:
+                err("Domain '%s' does not exist." % ex.faultString)
             else:
-                print  >>sys.stderr, "Error: %s" % ex.faultString
+                err(ex.faultString)
+            usage(argv[1])
             sys.exit(1)
         except xmlrpclib.ProtocolError, ex:
             if ex.errcode == -1:
@@ -1364,6 +1474,10 @@ def main(argv=sys.argv):
         except (ValueError, OverflowError):
             err("Invalid argument.")
             usage(argv[1])
+        except OptionError, e:
+            err(str(e))
+            usage(argv[1])
+            print e.usage()
         except:
             print "Unexpected error:", sys.exc_info()[0]
             print
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/makepolicy.py
--- a/tools/python/xen/xm/makepolicy.py Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/makepolicy.py Fri Sep 22 17:22:18 2006 +0100
@@ -20,7 +20,7 @@ import sys
 import sys
 import traceback
 from xen.util.security import ACMError, err, make_policy
-
+from xen.xm.opts import OptionError
 
 def usage():
     print "\nUsage: xm makepolicy <policy>\n"
@@ -29,13 +29,12 @@ def usage():
     err("Usage")
 
 
+def main(argv):
+    if len(argv) != 2:
+        raise OptionError('No XML policy file specified')
 
-def main(argv):
     try:
-        if len(argv) != 2:
-            usage()
         make_policy(argv[1])
-
     except ACMError:
         sys.exit(-1)
     except:
@@ -43,7 +42,6 @@ def main(argv):
         sys.exit(-1)
 
 
-
 if __name__ == '__main__':
     main(sys.argv)
 
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/migrate.py
--- a/tools/python/xen/xm/migrate.py    Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/migrate.py    Fri Sep 22 17:22:18 2006 +0100
@@ -46,19 +46,17 @@ gopts.opt('resource', short='r', val='MB
           fn=set_int, default=0,
           use="Set level of resource usage for migration.")
 
-def help(argv):
-    gopts.argv = argv
-    gopts.usage()
+def help():
+    return str(gopts)
     
 def main(argv):
     opts = gopts
     args = opts.parse(argv)
-    if opts.vals.help:
-        opts.usage()
-        return
+    
     if len(args) != 2:
-        opts.usage()
-        sys.exit(1)
+        raise OptionError('Invalid number of arguments')
+
     dom = args[0]
     dst = args[1]
-    server.xend.domain.migrate(dom, dst, opts.vals.live, opts.vals.resource, 
opts.vals.port)
+    server.xend.domain.migrate(dom, dst, opts.vals.live, opts.vals.resource,
+                               opts.vals.port)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/opts.py
--- a/tools/python/xen/xm/opts.py       Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/opts.py       Fri Sep 22 17:22:18 2006 +0100
@@ -23,6 +23,42 @@ import os.path
 import os.path
 import sys
 import types
+
+def _line_wrap(text, width = 70):
+    lines = []
+    current_line = ''
+    words = text.strip().split()
+    while words:
+        word = words.pop(0)
+        if len(current_line) + len(word) + 1 < width:
+            current_line += word + ' '
+        else:
+            lines.append(current_line.strip())
+            current_line = word + ' '
+            
+    if current_line:
+        lines.append(current_line.strip())
+    return lines
+
+def wrap(text, width = 70):
+    """ Really basic textwrap. Useful because textwrap is not available
+    for Python 2.2, and textwrap.wrap ignores newlines in Python 2.3+.
+    """
+    if len(text) < width:
+        return [text]
+    
+    lines = []
+    for line in text.split('\n'):
+        lines += _line_wrap(line, width)
+    return lines
+
+class OptionError(Exception):
+    """Denotes an error in option parsing."""
+    def __init__(self, message, usage = ''):
+        self.message = message
+        self.usage = usage
+    def __str__(self):
+        return self.message
 
 class Opt:
     """An individual option.
@@ -72,7 +108,21 @@ class Opt:
     def __repr__(self):
         return self.name + '=' + str(self.specified_val)
 
-    __str__ = __repr__
+    def __str__(self):
+        """ Formats the option into:
+        '-k, --key     description'
+        """
+        PARAM_WIDTH = 20
+        if self.val:
+            keys = ', '.join(['%s=%s' % (k, self.val) for k in self.optkeys])
+        else:
+            keys = ', '.join(self.optkeys)
+        desc = wrap(self.use, 55)
+        if len(keys) > PARAM_WIDTH:
+            desc = [''] + desc
+            
+        wrapped = ('\n' + ' ' * (PARAM_WIDTH + 1)).join(desc)
+        return keys.ljust(PARAM_WIDTH + 1) + wrapped
 
     def set(self, value):
         """Set the option value.
@@ -243,8 +293,24 @@ class Opts:
     def __repr__(self):
         return '\n'.join(map(str, self.options))
 
-    __str__ = __repr__
-
+    def __str__(self):
+        options = [s for s in self.options if s.optkeys[0][0] == '-']
+        output = ''
+        if options:
+            output += '\nOptions:\n\n'
+            output += '\n'.join([str(o) for o in options])
+            output += '\n'
+        return output
+
+    def val_usage(self):
+        optvals = [s for s in self.options if s.optkeys[0][0] != '-']
+        output = ''
+        if optvals:
+            output += '\nValues:\n\n'
+            output += '\n'.join([str(o) for o in optvals])
+            output += '\n'
+        return output
+    
     def opt(self, name, **args):
         """Add an option.
 
@@ -338,14 +404,14 @@ class Opts:
                                               self.short_opts(),
                                               self.long_opts())
             except getopt.GetoptError, err:
-                self.err(str(err))
+                raise OptionError(str(err), self.use)
+            #self.err(str(err))
                 
             for (k, v) in xvals:
                 for opt in self.options:
                     if opt.specify(k, v): break
                 else:
-                    print >>sys.stderr, "Error: Unknown option:", k
-                    self.usage()
+                    raise OptionError('Unknown option: %s' % k, self.use)
 
             if not args:
                 break
@@ -390,10 +456,10 @@ class Opts:
     def usage(self):
         print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
         print
-        for opt in self.options:
-            opt.show()
-            print
         if self.options:
+            for opt in self.options:
+                opt.show()
+                print
             print
 
     def var_usage(self):
@@ -427,7 +493,9 @@ class Opts:
                 self.load(p, help)
                 break
         else:
-            self.err('Cannot open config file "%s"' % self.vals.defconfig)
+            raise OptionError('Unable to open config file: %s' % \
+                              self.vals.defconfig,
+                              self.use)
 
     def load(self, defconfig, help):
         """Load a defconfig file. Local variables in the file
@@ -478,9 +546,9 @@ def set_bool(opt, k, v):
 def set_bool(opt, k, v):
     """Set a boolean option.
     """
-    if v in ['yes']:
+    if v in ('yes', 'y'):
         opt.set(1)
-    elif v in ['no']:
+    elif v in ('no', 'n'):
         opt.set(0)
     else:
         opt.opts.err('Invalid value:' +v)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/resources.py
--- a/tools/python/xen/xm/resources.py  Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/resources.py  Fri Sep 22 17:22:18 2006 +0100
@@ -21,13 +21,12 @@ import sys
 import sys
 from xen.util import dictio
 from xen.util import security
+from xen.xm.opts import OptionError
 
-def usage():
-    print "\nUsage: xm resource\n"
-    print "  This program lists information for each resource in the"
-    print "  global resource label file\n"
-    security.err("Usage")
-
+def help():
+    return """Usage: xm resource
+    This program lists information for each resource in the
+    global resource label file."""
 
 def print_resource_data(access_control):
     """Prints out a resource dictionary to stdout
@@ -38,11 +37,16 @@ def print_resource_data(access_control):
         print "    policy: "+policy
         print "    label:  "+label
 
-
 def main (argv):
+    if len(argv) > 1:
+        raise OptionError("No arguments required")
+    
     try:
-        if len(argv) != 1:
-            usage()
+        filename = security.res_label_filename
+        access_control = dictio.dict_read("resources", filename)
+    except:
+        print "Resource file not found."
+        return
 
         try:
             file = security.res_label_filename
@@ -52,9 +56,6 @@ def main (argv):
 
         print_resource_data(access_control)
 
-    except security.ACMError:
-        sys.exit(-1)
-
 if __name__ == '__main__':
     main(sys.argv)
 
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/rmlabel.py
--- a/tools/python/xen/xm/rmlabel.py    Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/rmlabel.py    Fri Sep 22 17:22:18 2006 +0100
@@ -21,15 +21,17 @@ import sys, os, re
 import sys, os, re
 from xen.util import dictio
 from xen.util import security
+from xen.xm.opts import OptionError
 
-def usage():
-    print "\nUsage: xm rmlabel dom <configfile>"
-    print "       xm rmlabel res <resource>\n"
-    print "  This program removes an acm_label entry from the 'configfile'"
-    print "  for a domain or from the global resource label file for a"
-    print "  resource. If the label does not exist for the given domain or"
-    print "  resource, then rmlabel fails.\n"
-    security.err("Usage")
+def help():
+    return """
+    Example: xm rmlabel dom <configfile>
+             xm rmlabel res <resource>
+
+    This program removes an acm_label entry from the 'configfile'
+    for a domain or from the global resource label file for a
+    resource. If the label does not exist for the given domain or
+    resource, then rmlabel fails."""
 
 
 def rm_resource_label(resource):
@@ -93,22 +95,22 @@ def rm_domain_label(configfile):
 
 
 def main (argv):
+
+    if len(argv) != 3:
+        raise OptionError('Requires 2 arguments')
+    
+    if argv[1].lower() not in ('dom', 'res'):
+        raise OptionError('Unrecognised type argument: %s' % argv[1])
+
     try:
-        if len(argv) != 3:
-            usage()
-
         if argv[1].lower() == "dom":
             configfile = argv[2]
             rm_domain_label(configfile)
         elif argv[1].lower() == "res":
             resource = argv[2]
             rm_resource_label(resource)
-        else:
-            usage()
-
     except security.ACMError:
         sys.exit(-1)
-
 
 if __name__ == '__main__':
     main(sys.argv)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/shutdown.py
--- a/tools/python/xen/xm/shutdown.py   Fri Sep 22 17:21:52 2006 +0100
+++ b/tools/python/xen/xm/shutdown.py   Fri Sep 22 17:22:18 2006 +0100
@@ -120,7 +120,6 @@ def main(argv):
     opts = gopts
     args = opts.parse(argv)
     if opts.vals.help:
-        opts.usage()
         return
     if opts.vals.all:
         main_all(opts, args)
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/arch/x86/hvm/platform.c       Fri Sep 22 17:22:18 2006 +0100
@@ -416,6 +416,11 @@ static int hvm_decode(int realmode, unsi
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
         return reg_mem(instr->op_size, opcode, instr, rex);
 
+    case 0x3A: /* cmp r8, r8/m8 */
+        instr->instr = INSTR_CMP;
+        GET_OP_SIZE_FOR_BYTE(instr->op_size);
+        return reg_mem(instr->op_size, opcode, instr, rex);
+
     case 0x3B: /* cmp m32/16, r32/16 */
         instr->instr = INSTR_CMP;
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
@@ -470,6 +475,11 @@ static int hvm_decode(int realmode, unsi
         instr->op_size = BYTE;
         GET_OP_SIZE_FOR_BYTE(size_reg);
         return mem_reg(size_reg, opcode, instr, rex);
+
+    case 0x85: /* text m16/32, r16/32 */
+        instr->instr = INSTR_TEST;
+        GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+        return mem_reg(instr->op_size, opcode, instr, rex);
 
     case 0x87:  /* xchg {r/m16|r/m32}, {m/r16|m/r32} */
         instr->instr = INSTR_XCHG;
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Fri Sep 22 17:22:18 2006 +0100
@@ -259,6 +259,17 @@ static int svm_paging_enabled(struct vcp
     return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
 }
 
+static int svm_pae_enabled(struct vcpu *v)
+{
+    unsigned long cr4;
+
+    if(!svm_paging_enabled(v))
+        return 0;
+
+    cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
+
+    return (cr4 & X86_CR4_PAE);
+}
 
 #define IS_CANO_ADDRESS(add) 1
 
@@ -865,6 +876,7 @@ int start_svm(void)
     hvm_funcs.realmode = svm_realmode;
     hvm_funcs.paging_enabled = svm_paging_enabled;
     hvm_funcs.long_mode_enabled = svm_long_mode_enabled;
+    hvm_funcs.pae_enabled = svm_pae_enabled;
     hvm_funcs.guest_x86_mode = svm_guest_x86_mode;
     hvm_funcs.instruction_length = svm_instruction_length;
     hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
@@ -1847,12 +1859,12 @@ static int svm_cr_access(struct vcpu *v,
        where the prefix lives later on */
     index = skip_prefix_bytes(buffer, sizeof(buffer));
     
-    if (type == TYPE_MOV_TO_CR) 
+    if ( type == TYPE_MOV_TO_CR )
     {
         inst_len = __get_instruction_length_from_list(
             vmcb, list_a, ARR_SIZE(list_a), &buffer[index], &match);
     }
-    else
+    else /* type == TYPE_MOV_FROM_CR */
     {
         inst_len = __get_instruction_length_from_list(
             vmcb, list_b, ARR_SIZE(list_b), &buffer[index], &match);
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/io.c Fri Sep 22 17:22:18 2006 +0100
@@ -108,11 +108,17 @@ asmlinkage void vmx_intr_assist(void)
         return;
     }
 
+    /* This could be moved earlier in the VMX resume sequence. */
     __vmread(IDT_VECTORING_INFO_FIELD, &idtv_info_field);
     if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) {
         __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
 
-        __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+        /*
+         * Safe: the length will only be interpreted for software exceptions
+         * and interrupts. If we get here then delivery of some event caused a
+         * fault, and this always results in defined VM_EXIT_INSTRUCTION_LEN.
+         */
+        __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len); /* Safe */
         __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
 
         if (unlikely(idtv_info_field & 0x800)) { /* valid error code */
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Fri Sep 22 17:22:18 2006 +0100
@@ -597,7 +597,7 @@ static int vmx_instruction_length(struct
 {
     unsigned long inst_len;
 
-    if (__vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len))
+    if ( __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len) ) /* XXX Unsafe XXX */
         return 0;
     return inst_len;
 }
@@ -746,6 +746,7 @@ static void vmx_setup_hvm_funcs(void)
     hvm_funcs.realmode = vmx_realmode;
     hvm_funcs.paging_enabled = vmx_paging_enabled;
     hvm_funcs.long_mode_enabled = vmx_long_mode_enabled;
+    hvm_funcs.pae_enabled = vmx_pae_enabled;
     hvm_funcs.guest_x86_mode = vmx_guest_x86_mode;
     hvm_funcs.instruction_length = vmx_instruction_length;
     hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
@@ -836,11 +837,16 @@ int start_vmx(void)
 
 /*
  * Not all cases receive valid value in the VM-exit instruction length field.
+ * Callers must know what they're doing!
  */
-#define __get_instruction_length(len) \
-    __vmread(VM_EXIT_INSTRUCTION_LEN, &(len)); \
-     if ((len) < 1 || (len) > 15) \
-        __hvm_bug(&regs);
+static int __get_instruction_length(void)
+{
+    int len;
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &len); /* Safe: callers audited */
+    if ( (len < 1) || (len > 15) )
+        __hvm_bug(guest_cpu_user_regs());
+    return len;
+}
 
 static void inline __update_guest_eip(unsigned long inst_len)
 {
@@ -1051,15 +1057,18 @@ static int check_for_null_selector(unsig
     int i, inst_len;
     int inst_copy_from_guest(unsigned char *, unsigned long, int);
 
-    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+    inst_len = __get_instruction_length(); /* Safe: INS/OUTS */
     memset(inst, 0, MAX_INST_LEN);
-    if (inst_copy_from_guest(inst, eip, inst_len) != inst_len) {
+    if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len )
+    {
         printf("check_for_null_selector: get guest instruction failed\n");
         domain_crash_synchronous();
     }
 
-    for (i = 0; i < inst_len; i++) {
-        switch (inst[i]) {
+    for ( i = 0; i < inst_len; i++ )
+    {
+        switch ( inst[i] )
+        {
         case 0xf3: /* REPZ */
         case 0xf2: /* REPNZ */
         case 0xf0: /* LOCK */
@@ -1184,15 +1193,14 @@ static void vmx_io_instruction(unsigned 
     }
 }
 
-int
-vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
-{
-    unsigned long inst_len;
+static int vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
+{
     int error = 0;
 
-    error |= __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+    /* NB. Skip transition instruction. */
     error |= __vmread(GUEST_RIP, &c->eip);
-    c->eip += inst_len; /* skip transition instruction */
+    c->eip += __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */
+
     error |= __vmread(GUEST_RSP, &c->esp);
     error |= __vmread(GUEST_RFLAGS, &c->eflags);
 
@@ -1249,8 +1257,7 @@ vmx_world_save(struct vcpu *v, struct vm
     return !error;
 }
 
-int
-vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
+static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
 {
     unsigned long mfn, old_cr4, old_base_mfn;
     int error = 0;
@@ -1364,8 +1371,7 @@ vmx_world_restore(struct vcpu *v, struct
 
 enum { VMX_ASSIST_INVOKE = 0, VMX_ASSIST_RESTORE };
 
-int
-vmx_assist(struct vcpu *v, int mode)
+static int vmx_assist(struct vcpu *v, int mode)
 {
     struct vmx_assist_context c;
     u32 magic;
@@ -1408,8 +1414,8 @@ vmx_assist(struct vcpu *v, int mode)
         break;
 
         /*
-         * Restore the VMXASSIST_OLD_CONTEXT that was saved by 
VMX_ASSIST_INVOKE
-         * above.
+         * Restore the VMXASSIST_OLD_CONTEXT that was saved by
+         * VMX_ASSIST_INVOKE above.
          */
     case VMX_ASSIST_RESTORE:
         /* save the old context */
@@ -1552,7 +1558,8 @@ static int vmx_set_cr0(unsigned long val
             }
         }
 
-        if ( vmx_assist(v, VMX_ASSIST_INVOKE) ) {
+        if ( vmx_assist(v, VMX_ASSIST_INVOKE) )
+        {
             set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &v->arch.hvm_vmx.cpu_state);
             __vmread(GUEST_RIP, &eip);
             HVM_DBG_LOG(DBG_LEVEL_1,
@@ -1815,7 +1822,8 @@ static void mov_from_cr(int cr, int gp, 
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR%d, value = %lx", cr, value);
 }
 
-static int vmx_cr_access(unsigned long exit_qualification, struct 
cpu_user_regs *regs)
+static int vmx_cr_access(unsigned long exit_qualification,
+                         struct cpu_user_regs *regs)
 {
     unsigned int gp, cr;
     unsigned long value;
@@ -2069,6 +2077,47 @@ void restore_cpu_user_regs(struct cpu_us
 }
 #endif
 
+static void vmx_reflect_exception(struct vcpu *v)
+{
+    int error_code, intr_info, vector;
+
+    __vmread(VM_EXIT_INTR_INFO, &intr_info);
+    vector = intr_info & 0xff;
+    if ( intr_info & INTR_INFO_DELIVER_CODE_MASK )
+        __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
+    else
+        error_code = VMX_DELIVER_NO_ERROR_CODE;
+
+#ifndef NDEBUG
+    {
+        unsigned long rip;
+
+        __vmread(GUEST_RIP, &rip);
+        HVM_DBG_LOG(DBG_LEVEL_1, "rip = %lx, error_code = %x",
+                    rip, error_code);
+    }
+#endif /* NDEBUG */
+
+    /*
+     * According to Intel Virtualization Technology Specification for
+     * the IA-32 Intel Architecture (C97063-002 April 2005), section
+     * 2.8.3, SW_EXCEPTION should be used for #BP and #OV, and
+     * HW_EXCEPTION used for everything else.  The main difference
+     * appears to be that for SW_EXCEPTION, the EIP/RIP is incremented
+     * by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION,
+     * it is not.
+     */
+    if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION )
+    {
+        int ilen = __get_instruction_length(); /* Safe: software exception */
+        vmx_inject_sw_exception(v, vector, ilen);
+    }
+    else
+    {
+        vmx_inject_hw_exception(v, vector, error_code);
+    }
+}
+
 asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
 {
     unsigned int exit_reason;
@@ -2116,7 +2165,8 @@ asmlinkage void vmx_vmexit_handler(struc
 
     TRACE_VMEXIT(0,exit_reason);
 
-    switch ( exit_reason ) {
+    switch ( exit_reason )
+    {
     case EXIT_REASON_EXCEPTION_NMI:
     {
         /*
@@ -2242,43 +2292,38 @@ asmlinkage void vmx_vmexit_handler(struc
         domain_crash_synchronous();
         break;
     case EXIT_REASON_CPUID:
+        inst_len = __get_instruction_length(); /* Safe: CPUID */
+        __update_guest_eip(inst_len);
         vmx_vmexit_do_cpuid(&regs);
-        __get_instruction_length(inst_len);
-        __update_guest_eip(inst_len);
         break;
     case EXIT_REASON_HLT:
-        __get_instruction_length(inst_len);
+        inst_len = __get_instruction_length(); /* Safe: HLT */
         __update_guest_eip(inst_len);
         vmx_vmexit_do_hlt();
         break;
     case EXIT_REASON_INVLPG:
     {
-        unsigned long   va;
-
+        unsigned long va;
+        inst_len = __get_instruction_length(); /* Safe: INVLPG */
+        __update_guest_eip(inst_len);
         __vmread(EXIT_QUALIFICATION, &va);
         vmx_vmexit_do_invlpg(va);
-        __get_instruction_length(inst_len);
+        break;
+    }
+    case EXIT_REASON_VMCALL:
+    {
+        inst_len = __get_instruction_length(); /* Safe: VMCALL */
         __update_guest_eip(inst_len);
-        break;
-    }
-    case EXIT_REASON_VMCALL:
-    {
-        __get_instruction_length(inst_len);
         __vmread(GUEST_RIP, &rip);
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
-
         hvm_do_hypercall(&regs);
-        __update_guest_eip(inst_len);
         break;
     }
     case EXIT_REASON_CR_ACCESS:
     {
         __vmread(GUEST_RIP, &rip);
-        __get_instruction_length(inst_len);
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
-
-        HVM_DBG_LOG(DBG_LEVEL_1, "rip = %lx, inst_len =%lx, exit_qualification 
= %lx",
-                    rip, inst_len, exit_qualification);
+        inst_len = __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */
         if ( vmx_cr_access(exit_qualification, &regs) )
             __update_guest_eip(inst_len);
         TRACE_VMEXIT(3,regs.error_code);
@@ -2291,19 +2336,19 @@ asmlinkage void vmx_vmexit_handler(struc
         break;
     case EXIT_REASON_IO_INSTRUCTION:
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
-        __get_instruction_length(inst_len);
+        inst_len = __get_instruction_length(); /* Safe: IN, INS, OUT, OUTS */
         vmx_io_instruction(exit_qualification, inst_len);
         TRACE_VMEXIT(4,exit_qualification);
         break;
     case EXIT_REASON_MSR_READ:
-        __get_instruction_length(inst_len);
+        inst_len = __get_instruction_length(); /* Safe: RDMSR */
+        __update_guest_eip(inst_len);
         vmx_do_msr_read(&regs);
+        break;
+    case EXIT_REASON_MSR_WRITE:
+        inst_len = __get_instruction_length(); /* Safe: WRMSR */
         __update_guest_eip(inst_len);
-        break;
-    case EXIT_REASON_MSR_WRITE:
         vmx_do_msr_write(&regs);
-        __get_instruction_length(inst_len);
-        __update_guest_eip(inst_len);
         break;
     case EXIT_REASON_MWAIT_INSTRUCTION:
     case EXIT_REASON_MONITOR_INSTRUCTION:
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Fri Sep 22 17:22:18 2006 +0100
@@ -2343,7 +2343,7 @@ void sh_update_paging_modes(struct vcpu 
             }
             else
 #endif
-                if ( hvm_get_guest_ctrl_reg(v, 4) & X86_CR4_PAE )
+                if ( hvm_pae_enabled(v) )
                 {
 #if CONFIG_PAGING_LEVELS >= 3
                     // 32-bit PAE mode guest...
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Fri Sep 22 17:22:18 2006 +0100
@@ -57,6 +57,7 @@ struct hvm_function_table {
     int (*realmode)(struct vcpu *v);
     int (*paging_enabled)(struct vcpu *v);
     int (*long_mode_enabled)(struct vcpu *v);
+    int (*pae_enabled)(struct vcpu *v);
     int (*guest_x86_mode)(struct vcpu *v);
     int (*instruction_length)(struct vcpu *v);
     unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
@@ -146,6 +147,12 @@ hvm_long_mode_enabled(struct vcpu *v)
     return hvm_funcs.long_mode_enabled(v);
 }
 
+ static inline int
+hvm_pae_enabled(struct vcpu *v)
+{
+    return hvm_funcs.pae_enabled(v);
+}
+
 static inline int
 hvm_guest_x86_mode(struct vcpu *v)
 {
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/include/asm-x86/hvm/svm/emulate.h
--- a/xen/include/asm-x86/hvm/svm/emulate.h     Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/include/asm-x86/hvm/svm/emulate.h     Fri Sep 22 17:22:18 2006 +0100
@@ -94,15 +94,14 @@ static inline int __get_instruction_leng
 static inline int __get_instruction_length(struct vmcb_struct *vmcb, 
         enum instruction_index instr, u8 *guest_eip_buf)
 {
-    return __get_instruction_length_from_list(vmcb, &instr, 1, guest_eip_buf, 
-            NULL);
+    return __get_instruction_length_from_list(
+        vmcb, &instr, 1, guest_eip_buf, NULL);
 }
 
 
 static inline unsigned int is_prefix(u8 opc)
 {
-    switch(opc)
-    {
+    switch ( opc ) {
     case 0x66:
     case 0x67:
     case 0x2E:
@@ -115,22 +114,7 @@ static inline unsigned int is_prefix(u8 
     case 0xF3:
     case 0xF2:
 #if __x86_64__
-    case 0x40:
-    case 0x41:
-    case 0x42:
-    case 0x43:
-    case 0x44:
-    case 0x45:
-    case 0x46:
-    case 0x47:
-    case 0x48:
-    case 0x49:
-    case 0x4a:
-    case 0x4b:
-    case 0x4c:
-    case 0x4d:
-    case 0x4e:
-    case 0x4f:
+    case 0x40 ... 0x4f:
 #endif /* __x86_64__ */
         return 1;
     }
@@ -141,15 +125,15 @@ static inline int skip_prefix_bytes(u8 *
 static inline int skip_prefix_bytes(u8 *buf, size_t size)
 {
     int index;
-    for (index = 0; index < size && is_prefix(buf[index]); index ++)  
-        /* do nothing */ ;
+    for ( index = 0; index < size && is_prefix(buf[index]); index++ )
+        continue;
     return index;
 }
 
 
 
-static void inline __update_guest_eip(struct vmcb_struct *vmcb, 
-        int inst_len) 
+static void inline __update_guest_eip(
+    struct vmcb_struct *vmcb, int inst_len) 
 {
     ASSERT(inst_len > 0);
     vmcb->rip += inst_len;
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Fri Sep 22 17:22:18 2006 +0100
@@ -38,6 +38,9 @@ enum {
 
 #define VMX_LONG_GUEST(ed)    \
   (test_bit(VMX_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_vmx.cpu_state))
+
+#define VMX_PAE_GUEST(ed)       \
+  (test_bit(VMX_CPU_STATE_PAE_ENABLED, &ed->arch.hvm_vmx.cpu_state))
 
 struct vmcs_struct {
     u32 vmcs_revision_id;
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Fri Sep 22 17:22:18 2006 +0100
@@ -418,6 +418,12 @@ static inline int vmx_long_mode_enabled(
     return VMX_LONG_GUEST(current);
 }
 
+static inline int vmx_pae_enabled(struct vcpu *v)
+{
+    ASSERT(v == current);
+    return VMX_PAE_GUEST(current);
+}
+
 /* Works only for vcpu == current */
 static inline int vmx_realmode(struct vcpu *v)
 {
@@ -469,7 +475,7 @@ static inline void __vmx_inject_exceptio
     if ( error_code != VMX_DELIVER_NO_ERROR_CODE ) {
         __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
         intr_fields |= INTR_INFO_DELIVER_CODE_MASK;
-     }
+    }
 
     if ( ilen )
       __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen);
@@ -499,40 +505,4 @@ static inline void vmx_inject_extint(str
     __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
 }
 
-static inline void vmx_reflect_exception(struct vcpu *v)
-{
-    int error_code, intr_info, vector;
-
-    __vmread(VM_EXIT_INTR_INFO, &intr_info);
-    vector = intr_info & 0xff;
-    if ( intr_info & INTR_INFO_DELIVER_CODE_MASK )
-        __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
-    else
-        error_code = VMX_DELIVER_NO_ERROR_CODE;
-
-#ifndef NDEBUG
-    {
-        unsigned long rip;
-
-        __vmread(GUEST_RIP, &rip);
-        HVM_DBG_LOG(DBG_LEVEL_1, "rip = %lx, error_code = %x",
-                    rip, error_code);
-    }
-#endif /* NDEBUG */
-
-    /* According to Intel Virtualization Technology Specification for
-       the IA-32 Intel Architecture (C97063-002 April 2005), section
-       2.8.3, SW_EXCEPTION should be used for #BP and #OV, and
-       HW_EXCPEPTION used for everything else.  The main difference
-       appears to be that for SW_EXCEPTION, the EIP/RIP is incremented
-       by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION,
-       it is not.  */
-    if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION ) {
-        int ilen;
-        __vmread(VM_EXIT_INSTRUCTION_LEN, &ilen);
-        vmx_inject_sw_exception(v, vector, ilen);
-    } else
-        vmx_inject_hw_exception(v, vector, error_code);
-}
-
 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */
diff -r 08a582a98471 -r cdd03c7ec8d3 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Fri Sep 22 17:21:52 2006 +0100
+++ b/xen/include/asm-x86/mm.h  Fri Sep 22 17:22:18 2006 +0100
@@ -181,9 +181,6 @@ int alloc_page_type(struct page_info *pa
 int alloc_page_type(struct page_info *page, unsigned long type);
 void free_page_type(struct page_info *page, unsigned long type);
 extern void invalidate_shadow_ldt(struct vcpu *d);
-extern int shadow_remove_all_write_access(
-    struct domain *d, unsigned long gmfn, unsigned long mfn);
-extern u32 shadow_remove_all_access( struct domain *d, unsigned long gmfn);
 extern int _shadow_mode_refcounts(struct domain *d);
 
 static inline void put_page(struct page_info *page)
diff -r 08a582a98471 -r cdd03c7ec8d3 tools/python/xen/xm/sysrq.py
--- a/tools/python/xen/xm/sysrq.py      Fri Sep 22 17:21:52 2006 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-# (C) Matthew Bloch <matthew@xxxxxxxxxxxxxx> 2004
-# Copyright (C) 2005 XenSource Ltd
-
-"""Domain sysrq.
-"""
-
-from xen.xend.XendClient import server
-from xen.xm.opts import *
-
-gopts = Opts(use="""[DOM] [letter]
-
-Sends a Linux sysrq to a domain.
-""")
-
-gopts.opt('help', short='h',
-         fn=set_true, default=0,
-         use="Print this help.")
-
-def main(argv):
-    opts = gopts
-    args = opts.parse(argv)
-    if opts.vals.help:
-        opts.usage()
-        return
-        
-    # no options for the moment
-    if len(args) != 2:
-        opts.usage()
-        sys.exit(1)
-    dom = args[0]
-    req = ord(args[1][0])
-    server.xend.domain.send_sysrq(dom, req)

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

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