direct-io.hg

changeset 11282:24258e322e88

[XEND] abstract architecture-specific bits in image.py
- create arch.type (which evaluates to "x86", "ia64" or "powerpc")
- create subclasses for x86 and ia64 HVM loaders
- rework findImageHandlerClass()
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Aug 29 23:20:22 2006 +0100 (2006-08-29)
parents 051dc0911547
children 90fb2c4d33a5
files tools/python/xen/xend/FlatDeviceTree.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/arch.py tools/python/xen/xend/image.py
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/python/xen/xend/FlatDeviceTree.py	Tue Aug 29 23:20:22 2006 +0100
     1.3 @@ -0,0 +1,323 @@
     1.4 +#!/usr/bin/env python
     1.5 +#
     1.6 +# This library is free software; you can redistribute it and/or
     1.7 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     1.8 +# License as published by the Free Software Foundation.
     1.9 +#
    1.10 +# This library is distributed in the hope that it will be useful,
    1.11 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.12 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.13 +# Lesser General Public License for more details.
    1.14 +#
    1.15 +# You should have received a copy of the GNU Lesser General Public
    1.16 +# License along with this library; if not, write to the Free Software
    1.17 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.18 +#
    1.19 +# Copyright (C) IBM Corp. 2006
    1.20 +#
    1.21 +# Authors: Hollis Blanchard <hollisb@us.ibm.com>
    1.22 +
    1.23 +import os
    1.24 +import sys
    1.25 +import struct
    1.26 +import stat
    1.27 +import re
    1.28 +
    1.29 +_OF_DT_HEADER = int("d00dfeed", 16) # avoid signed/unsigned FutureWarning
    1.30 +_OF_DT_BEGIN_NODE = 0x1
    1.31 +_OF_DT_END_NODE = 0x2
    1.32 +_OF_DT_PROP = 0x3
    1.33 +_OF_DT_END = 0x9
    1.34 +
    1.35 +def _bincat(seq, separator=''):
    1.36 +    '''Concatenate the contents of seq into a bytestream.'''
    1.37 +    strs = []
    1.38 +    for item in seq:
    1.39 +        if type(item) == type(0):
    1.40 +            strs.append(struct.pack(">I", item))
    1.41 +        else:
    1.42 +            try:
    1.43 +                strs.append(item.to_bin())
    1.44 +            except AttributeError, e:
    1.45 +                strs.append(item)
    1.46 +    return separator.join(strs)
    1.47 +
    1.48 +def _alignup(val, alignment):
    1.49 +    return (val + alignment - 1) & ~(alignment - 1)
    1.50 +
    1.51 +def _pad(buf, alignment):
    1.52 +    '''Pad bytestream with NULLs to specified alignment.'''
    1.53 +    padlen = _alignup(len(buf), alignment)
    1.54 +    return buf + '\0' * (padlen - len(buf))
    1.55 +    # not present in Python 2.3:
    1.56 +    #return buf.ljust(_padlen, '\0')
    1.57 +
    1.58 +def _indent(item):
    1.59 +    indented = []
    1.60 +    for line in str(item).splitlines(True):
    1.61 +        indented.append('    ' + line)
    1.62 +    return ''.join(indented)
    1.63 +
    1.64 +class _Property:
    1.65 +    _nonprint = re.compile('[\000-\037\200-\377]')
    1.66 +    def __init__(self, node, name, value):
    1.67 +        self.node = node
    1.68 +        self.value = value
    1.69 +        self.name = name
    1.70 +        self.node.tree.stradd(name)
    1.71 +
    1.72 +    def __str__(self):
    1.73 +        result = self.name
    1.74 +        if self.value:
    1.75 +            searchtext = self.value
    1.76 +            # it's ok for a string to end in NULL
    1.77 +            if searchtext.find('\000') == len(searchtext)-1:
    1.78 +                searchtext = searchtext[:-1]
    1.79 +            m = self._nonprint.search(searchtext)
    1.80 +            if m:
    1.81 +                bytes = struct.unpack("B" * len(self.value), self.value)
    1.82 +                hexbytes = [ '%02x' % b for b in bytes ]
    1.83 +                words = []
    1.84 +                for i in range(0, len(self.value), 4):
    1.85 +                    words.append(''.join(hexbytes[i:i+4]))
    1.86 +                v = '<' + ' '.join(words) + '>'
    1.87 +            else:
    1.88 +                v = '"%s"' % self.value
    1.89 +            result += ': ' + v
    1.90 +        return result
    1.91 +
    1.92 +    def to_bin(self):
    1.93 +        offset = self.node.tree.stroffset(self.name)
    1.94 +        return struct.pack('>III', _OF_DT_PROP, len(self.value), offset) \
    1.95 +            + _pad(self.value, 4)
    1.96 +
    1.97 +class _Node:
    1.98 +    def __init__(self, tree, name):
    1.99 +        self.tree = tree
   1.100 +        self.name = name
   1.101 +        self.props = {}
   1.102 +        self.children = {}
   1.103 +        self.phandle = 0
   1.104 +
   1.105 +    def __str__(self):
   1.106 +        propstrs = [ _indent(prop) for prop in self.props.values() ]
   1.107 +        childstrs = [ _indent(child) for child in self.children.values() ]
   1.108 +        return '%s:\n%s\n%s' % (self.name, '\n'.join(propstrs),
   1.109 +            '\n'.join(childstrs))
   1.110 +
   1.111 +    def to_bin(self):
   1.112 +        name = _pad(self.name + '\0', 4)
   1.113 +        return struct.pack('>I', _OF_DT_BEGIN_NODE) + \
   1.114 +                name + \
   1.115 +                _bincat(self.props.values()) + \
   1.116 +                _bincat(self.children.values()) + \
   1.117 +                struct.pack('>I', _OF_DT_END_NODE)
   1.118 +
   1.119 +    def addprop(self, propname, *cells):
   1.120 +        '''setprop with duplicate error-checking.'''
   1.121 +        if propname in self.props:
   1.122 +            raise AttributeError('%s/%s already exists' % (self.name, propname))
   1.123 +        self.setprop(propname, *cells)
   1.124 +
   1.125 +    def setprop(self, propname, *cells):
   1.126 +        self.props[propname] = _Property(self, propname, _bincat(cells))
   1.127 +
   1.128 +    def addnode(self, nodename):
   1.129 +        '''newnode with duplicate error-checking.'''
   1.130 +        if nodename in self.children:
   1.131 +            raise AttributeError('%s/%s already exists' % (self.name, nodename))
   1.132 +        return self.newnode(nodename)
   1.133 +
   1.134 +    def newnode(self, nodename):
   1.135 +        node = _Node(self.tree, nodename)
   1.136 +        self.children[nodename] = node
   1.137 +        return node
   1.138 +
   1.139 +    def getprop(self, propname):
   1.140 +        return self.props[propname]
   1.141 +
   1.142 +    def getchild(self, nodename):
   1.143 +        return self.children[nodename]
   1.144 +
   1.145 +    def get_phandle(self):
   1.146 +        if self.phandle:
   1.147 +            return self.phandle
   1.148 +        self.phandle = self.tree.alloc_phandle()
   1.149 +        self.addprop('linux,phandle', self.phandle)
   1.150 +        return self.phandle
   1.151 +
   1.152 +class _Header:
   1.153 +    def __init__(self):
   1.154 +        self.magic = 0
   1.155 +        self.totalsize = 0
   1.156 +        self.off_dt_struct = 0
   1.157 +        self.off_dt_strings = 0
   1.158 +        self.off_mem_rsvmap = 0
   1.159 +        self.version = 0
   1.160 +        self.last_comp_version = 0
   1.161 +        self.boot_cpuid_phys = 0
   1.162 +        self.size_dt_strings = 0
   1.163 +    def to_bin(self):
   1.164 +        return struct.pack('>9I',
   1.165 +            self.magic,
   1.166 +            self.totalsize,
   1.167 +            self.off_dt_struct,
   1.168 +            self.off_dt_strings,
   1.169 +            self.off_mem_rsvmap,
   1.170 +            self.version,
   1.171 +            self.last_comp_version,
   1.172 +            self.boot_cpuid_phys,
   1.173 +            self.size_dt_strings)
   1.174 +
   1.175 +class _StringBlock:
   1.176 +    def __init__(self):
   1.177 +        self.table = []
   1.178 +    def to_bin(self):
   1.179 +        return _bincat(self.table, '\0') + '\0'
   1.180 +    def add(self, str):
   1.181 +        self.table.append(str)
   1.182 +    def getoffset(self, str):
   1.183 +        return self.to_bin().index(str + '\0')
   1.184 +
   1.185 +class Tree(_Node):
   1.186 +    def __init__(self):
   1.187 +        self.last_phandle = 0
   1.188 +        self.strings = _StringBlock()
   1.189 +        self.reserved = [(0, 0)]
   1.190 +        _Node.__init__(self, self, '\0')
   1.191 +
   1.192 +    def alloc_phandle(self):
   1.193 +        self.last_phandle += 1
   1.194 +        return self.last_phandle
   1.195 +
   1.196 +    def stradd(self, str):
   1.197 +        return self.strings.add(str)
   1.198 +
   1.199 +    def stroffset(self, str):
   1.200 +        return self.strings.getoffset(str)
   1.201 +
   1.202 +    def reserve(self, start, len):
   1.203 +        self.reserved.insert(0, (start, len))
   1.204 +
   1.205 +    def to_bin(self):
   1.206 +        # layout:
   1.207 +        #   header
   1.208 +        #   reservation map
   1.209 +        #   string block
   1.210 +        #   data block
   1.211 +
   1.212 +        datablock = _Node.to_bin(self)
   1.213 +
   1.214 +        r = [ struct.pack('>QQ', rsrv[0], rsrv[1]) for rsrv in self.reserved ]
   1.215 +        reserved = _bincat(r)
   1.216 +
   1.217 +        strblock = _pad(self.strings.to_bin(), 4)
   1.218 +        strblocklen = len(strblock)
   1.219 +
   1.220 +        header = _Header()
   1.221 +        header.magic = _OF_DT_HEADER
   1.222 +        header.off_mem_rsvmap = _alignup(len(header.to_bin()), 8)
   1.223 +        header.off_dt_strings = header.off_mem_rsvmap + len(reserved)
   1.224 +        header.off_dt_struct = header.off_dt_strings + strblocklen
   1.225 +        header.version = 0x10
   1.226 +        header.last_comp_version = 0x10
   1.227 +        header.boot_cpuid_phys = 0
   1.228 +        header.size_dt_strings = strblocklen
   1.229 +
   1.230 +        payload = reserved + \
   1.231 +                strblock + \
   1.232 +                datablock + \
   1.233 +                struct.pack('>I', _OF_DT_END)
   1.234 +        header.totalsize = len(payload) + _alignup(len(header.to_bin()), 8)
   1.235 +        return _pad(header.to_bin(), 8) + payload
   1.236 +
   1.237 +_host_devtree_root = '/proc/device-tree'
   1.238 +def _getprop(propname):
   1.239 +    '''Extract a property from the system's device tree.'''
   1.240 +    f = file(os.path.join(_host_devtree_root, propname), 'r')
   1.241 +    data = f.read()
   1.242 +    f.close()
   1.243 +    return data
   1.244 +
   1.245 +def _copynode(node, dirpath, propfilter):
   1.246 +    '''Extract all properties from a node in the system's device tree.'''
   1.247 +    dirents = os.listdir(dirpath)
   1.248 +    for dirent in dirents:
   1.249 +        fullpath = os.path.join(dirpath, dirent)
   1.250 +        st = os.lstat(fullpath)
   1.251 +        if stat.S_ISDIR(st.st_mode):
   1.252 +            child = node.addnode(dirent)
   1.253 +            _copytree(child, fullpath, propfilter)
   1.254 +        elif stat.S_ISREG(st.st_mode) and propfilter(fullpath):
   1.255 +            node.addprop(dirent, _getprop(fullpath))
   1.256 +
   1.257 +def _copytree(node, dirpath, propfilter):
   1.258 +    path = os.path.join(_host_devtree_root, dirpath)
   1.259 +    _copynode(node, path, propfilter)
   1.260 +
   1.261 +def build(imghandler):
   1.262 +    '''Construct a device tree by combining the domain's configuration and
   1.263 +    the host's device tree.'''
   1.264 +    root = Tree()
   1.265 +
   1.266 +    # 4 pages: start_info, console, store, shared_info
   1.267 +    root.reserve(0x3ffc000, 0x4000)
   1.268 +
   1.269 +    root.addprop('device_type', 'chrp-but-not-really\0')
   1.270 +    root.addprop('#size-cells', 2)
   1.271 +    root.addprop('#address-cells', 2)
   1.272 +    root.addprop('model', 'Momentum,Maple-D\0')
   1.273 +    root.addprop('compatible', 'Momentum,Maple\0')
   1.274 +
   1.275 +    xen = root.addnode('xen')
   1.276 +    xen.addprop('start-info', 0, 0x3ffc000, 0, 0x1000)
   1.277 +    xen.addprop('version', 'Xen-3.0-unstable\0')
   1.278 +    xen.addprop('reg', 0, imghandler.vm.domid, 0, 0)
   1.279 +    xen.addprop('domain-name', imghandler.vm.getName() + '\0')
   1.280 +    xencons = xen.addnode('console')
   1.281 +    xencons.addprop('interrupts', 1, 0)
   1.282 +
   1.283 +    # XXX split out RMA node
   1.284 +    mem = root.addnode('memory@0')
   1.285 +    totalmem = imghandler.vm.getMemoryTarget() * 1024
   1.286 +    mem.addprop('reg', 0, 0, 0, totalmem)
   1.287 +    mem.addprop('device_type', 'memory\0')
   1.288 +
   1.289 +    cpus = root.addnode('cpus')
   1.290 +    cpus.addprop('smp-enabled')
   1.291 +    cpus.addprop('#size-cells', 0)
   1.292 +    cpus.addprop('#address-cells', 1)
   1.293 +
   1.294 +    # Copy all properties the system firmware gave us, except for 'linux,'
   1.295 +    # properties, from 'cpus/@0', once for every vcpu. Hopefully all cpus are
   1.296 +    # identical...
   1.297 +    cpu0 = None
   1.298 +    def _nolinuxprops(fullpath):
   1.299 +        return not os.path.basename(fullpath).startswith('linux,')
   1.300 +    for i in range(imghandler.vm.getVCpuCount()):
   1.301 +        cpu = cpus.addnode('PowerPC,970@0')
   1.302 +        _copytree(cpu, 'cpus/PowerPC,970@0', _nolinuxprops)
   1.303 +        # and then overwrite what we need to
   1.304 +        pft_size = imghandler.vm.info.get('pft-size', 0x14)
   1.305 +        cpu.setprop('ibm,pft-size', 0, pft_size)
   1.306 +
   1.307 +        # set default CPU
   1.308 +        if cpu0 == None:
   1.309 +            cpu0 = cpu
   1.310 +
   1.311 +    chosen = root.addnode('chosen')
   1.312 +    chosen.addprop('cpu', cpu0.get_phandle())
   1.313 +    chosen.addprop('memory', mem.get_phandle())
   1.314 +    chosen.addprop('linux,stdout-path', '/xen/console\0')
   1.315 +    chosen.addprop('interrupt-controller', xen.get_phandle())
   1.316 +    chosen.addprop('bootargs', imghandler.cmdline + '\0')
   1.317 +    # xc_linux_load.c will overwrite these 64-bit properties later
   1.318 +    chosen.addprop('linux,initrd-start', 0, 0)
   1.319 +    chosen.addprop('linux,initrd-end', 0, 0)
   1.320 +
   1.321 +    if 1:
   1.322 +        f = file('/tmp/domU.dtb', 'w')
   1.323 +        f.write(root.to_bin())
   1.324 +        f.close()
   1.325 +
   1.326 +    return root
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Aug 29 22:51:06 2006 +0100
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Aug 29 23:20:22 2006 +0100
     2.3 @@ -30,7 +30,6 @@ import string
     2.4  import time
     2.5  import threading
     2.6  import os
     2.7 -import math
     2.8  
     2.9  import xen.lowlevel.xc
    2.10  from xen.util import asserts
    2.11 @@ -1286,34 +1285,27 @@ class XendDomainInfo:
    2.12                  for v in range(0, self.info['max_vcpu_id']+1):
    2.13                      xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
    2.14  
    2.15 -            # set domain maxmem in KiB
    2.16 -            xc.domain_setmaxmem(self.domid, self.info['maxmem'] * 1024)
    2.17 +            # set memory limit
    2.18 +            maxmem = self.image.getRequiredMemory(self.info['maxmem'] * 1024)
    2.19 +            xc.domain_setmaxmem(self.domid, maxmem)
    2.20  
    2.21 -            m = self.image.getDomainMemory(self.info['memory'] * 1024)
    2.22 +            mem_kb = self.image.getRequiredMemory(self.info['memory'] * 1024)
    2.23  
    2.24              # get the domain's shadow memory requirement
    2.25 -            sm = int(math.ceil(self.image.getDomainShadowMemory(m) / 1024.0))
    2.26 -            if self.info['shadow_memory'] > sm:
    2.27 -                sm = self.info['shadow_memory']
    2.28 +            shadow_kb = self.image.getRequiredShadowMemory(mem_kb)
    2.29 +            shadow_kb_req = self.info['shadow_memory'] * 1024
    2.30 +            if shadow_kb_req > shadow_kb:
    2.31 +                shadow_kb = shadow_kb_req
    2.32  
    2.33              # Make sure there's enough RAM available for the domain
    2.34 -            balloon.free(m + sm * 1024)
    2.35 +            balloon.free(mem_kb + shadow_kb)
    2.36  
    2.37              # Set up the shadow memory
    2.38 -            sm = xc.shadow_mem_control(self.domid, mb=sm)
    2.39 -            self.info['shadow_memory'] = sm
    2.40 +            shadow_cur = xc.shadow_mem_control(self.domid, shadow_kb * 1024)
    2.41 +            self.info['shadow_memory'] = shadow_cur
    2.42  
    2.43 -            init_reservation = self.info['memory'] * 1024
    2.44 -            if os.uname()[4] in ('ia64', 'ppc64'):
    2.45 -                # Workaround for architectures that don't yet support
    2.46 -                # ballooning.
    2.47 -                init_reservation = m
    2.48 -                # Following line from xiantao.zhang@intel.com
    2.49 -                # Needed for IA64 until supports ballooning -- okay for PPC64?
    2.50 -                xc.domain_setmaxmem(self.domid, m)
    2.51 -
    2.52 -            xc.domain_memory_increase_reservation(self.domid, init_reservation,
    2.53 -                                                  0, 0)
    2.54 +            # initial memory allocation
    2.55 +            xc.domain_memory_increase_reservation(self.domid, mem_kb, 0, 0)
    2.56  
    2.57              self.createChannels()
    2.58  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/python/xen/xend/arch.py	Tue Aug 29 23:20:22 2006 +0100
     3.3 @@ -0,0 +1,31 @@
     3.4 +#!/usr/bin/env python
     3.5 +#
     3.6 +# This library is free software; you can redistribute it and/or
     3.7 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     3.8 +# License as published by the Free Software Foundation.
     3.9 +#
    3.10 +# This library is distributed in the hope that it will be useful,
    3.11 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.12 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    3.13 +# Lesser General Public License for more details.
    3.14 +#
    3.15 +# You should have received a copy of the GNU Lesser General Public
    3.16 +# License along with this library; if not, write to the Free Software
    3.17 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.18 +#
    3.19 +# Copyright (C) IBM Corp. 2006
    3.20 +#
    3.21 +# Authors: Hollis Blanchard <hollisb@us.ibm.com>
    3.22 +
    3.23 +import os
    3.24 +
    3.25 +_types = {
    3.26 +    "i386": "x86",
    3.27 +    "i486": "x86",
    3.28 +    "i586": "x86",
    3.29 +    "i686": "x86",
    3.30 +    "ia64": "ia64",
    3.31 +    "ppc": "powerpc",
    3.32 +    "ppc64": "powerpc",
    3.33 +}
    3.34 +type = _types.get(os.uname()[4], "unknown")
     4.1 --- a/tools/python/xen/xend/image.py	Tue Aug 29 22:51:06 2006 +0100
     4.2 +++ b/tools/python/xen/xend/image.py	Tue Aug 29 23:20:22 2006 +0100
     4.3 @@ -27,6 +27,8 @@ from xen.xend.XendError import VmError
     4.4  from xen.xend.XendLogging import log
     4.5  from xen.xend.server.netif import randomMAC
     4.6  from xen.xend.xenstore.xswatch import xswatch
     4.7 +from xen.xend import arch
     4.8 +from xen.xend import FlatDeviceTree
     4.9  
    4.10  
    4.11  xc = xen.lowlevel.xc.xc()
    4.12 @@ -141,19 +143,10 @@ class ImageHandler:
    4.13              raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
    4.14                            % (self.ostype, self.vm.getDomid(), str(result)))
    4.15  
    4.16 -
    4.17 -    def getDomainMemory(self, mem_kb):
    4.18 -        """@return The memory required, in KiB, by the domain to store the
    4.19 -        given amount, also in KiB."""
    4.20 -        if os.uname()[4] != 'ia64':
    4.21 -            # A little extra because auto-ballooning is broken w.r.t. HVM
    4.22 -            # guests. Also, slack is necessary for live migration since that
    4.23 -            # uses shadow page tables.
    4.24 -            if 'hvm' in xc.xeninfo()['xen_caps']:
    4.25 -                mem_kb += 4*1024;
    4.26 +    def getRequiredMemory(self, mem_kb):
    4.27          return mem_kb
    4.28  
    4.29 -    def getDomainShadowMemory(self, mem_kb):
    4.30 +    def getRequiredShadowMemory(self, mem_kb):
    4.31          """@return The minimum shadow memory required, in KiB, for a domain 
    4.32          with mem_kb KiB of RAM."""
    4.33          # PV domains don't need any shadow memory
    4.34 @@ -197,9 +190,39 @@ class LinuxImageHandler(ImageHandler):
    4.35                                ramdisk        = self.ramdisk,
    4.36                                features       = self.vm.getFeatures())
    4.37  
    4.38 -class HVMImageHandler(ImageHandler):
    4.39 +class PPC_LinuxImageHandler(LinuxImageHandler):
    4.40 +
    4.41 +    ostype = "linux"
    4.42 +
    4.43 +    def configure(self, imageConfig, deviceConfig):
    4.44 +        LinuxImageHandler.configure(self, imageConfig, deviceConfig)
    4.45 +        self.imageConfig = imageConfig
    4.46 +
    4.47 +    def buildDomain(self):
    4.48 +        store_evtchn = self.vm.getStorePort()
    4.49 +        console_evtchn = self.vm.getConsolePort()
    4.50  
    4.51 -    ostype = "hvm"
    4.52 +        log.debug("dom            = %d", self.vm.getDomid())
    4.53 +        log.debug("image          = %s", self.kernel)
    4.54 +        log.debug("store_evtchn   = %d", store_evtchn)
    4.55 +        log.debug("console_evtchn = %d", console_evtchn)
    4.56 +        log.debug("cmdline        = %s", self.cmdline)
    4.57 +        log.debug("ramdisk        = %s", self.ramdisk)
    4.58 +        log.debug("vcpus          = %d", self.vm.getVCpuCount())
    4.59 +        log.debug("features       = %s", self.vm.getFeatures())
    4.60 +
    4.61 +        devtree = FlatDeviceTree.build(self)
    4.62 +
    4.63 +        return xc.linux_build(dom            = self.vm.getDomid(),
    4.64 +                              image          = self.kernel,
    4.65 +                              store_evtchn   = store_evtchn,
    4.66 +                              console_evtchn = console_evtchn,
    4.67 +                              cmdline        = self.cmdline,
    4.68 +                              ramdisk        = self.ramdisk,
    4.69 +                              features       = self.vm.getFeatures(),
    4.70 +                              arch_args      = devtree.to_bin())
    4.71 +
    4.72 +class HVMImageHandler(ImageHandler):
    4.73  
    4.74      def configure(self, imageConfig, deviceConfig):
    4.75          ImageHandler.configure(self, imageConfig, deviceConfig)
    4.76 @@ -355,32 +378,6 @@ class HVMImageHandler(ImageHandler):
    4.77          os.waitpid(self.pid, 0)
    4.78          self.pid = 0
    4.79  
    4.80 -    def getDomainMemory(self, mem_kb):
    4.81 -        """@see ImageHandler.getDomainMemory"""
    4.82 -        if os.uname()[4] == 'ia64':
    4.83 -            page_kb = 16
    4.84 -            # ROM size for guest firmware, ioreq page and xenstore page
    4.85 -            extra_pages = 1024 + 2
    4.86 -        else:
    4.87 -            page_kb = 4
    4.88 -            # This was derived emperically:
    4.89 -            #   2.4 MB overhead per 1024 MB RAM + 8 MB constant
    4.90 -            #   + 4 to avoid low-memory condition
    4.91 -            extra_mb = (2.4/1024) * (mem_kb/1024.0) + 12;
    4.92 -            extra_pages = int( math.ceil( extra_mb*1024 / page_kb ))
    4.93 -        return mem_kb + extra_pages * page_kb
    4.94 -
    4.95 -    def getDomainShadowMemory(self, mem_kb):
    4.96 -        """@return The minimum shadow memory required, in KiB, for a domain 
    4.97 -        with mem_kb KiB of RAM."""
    4.98 -        if os.uname()[4] in ('ia64', 'ppc64'):
    4.99 -            # Explicit shadow memory is not a concept 
   4.100 -            return 0
   4.101 -        else:
   4.102 -            # 1MB per vcpu plus 4Kib/Mib of RAM.  This is higher than 
   4.103 -            # the minimum that Xen would allocate if no value were given.
   4.104 -            return 1024 * self.vm.getVCpuCount() + mem_kb / 256
   4.105 -
   4.106      def register_shutdown_watch(self):
   4.107          """ add xen store watch on control/shutdown """
   4.108          self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \
   4.109 @@ -417,15 +414,51 @@ class HVMImageHandler(ImageHandler):
   4.110  
   4.111          return 1 # Keep watching
   4.112  
   4.113 -"""Table of image handler classes for virtual machine images.  Indexed by
   4.114 -image type.
   4.115 -"""
   4.116 -imageHandlerClasses = {}
   4.117 +class IA64_HVM_ImageHandler(HVMImageHandler):
   4.118 +
   4.119 +    ostype = "hvm"
   4.120 +
   4.121 +    def getRequiredMemory(self, mem_kb):
   4.122 +        page_kb = 16
   4.123 +        # ROM size for guest firmware, ioreq page and xenstore page
   4.124 +        extra_pages = 1024 + 2
   4.125 +        return mem_kb + extra_pages * page_kb
   4.126 +
   4.127 +    def getRequiredShadowMemory(self, mem_kb):
   4.128 +        # Explicit shadow memory is not a concept 
   4.129 +        return 0
   4.130 +
   4.131 +class X86_HVM_ImageHandler(HVMImageHandler):
   4.132 +
   4.133 +    ostype = "hvm"
   4.134  
   4.135 +    def getRequiredMemory(self, mem_kb):
   4.136 +        page_kb = 4
   4.137 +        # This was derived emperically:
   4.138 +        #   2.4 MB overhead per 1024 MB RAM + 8 MB constant
   4.139 +        #   + 4 to avoid low-memory condition
   4.140 +        extra_mb = (2.4/1024) * (mem_kb/1024.0) + 12;
   4.141 +        extra_pages = int( math.ceil( extra_mb*1024 / page_kb ))
   4.142 +        return mem_kb + extra_pages * page_kb
   4.143  
   4.144 -for h in LinuxImageHandler, HVMImageHandler:
   4.145 -    imageHandlerClasses[h.ostype] = h
   4.146 +    def getRequiredShadowMemory(self, mem_kb):
   4.147 +        # 1MB per vcpu plus 4Kib/Mib of RAM.  This is higher than 
   4.148 +        # the minimum that Xen would allocate if no value were given.
   4.149 +        return 1024 * self.vm.getVCpuCount() + mem_kb / 256
   4.150  
   4.151 +_handlers = {
   4.152 +    "powerpc": {
   4.153 +        "linux": PPC_LinuxImageHandler,
   4.154 +    },
   4.155 +    "ia64": {
   4.156 +        "linux": LinuxImageHandler,
   4.157 +        "hvm": IA64_HVM_ImageHandler,
   4.158 +    },
   4.159 +    "x86": {
   4.160 +        "linux": LinuxImageHandler,
   4.161 +        "hvm": X86_HVM_ImageHandler,
   4.162 +    },
   4.163 +}
   4.164  
   4.165  def findImageHandlerClass(image):
   4.166      """Find the image handler class for an image config.
   4.167 @@ -433,10 +466,10 @@ def findImageHandlerClass(image):
   4.168      @param image config
   4.169      @return ImageHandler subclass or None
   4.170      """
   4.171 -    ty = sxp.name(image)
   4.172 -    if ty is None:
   4.173 +    type = sxp.name(image)
   4.174 +    if type is None:
   4.175          raise VmError('missing image type')
   4.176 -    imageClass = imageHandlerClasses.get(ty)
   4.177 -    if imageClass is None:
   4.178 -        raise VmError('unknown image type: ' + ty)
   4.179 -    return imageClass
   4.180 +    try:
   4.181 +        return _handlers[arch.type][type]
   4.182 +    except KeyError:
   4.183 +        raise VmError('unknown image type: ' + type)