From 8537fbaeade8b85d8751b2702b0b3e76dabaeff6 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 5 Dec 2006 17:01:34 +0000 Subject: [PATCH 01/69] [LINUX] The crash note resource should be nested inside the hypervisor resource. This was exposed by 12709:98413fa7826c which corrected the length of the hypervisor resource. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c index 88a2423340..1f4a828e55 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c @@ -106,7 +106,7 @@ void xen_machine_kexec_register_resources(struct resource *res) request_resource(res, &xen_hypervisor_res); for (k = 0; k < xen_max_nr_phys_cpus; k++) - request_resource(res, xen_phys_cpus + k); + request_resource(&xen_hypervisor_res, xen_phys_cpus + k); } From b988d46a49abccb54f11dc41618e2db41f0f2f77 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 6 Dec 2006 10:05:41 +0000 Subject: [PATCH 02/69] Fixes a mistake in changeset 12732 Signed-off-by: Xiaohui Xin Signed-off-by: Anthony Xu Signed-off-by: Dexuan Cui --- xen/arch/x86/mm/shadow/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 1f295758d8..881f91a81d 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1280,7 +1280,7 @@ sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn) * Instead, just count the number of l3es from zero. It's safe * to do this because we already checked that the gfn is within * the bounds of the p2m. */ - l3e += (((addr) & VADDR_MASK) >> L3_PAGETABLE_SHIFT); + l3e += (addr >> L3_PAGETABLE_SHIFT); #else l3e += l3_table_offset(addr); #endif From ec168504b9564819c67b10521f0eb5896c518dd9 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 5 Dec 2006 15:47:43 +0000 Subject: [PATCH 03/69] Fix error message. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 5ebb7e6240..cc3c5c783e 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -808,7 +808,7 @@ class XendDomain: raise XendError("Cannot save privileged domain %s" % domname) if dominfo.state != DOM_STATE_HALTED: - raise XendError("Cannot suspend domain that is not running.") + raise XendError("Cannot resume domain that is not halted.") dom_uuid = dominfo.get_uuid() chkpath = self._managed_check_point_path(dom_uuid) From 6e66f078d444f2f49450bb957ae4245cf296626a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 10:10:06 +0000 Subject: [PATCH 04/69] Fix HTTP server. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/server/SrvServer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py index 6bfff3a318..95453d7b46 100644 --- a/tools/python/xen/xend/server/SrvServer.py +++ b/tools/python/xen/xend/server/SrvServer.py @@ -165,7 +165,7 @@ class XendServers: else: break -def _loadConfig(servers): +def _loadConfig(servers, root): if xroot.get_xend_http_server(): servers.add(HttpServer(root, xroot.get_xend_address(), @@ -219,5 +219,5 @@ def create(): root = SrvDir() root.putChild('xend', SrvRoot()) servers = XendServers() - _loadConfig(servers) + _loadConfig(servers, root) return servers From 1d68773ad2199a0b5dfac08f8cdc54a95a0611ae Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 10:12:39 +0000 Subject: [PATCH 05/69] Move the actual call routed by do_legacy_api_with_uuid out of the scope of the domains_lock. The call itself is already locking as necessary, and it is important for domain_start to be able to release the lock across the scope of waitForDevices. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomain.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index cc3c5c783e..4b11634403 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -641,17 +641,22 @@ class XendDomain: return (self.get_vm_with_dev_uuid(klass, dev_uuid) != None) def do_legacy_api_with_uuid(self, fn, vm_uuid, *args, **kwargs): + dom = self.uuid_to_dom(vm_uuid) + fn(dom, *args, **kwargs) + + def uuid_to_dom(self, vm_uuid): self.domains_lock.acquire() try: for domid, dom in self.domains.items(): - if dom.get_uuid == vm_uuid: - return fn(domid, *args, **kwargs) + if dom.get_uuid() == vm_uuid: + return domid if vm_uuid in self.managed_domains: domid = self.managed_domains[vm_uuid].getDomid() - if domid == None: - domid = self.managed_domains[vm_uuid].getName() - return fn(domid, *args, **kwargs) + if domid is None: + return self.managed_domains[vm_uuid].getName() + else: + return domid raise XendInvalidDomain("Domain does not exist") finally: From 81f605d9cbcedb8494a6da10b442b42f4bfe6c6d Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 10:13:46 +0000 Subject: [PATCH 06/69] Don't trace inside SrvServer.py -- it's doing a one-second sleep in a loop, so it just fills the trace with useless clutter. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/server/SrvDaemon.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 155062a704..bd93e6fc56 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -278,6 +278,8 @@ class Daemon: modulename = m.group(1) if re.search('sxp.py', modulename): return None + if re.search('SrvServer.py', modulename): + return None self.traceindent += 1 self.print_trace("> %s:%s\n" % (modulename, code.co_name)) From 5ef203e373b2f0380848f63b1d63d817d4301f0f Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 10:37:10 +0000 Subject: [PATCH 07/69] Fix server reloading when the HTTP server is enabled. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/server/SrvServer.py | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py index 95453d7b46..4dfe8584e0 100644 --- a/tools/python/xen/xend/server/SrvServer.py +++ b/tools/python/xen/xend/server/SrvServer.py @@ -62,8 +62,9 @@ xroot = XendRoot.instance() class XendServers: - def __init__(self): + def __init__(self, root): self.servers = [] + self.root = root self.cleaningUp = False self.reloadingConfig = False @@ -101,6 +102,9 @@ class XendServers: while True: threads = [] for server in self.servers: + if server.ready: + continue + thread = Thread(target=server.run, name=server.__class__.__name__) if isinstance(server, HttpServer): thread.setDaemon(True) @@ -156,21 +160,23 @@ class XendServers: pass if self.reloadingConfig: - log.info("Restarting all servers...") + log.info("Restarting all XML-RPC and Xen-API servers...") self.cleaningUp = False self.reloadingConfig = False xroot.set_config() - self.servers = [] - _loadConfig(self) + new_servers = [x for x in self.servers + if isinstance(x, HttpServer)] + self.servers = new_servers + _loadConfig(self, self.root, True) else: break -def _loadConfig(servers, root): - if xroot.get_xend_http_server(): +def _loadConfig(servers, root, reload): + if not reload and xroot.get_xend_http_server(): servers.add(HttpServer(root, xroot.get_xend_address(), xroot.get_xend_port())) - if xroot.get_xend_unix_server(): + if not reload and xroot.get_xend_unix_server(): path = xroot.get_xend_unix_path() log.info('unix path=' + path) servers.add(UnixHttpServer(root, path)) @@ -218,6 +224,6 @@ def _loadConfig(servers, root): def create(): root = SrvDir() root.putChild('xend', SrvRoot()) - servers = XendServers() - _loadConfig(servers, root) + servers = XendServers(root) + _loadConfig(servers, root, False) return servers From 6455e182f2cd18f7e21cf55a9a986b206a9b4549 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 10:47:31 +0000 Subject: [PATCH 08/69] Added server proxy and session manager for Xen-API clients. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/XenAPI.py | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tools/python/xen/xm/XenAPI.py diff --git a/tools/python/xen/xm/XenAPI.py b/tools/python/xen/xm/XenAPI.py new file mode 100644 index 0000000000..7d469fc997 --- /dev/null +++ b/tools/python/xen/xm/XenAPI.py @@ -0,0 +1,132 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2006 XenSource Inc. +#============================================================================ +# +# Parts of this file are based upon xmlrpclib.py, the XML-RPC client +# interface included in the Python distribution. +# +# Copyright (c) 1999-2002 by Secret Labs AB +# Copyright (c) 1999-2002 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its +# associated documentation, you agree that you have read, understood, +# and will comply with the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and +# its associated documentation for any purpose and without fee is +# hereby granted, provided that the above copyright notice appears in +# all copies, and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Secret Labs AB or the author not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# -------------------------------------------------------------------- + +import xmlrpclib + +import xen.util.xmlrpclib2 + + +class Failure(Exception): + def __init__(self, details): + self.details = details + + def __str__(self): + return "Xen-API failure: %s" % str(self.details) + + +class Session(xen.util.xmlrpclib2.ServerProxy): + """A server proxy and session manager for communicating with Xend using + the Xen-API. + + Example: + + session = Session('http://localhost:9363/') + session.login_with_password('me', 'mypassword') + session.xenapi.VM.start(vm_uuid) + session.xenapi.session.logout() + + For now, this class also supports the legacy XML-RPC API, using + session.xend.domain('Domain-0') and similar. This support will disappear + once there is a working Xen-API replacement for every call in the legacy + API. + """ + + def __init__(self, uri, transport=None, encoding=None, verbose=0, + allow_none=1): + xen.util.xmlrpclib2.ServerProxy.__init__(self, uri, transport, + encoding, verbose, + allow_none) + self._session = None + + + def _xen_request(self, methodname, params): + full_params = (self._session,) + params + return _parse_result(getattr(self, methodname)(*full_params)) + + + def _login(self, method, username, password): + self._session = _parse_result( + getattr(self, 'session.%s' % method)(username, password)) + + + def __getattr__(self, name): + if name == 'xenapi': + return _Dispatcher(self._xen_request, None) + elif name.startswith('login'): + return lambda u, p: self._login(name, u, p) + else: + return xen.util.xmlrpclib2.ServerProxy.__getattr__(self, name) + + +def _parse_result(result): + if 'Status' not in result: + raise xmlrpclib.Fault(500, 'Missing Status in response from server') + if result['Status'] == 'Success': + if 'Value' in result: + return result['Value'] + else: + raise xmlrpclib.Fault(500, + 'Missing Value in response from server') + else: + if 'ErrorDescription' in result: + raise Failure(result['ErrorDescription']) + else: + raise xmlrpclib.Fault( + 500, 'Missing ErrorDescription in response from server') + + +# Based upon _Method from xmlrpclib. +class _Dispatcher: + def __init__(self, send, name): + self.__send = send + self.__name = name + def __getattr__(self, name): + if self.__name is None: + return _Dispatcher(self.__send, name) + else: + return _Dispatcher(self.__send, "%s.%s" % (self.__name, name)) + def __call__(self, *args): + return self.__send(self.__name, args) From 8edc7b1c06a06f9291f359500805251609613eb9 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 11:02:32 +0000 Subject: [PATCH 09/69] Added support for configuration file for xm, and use that to specify contact and authentication details for the Xen-API server. The default behaviour is still to use the existing legacy XML-RPC server. Signed-off-by: Ewan Mellor --- tools/examples/xm-config.xml | 43 ++++++++++++++++ tools/python/xen/xm/create.py | 2 +- tools/python/xen/xm/main.py | 89 +++++++++++++++++++++++++++++++-- tools/python/xen/xm/migrate.py | 3 +- tools/python/xen/xm/new.py | 5 +- tools/python/xen/xm/shutdown.py | 4 +- 6 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 tools/examples/xm-config.xml diff --git a/tools/examples/xm-config.xml b/tools/examples/xm-config.xml new file mode 100644 index 0000000000..dbd8778bae --- /dev/null +++ b/tools/examples/xm-config.xml @@ -0,0 +1,43 @@ + + + + + + + + diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 8b5301b9e8..c081560f8e 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -29,13 +29,13 @@ import xmlrpclib from xen.xend import sxp from xen.xend import PrettyPrint import xen.xend.XendClient -from xen.xend.XendClient import server from xen.xend.XendBootloader import bootloader from xen.util import blkif from xen.util import security from xen.xm.opts import * +from main import server import console diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 9982dc3388..4a545cb9a6 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -21,6 +21,7 @@ """Grand unified management application for Xen. """ +import atexit import os import sys import re @@ -31,6 +32,7 @@ import xmlrpclib import traceback import datetime from select import select +import xml.dom.minidom import warnings warnings.filterwarnings('ignore', category=FutureWarning) @@ -38,12 +40,14 @@ warnings.filterwarnings('ignore', category=FutureWarning) from xen.xend import PrettyPrint from xen.xend import sxp from xen.xend import XendClient -from xen.xend.XendClient import server from xen.xend.XendConstants import * from xen.xm.opts import OptionError, Opts, wrap, set_true from xen.xm import console from xen.util import security +from xen.util.xmlrpclib2 import ServerProxy + +import XenAPI # 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,6 +55,12 @@ from xen.util import security if not hasattr(getopt, 'gnu_getopt'): getopt.gnu_getopt = getopt.getopt +XM_CONFIG_FILE = '/etc/xen/xm-config.xml' + +# Supported types of server +SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC' +SERVER_XEN_API = 'Xen-API' + # General help message USAGE_HELP = "Usage: xm [args]\n\n" \ @@ -319,6 +329,35 @@ acm_commands = [ all_commands = (domain_commands + host_commands + scheduler_commands + device_commands + vnet_commands + acm_commands) + +## +# Configuration File Parsing +## + +if os.path.isfile(XM_CONFIG_FILE): + config = xml.dom.minidom.parse(XM_CONFIG_FILE) +else: + config = None + +def parseServer(): + if config: + server = config.getElementsByTagName('server') + if server: + st = server[0].getAttribute('type') + if st != SERVER_XEN_API: + st = SERVER_LEGACY_XMLRPC + return (st, server[0].getAttribute('uri')) + + return SERVER_LEGACY_XMLRPC, XendClient.uri + +def parseAuthentication(): + server = config.getElementsByTagName('server')[0] + return (server.getAttribute('username'), + server.getAttribute('password')) + +serverType, serverURI = parseServer() + + #################################################################### # # Help/usage printing functions @@ -469,6 +508,16 @@ def err(msg): print >>sys.stderr, "Error:", msg +def get_single_vm(dom): + uuids = server.xenapi.VM.get_by_name_label(dom) + n = len(uuids) + if n == 1: + return uuids[0] + else: + dominfo = server.xend.domain(dom, False) + return dominfo['uuid'] + + ######################################################################### # # Main xm functions @@ -767,17 +816,26 @@ def xm_start(args): sys.exit(1) dom = params[0] - server.xend.domain.start(dom, paused) + if serverType == SERVER_XEN_API: + server.xenapi.VM.start(get_single_vm(dom), paused) + else: + server.xend.domain.start(dom, paused) def xm_delete(args): arg_check(args, "delete", 1) dom = args[0] - server.xend.domain.delete(dom) + if serverType == SERVER_XEN_API: + server.xenapi.VM.destroy(dom) + else: + server.xend.domain.delete(dom) def xm_suspend(args): arg_check(args, "suspend", 1) dom = args[0] - server.xend.domain.suspend(dom) + if serverType == SERVER_XEN_API: + server.xenapi.VM.suspend(get_single_vm(dom)) + else: + server.xend.domain.suspend(dom) def xm_resume(args): arg_check(args, "resume", 1, 2) @@ -799,7 +857,10 @@ def xm_resume(args): sys.exit(1) dom = params[0] - server.xend.domain.resume(dom, paused) + if serverType == SERVER_XEN_API: + server.xenapi.VM.resume(dom, paused) + else: + server.xend.domain.resume(dom, paused) def xm_reboot(args): arg_check(args, "reboot", 1, 3) @@ -1577,6 +1638,8 @@ def deprecated(old,new): "Command %s is deprecated. Please use xm %s instead." % (old, new)) def main(argv=sys.argv): + global server + if len(argv) < 2: usage() @@ -1595,6 +1658,19 @@ def main(argv=sys.argv): args = argv[2:] if cmd: try: + if serverType == SERVER_XEN_API: + server = XenAPI.Session(serverURI) + username, password = parseAuthentication() + server.login_with_password(username, password) + def logout(): + try: + server.xenapi.session.logout() + except: + pass + atexit.register(logout) + else: + server = ServerProxy(serverURI) + rc = cmd(args) if rc: usage() @@ -1615,6 +1691,9 @@ def main(argv=sys.argv): sys.exit(1) except SystemExit: sys.exit(1) + except XenAPI.Failure, exn: + err(str(exn)) + sys.exit(1) except xmlrpclib.Fault, ex: if ex.faultCode == XendClient.ERROR_INVALID_DOMAIN: err("Domain '%s' does not exist." % ex.faultString) diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py index b362ae9057..72aca71932 100644 --- a/tools/python/xen/xm/migrate.py +++ b/tools/python/xen/xm/migrate.py @@ -21,9 +21,10 @@ import sys -from xen.xend.XendClient import server from xen.xm.opts import * +from main import server + gopts = Opts(use="""[options] DOM HOST Migrate domain DOM to host HOST. diff --git a/tools/python/xen/xm/new.py b/tools/python/xen/xm/new.py index 7af65510a9..2c6cae84b6 100644 --- a/tools/python/xen/xm/new.py +++ b/tools/python/xen/xm/new.py @@ -21,10 +21,9 @@ import xmlrpclib from xen.xend import PrettyPrint from xen.xend import sxp from xen.xend import XendClient -from xen.xend.XendClient import server -from xen.xm.opts import * -from xen.xm.create import * +from opts import * +from create import * def make_unstarted_domain(opts, config): """Create an unstarted domain. diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py index a63c3523ca..b5542d9611 100644 --- a/tools/python/xen/xm/shutdown.py +++ b/tools/python/xen/xm/shutdown.py @@ -19,9 +19,9 @@ """ import time -from xen.xend.XendClient import server from xen.xend import sxp -from xen.xm.opts import * +from opts import * +from main import server gopts = Opts(use="""[options] [DOM] From 2420eb41c59500b35ccca9af5520cad65b3389f8 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 11:24:37 +0000 Subject: [PATCH 10/69] Implement VM.set_name_label. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 9f3b2ed459..0b4e35b8ce 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -821,8 +821,9 @@ class XendAPI: dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() - def VM_set_name_label(self, session, vm_ref): + def VM_set_name_label(self, session, vm_ref, label): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + dom.setName(label) return xen_api_success_void() def VM_set_name_description(self, session, vm_ref): From 556d54c7ce8d0ed4a3bf78960c697b53d1c54794 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 11:25:51 +0000 Subject: [PATCH 11/69] Added Xen-API implementations for xm pause, xm unpause, xm destroy, xm rename, and fix xm suspend and xm delete. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 4a545cb9a6..95cbda9033 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -825,7 +825,7 @@ def xm_delete(args): arg_check(args, "delete", 1) dom = args[0] if serverType == SERVER_XEN_API: - server.xenapi.VM.destroy(dom) + server.xenapi.VM.destroy(get_single_vm(dom)) else: server.xend.domain.delete(dom) @@ -858,7 +858,7 @@ def xm_resume(args): dom = params[0] if serverType == SERVER_XEN_API: - server.xenapi.VM.resume(dom, paused) + server.xenapi.VM.resume(get_single_vm(dom), paused) else: server.xend.domain.resume(dom, paused) @@ -876,13 +876,19 @@ def xm_pause(args): arg_check(args, "pause", 1) dom = args[0] - server.xend.domain.pause(dom) + if serverType == SERVER_XEN_API: + server.xenapi.VM.pause(get_single_vm(dom)) + else: + server.xend.domain.pause(dom) def xm_unpause(args): arg_check(args, "unpause", 1) dom = args[0] - server.xend.domain.unpause(dom) + if serverType == SERVER_XEN_API: + server.xenapi.VM.unpause(get_single_vm(dom)) + else: + server.xend.domain.unpause(dom) def xm_dump_core(args): live = False @@ -923,7 +929,10 @@ def xm_dump_core(args): def xm_rename(args): arg_check(args, "rename", 2) - server.xend.domain.setName(args[0], args[1]) + if serverType == SERVER_XEN_API: + server.xenapi.VM.set_name_label(get_single_vm(args[0]), args[1]) + else: + server.xend.domain.setName(args[0], args[1]) def xm_importcommand(command, args): cmd = __import__(command, globals(), locals(), 'xen.xm') @@ -981,7 +990,12 @@ def xm_vcpu_set(args): def xm_destroy(args): arg_check(args, "destroy", 1) - server.xend.domain.destroy(args[0]) + + dom = args[0] + if serverType == SERVER_XEN_API: + server.xenapi.VM.hard_shutdown(get_single_vm(dom)) + else: + server.xend.domain.destroy(dom) def xm_domid(args): From f1717b30d4f0061487c82b417991e94708a852dd Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 6 Dec 2006 12:13:22 +0000 Subject: [PATCH 12/69] [XEN] remove unused monitor_vtable mapping. Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/common.c | 8 +++----- xen/include/asm-x86/domain.h | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 881f91a81d..d554896e83 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2433,11 +2433,10 @@ void sh_update_paging_modes(struct vcpu *v) } } - if ( pagetable_get_pfn(v->arch.monitor_table) == 0 ) + if ( pagetable_is_null(v->arch.monitor_table) ) { mfn_t mmfn = shadow_make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(mmfn); - v->arch.monitor_vtable = sh_map_domain_page(mmfn); } if ( v->arch.shadow.mode != old_mode ) @@ -2467,12 +2466,10 @@ void sh_update_paging_modes(struct vcpu *v) return; } - sh_unmap_domain_page(v->arch.monitor_vtable); old_mfn = pagetable_get_mfn(v->arch.monitor_table); v->arch.monitor_table = pagetable_null(); new_mfn = v->arch.shadow.mode->make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(new_mfn); - v->arch.monitor_vtable = sh_map_domain_page(new_mfn); SHADOW_PRINTK("new monitor table %"SH_PRI_mfn "\n", mfn_x(new_mfn)); @@ -3272,7 +3269,8 @@ void shadow_audit_p2m(struct domain *d) //SHADOW_PRINTK("p2m audit starts\n"); - test_linear = ( (d == current->domain) && current->arch.monitor_vtable ); + test_linear = ( (d == current->domain) + && !pagetable_is_null(current->arch.monitor_table) ); if ( test_linear ) local_flush_tlb(); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index a7b511fc32..20793910ba 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -196,7 +196,6 @@ struct arch_vcpu unsigned long cr3; /* (MA) value to install in HW CR3 */ void *guest_vtable; /* virtual addr of pagetable */ - root_pgentry_t *monitor_vtable; /* virtual addr of monitor_table */ /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; From 3f4a3b36025877a71b55fdf800d0486d8642b0c5 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 13:24:28 +0000 Subject: [PATCH 13/69] Tidy-up some of the descriptions. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 374 +++++++++++++++--------------- 1 file changed, 187 insertions(+), 187 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 81cd8828d4..de023012ac 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -23,7 +23,7 @@ The following classes are defined: Name & Description \\ \hline {\tt session} & A session \\ -{\tt task} & A longrunning asynchronous task \\ +{\tt task} & A long-running asynchronous task \\ {\tt VM} & A virtual machine (or 'guest') \\ {\tt host} & A physical host \\ {\tt host\_cpu} & A physical CPU \\ @@ -336,7 +336,7 @@ void \subsubsection{RPC name:~get\_this\_host} {\bf Overview:} -get accessor message derived from field this\_host of object session +Get the this\_host field of the given session. \noindent {\bf Signature:} \begin{verbatim} (host ref) get_this_host (session_id s, session ref self)\end{verbatim} @@ -368,7 +368,7 @@ value of the field \subsubsection{RPC name:~get\_this\_user} {\bf Overview:} -get accessor message derived from field this\_user of object session +Get the this\_user field of the given session. \noindent {\bf Signature:} \begin{verbatim} (user ref) get_this_user (session_id s, session ref self)\end{verbatim} @@ -533,7 +533,7 @@ all fields from the object \begin{longtable}{|lllp{0.38\textwidth}|} \hline \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf task} \\ -\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A longrunning asynchronous task}} \\ +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A long-running asynchronous task}} \\ \hline Quals & Field & Type & Description \\ \hline @@ -602,7 +602,7 @@ return the user's running tasks. \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object task +Get the uuid field of the given task. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, task ref self)\end{verbatim} @@ -634,7 +634,7 @@ value of the field \subsubsection{RPC name:~get\_name\_label} {\bf Overview:} -get accessor message derived from field name/label of object task +Get the name/label field of the given task. \noindent {\bf Signature:} \begin{verbatim} string get_name_label (session_id s, task ref self)\end{verbatim} @@ -666,7 +666,7 @@ value of the field \subsubsection{RPC name:~set\_name\_label} {\bf Overview:} -set accessor message derived from field name/label of object task +Set the name/label field of the given task. \noindent {\bf Signature:} \begin{verbatim} void set_name_label (session_id s, task ref self, string value)\end{verbatim} @@ -700,7 +700,7 @@ void \subsubsection{RPC name:~get\_name\_description} {\bf Overview:} -get accessor message derived from field name/description of object task +Get the name/description field of the given task. \noindent {\bf Signature:} \begin{verbatim} string get_name_description (session_id s, task ref self)\end{verbatim} @@ -732,7 +732,7 @@ value of the field \subsubsection{RPC name:~set\_name\_description} {\bf Overview:} -set accessor message derived from field name/description of object task +Set the name/description field of the given task. \noindent {\bf Signature:} \begin{verbatim} void set_name_description (session_id s, task ref self, string value)\end{verbatim} @@ -1335,7 +1335,7 @@ A list of all the IDs of all the VMs \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object VM +Get the uuid field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, VM ref self)\end{verbatim} @@ -1367,7 +1367,7 @@ value of the field \subsubsection{RPC name:~get\_power\_state} {\bf Overview:} -get accessor message derived from field power\_state of object VM +Get the power\_state field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (vm_power_state) get_power_state (session_id s, VM ref self)\end{verbatim} @@ -1399,7 +1399,7 @@ value of the field \subsubsection{RPC name:~get\_name\_label} {\bf Overview:} -get accessor message derived from field name/label of object VM +Get the name/label field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_name_label (session_id s, VM ref self)\end{verbatim} @@ -1431,7 +1431,7 @@ value of the field \subsubsection{RPC name:~set\_name\_label} {\bf Overview:} -set accessor message derived from field name/label of object VM +Set the name/label field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_name_label (session_id s, VM ref self, string value)\end{verbatim} @@ -1465,7 +1465,7 @@ void \subsubsection{RPC name:~get\_name\_description} {\bf Overview:} -get accessor message derived from field name/description of object VM +Get the name/description field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_name_description (session_id s, VM ref self)\end{verbatim} @@ -1497,7 +1497,7 @@ value of the field \subsubsection{RPC name:~set\_name\_description} {\bf Overview:} -set accessor message derived from field name/description of object VM +Set the name/description field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_name_description (session_id s, VM ref self, string value)\end{verbatim} @@ -1531,7 +1531,7 @@ void \subsubsection{RPC name:~get\_user\_version} {\bf Overview:} -get accessor message derived from field user\_version of object VM +Get the user\_version field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_user_version (session_id s, VM ref self)\end{verbatim} @@ -1563,7 +1563,7 @@ value of the field \subsubsection{RPC name:~set\_user\_version} {\bf Overview:} -set accessor message derived from field user\_version of object VM +Set the user\_version field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_user_version (session_id s, VM ref self, int value)\end{verbatim} @@ -1597,7 +1597,7 @@ void \subsubsection{RPC name:~get\_is\_a\_template} {\bf Overview:} -get accessor message derived from field is\_a\_template of object VM +Get the is\_a\_template field of the given VM. \noindent {\bf Signature:} \begin{verbatim} bool get_is_a_template (session_id s, VM ref self)\end{verbatim} @@ -1629,7 +1629,7 @@ value of the field \subsubsection{RPC name:~set\_is\_a\_template} {\bf Overview:} -set accessor message derived from field is\_a\_template of object VM +Set the is\_a\_template field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_is_a_template (session_id s, VM ref self, bool value)\end{verbatim} @@ -1663,7 +1663,7 @@ void \subsubsection{RPC name:~get\_resident\_on} {\bf Overview:} -get accessor message derived from field resident\_on of object VM +Get the resident\_on field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (host ref) get_resident_on (session_id s, VM ref self)\end{verbatim} @@ -1695,7 +1695,7 @@ value of the field \subsubsection{RPC name:~get\_memory\_static\_max} {\bf Overview:} -get accessor message derived from field memory/static\_max of object VM +Get the memory/static\_max field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_memory_static_max (session_id s, VM ref self)\end{verbatim} @@ -1727,7 +1727,7 @@ value of the field \subsubsection{RPC name:~get\_memory\_dynamic\_max} {\bf Overview:} -get accessor message derived from field memory/dynamic\_max of object VM +Get the memory/dynamic\_max field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_memory_dynamic_max (session_id s, VM ref self)\end{verbatim} @@ -1759,7 +1759,7 @@ value of the field \subsubsection{RPC name:~set\_memory\_dynamic\_max} {\bf Overview:} -set accessor message derived from field memory/dynamic\_max of object VM +Set the memory/dynamic\_max field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_memory_dynamic_max (session_id s, VM ref self, int value)\end{verbatim} @@ -1793,7 +1793,7 @@ void \subsubsection{RPC name:~get\_memory\_actual} {\bf Overview:} -get accessor message derived from field memory/actual of object VM +Get the memory/actual field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_memory_actual (session_id s, VM ref self)\end{verbatim} @@ -1825,7 +1825,7 @@ value of the field \subsubsection{RPC name:~get\_memory\_dynamic\_min} {\bf Overview:} -get accessor message derived from field memory/dynamic\_min of object VM +Get the memory/dynamic\_min field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_memory_dynamic_min (session_id s, VM ref self)\end{verbatim} @@ -1857,7 +1857,7 @@ value of the field \subsubsection{RPC name:~set\_memory\_dynamic\_min} {\bf Overview:} -set accessor message derived from field memory/dynamic\_min of object VM +Set the memory/dynamic\_min field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_memory_dynamic_min (session_id s, VM ref self, int value)\end{verbatim} @@ -1891,7 +1891,7 @@ void \subsubsection{RPC name:~get\_memory\_static\_min} {\bf Overview:} -get accessor message derived from field memory/static\_min of object VM +Get the memory/static\_min field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_memory_static_min (session_id s, VM ref self)\end{verbatim} @@ -1923,7 +1923,7 @@ value of the field \subsubsection{RPC name:~get\_VCPUs\_policy} {\bf Overview:} -get accessor message derived from field VCPUs/policy of object VM +Get the VCPUs/policy field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_VCPUs_policy (session_id s, VM ref self)\end{verbatim} @@ -1955,7 +1955,7 @@ value of the field \subsubsection{RPC name:~set\_VCPUs\_policy} {\bf Overview:} -set accessor message derived from field VCPUs/policy of object VM +Set the VCPUs/policy field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_VCPUs_policy (session_id s, VM ref self, string value)\end{verbatim} @@ -1989,7 +1989,7 @@ void \subsubsection{RPC name:~get\_VCPUs\_params} {\bf Overview:} -get accessor message derived from field VCPUs/params of object VM +Get the VCPUs/params field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_VCPUs_params (session_id s, VM ref self)\end{verbatim} @@ -2021,7 +2021,7 @@ value of the field \subsubsection{RPC name:~set\_VCPUs\_params} {\bf Overview:} -set accessor message derived from field VCPUs/params of object VM +Set the VCPUs/params field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_VCPUs_params (session_id s, VM ref self, string value)\end{verbatim} @@ -2055,7 +2055,7 @@ void \subsubsection{RPC name:~get\_VCPUs\_number} {\bf Overview:} -get accessor message derived from field VCPUs/number of object VM +Get the VCPUs/number field of the given VM. \noindent {\bf Signature:} \begin{verbatim} int get_VCPUs_number (session_id s, VM ref self)\end{verbatim} @@ -2087,7 +2087,7 @@ value of the field \subsubsection{RPC name:~get\_VCPUs\_utilisation} {\bf Overview:} -get accessor message derived from field VCPUs/utilisation of object VM +Get the VCPUs/utilisation field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((int -> float) Map) get_VCPUs_utilisation (session_id s, VM ref self)\end{verbatim} @@ -2119,7 +2119,7 @@ value of the field \subsubsection{RPC name:~get\_VCPUs\_features\_required} {\bf Overview:} -get accessor message derived from field VCPUs/features/required of object VM +Get the VCPUs/features/required field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((cpu_feature) Set) get_VCPUs_features_required (session_id s, VM ref self)\end{verbatim} @@ -2151,7 +2151,7 @@ value of the field \subsubsection{RPC name:~get\_VCPUs\_features\_can\_use} {\bf Overview:} -get accessor message derived from field VCPUs/features/can\_use of object VM +Get the VCPUs/features/can\_use field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((cpu_feature) Set) get_VCPUs_features_can_use (session_id s, VM ref self)\end{verbatim} @@ -2183,7 +2183,7 @@ value of the field \subsubsection{RPC name:~get\_VCPUs\_features\_force\_on} {\bf Overview:} -get accessor message derived from field VCPUs/features/force\_on of object VM +Get the VCPUs/features/force\_on field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((cpu_feature) Set) get_VCPUs_features_force_on (session_id s, VM ref self)\end{verbatim} @@ -2283,7 +2283,7 @@ void \subsubsection{RPC name:~get\_VCPUs\_features\_force\_off} {\bf Overview:} -get accessor message derived from field VCPUs/features/force\_off of object VM +Get the VCPUs/features/force\_off field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((cpu_feature) Set) get_VCPUs_features_force_off (session_id s, VM ref self)\end{verbatim} @@ -2383,7 +2383,7 @@ void \subsubsection{RPC name:~get\_actions\_after\_shutdown} {\bf Overview:} -get accessor message derived from field actions/after\_shutdown of object VM +Get the actions/after\_shutdown field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (on_normal_exit) get_actions_after_shutdown (session_id s, VM ref self)\end{verbatim} @@ -2415,7 +2415,7 @@ value of the field \subsubsection{RPC name:~set\_actions\_after\_shutdown} {\bf Overview:} -set accessor message derived from field actions/after\_shutdown of object VM +Set the actions/after\_shutdown field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_actions_after_shutdown (session_id s, VM ref self, on_normal_exit value)\end{verbatim} @@ -2449,7 +2449,7 @@ void \subsubsection{RPC name:~get\_actions\_after\_reboot} {\bf Overview:} -get accessor message derived from field actions/after\_reboot of object VM +Get the actions/after\_reboot field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (on_normal_exit) get_actions_after_reboot (session_id s, VM ref self)\end{verbatim} @@ -2481,7 +2481,7 @@ value of the field \subsubsection{RPC name:~set\_actions\_after\_reboot} {\bf Overview:} -set accessor message derived from field actions/after\_reboot of object VM +Set the actions/after\_reboot field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_actions_after_reboot (session_id s, VM ref self, on_normal_exit value)\end{verbatim} @@ -2515,7 +2515,7 @@ void \subsubsection{RPC name:~get\_actions\_after\_suspend} {\bf Overview:} -get accessor message derived from field actions/after\_suspend of object VM +Get the actions/after\_suspend field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (on_normal_exit) get_actions_after_suspend (session_id s, VM ref self)\end{verbatim} @@ -2547,7 +2547,7 @@ value of the field \subsubsection{RPC name:~set\_actions\_after\_suspend} {\bf Overview:} -set accessor message derived from field actions/after\_suspend of object VM +Set the actions/after\_suspend field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_actions_after_suspend (session_id s, VM ref self, on_normal_exit value)\end{verbatim} @@ -2581,7 +2581,7 @@ void \subsubsection{RPC name:~get\_actions\_after\_crash} {\bf Overview:} -get accessor message derived from field actions/after\_crash of object VM +Get the actions/after\_crash field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (on_crash_behaviour) get_actions_after_crash (session_id s, VM ref self)\end{verbatim} @@ -2613,7 +2613,7 @@ value of the field \subsubsection{RPC name:~set\_actions\_after\_crash} {\bf Overview:} -set accessor message derived from field actions/after\_crash of object VM +Set the actions/after\_crash field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_actions_after_crash (session_id s, VM ref self, on_crash_behaviour value)\end{verbatim} @@ -2679,7 +2679,7 @@ value of the field \subsubsection{RPC name:~get\_VIFs} {\bf Overview:} -get accessor message derived from field VIFs of object VM +Get the VIFs field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((VIF ref) Set) get_VIFs (session_id s, VM ref self)\end{verbatim} @@ -2711,7 +2711,7 @@ value of the field \subsubsection{RPC name:~get\_VBDs} {\bf Overview:} -get accessor message derived from field VBDs of object VM +Get the VBDs field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((VBD ref) Set) get_VBDs (session_id s, VM ref self)\end{verbatim} @@ -2743,7 +2743,7 @@ value of the field \subsubsection{RPC name:~get\_VTPMs} {\bf Overview:} -get accessor message derived from field VTPMs of object VM +Get the VTPMs field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((VTPM ref) Set) get_VTPMs (session_id s, VM ref self)\end{verbatim} @@ -2775,7 +2775,7 @@ value of the field \subsubsection{RPC name:~get\_bios\_boot} {\bf Overview:} -get accessor message derived from field bios/boot of object VM +Get the bios/boot field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_bios_boot (session_id s, VM ref self)\end{verbatim} @@ -2807,7 +2807,7 @@ value of the field \subsubsection{RPC name:~set\_bios\_boot} {\bf Overview:} -set accessor message derived from field bios/boot of object VM +Set the bios/boot field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_bios_boot (session_id s, VM ref self, string value)\end{verbatim} @@ -2841,7 +2841,7 @@ void \subsubsection{RPC name:~get\_platform\_std\_VGA} {\bf Overview:} -get accessor message derived from field platform/std\_VGA of object VM +Get the platform/std\_VGA field of the given VM. \noindent {\bf Signature:} \begin{verbatim} bool get_platform_std_VGA (session_id s, VM ref self)\end{verbatim} @@ -2873,7 +2873,7 @@ value of the field \subsubsection{RPC name:~set\_platform\_std\_VGA} {\bf Overview:} -set accessor message derived from field platform/std\_VGA of object VM +Set the platform/std\_VGA field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_platform_std_VGA (session_id s, VM ref self, bool value)\end{verbatim} @@ -2907,7 +2907,7 @@ void \subsubsection{RPC name:~get\_platform\_serial} {\bf Overview:} -get accessor message derived from field platform/serial of object VM +Get the platform/serial field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_platform_serial (session_id s, VM ref self)\end{verbatim} @@ -2939,7 +2939,7 @@ value of the field \subsubsection{RPC name:~set\_platform\_serial} {\bf Overview:} -set accessor message derived from field platform/serial of object VM +Set the platform/serial field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_platform_serial (session_id s, VM ref self, string value)\end{verbatim} @@ -2973,7 +2973,7 @@ void \subsubsection{RPC name:~get\_platform\_localtime} {\bf Overview:} -get accessor message derived from field platform/localtime of object VM +Get the platform/localtime field of the given VM. \noindent {\bf Signature:} \begin{verbatim} bool get_platform_localtime (session_id s, VM ref self)\end{verbatim} @@ -3005,7 +3005,7 @@ value of the field \subsubsection{RPC name:~set\_platform\_localtime} {\bf Overview:} -set accessor message derived from field platform/localtime of object VM +Set the platform/localtime field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_platform_localtime (session_id s, VM ref self, bool value)\end{verbatim} @@ -3039,7 +3039,7 @@ void \subsubsection{RPC name:~get\_platform\_clock\_offset} {\bf Overview:} -get accessor message derived from field platform/clock\_offset of object VM +Get the platform/clock\_offset field of the given VM. \noindent {\bf Signature:} \begin{verbatim} bool get_platform_clock_offset (session_id s, VM ref self)\end{verbatim} @@ -3071,7 +3071,7 @@ value of the field \subsubsection{RPC name:~set\_platform\_clock\_offset} {\bf Overview:} -set accessor message derived from field platform/clock\_offset of object VM +Set the platform/clock\_offset field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_platform_clock_offset (session_id s, VM ref self, bool value)\end{verbatim} @@ -3105,7 +3105,7 @@ void \subsubsection{RPC name:~get\_platform\_enable\_audio} {\bf Overview:} -get accessor message derived from field platform/enable\_audio of object VM +Get the platform/enable\_audio field of the given VM. \noindent {\bf Signature:} \begin{verbatim} bool get_platform_enable_audio (session_id s, VM ref self)\end{verbatim} @@ -3137,7 +3137,7 @@ value of the field \subsubsection{RPC name:~set\_platform\_enable\_audio} {\bf Overview:} -set accessor message derived from field platform/enable\_audio of object VM +Set the platform/enable\_audio field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_platform_enable_audio (session_id s, VM ref self, bool value)\end{verbatim} @@ -3171,7 +3171,7 @@ void \subsubsection{RPC name:~get\_builder} {\bf Overview:} -get accessor message derived from field builder of object VM +Get the builder field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_builder (session_id s, VM ref self)\end{verbatim} @@ -3203,7 +3203,7 @@ value of the field \subsubsection{RPC name:~set\_builder} {\bf Overview:} -set accessor message derived from field builder of object VM +Set the builder field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_builder (session_id s, VM ref self, string value)\end{verbatim} @@ -3237,7 +3237,7 @@ void \subsubsection{RPC name:~get\_boot\_method} {\bf Overview:} -get accessor message derived from field boot\_method of object VM +Get the boot\_method field of the given VM. \noindent {\bf Signature:} \begin{verbatim} (boot_type) get_boot_method (session_id s, VM ref self)\end{verbatim} @@ -3269,7 +3269,7 @@ value of the field \subsubsection{RPC name:~set\_boot\_method} {\bf Overview:} -set accessor message derived from field boot\_method of object VM +Set the boot\_method field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_boot_method (session_id s, VM ref self, boot_type value)\end{verbatim} @@ -3303,7 +3303,7 @@ void \subsubsection{RPC name:~get\_kernel\_kernel} {\bf Overview:} -get accessor message derived from field kernel/kernel of object VM +Get the kernel/kernel field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_kernel_kernel (session_id s, VM ref self)\end{verbatim} @@ -3335,7 +3335,7 @@ value of the field \subsubsection{RPC name:~set\_kernel\_kernel} {\bf Overview:} -set accessor message derived from field kernel/kernel of object VM +Set the kernel/kernel field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_kernel_kernel (session_id s, VM ref self, string value)\end{verbatim} @@ -3369,7 +3369,7 @@ void \subsubsection{RPC name:~get\_kernel\_initrd} {\bf Overview:} -get accessor message derived from field kernel/initrd of object VM +Get the kernel/initrd field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_kernel_initrd (session_id s, VM ref self)\end{verbatim} @@ -3401,7 +3401,7 @@ value of the field \subsubsection{RPC name:~set\_kernel\_initrd} {\bf Overview:} -set accessor message derived from field kernel/initrd of object VM +Set the kernel/initrd field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_kernel_initrd (session_id s, VM ref self, string value)\end{verbatim} @@ -3435,7 +3435,7 @@ void \subsubsection{RPC name:~get\_kernel\_args} {\bf Overview:} -get accessor message derived from field kernel/args of object VM +Get the kernel/args field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_kernel_args (session_id s, VM ref self)\end{verbatim} @@ -3467,7 +3467,7 @@ value of the field \subsubsection{RPC name:~set\_kernel\_args} {\bf Overview:} -set accessor message derived from field kernel/args of object VM +Set the kernel/args field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_kernel_args (session_id s, VM ref self, string value)\end{verbatim} @@ -3501,7 +3501,7 @@ void \subsubsection{RPC name:~get\_grub\_cmdline} {\bf Overview:} -get accessor message derived from field grub/cmdline of object VM +Get the grub/cmdline field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_grub_cmdline (session_id s, VM ref self)\end{verbatim} @@ -3533,7 +3533,7 @@ value of the field \subsubsection{RPC name:~set\_grub\_cmdline} {\bf Overview:} -set accessor message derived from field grub/cmdline of object VM +Set the grub/cmdline field of the given VM. \noindent {\bf Signature:} \begin{verbatim} void set_grub_cmdline (session_id s, VM ref self, string value)\end{verbatim} @@ -3567,7 +3567,7 @@ void \subsubsection{RPC name:~get\_PCI\_bus} {\bf Overview:} -get accessor message derived from field PCI\_bus of object VM +Get the PCI\_bus field of the given VM. \noindent {\bf Signature:} \begin{verbatim} string get_PCI_bus (session_id s, VM ref self)\end{verbatim} @@ -3599,7 +3599,7 @@ value of the field \subsubsection{RPC name:~get\_tools\_version} {\bf Overview:} -get accessor message derived from field tools\_version of object VM +Get the tools\_version field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((string -> string) Map) get_tools_version (session_id s, VM ref self)\end{verbatim} @@ -3631,7 +3631,7 @@ value of the field \subsubsection{RPC name:~get\_otherConfig} {\bf Overview:} -get accessor message derived from field otherConfig of object VM +Get the otherConfig field of the given VM. \noindent {\bf Signature:} \begin{verbatim} ((string -> string) Map) get_otherConfig (session_id s, VM ref self)\end{verbatim} @@ -4064,7 +4064,7 @@ A list of all the IDs of all the hosts \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object host +Get the uuid field of the given host. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, host ref self)\end{verbatim} @@ -4096,7 +4096,7 @@ value of the field \subsubsection{RPC name:~get\_name\_label} {\bf Overview:} -get accessor message derived from field name/label of object host +Get the name/label field of the given host. \noindent {\bf Signature:} \begin{verbatim} string get_name_label (session_id s, host ref self)\end{verbatim} @@ -4128,7 +4128,7 @@ value of the field \subsubsection{RPC name:~set\_name\_label} {\bf Overview:} -set accessor message derived from field name/label of object host +Set the name/label field of the given host. \noindent {\bf Signature:} \begin{verbatim} void set_name_label (session_id s, host ref self, string value)\end{verbatim} @@ -4162,7 +4162,7 @@ void \subsubsection{RPC name:~get\_name\_description} {\bf Overview:} -get accessor message derived from field name/description of object host +Get the name/description field of the given host. \noindent {\bf Signature:} \begin{verbatim} string get_name_description (session_id s, host ref self)\end{verbatim} @@ -4194,7 +4194,7 @@ value of the field \subsubsection{RPC name:~set\_name\_description} {\bf Overview:} -set accessor message derived from field name/description of object host +Set the name/description field of the given host. \noindent {\bf Signature:} \begin{verbatim} void set_name_description (session_id s, host ref self, string value)\end{verbatim} @@ -4228,7 +4228,7 @@ void \subsubsection{RPC name:~get\_software\_version} {\bf Overview:} -get accessor message derived from field software\_version of object host +Get the software\_version field of the given host. \noindent {\bf Signature:} \begin{verbatim} ((string -> string) Map) get_software_version (session_id s, host ref self)\end{verbatim} @@ -4260,7 +4260,7 @@ value of the field \subsubsection{RPC name:~get\_resident\_VMs} {\bf Overview:} -get accessor message derived from field resident\_VMs of object host +Get the resident\_VMs field of the given host. \noindent {\bf Signature:} \begin{verbatim} ((VM ref) Set) get_resident_VMs (session_id s, host ref self)\end{verbatim} @@ -4292,7 +4292,7 @@ value of the field \subsubsection{RPC name:~get\_PIFs} {\bf Overview:} -get accessor message derived from field PIFs of object host +Get the PIFs field of the given host. \noindent {\bf Signature:} \begin{verbatim} ((PIF ref) Set) get_PIFs (session_id s, host ref self)\end{verbatim} @@ -4324,7 +4324,7 @@ value of the field \subsubsection{RPC name:~get\_host\_CPUs} {\bf Overview:} -get accessor message derived from field host\_CPUs of object host +Get the host\_CPUs field of the given host. \noindent {\bf Signature:} \begin{verbatim} ((host_cpu ref) Set) get_host_CPUs (session_id s, host ref self)\end{verbatim} @@ -4539,7 +4539,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt utilisation} & float & the current CPU utilis \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object host\_cpu +Get the uuid field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, host_cpu ref self)\end{verbatim} @@ -4571,7 +4571,7 @@ value of the field \subsubsection{RPC name:~get\_host} {\bf Overview:} -get accessor message derived from field host of object host\_cpu +Get the host field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} (host ref) get_host (session_id s, host_cpu ref self)\end{verbatim} @@ -4603,7 +4603,7 @@ value of the field \subsubsection{RPC name:~get\_number} {\bf Overview:} -get accessor message derived from field number of object host\_cpu +Get the number field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} int get_number (session_id s, host_cpu ref self)\end{verbatim} @@ -4635,7 +4635,7 @@ value of the field \subsubsection{RPC name:~get\_vendor} {\bf Overview:} -get accessor message derived from field vendor of object host\_cpu +Get the vendor field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} string get_vendor (session_id s, host_cpu ref self)\end{verbatim} @@ -4667,7 +4667,7 @@ value of the field \subsubsection{RPC name:~get\_speed} {\bf Overview:} -get accessor message derived from field speed of object host\_cpu +Get the speed field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} int get_speed (session_id s, host_cpu ref self)\end{verbatim} @@ -4699,7 +4699,7 @@ value of the field \subsubsection{RPC name:~get\_modelname} {\bf Overview:} -get accessor message derived from field modelname of object host\_cpu +Get the modelname field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} string get_modelname (session_id s, host_cpu ref self)\end{verbatim} @@ -4731,7 +4731,7 @@ value of the field \subsubsection{RPC name:~get\_features} {\bf Overview:} -get accessor message derived from field features of object host\_cpu +Get the features field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} ((cpu_feature) Set) get_features (session_id s, host_cpu ref self)\end{verbatim} @@ -4763,7 +4763,7 @@ value of the field \subsubsection{RPC name:~get\_utilisation} {\bf Overview:} -get accessor message derived from field utilisation of object host\_cpu +Get the utilisation field of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} float get_utilisation (session_id s, host_cpu ref self)\end{verbatim} @@ -4966,7 +4966,7 @@ A list of all the IDs of all the networks \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object network +Get the uuid field of the given network. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, network ref self)\end{verbatim} @@ -4998,7 +4998,7 @@ value of the field \subsubsection{RPC name:~get\_name\_label} {\bf Overview:} -get accessor message derived from field name/label of object network +Get the name/label field of the given network. \noindent {\bf Signature:} \begin{verbatim} string get_name_label (session_id s, network ref self)\end{verbatim} @@ -5030,7 +5030,7 @@ value of the field \subsubsection{RPC name:~set\_name\_label} {\bf Overview:} -set accessor message derived from field name/label of object network +Set the name/label field of the given network. \noindent {\bf Signature:} \begin{verbatim} void set_name_label (session_id s, network ref self, string value)\end{verbatim} @@ -5064,7 +5064,7 @@ void \subsubsection{RPC name:~get\_name\_description} {\bf Overview:} -get accessor message derived from field name/description of object network +Get the name/description field of the given network. \noindent {\bf Signature:} \begin{verbatim} string get_name_description (session_id s, network ref self)\end{verbatim} @@ -5096,7 +5096,7 @@ value of the field \subsubsection{RPC name:~set\_name\_description} {\bf Overview:} -set accessor message derived from field name/description of object network +Set the name/description field of the given network. \noindent {\bf Signature:} \begin{verbatim} void set_name_description (session_id s, network ref self, string value)\end{verbatim} @@ -5130,7 +5130,7 @@ void \subsubsection{RPC name:~get\_VIFs} {\bf Overview:} -get accessor message derived from field VIFs of object network +Get the VIFs field of the given network. \noindent {\bf Signature:} \begin{verbatim} ((VIF ref) Set) get_VIFs (session_id s, network ref self)\end{verbatim} @@ -5162,7 +5162,7 @@ value of the field \subsubsection{RPC name:~get\_PIFs} {\bf Overview:} -get accessor message derived from field PIFs of object network +Get the PIFs field of the given network. \noindent {\bf Signature:} \begin{verbatim} ((PIF ref) Set) get_PIFs (session_id s, network ref self)\end{verbatim} @@ -5194,7 +5194,7 @@ value of the field \subsubsection{RPC name:~get\_default\_gateway} {\bf Overview:} -get accessor message derived from field default\_gateway of object network +Get the default\_gateway field of the given network. \noindent {\bf Signature:} \begin{verbatim} string get_default_gateway (session_id s, network ref self)\end{verbatim} @@ -5226,7 +5226,7 @@ value of the field \subsubsection{RPC name:~set\_default\_gateway} {\bf Overview:} -set accessor message derived from field default\_gateway of object network +Set the default\_gateway field of the given network. \noindent {\bf Signature:} \begin{verbatim} void set_default_gateway (session_id s, network ref self, string value)\end{verbatim} @@ -5260,7 +5260,7 @@ void \subsubsection{RPC name:~get\_default\_netmask} {\bf Overview:} -get accessor message derived from field default\_netmask of object network +Get the default\_netmask field of the given network. \noindent {\bf Signature:} \begin{verbatim} string get_default_netmask (session_id s, network ref self)\end{verbatim} @@ -5292,7 +5292,7 @@ value of the field \subsubsection{RPC name:~set\_default\_netmask} {\bf Overview:} -set accessor message derived from field default\_netmask of object network +Set the default\_netmask field of the given network. \noindent {\bf Signature:} \begin{verbatim} void set_default_netmask (session_id s, network ref self, string value)\end{verbatim} @@ -5511,7 +5511,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object VIF +Get the uuid field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, VIF ref self)\end{verbatim} @@ -5543,7 +5543,7 @@ value of the field \subsubsection{RPC name:~get\_name} {\bf Overview:} -get accessor message derived from field name of object VIF +Get the name field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} string get_name (session_id s, VIF ref self)\end{verbatim} @@ -5575,7 +5575,7 @@ value of the field \subsubsection{RPC name:~set\_name} {\bf Overview:} -set accessor message derived from field name of object VIF +Set the name field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_name (session_id s, VIF ref self, string value)\end{verbatim} @@ -5609,7 +5609,7 @@ void \subsubsection{RPC name:~get\_type} {\bf Overview:} -get accessor message derived from field type of object VIF +Get the type field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} (driver_type) get_type (session_id s, VIF ref self)\end{verbatim} @@ -5641,7 +5641,7 @@ value of the field \subsubsection{RPC name:~set\_type} {\bf Overview:} -set accessor message derived from field type of object VIF +Set the type field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_type (session_id s, VIF ref self, driver_type value)\end{verbatim} @@ -5675,7 +5675,7 @@ void \subsubsection{RPC name:~get\_device} {\bf Overview:} -get accessor message derived from field device of object VIF +Get the device field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} string get_device (session_id s, VIF ref self)\end{verbatim} @@ -5707,7 +5707,7 @@ value of the field \subsubsection{RPC name:~set\_device} {\bf Overview:} -set accessor message derived from field device of object VIF +Set the device field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_device (session_id s, VIF ref self, string value)\end{verbatim} @@ -5741,7 +5741,7 @@ void \subsubsection{RPC name:~get\_network} {\bf Overview:} -get accessor message derived from field network of object VIF +Get the network field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} (network ref) get_network (session_id s, VIF ref self)\end{verbatim} @@ -5773,7 +5773,7 @@ value of the field \subsubsection{RPC name:~set\_network} {\bf Overview:} -set accessor message derived from field network of object VIF +Set the network field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_network (session_id s, VIF ref self, network ref value)\end{verbatim} @@ -5807,7 +5807,7 @@ void \subsubsection{RPC name:~get\_VM} {\bf Overview:} -get accessor message derived from field VM of object VIF +Get the VM field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} (VM ref) get_VM (session_id s, VIF ref self)\end{verbatim} @@ -5839,7 +5839,7 @@ value of the field \subsubsection{RPC name:~set\_VM} {\bf Overview:} -set accessor message derived from field VM of object VIF +Set the VM field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_VM (session_id s, VIF ref self, VM ref value)\end{verbatim} @@ -5873,7 +5873,7 @@ void \subsubsection{RPC name:~get\_MAC} {\bf Overview:} -get accessor message derived from field MAC of object VIF +Get the MAC field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} string get_MAC (session_id s, VIF ref self)\end{verbatim} @@ -5905,7 +5905,7 @@ value of the field \subsubsection{RPC name:~set\_MAC} {\bf Overview:} -set accessor message derived from field MAC of object VIF +Set the MAC field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_MAC (session_id s, VIF ref self, string value)\end{verbatim} @@ -5939,7 +5939,7 @@ void \subsubsection{RPC name:~get\_MTU} {\bf Overview:} -get accessor message derived from field MTU of object VIF +Get the MTU field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} int get_MTU (session_id s, VIF ref self)\end{verbatim} @@ -5971,7 +5971,7 @@ value of the field \subsubsection{RPC name:~set\_MTU} {\bf Overview:} -set accessor message derived from field MTU of object VIF +Set the MTU field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} void set_MTU (session_id s, VIF ref self, int value)\end{verbatim} @@ -6005,7 +6005,7 @@ void \subsubsection{RPC name:~get\_io\_read\_kbs} {\bf Overview:} -get accessor message derived from field io/read\_kbs of object VIF +Get the io/read\_kbs field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} float get_io_read_kbs (session_id s, VIF ref self)\end{verbatim} @@ -6037,7 +6037,7 @@ value of the field \subsubsection{RPC name:~get\_io\_write\_kbs} {\bf Overview:} -get accessor message derived from field io/write\_kbs of object VIF +Get the io/write\_kbs field of the given VIF. \noindent {\bf Signature:} \begin{verbatim} float get_io_write_kbs (session_id s, VIF ref self)\end{verbatim} @@ -6221,7 +6221,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object PIF +Get the uuid field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, PIF ref self)\end{verbatim} @@ -6253,7 +6253,7 @@ value of the field \subsubsection{RPC name:~get\_name} {\bf Overview:} -get accessor message derived from field name of object PIF +Get the name field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} string get_name (session_id s, PIF ref self)\end{verbatim} @@ -6285,7 +6285,7 @@ value of the field \subsubsection{RPC name:~set\_name} {\bf Overview:} -set accessor message derived from field name of object PIF +Set the name field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} void set_name (session_id s, PIF ref self, string value)\end{verbatim} @@ -6319,7 +6319,7 @@ void \subsubsection{RPC name:~get\_network} {\bf Overview:} -get accessor message derived from field network of object PIF +Get the network field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} (network ref) get_network (session_id s, PIF ref self)\end{verbatim} @@ -6351,7 +6351,7 @@ value of the field \subsubsection{RPC name:~set\_network} {\bf Overview:} -set accessor message derived from field network of object PIF +Set the network field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} void set_network (session_id s, PIF ref self, network ref value)\end{verbatim} @@ -6385,7 +6385,7 @@ void \subsubsection{RPC name:~get\_host} {\bf Overview:} -get accessor message derived from field host of object PIF +Get the host field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} (host ref) get_host (session_id s, PIF ref self)\end{verbatim} @@ -6417,7 +6417,7 @@ value of the field \subsubsection{RPC name:~set\_host} {\bf Overview:} -set accessor message derived from field host of object PIF +Set the host field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} void set_host (session_id s, PIF ref self, host ref value)\end{verbatim} @@ -6451,7 +6451,7 @@ void \subsubsection{RPC name:~get\_MAC} {\bf Overview:} -get accessor message derived from field MAC of object PIF +Get the MAC field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} string get_MAC (session_id s, PIF ref self)\end{verbatim} @@ -6483,7 +6483,7 @@ value of the field \subsubsection{RPC name:~set\_MAC} {\bf Overview:} -set accessor message derived from field MAC of object PIF +Set the MAC field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} void set_MAC (session_id s, PIF ref self, string value)\end{verbatim} @@ -6517,7 +6517,7 @@ void \subsubsection{RPC name:~get\_MTU} {\bf Overview:} -get accessor message derived from field MTU of object PIF +Get the MTU field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} int get_MTU (session_id s, PIF ref self)\end{verbatim} @@ -6549,7 +6549,7 @@ value of the field \subsubsection{RPC name:~set\_MTU} {\bf Overview:} -set accessor message derived from field MTU of object PIF +Set the MTU field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} void set_MTU (session_id s, PIF ref self, int value)\end{verbatim} @@ -6583,7 +6583,7 @@ void \subsubsection{RPC name:~get\_VLAN} {\bf Overview:} -get accessor message derived from field VLAN of object PIF +Get the VLAN field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} string get_VLAN (session_id s, PIF ref self)\end{verbatim} @@ -6615,7 +6615,7 @@ value of the field \subsubsection{RPC name:~set\_VLAN} {\bf Overview:} -set accessor message derived from field VLAN of object PIF +Set the VLAN field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} void set_VLAN (session_id s, PIF ref self, string value)\end{verbatim} @@ -6649,7 +6649,7 @@ void \subsubsection{RPC name:~get\_io\_read\_kbs} {\bf Overview:} -get accessor message derived from field io/read\_kbs of object PIF +Get the io/read\_kbs field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} float get_io_read_kbs (session_id s, PIF ref self)\end{verbatim} @@ -6681,7 +6681,7 @@ value of the field \subsubsection{RPC name:~get\_io\_write\_kbs} {\bf Overview:} -get accessor message derived from field io/write\_kbs of object PIF +Get the io/write\_kbs field of the given PIF. \noindent {\bf Signature:} \begin{verbatim} float get_io_write_kbs (session_id s, PIF ref self)\end{verbatim} @@ -6923,7 +6923,7 @@ A list of all the IDs of all the Storage Repositories \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object SR +Get the uuid field of the given SR. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, SR ref self)\end{verbatim} @@ -6955,7 +6955,7 @@ value of the field \subsubsection{RPC name:~get\_name\_label} {\bf Overview:} -get accessor message derived from field name/label of object SR +Get the name/label field of the given SR. \noindent {\bf Signature:} \begin{verbatim} string get_name_label (session_id s, SR ref self)\end{verbatim} @@ -6987,7 +6987,7 @@ value of the field \subsubsection{RPC name:~set\_name\_label} {\bf Overview:} -set accessor message derived from field name/label of object SR +Set the name/label field of the given SR. \noindent {\bf Signature:} \begin{verbatim} void set_name_label (session_id s, SR ref self, string value)\end{verbatim} @@ -7021,7 +7021,7 @@ void \subsubsection{RPC name:~get\_name\_description} {\bf Overview:} -get accessor message derived from field name/description of object SR +Get the name/description field of the given SR. \noindent {\bf Signature:} \begin{verbatim} string get_name_description (session_id s, SR ref self)\end{verbatim} @@ -7053,7 +7053,7 @@ value of the field \subsubsection{RPC name:~set\_name\_description} {\bf Overview:} -set accessor message derived from field name/description of object SR +Set the name/description field of the given SR. \noindent {\bf Signature:} \begin{verbatim} void set_name_description (session_id s, SR ref self, string value)\end{verbatim} @@ -7087,7 +7087,7 @@ void \subsubsection{RPC name:~get\_VDIs} {\bf Overview:} -get accessor message derived from field VDIs of object SR +Get the VDIs field of the given SR. \noindent {\bf Signature:} \begin{verbatim} ((VDI ref) Set) get_VDIs (session_id s, SR ref self)\end{verbatim} @@ -7119,7 +7119,7 @@ value of the field \subsubsection{RPC name:~get\_virtual\_allocation} {\bf Overview:} -get accessor message derived from field virtual\_allocation of object SR +Get the virtual\_allocation field of the given SR. \noindent {\bf Signature:} \begin{verbatim} int get_virtual_allocation (session_id s, SR ref self)\end{verbatim} @@ -7151,7 +7151,7 @@ value of the field \subsubsection{RPC name:~get\_physical\_utilisation} {\bf Overview:} -get accessor message derived from field physical\_utilisation of object SR +Get the physical\_utilisation field of the given SR. \noindent {\bf Signature:} \begin{verbatim} int get_physical_utilisation (session_id s, SR ref self)\end{verbatim} @@ -7183,7 +7183,7 @@ value of the field \subsubsection{RPC name:~get\_physical\_size} {\bf Overview:} -get accessor message derived from field physical\_size of object SR +Get the physical\_size field of the given SR. \noindent {\bf Signature:} \begin{verbatim} int get_physical_size (session_id s, SR ref self)\end{verbatim} @@ -7215,7 +7215,7 @@ value of the field \subsubsection{RPC name:~get\_type} {\bf Overview:} -get accessor message derived from field type of object SR +Get the type field of the given SR. \noindent {\bf Signature:} \begin{verbatim} string get_type (session_id s, SR ref self)\end{verbatim} @@ -7247,7 +7247,7 @@ value of the field \subsubsection{RPC name:~get\_location} {\bf Overview:} -get accessor message derived from field location of object SR +Get the location field of the given SR. \noindent {\bf Signature:} \begin{verbatim} string get_location (session_id s, SR ref self)\end{verbatim} @@ -7533,7 +7533,7 @@ void \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object VDI +Get the uuid field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, VDI ref self)\end{verbatim} @@ -7565,7 +7565,7 @@ value of the field \subsubsection{RPC name:~get\_name\_label} {\bf Overview:} -get accessor message derived from field name/label of object VDI +Get the name/label field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} string get_name_label (session_id s, VDI ref self)\end{verbatim} @@ -7597,7 +7597,7 @@ value of the field \subsubsection{RPC name:~set\_name\_label} {\bf Overview:} -set accessor message derived from field name/label of object VDI +Set the name/label field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} void set_name_label (session_id s, VDI ref self, string value)\end{verbatim} @@ -7631,7 +7631,7 @@ void \subsubsection{RPC name:~get\_name\_description} {\bf Overview:} -get accessor message derived from field name/description of object VDI +Get the name/description field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} string get_name_description (session_id s, VDI ref self)\end{verbatim} @@ -7663,7 +7663,7 @@ value of the field \subsubsection{RPC name:~set\_name\_description} {\bf Overview:} -set accessor message derived from field name/description of object VDI +Set the name/description field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} void set_name_description (session_id s, VDI ref self, string value)\end{verbatim} @@ -7697,7 +7697,7 @@ void \subsubsection{RPC name:~get\_SR} {\bf Overview:} -get accessor message derived from field SR of object VDI +Get the SR field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} (SR ref) get_SR (session_id s, VDI ref self)\end{verbatim} @@ -7729,7 +7729,7 @@ value of the field \subsubsection{RPC name:~set\_SR} {\bf Overview:} -set accessor message derived from field SR of object VDI +Set the SR field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} void set_SR (session_id s, VDI ref self, SR ref value)\end{verbatim} @@ -7763,7 +7763,7 @@ void \subsubsection{RPC name:~get\_VBDs} {\bf Overview:} -get accessor message derived from field VBDs of object VDI +Get the VBDs field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} ((VBD ref) Set) get_VBDs (session_id s, VDI ref self)\end{verbatim} @@ -7795,7 +7795,7 @@ value of the field \subsubsection{RPC name:~get\_virtual\_size} {\bf Overview:} -get accessor message derived from field virtual\_size of object VDI +Get the virtual\_size field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} int get_virtual_size (session_id s, VDI ref self)\end{verbatim} @@ -7827,7 +7827,7 @@ value of the field \subsubsection{RPC name:~set\_virtual\_size} {\bf Overview:} -set accessor message derived from field virtual\_size of object VDI +Set the virtual\_size field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} void set_virtual_size (session_id s, VDI ref self, int value)\end{verbatim} @@ -7861,7 +7861,7 @@ void \subsubsection{RPC name:~get\_physical\_utilisation} {\bf Overview:} -get accessor message derived from field physical\_utilisation of object VDI +Get the physical\_utilisation field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} int get_physical_utilisation (session_id s, VDI ref self)\end{verbatim} @@ -7893,7 +7893,7 @@ value of the field \subsubsection{RPC name:~get\_sector\_size} {\bf Overview:} -get accessor message derived from field sector\_size of object VDI +Get the sector\_size field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} int get_sector_size (session_id s, VDI ref self)\end{verbatim} @@ -7925,7 +7925,7 @@ value of the field \subsubsection{RPC name:~get\_type} {\bf Overview:} -get accessor message derived from field type of object VDI +Get the type field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim} @@ -7957,7 +7957,7 @@ value of the field \subsubsection{RPC name:~get\_parent} {\bf Overview:} -get accessor message derived from field parent of object VDI +Get the parent field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} (VDI ref) get_parent (session_id s, VDI ref self)\end{verbatim} @@ -7989,7 +7989,7 @@ value of the field \subsubsection{RPC name:~get\_children} {\bf Overview:} -get accessor message derived from field children of object VDI +Get the children field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} ((VDI ref) Set) get_children (session_id s, VDI ref self)\end{verbatim} @@ -8021,7 +8021,7 @@ value of the field \subsubsection{RPC name:~get\_sharable} {\bf Overview:} -get accessor message derived from field sharable of object VDI +Get the sharable field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim} @@ -8053,7 +8053,7 @@ value of the field \subsubsection{RPC name:~set\_sharable} {\bf Overview:} -set accessor message derived from field sharable of object VDI +Set the sharable field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} void set_sharable (session_id s, VDI ref self, bool value)\end{verbatim} @@ -8087,7 +8087,7 @@ void \subsubsection{RPC name:~get\_read\_only} {\bf Overview:} -get accessor message derived from field read\_only of object VDI +Get the read\_only field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} bool get_read_only (session_id s, VDI ref self)\end{verbatim} @@ -8119,7 +8119,7 @@ value of the field \subsubsection{RPC name:~set\_read\_only} {\bf Overview:} -set accessor message derived from field read\_only of object VDI +Set the read\_only field of the given VDI. \noindent {\bf Signature:} \begin{verbatim} void set_read_only (session_id s, VDI ref self, bool value)\end{verbatim} @@ -8370,7 +8370,7 @@ void \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object VBD +Get the uuid field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, VBD ref self)\end{verbatim} @@ -8402,7 +8402,7 @@ value of the field \subsubsection{RPC name:~get\_VM} {\bf Overview:} -get accessor message derived from field VM of object VBD +Get the VM field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} (VM ref) get_VM (session_id s, VBD ref self)\end{verbatim} @@ -8434,7 +8434,7 @@ value of the field \subsubsection{RPC name:~set\_VM} {\bf Overview:} -set accessor message derived from field VM of object VBD +Set the VM field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} void set_VM (session_id s, VBD ref self, VM ref value)\end{verbatim} @@ -8468,7 +8468,7 @@ void \subsubsection{RPC name:~get\_VDI} {\bf Overview:} -get accessor message derived from field VDI of object VBD +Get the VDI field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} (VDI ref) get_VDI (session_id s, VBD ref self)\end{verbatim} @@ -8500,7 +8500,7 @@ value of the field \subsubsection{RPC name:~set\_VDI} {\bf Overview:} -set accessor message derived from field VDI of object VBD +Set the VDI field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} void set_VDI (session_id s, VBD ref self, VDI ref value)\end{verbatim} @@ -8534,7 +8534,7 @@ void \subsubsection{RPC name:~get\_device} {\bf Overview:} -get accessor message derived from field device of object VBD +Get the device field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} string get_device (session_id s, VBD ref self)\end{verbatim} @@ -8566,7 +8566,7 @@ value of the field \subsubsection{RPC name:~set\_device} {\bf Overview:} -set accessor message derived from field device of object VBD +Set the device field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} void set_device (session_id s, VBD ref self, string value)\end{verbatim} @@ -8600,7 +8600,7 @@ void \subsubsection{RPC name:~get\_mode} {\bf Overview:} -get accessor message derived from field mode of object VBD +Get the mode field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} (vbd_mode) get_mode (session_id s, VBD ref self)\end{verbatim} @@ -8632,7 +8632,7 @@ value of the field \subsubsection{RPC name:~set\_mode} {\bf Overview:} -set accessor message derived from field mode of object VBD +Set the mode field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} void set_mode (session_id s, VBD ref self, vbd_mode value)\end{verbatim} @@ -8666,7 +8666,7 @@ void \subsubsection{RPC name:~get\_driver} {\bf Overview:} -get accessor message derived from field driver of object VBD +Get the driver field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} (driver_type) get_driver (session_id s, VBD ref self)\end{verbatim} @@ -8698,7 +8698,7 @@ value of the field \subsubsection{RPC name:~set\_driver} {\bf Overview:} -set accessor message derived from field driver of object VBD +Set the driver field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} void set_driver (session_id s, VBD ref self, driver_type value)\end{verbatim} @@ -8732,7 +8732,7 @@ void \subsubsection{RPC name:~get\_io\_read\_kbs} {\bf Overview:} -get accessor message derived from field io/read\_kbs of object VBD +Get the io/read\_kbs field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} float get_io_read_kbs (session_id s, VBD ref self)\end{verbatim} @@ -8764,7 +8764,7 @@ value of the field \subsubsection{RPC name:~get\_io\_write\_kbs} {\bf Overview:} -get accessor message derived from field io/write\_kbs of object VBD +Get the io/write\_kbs field of the given VBD. \noindent {\bf Signature:} \begin{verbatim} float get_io_write_kbs (session_id s, VBD ref self)\end{verbatim} @@ -8944,7 +8944,7 @@ $\mathit{RO}_\mathit{ins}$ & {\tt instance} & int & the instance number the vir \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object VTPM +Get the uuid field of the given VTPM. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, VTPM ref self)\end{verbatim} @@ -8976,7 +8976,7 @@ value of the field \subsubsection{RPC name:~get\_VM} {\bf Overview:} -get accessor message derived from field VM of object VTPM +Get the VM field of the given VTPM. \noindent {\bf Signature:} \begin{verbatim} (VM ref) get_VM (session_id s, VTPM ref self)\end{verbatim} @@ -9008,7 +9008,7 @@ value of the field \subsubsection{RPC name:~get\_backend} {\bf Overview:} -get accessor message derived from field backend of object VTPM +Get the backend field of the given VTPM. \noindent {\bf Signature:} \begin{verbatim} (VM ref) get_backend (session_id s, VTPM ref self)\end{verbatim} @@ -9040,7 +9040,7 @@ value of the field \subsubsection{RPC name:~get\_driver} {\bf Overview:} -get accessor message derived from field driver of object VTPM +Get the driver field of the given VTPM. \noindent {\bf Signature:} \begin{verbatim} (driver_type) get_driver (session_id s, VTPM ref self)\end{verbatim} @@ -9072,7 +9072,7 @@ value of the field \subsubsection{RPC name:~get\_instance} {\bf Overview:} -get accessor message derived from field instance of object VTPM +Get the instance field of the given VTPM. \noindent {\bf Signature:} \begin{verbatim} int get_instance (session_id s, VTPM ref self)\end{verbatim} @@ -9525,7 +9525,7 @@ $\mathit{RW}$ & {\tt fullname} & string & full name \\ \subsubsection{RPC name:~get\_uuid} {\bf Overview:} -get accessor message derived from field uuid of object user +Get the uuid field of the given user. \noindent {\bf Signature:} \begin{verbatim} string get_uuid (session_id s, user ref self)\end{verbatim} @@ -9557,7 +9557,7 @@ value of the field \subsubsection{RPC name:~get\_short\_name} {\bf Overview:} -get accessor message derived from field short\_name of object user +Get the short\_name field of the given user. \noindent {\bf Signature:} \begin{verbatim} string get_short_name (session_id s, user ref self)\end{verbatim} @@ -9589,7 +9589,7 @@ value of the field \subsubsection{RPC name:~get\_fullname} {\bf Overview:} -get accessor message derived from field fullname of object user +Get the fullname field of the given user. \noindent {\bf Signature:} \begin{verbatim} string get_fullname (session_id s, user ref self)\end{verbatim} @@ -9621,7 +9621,7 @@ value of the field \subsubsection{RPC name:~set\_fullname} {\bf Overview:} -set accessor message derived from field fullname of object user +Set the fullname field of the given user. \noindent {\bf Signature:} \begin{verbatim} void set_fullname (session_id s, user ref self, string value)\end{verbatim} From 46bdf803f9183b9f80375300bab97fbe7f5f3b9a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 13:28:37 +0000 Subject: [PATCH 14/69] More description tidyups -- constructors and destructors this time. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 56 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index de023012ac..e2ce7e51d3 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -400,7 +400,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class session +Create a new session instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (session ref) create (session_id s, session record args)\end{verbatim} @@ -432,7 +432,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class session +Destroy the specified session instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, session ref self)\end{verbatim} @@ -766,7 +766,7 @@ void \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class task +Create a new task instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (task ref) create (session_id s, task record args)\end{verbatim} @@ -798,7 +798,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class task +Destroy the specified task instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, task ref self)\end{verbatim} @@ -3733,7 +3733,7 @@ void \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class VM +Create a new VM instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (VM ref) create (session_id s, VM record args)\end{verbatim} @@ -3765,7 +3765,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class VM +Destroy the specified VM instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, VM ref self)\end{verbatim} @@ -4356,7 +4356,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class host +Create a new host instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (host ref) create (session_id s, host record args)\end{verbatim} @@ -4388,7 +4388,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class host +Destroy the specified host instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, host ref self)\end{verbatim} @@ -4795,7 +4795,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class host\_cpu +Create a new host\_cpu instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (host_cpu ref) create (session_id s, host_cpu record args)\end{verbatim} @@ -4827,7 +4827,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class host\_cpu +Destroy the specified host\_cpu instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, host_cpu ref self)\end{verbatim} @@ -5326,7 +5326,7 @@ void \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class network +Create a new network instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (network ref) create (session_id s, network record args)\end{verbatim} @@ -5358,7 +5358,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class network +Destroy the specified network instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, network ref self)\end{verbatim} @@ -6069,7 +6069,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class VIF +Create a new VIF instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (VIF ref) create (session_id s, VIF record args)\end{verbatim} @@ -6101,7 +6101,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class VIF +Destroy the specified VIF instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, VIF ref self)\end{verbatim} @@ -6713,7 +6713,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class PIF +Create a new PIF instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (PIF ref) create (session_id s, PIF record args)\end{verbatim} @@ -6745,7 +6745,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class PIF +Destroy the specified PIF instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, PIF ref self)\end{verbatim} @@ -7279,7 +7279,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class SR +Create a new SR instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (SR ref) create (session_id s, SR record args)\end{verbatim} @@ -7311,7 +7311,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class SR +Destroy the specified SR instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, SR ref self)\end{verbatim} @@ -8153,7 +8153,7 @@ void \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class VDI +Create a new VDI instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (VDI ref) create (session_id s, VDI record args)\end{verbatim} @@ -8185,7 +8185,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class VDI +Destroy the specified VDI instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, VDI ref self)\end{verbatim} @@ -8796,7 +8796,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class VBD +Create a new VBD instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (VBD ref) create (session_id s, VBD record args)\end{verbatim} @@ -8828,7 +8828,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class VBD +Destroy the specified VBD instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, VBD ref self)\end{verbatim} @@ -9104,7 +9104,7 @@ value of the field \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class VTPM +Create a new VTPM instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (VTPM ref) create (session_id s, VTPM record args)\end{verbatim} @@ -9136,7 +9136,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class VTPM +Destroy the specified VTPM instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, VTPM ref self)\end{verbatim} @@ -9655,7 +9655,7 @@ void \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class user +Create a new user instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (user ref) create (session_id s, user record args)\end{verbatim} @@ -9687,7 +9687,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class user +Destroy the specified user instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, user ref self)\end{verbatim} @@ -9832,7 +9832,7 @@ void \subsubsection{RPC name:~create} {\bf Overview:} -constructor for class debug +Create a new debug instance, and return its handle. \noindent {\bf Signature:} \begin{verbatim} (debug ref) create (session_id s, debug record args)\end{verbatim} @@ -9864,7 +9864,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -destructor for class debug +Destroy the specified debug instance. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, debug ref self)\end{verbatim} From 9b308331446359cdc166b06d613174cc9e289c9a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:01:08 +0000 Subject: [PATCH 15/69] Tidy up the get_record and get_by_uuid descriptions. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 56 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index e2ce7e51d3..e21ad3ddc6 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -464,7 +464,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the session instance with a particular uuid +Get a reference to the session instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (session ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -496,7 +496,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class session +Get a record containing the current state of the given session. \noindent {\bf Signature:} \begin{verbatim} (session record) get_record (session_id s, session ref self)\end{verbatim} @@ -830,7 +830,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the task instance with a particular uuid +Get a reference to the task instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (task ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -862,7 +862,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class task +Get a record containing the current state of the given task. \noindent {\bf Signature:} \begin{verbatim} (task record) get_record (session_id s, task ref self)\end{verbatim} @@ -3797,7 +3797,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the VM instance with a particular uuid +Get a reference to the VM instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (VM ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -3829,7 +3829,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class VM +Get a record containing the current state of the given VM. \noindent {\bf Signature:} \begin{verbatim} (VM record) get_record (session_id s, VM ref self)\end{verbatim} @@ -4420,7 +4420,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the host instance with a particular uuid +Get a reference to the host instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (host ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -4452,7 +4452,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class host +Get a record containing the current state of the given host. \noindent {\bf Signature:} \begin{verbatim} (host record) get_record (session_id s, host ref self)\end{verbatim} @@ -4859,7 +4859,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the host\_cpu instance with a particular uuid +Get a reference to the host\_cpu instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (host_cpu ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -4891,7 +4891,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class host\_cpu +Get a record containing the current state of the given host\_cpu. \noindent {\bf Signature:} \begin{verbatim} (host_cpu record) get_record (session_id s, host_cpu ref self)\end{verbatim} @@ -5390,7 +5390,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the network instance with a particular uuid +Get a reference to the network instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (network ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -5422,7 +5422,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class network +Get a record containing the current state of the given network. \noindent {\bf Signature:} \begin{verbatim} (network record) get_record (session_id s, network ref self)\end{verbatim} @@ -6133,7 +6133,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the VIF instance with a particular uuid +Get a reference to the VIF instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (VIF ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -6165,7 +6165,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class VIF +Get a record containing the current state of the given VIF. \noindent {\bf Signature:} \begin{verbatim} (VIF record) get_record (session_id s, VIF ref self)\end{verbatim} @@ -6777,7 +6777,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the PIF instance with a particular uuid +Get a reference to the PIF instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (PIF ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -6809,7 +6809,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class PIF +Get a record containing the current state of the given PIF. \noindent {\bf Signature:} \begin{verbatim} (PIF record) get_record (session_id s, PIF ref self)\end{verbatim} @@ -7343,7 +7343,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the SR instance with a particular uuid +Get a reference to the SR instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (SR ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -7375,7 +7375,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class SR +Get a record containing the current state of the given SR. \noindent {\bf Signature:} \begin{verbatim} (SR record) get_record (session_id s, SR ref self)\end{verbatim} @@ -8217,7 +8217,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the VDI instance with a particular uuid +Get a reference to the VDI instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (VDI ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -8249,7 +8249,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class VDI +Get a record containing the current state of the given VDI. \noindent {\bf Signature:} \begin{verbatim} (VDI record) get_record (session_id s, VDI ref self)\end{verbatim} @@ -8860,7 +8860,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the VBD instance with a particular uuid +Get a reference to the VBD instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (VBD ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -8892,7 +8892,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class VBD +Get a record containing the current state of the given VBD. \noindent {\bf Signature:} \begin{verbatim} (VBD record) get_record (session_id s, VBD ref self)\end{verbatim} @@ -9168,7 +9168,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the VTPM instance with a particular uuid +Get a reference to the VTPM instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (VTPM ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -9200,7 +9200,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class VTPM +Get a record containing the current state of the given VTPM. \noindent {\bf Signature:} \begin{verbatim} (VTPM record) get_record (session_id s, VTPM ref self)\end{verbatim} @@ -9719,7 +9719,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the user instance with a particular uuid +Get a reference to the user instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (user ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -9751,7 +9751,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class user +Get a record containing the current state of the given user. \noindent {\bf Signature:} \begin{verbatim} (user record) get_record (session_id s, user ref self)\end{verbatim} @@ -9896,7 +9896,7 @@ void \subsubsection{RPC name:~get\_by\_uuid} {\bf Overview:} -returns the debug instance with a particular uuid +Get a reference to the debug instance with the specified UUID. \noindent {\bf Signature:} \begin{verbatim} (debug ref) get_by_uuid (session_id s, string uuid)\end{verbatim} @@ -9928,7 +9928,7 @@ reference to the object \subsubsection{RPC name:~get\_record} {\bf Overview:} -returns a record containing the state of an instance of class debug +Get a record containing the current state of the given debug. \noindent {\bf Signature:} \begin{verbatim} (debug record) get_record (session_id s, debug ref self)\end{verbatim} From 449775b249c3a63547f27afff10fc9f24e60ad26 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:05:23 +0000 Subject: [PATCH 16/69] Clarify that the self parameter is an object reference, not the instance (i.e. record) itself. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 422 +++++++++++++++--------------- 1 file changed, 211 insertions(+), 211 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index e21ad3ddc6..a51f35743c 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -349,7 +349,7 @@ Get the this\_host field of the given session. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt session ref } & self & object instance \\ \hline +{\tt session ref } & self & reference to the object \\ \hline \end{tabular} @@ -381,7 +381,7 @@ Get the this\_user field of the given session. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt session ref } & self & object instance \\ \hline +{\tt session ref } & self & reference to the object \\ \hline \end{tabular} @@ -445,7 +445,7 @@ Destroy the specified session instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt session ref } & self & object instance \\ \hline +{\tt session ref } & self & reference to the object \\ \hline \end{tabular} @@ -615,7 +615,7 @@ Get the uuid field of the given task. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & self & object instance \\ \hline +{\tt task ref } & self & reference to the object \\ \hline \end{tabular} @@ -647,7 +647,7 @@ Get the name/label field of the given task. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & self & object instance \\ \hline +{\tt task ref } & self & reference to the object \\ \hline \end{tabular} @@ -679,7 +679,7 @@ Set the name/label field of the given task. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & self & object instance \\ \hline +{\tt task ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -713,7 +713,7 @@ Get the name/description field of the given task. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & self & object instance \\ \hline +{\tt task ref } & self & reference to the object \\ \hline \end{tabular} @@ -745,7 +745,7 @@ Set the name/description field of the given task. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & self & object instance \\ \hline +{\tt task ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -811,7 +811,7 @@ Destroy the specified task instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & self & object instance \\ \hline +{\tt task ref } & self & reference to the object \\ \hline \end{tabular} @@ -1348,7 +1348,7 @@ Get the uuid field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1380,7 +1380,7 @@ Get the power\_state field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1412,7 +1412,7 @@ Get the name/label field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1444,7 +1444,7 @@ Set the name/label field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -1478,7 +1478,7 @@ Get the name/description field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1510,7 +1510,7 @@ Set the name/description field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -1544,7 +1544,7 @@ Get the user\_version field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1576,7 +1576,7 @@ Set the user\_version field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt int } & value & New value to set \\ \hline @@ -1610,7 +1610,7 @@ Get the is\_a\_template field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1642,7 +1642,7 @@ Set the is\_a\_template field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -1676,7 +1676,7 @@ Get the resident\_on field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1708,7 +1708,7 @@ Get the memory/static\_max field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1740,7 +1740,7 @@ Get the memory/dynamic\_max field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1772,7 +1772,7 @@ Set the memory/dynamic\_max field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt int } & value & New value to set \\ \hline @@ -1806,7 +1806,7 @@ Get the memory/actual field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1838,7 +1838,7 @@ Get the memory/dynamic\_min field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1870,7 +1870,7 @@ Set the memory/dynamic\_min field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt int } & value & New value to set \\ \hline @@ -1904,7 +1904,7 @@ Get the memory/static\_min field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1936,7 +1936,7 @@ Get the VCPUs/policy field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -1968,7 +1968,7 @@ Set the VCPUs/policy field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -2002,7 +2002,7 @@ Get the VCPUs/params field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2034,7 +2034,7 @@ Set the VCPUs/params field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -2068,7 +2068,7 @@ Get the VCPUs/number field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2100,7 +2100,7 @@ Get the VCPUs/utilisation field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2132,7 +2132,7 @@ Get the VCPUs/features/required field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2164,7 +2164,7 @@ Get the VCPUs/features/can\_use field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2196,7 +2196,7 @@ Get the VCPUs/features/force\_on field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2228,7 +2228,7 @@ set add message derived from field VCPUs/features/force\_on of object VM \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt cpu\_feature } & value & New value to add \\ \hline @@ -2262,7 +2262,7 @@ set remove message derived from field VCPUs/features/force\_on of object VM \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt cpu\_feature } & value & Value to remove \\ \hline @@ -2296,7 +2296,7 @@ Get the VCPUs/features/force\_off field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2328,7 +2328,7 @@ set add message derived from field VCPUs/features/force\_off of object VM \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt cpu\_feature } & value & New value to add \\ \hline @@ -2362,7 +2362,7 @@ set remove message derived from field VCPUs/features/force\_off of object VM \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt cpu\_feature } & value & Value to remove \\ \hline @@ -2396,7 +2396,7 @@ Get the actions/after\_shutdown field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2428,7 +2428,7 @@ Set the actions/after\_shutdown field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt on\_normal\_exit } & value & New value to set \\ \hline @@ -2462,7 +2462,7 @@ Get the actions/after\_reboot field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2494,7 +2494,7 @@ Set the actions/after\_reboot field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt on\_normal\_exit } & value & New value to set \\ \hline @@ -2528,7 +2528,7 @@ Get the actions/after\_suspend field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2560,7 +2560,7 @@ Set the actions/after\_suspend field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt on\_normal\_exit } & value & New value to set \\ \hline @@ -2594,7 +2594,7 @@ Get the actions/after\_crash field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2626,7 +2626,7 @@ Set the actions/after\_crash field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt on\_crash\_behaviour } & value & New value to set \\ \hline @@ -2660,7 +2660,7 @@ Get the consoles field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2692,7 +2692,7 @@ Get the VIFs field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2724,7 +2724,7 @@ Get the VBDs field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2756,7 +2756,7 @@ Get the VTPMs field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2788,7 +2788,7 @@ Get the bios/boot field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2820,7 +2820,7 @@ Set the bios/boot field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -2854,7 +2854,7 @@ Get the platform/std\_VGA field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2886,7 +2886,7 @@ Set the platform/std\_VGA field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -2920,7 +2920,7 @@ Get the platform/serial field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -2952,7 +2952,7 @@ Set the platform/serial field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -2986,7 +2986,7 @@ Get the platform/localtime field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3018,7 +3018,7 @@ Set the platform/localtime field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -3052,7 +3052,7 @@ Get the platform/clock\_offset field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3084,7 +3084,7 @@ Set the platform/clock\_offset field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -3118,7 +3118,7 @@ Get the platform/enable\_audio field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3150,7 +3150,7 @@ Set the platform/enable\_audio field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -3184,7 +3184,7 @@ Get the builder field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3216,7 +3216,7 @@ Set the builder field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -3250,7 +3250,7 @@ Get the boot\_method field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3282,7 +3282,7 @@ Set the boot\_method field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt boot\_type } & value & New value to set \\ \hline @@ -3316,7 +3316,7 @@ Get the kernel/kernel field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3348,7 +3348,7 @@ Set the kernel/kernel field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -3382,7 +3382,7 @@ Get the kernel/initrd field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3414,7 +3414,7 @@ Set the kernel/initrd field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -3448,7 +3448,7 @@ Get the kernel/args field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3480,7 +3480,7 @@ Set the kernel/args field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -3514,7 +3514,7 @@ Get the grub/cmdline field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3546,7 +3546,7 @@ Set the grub/cmdline field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -3580,7 +3580,7 @@ Get the PCI\_bus field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3612,7 +3612,7 @@ Get the tools\_version field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3644,7 +3644,7 @@ Get the otherConfig field of the given VM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -3676,7 +3676,7 @@ map add message derived from field otherConfig of object VM \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & key & Key to add \\ \hline @@ -3712,7 +3712,7 @@ map remove message derived from field otherConfig of object VM \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline {\tt string } & key & Key to remove \\ \hline @@ -3778,7 +3778,7 @@ Destroy the specified VM instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & object instance \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline \end{tabular} @@ -4077,7 +4077,7 @@ Get the uuid field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4109,7 +4109,7 @@ Get the name/label field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4141,7 +4141,7 @@ Set the name/label field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -4175,7 +4175,7 @@ Get the name/description field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4207,7 +4207,7 @@ Set the name/description field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -4241,7 +4241,7 @@ Get the software\_version field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4273,7 +4273,7 @@ Get the resident\_VMs field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4305,7 +4305,7 @@ Get the PIFs field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4337,7 +4337,7 @@ Get the host\_CPUs field of the given host. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4401,7 +4401,7 @@ Destroy the specified host instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host ref } & self & object instance \\ \hline +{\tt host ref } & self & reference to the object \\ \hline \end{tabular} @@ -4552,7 +4552,7 @@ Get the uuid field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4584,7 +4584,7 @@ Get the host field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4616,7 +4616,7 @@ Get the number field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4648,7 +4648,7 @@ Get the vendor field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4680,7 +4680,7 @@ Get the speed field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4712,7 +4712,7 @@ Get the modelname field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4744,7 +4744,7 @@ Get the features field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4776,7 +4776,7 @@ Get the utilisation field of the given host\_cpu. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4840,7 +4840,7 @@ Destroy the specified host\_cpu instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu ref } & self & object instance \\ \hline +{\tt host\_cpu ref } & self & reference to the object \\ \hline \end{tabular} @@ -4979,7 +4979,7 @@ Get the uuid field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5011,7 +5011,7 @@ Get the name/label field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5043,7 +5043,7 @@ Set the name/label field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5077,7 +5077,7 @@ Get the name/description field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5109,7 +5109,7 @@ Set the name/description field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5143,7 +5143,7 @@ Get the VIFs field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5175,7 +5175,7 @@ Get the PIFs field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5207,7 +5207,7 @@ Get the default\_gateway field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5239,7 +5239,7 @@ Set the default\_gateway field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5273,7 +5273,7 @@ Get the default\_netmask field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5305,7 +5305,7 @@ Set the default\_netmask field of the given network. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5371,7 +5371,7 @@ Destroy the specified network instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt network ref } & self & object instance \\ \hline +{\tt network ref } & self & reference to the object \\ \hline \end{tabular} @@ -5524,7 +5524,7 @@ Get the uuid field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5556,7 +5556,7 @@ Get the name field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5588,7 +5588,7 @@ Set the name field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5622,7 +5622,7 @@ Get the type field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5654,7 +5654,7 @@ Set the type field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt driver\_type } & value & New value to set \\ \hline @@ -5688,7 +5688,7 @@ Get the device field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5720,7 +5720,7 @@ Set the device field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5754,7 +5754,7 @@ Get the network field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5786,7 +5786,7 @@ Set the network field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt network ref } & value & New value to set \\ \hline @@ -5820,7 +5820,7 @@ Get the VM field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5852,7 +5852,7 @@ Set the VM field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt VM ref } & value & New value to set \\ \hline @@ -5886,7 +5886,7 @@ Get the MAC field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5918,7 +5918,7 @@ Set the MAC field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -5952,7 +5952,7 @@ Get the MTU field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -5984,7 +5984,7 @@ Set the MTU field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline {\tt int } & value & New value to set \\ \hline @@ -6018,7 +6018,7 @@ Get the io/read\_kbs field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6050,7 +6050,7 @@ Get the io/write\_kbs field of the given VIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6114,7 +6114,7 @@ Destroy the specified VIF instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VIF ref } & self & object instance \\ \hline +{\tt VIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6234,7 +6234,7 @@ Get the uuid field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6266,7 +6266,7 @@ Get the name field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6298,7 +6298,7 @@ Set the name field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -6332,7 +6332,7 @@ Get the network field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6364,7 +6364,7 @@ Set the network field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline {\tt network ref } & value & New value to set \\ \hline @@ -6398,7 +6398,7 @@ Get the host field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6430,7 +6430,7 @@ Set the host field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline {\tt host ref } & value & New value to set \\ \hline @@ -6464,7 +6464,7 @@ Get the MAC field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6496,7 +6496,7 @@ Set the MAC field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -6530,7 +6530,7 @@ Get the MTU field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6562,7 +6562,7 @@ Set the MTU field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline {\tt int } & value & New value to set \\ \hline @@ -6596,7 +6596,7 @@ Get the VLAN field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6628,7 +6628,7 @@ Set the VLAN field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -6662,7 +6662,7 @@ Get the io/read\_kbs field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6694,7 +6694,7 @@ Get the io/write\_kbs field of the given PIF. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6758,7 +6758,7 @@ Destroy the specified PIF instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt PIF ref } & self & object instance \\ \hline +{\tt PIF ref } & self & reference to the object \\ \hline \end{tabular} @@ -6936,7 +6936,7 @@ Get the uuid field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -6968,7 +6968,7 @@ Get the name/label field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7000,7 +7000,7 @@ Set the name/label field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -7034,7 +7034,7 @@ Get the name/description field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7066,7 +7066,7 @@ Set the name/description field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -7100,7 +7100,7 @@ Get the VDIs field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7132,7 +7132,7 @@ Get the virtual\_allocation field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7164,7 +7164,7 @@ Get the physical\_utilisation field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7196,7 +7196,7 @@ Get the physical\_size field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7228,7 +7228,7 @@ Get the type field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7260,7 +7260,7 @@ Get the location field of the given SR. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7324,7 +7324,7 @@ Destroy the specified SR instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt SR ref } & self & object instance \\ \hline +{\tt SR ref } & self & reference to the object \\ \hline \end{tabular} @@ -7546,7 +7546,7 @@ Get the uuid field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7578,7 +7578,7 @@ Get the name/label field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7610,7 +7610,7 @@ Set the name/label field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -7644,7 +7644,7 @@ Get the name/description field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7676,7 +7676,7 @@ Set the name/description field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -7710,7 +7710,7 @@ Get the SR field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7742,7 +7742,7 @@ Set the SR field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline {\tt SR ref } & value & New value to set \\ \hline @@ -7776,7 +7776,7 @@ Get the VBDs field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7808,7 +7808,7 @@ Get the virtual\_size field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7840,7 +7840,7 @@ Set the virtual\_size field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline {\tt int } & value & New value to set \\ \hline @@ -7874,7 +7874,7 @@ Get the physical\_utilisation field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7906,7 +7906,7 @@ Get the sector\_size field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7938,7 +7938,7 @@ Get the type field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -7970,7 +7970,7 @@ Get the parent field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -8002,7 +8002,7 @@ Get the children field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -8034,7 +8034,7 @@ Get the sharable field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -8066,7 +8066,7 @@ Set the sharable field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -8100,7 +8100,7 @@ Get the read\_only field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -8132,7 +8132,7 @@ Set the read\_only field of the given VDI. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline {\tt bool } & value & New value to set \\ \hline @@ -8198,7 +8198,7 @@ Destroy the specified VDI instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & object instance \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline \end{tabular} @@ -8383,7 +8383,7 @@ Get the uuid field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8415,7 +8415,7 @@ Get the VM field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8447,7 +8447,7 @@ Set the VM field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline {\tt VM ref } & value & New value to set \\ \hline @@ -8481,7 +8481,7 @@ Get the VDI field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8513,7 +8513,7 @@ Set the VDI field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline {\tt VDI ref } & value & New value to set \\ \hline @@ -8547,7 +8547,7 @@ Get the device field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8579,7 +8579,7 @@ Set the device field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -8613,7 +8613,7 @@ Get the mode field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8645,7 +8645,7 @@ Set the mode field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline {\tt vbd\_mode } & value & New value to set \\ \hline @@ -8679,7 +8679,7 @@ Get the driver field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8711,7 +8711,7 @@ Set the driver field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline {\tt driver\_type } & value & New value to set \\ \hline @@ -8745,7 +8745,7 @@ Get the io/read\_kbs field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8777,7 +8777,7 @@ Get the io/write\_kbs field of the given VBD. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8841,7 +8841,7 @@ Destroy the specified VBD instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VBD ref } & self & object instance \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline \end{tabular} @@ -8957,7 +8957,7 @@ Get the uuid field of the given VTPM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VTPM ref } & self & object instance \\ \hline +{\tt VTPM ref } & self & reference to the object \\ \hline \end{tabular} @@ -8989,7 +8989,7 @@ Get the VM field of the given VTPM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VTPM ref } & self & object instance \\ \hline +{\tt VTPM ref } & self & reference to the object \\ \hline \end{tabular} @@ -9021,7 +9021,7 @@ Get the backend field of the given VTPM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VTPM ref } & self & object instance \\ \hline +{\tt VTPM ref } & self & reference to the object \\ \hline \end{tabular} @@ -9053,7 +9053,7 @@ Get the driver field of the given VTPM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VTPM ref } & self & object instance \\ \hline +{\tt VTPM ref } & self & reference to the object \\ \hline \end{tabular} @@ -9085,7 +9085,7 @@ Get the instance field of the given VTPM. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VTPM ref } & self & object instance \\ \hline +{\tt VTPM ref } & self & reference to the object \\ \hline \end{tabular} @@ -9149,7 +9149,7 @@ Destroy the specified VTPM instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VTPM ref } & self & object instance \\ \hline +{\tt VTPM ref } & self & reference to the object \\ \hline \end{tabular} @@ -9360,7 +9360,7 @@ Destroy the specified console instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt console ref } & self & object instance \\ \hline +{\tt console ref } & self & reference to the object \\ \hline \end{tabular} @@ -9392,7 +9392,7 @@ Get the uuid field of the given console. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt console ref } & self & object instance \\ \hline +{\tt console ref } & self & reference to the object \\ \hline \end{tabular} @@ -9424,7 +9424,7 @@ Get the protocol field of the given console. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt console ref } & self & object instance \\ \hline +{\tt console ref } & self & reference to the object \\ \hline \end{tabular} @@ -9456,7 +9456,7 @@ Get the uri field of the given console. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt console ref } & self & object instance \\ \hline +{\tt console ref } & self & reference to the object \\ \hline \end{tabular} @@ -9488,7 +9488,7 @@ Get the VM field of the given console. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt console ref } & self & object instance \\ \hline +{\tt console ref } & self & reference to the object \\ \hline \end{tabular} @@ -9538,7 +9538,7 @@ Get the uuid field of the given user. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt user ref } & self & object instance \\ \hline +{\tt user ref } & self & reference to the object \\ \hline \end{tabular} @@ -9570,7 +9570,7 @@ Get the short\_name field of the given user. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt user ref } & self & object instance \\ \hline +{\tt user ref } & self & reference to the object \\ \hline \end{tabular} @@ -9602,7 +9602,7 @@ Get the fullname field of the given user. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt user ref } & self & object instance \\ \hline +{\tt user ref } & self & reference to the object \\ \hline \end{tabular} @@ -9634,7 +9634,7 @@ Set the fullname field of the given user. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt user ref } & self & object instance \\ \hline +{\tt user ref } & self & reference to the object \\ \hline {\tt string } & value & New value to set \\ \hline @@ -9700,7 +9700,7 @@ Destroy the specified user instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt user ref } & self & object instance \\ \hline +{\tt user ref } & self & reference to the object \\ \hline \end{tabular} @@ -9877,7 +9877,7 @@ Destroy the specified debug instance. \begin{tabular}{|c|c|p{7cm}|} \hline {\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt debug ref } & self & object instance \\ \hline +{\tt debug ref } & self & reference to the object \\ \hline \end{tabular} From 16eaa7dd1c9db6713f6fb86407540ff6db064fb4 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:13:33 +0000 Subject: [PATCH 17/69] Tidy up the get_by_name_label description. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index a51f35743c..71ffb8b524 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -894,7 +894,7 @@ all fields from the object \subsubsection{RPC name:~get\_by\_name\_label} {\bf Overview:} -returns the task instance with a particular name label +Get all the task instances with the given label. \noindent {\bf Signature:} \begin{verbatim} ((task ref) Set) get_by_name_label (session_id s, string label)\end{verbatim} @@ -3861,7 +3861,7 @@ all fields from the object \subsubsection{RPC name:~get\_by\_name\_label} {\bf Overview:} -returns the VM instance with a particular name label +Get all the VM instances with the given label. \noindent {\bf Signature:} \begin{verbatim} ((VM ref) Set) get_by_name_label (session_id s, string label)\end{verbatim} @@ -4484,7 +4484,7 @@ all fields from the object \subsubsection{RPC name:~get\_by\_name\_label} {\bf Overview:} -returns the host instance with a particular name label +Get all the host instances with the given label. \noindent {\bf Signature:} \begin{verbatim} ((host ref) Set) get_by_name_label (session_id s, string label)\end{verbatim} @@ -5454,7 +5454,7 @@ all fields from the object \subsubsection{RPC name:~get\_by\_name\_label} {\bf Overview:} -returns the network instance with a particular name label +Get all the network instances with the given label. \noindent {\bf Signature:} \begin{verbatim} ((network ref) Set) get_by_name_label (session_id s, string label)\end{verbatim} @@ -7407,7 +7407,7 @@ all fields from the object \subsubsection{RPC name:~get\_by\_name\_label} {\bf Overview:} -returns the SR instance with a particular name label +Get all the SR instances with the given label. \noindent {\bf Signature:} \begin{verbatim} ((SR ref) Set) get_by_name_label (session_id s, string label)\end{verbatim} @@ -8281,7 +8281,7 @@ all fields from the object \subsubsection{RPC name:~get\_by\_name\_label} {\bf Overview:} -returns the VDI instance with a particular name label +Get all the VDI instances with the given label. \noindent {\bf Signature:} \begin{verbatim} ((VDI ref) Set) get_by_name_label (session_id s, string label)\end{verbatim} From b7bca7b892104e5efb352c165412a7ddd19ebdcf Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:20:03 +0000 Subject: [PATCH 18/69] Improved task handling model. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 319 ++++++++++++++++++++++++++---- 1 file changed, 280 insertions(+), 39 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 71ffb8b524..cfd264bf94 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -109,6 +109,7 @@ The following enumeration types are used: \hline \end{longtable} +\vspace{1cm} \begin{longtable}{|ll|} \hline {\tt enum vdi\_type} & \\ @@ -133,6 +134,17 @@ The following enumeration types are used: \hline \end{longtable} +\vspace{1cm} +\begin{longtable}{|ll|} +\hline +{\tt enum task\_status\_type} & \\ +\hline +\hspace{0.5cm}{\tt pending} & task is in progress \\ +\hspace{0.5cm}{\tt success} & task was completed successfully \\ +\hspace{0.5cm}{\tt failure} & task has failed \\ +\hline +\end{longtable} + \vspace{1cm} \begin{longtable}{|ll|} \hline @@ -273,6 +285,7 @@ The following enumeration types are used: \hline Quals & Field & Type & Description \\ \hline +$\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ $\mathit{RO}_\mathit{ins}$ & {\tt this\_host} & host ref & Currently connected host \\ $\mathit{RO}_\mathit{ins}$ & {\tt this\_user} & user ref & Currently connected user \\ \hline @@ -330,6 +343,38 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_uuid} + +{\bf Overview:} +Get the uuid field of the given session. + + \noindent {\bf Signature:} +\begin{verbatim} string get_uuid (session_id s, session ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt session ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -540,48 +585,23 @@ Quals & Field & Type & Description \\ $\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ $\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\ +$\mathit{RO}_\mathit{run}$ & {\tt status} & task\_status\_type & current status of the task \\ +$\mathit{RO}_\mathit{run}$ & {\tt progress} & int & if the task is still pending, this field contains the estimated percentage complete (0-100). If task has completed (successfully or unsuccessfully) this should be 100. \\ +$\mathit{RO}_\mathit{run}$ & {\tt eta} & datetime & if the task is still pending, this field contains the estimated completion time. If the task has finished (successfully or not) it contains the time the task finished. \\ +$\mathit{RO}_\mathit{run}$ & {\tt type} & string & if the task has completed successfully, this field contains the type of the encoded result (i.e. name of the class whose reference is in the result field). Undefined otherwise. \\ +$\mathit{RO}_\mathit{run}$ & {\tt result} & string & if the task has completed successfully, this field contains the result value (either Void or an object reference). Undefined otherwise. \\ +$\mathit{RO}_\mathit{run}$ & {\tt error\_code} & int & if the task has failed, this field contains the error code. Undefined otherwise. \\ +$\mathit{RO}_\mathit{run}$ & {\tt error\_info} & string Set & if the task has failed, this field contains the set of associated error strings. Undefined otherwise. \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: task} -\subsubsection{RPC name:~get\_status} +\subsubsection{RPC name:~get\_all} {\bf Overview:} -Poll a running asynchronous RPC invocation and query its status +Return a list of all the tasks known to the system \noindent {\bf Signature:} -\begin{verbatim} (uuid ref) get_status (session_id s, task ref task)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt task ref } & task & The ID of the RPC call to poll \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -uuid ref -} - - -String describing status of specified asynchronous RPC invocation, including estimated completion time -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_all\_tasks} - -{\bf Overview:} -List all asynchronous RPC calls currently executing - - \noindent {\bf Signature:} -\begin{verbatim} ((task ref) Set) get_all_tasks (session_id s)\end{verbatim} +\begin{verbatim} ((task ref) Set) get_all (session_id s)\end{verbatim} \vspace{0.3cm} @@ -592,10 +612,7 @@ List all asynchronous RPC calls currently executing } -A list of tasks currently executing. Note that -tasks are associated with users rather than sessions. Thus, if you logout and -login again with a different session but the same user, this function will still -return the user's running tasks. +references to all objects \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -760,6 +777,230 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_status} + +{\bf Overview:} +Get the status field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} (task_status_type) get_status (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +task\_status\_type +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_progress} + +{\bf Overview:} +Get the progress field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} int get_progress (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_eta} + +{\bf Overview:} +Get the eta field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} datetime get_eta (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +datetime +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_type} + +{\bf Overview:} +Get the type field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} string get_type (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_result} + +{\bf Overview:} +Get the result field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} string get_result (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_error\_code} + +{\bf Overview:} +Get the error\_code field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} int get_error_code (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_error\_info} + +{\bf Overview:} +Get the error\_info field of the given task. + + \noindent {\bf Signature:} +\begin{verbatim} (string Set) get_error_info (session_id s, task ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt task ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string Set +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} From 41eb2f8c0de0fd155b40d10512bab82956cf5b7a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:38:29 +0000 Subject: [PATCH 19/69] Clarify that memory values are in bytes. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index cfd264bf94..18e9ba8ec8 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1183,11 +1183,11 @@ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human- $\mathit{RW}$ & {\tt user\_version} & int & a user version number for this machine \\ $\mathit{RW}$ & {\tt is\_a\_template} & bool & true if this is a template. Template VMs can never be started, they are used only for cloning other VMs \\ $\mathit{RO}_\mathit{run}$ & {\tt resident\_on} & host ref & the host the VM is currently resident on \\ -$\mathit{RO}_\mathit{ins}$ & {\tt memory/static\_max} & int & Statically-set (i.e. absolute) maximum \\ -$\mathit{RW}$ & {\tt memory/dynamic\_max} & int & Dynamic maximum \\ -$\mathit{RO}_\mathit{run}$ & {\tt memory/actual} & int & Guest's actual usage \\ -$\mathit{RW}$ & {\tt memory/dynamic\_min} & int & Dynamic minimum \\ -$\mathit{RO}_\mathit{ins}$ & {\tt memory/static\_min} & int & Statically-set (i.e. absolute) mininum \\ +$\mathit{RO}_\mathit{ins}$ & {\tt memory/static\_max} & int & Statically-set (i.e. absolute) maximum (bytes) \\ +$\mathit{RW}$ & {\tt memory/dynamic\_max} & int & Dynamic maximum (bytes) \\ +$\mathit{RO}_\mathit{run}$ & {\tt memory/actual} & int & Guest's actual usage (bytes) \\ +$\mathit{RW}$ & {\tt memory/dynamic\_min} & int & Dynamic minimum (bytes) \\ +$\mathit{RO}_\mathit{ins}$ & {\tt memory/static\_min} & int & Statically-set (i.e. absolute) mininum (bytes) \\ $\mathit{RW}$ & {\tt VCPUs/policy} & string & the name of the VCPU scheduling policy to be applied \\ $\mathit{RW}$ & {\tt VCPUs/params} & string & string-encoded parameters passed to selected VCPU policy \\ $\mathit{RO}_\mathit{run}$ & {\tt VCPUs/number} & int & Current number of VCPUs \\ From b916a8f2796bb727be29ee42f3df272a5a00c8d2 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:40:26 +0000 Subject: [PATCH 20/69] Add VM.auto_power_on field. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 18e9ba8ec8..29400f01ac 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1182,6 +1182,7 @@ $\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\ $\mathit{RW}$ & {\tt user\_version} & int & a user version number for this machine \\ $\mathit{RW}$ & {\tt is\_a\_template} & bool & true if this is a template. Template VMs can never be started, they are used only for cloning other VMs \\ +$\mathit{RW}$ & {\tt auto\_power\_on} & bool & true if this VM should be started automatically after host boot \\ $\mathit{RO}_\mathit{run}$ & {\tt resident\_on} & host ref & the host the VM is currently resident on \\ $\mathit{RO}_\mathit{ins}$ & {\tt memory/static\_max} & int & Statically-set (i.e. absolute) maximum (bytes) \\ $\mathit{RW}$ & {\tt memory/dynamic\_max} & int & Dynamic maximum (bytes) \\ @@ -1898,6 +1899,72 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_auto\_power\_on} + +{\bf Overview:} +Get the auto\_power\_on field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} bool get_auto_power_on (session_id s, VM ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +bool +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_auto\_power\_on} + +{\bf Overview:} +Set the auto\_power\_on field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} void set_auto_power_on (session_id s, VM ref self, bool value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +{\tt bool } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} From 76b9ef8804d5629b3317208e9807c1a26cbc5f6c Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:42:28 +0000 Subject: [PATCH 21/69] Add extra detail to the VM.destroy description. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 29400f01ac..6c039a28b4 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -4073,7 +4073,7 @@ reference to the newly created object \subsubsection{RPC name:~destroy} {\bf Overview:} -Destroy the specified VM instance. +Destroy the specified VM. The VM is completely removed from the system. This function can only be called when the VM is in the Halted State. \noindent {\bf Signature:} \begin{verbatim} void destroy (session_id s, VM ref self)\end{verbatim} From af87afdaafdc8c2ee347f9ff0b5b64944136a664 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 15:45:09 +0000 Subject: [PATCH 22/69] Added VBD.type field (CD or Disk). Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 6c039a28b4..80ecd56210 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -263,6 +263,16 @@ The following enumeration types are used: \hline \end{longtable} +\vspace{1cm} +\begin{longtable}{|ll|} +\hline +{\tt enum vbd\_type} & \\ +\hline +\hspace{0.5cm}{\tt CD} & VBD will appear to guest as CD \\ +\hspace{0.5cm}{\tt Disk} & VBD will appear to guest as disk \\ +\hline +\end{longtable} + \vspace{1cm} \begin{longtable}{|ll|} \hline @@ -8635,6 +8645,7 @@ $\mathit{RW}$ & {\tt VM} & VM ref & the virtual machine \\ $\mathit{RW}$ & {\tt VDI} & VDI ref & the virtual disk \\ $\mathit{RW}$ & {\tt device} & string & device seen by the guest e.g. hda1 \\ $\mathit{RW}$ & {\tt mode} & vbd\_mode & the mode the disk should be mounted with \\ +$\mathit{RW}$ & {\tt type} & vbd\_type & how the VBD will appear to the guest (e.g. disk or CD) \\ $\mathit{RW}$ & {\tt driver} & driver\_type & the style of driver \\ $\mathit{RO}_\mathit{run}$ & {\tt io/read\_kbs} & float & Read bandwidth (KiB/s) \\ $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\ @@ -8968,6 +8979,72 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_type} + +{\bf Overview:} +Get the type field of the given VBD. + + \noindent {\bf Signature:} +\begin{verbatim} (vbd_type) get_type (session_id s, VBD ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +vbd\_type +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_type} + +{\bf Overview:} +Set the type field of the given VBD. + + \noindent {\bf Signature:} +\begin{verbatim} void set_type (session_id s, VBD ref self, vbd_type value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VBD ref } & self & reference to the object \\ \hline + +{\tt vbd\_type } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} From a784042736e5b955e59b9690fe107457e30946b1 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 16:26:53 +0000 Subject: [PATCH 23/69] Make VM.VCPUs.number a writable field. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 36 ++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 80ecd56210..cb3c347eaf 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1201,7 +1201,7 @@ $\mathit{RW}$ & {\tt memory/dynamic\_min} & int & Dynamic minimum (bytes) \\ $\mathit{RO}_\mathit{ins}$ & {\tt memory/static\_min} & int & Statically-set (i.e. absolute) mininum (bytes) \\ $\mathit{RW}$ & {\tt VCPUs/policy} & string & the name of the VCPU scheduling policy to be applied \\ $\mathit{RW}$ & {\tt VCPUs/params} & string & string-encoded parameters passed to selected VCPU policy \\ -$\mathit{RO}_\mathit{run}$ & {\tt VCPUs/number} & int & Current number of VCPUs \\ +$\mathit{RW}$ & {\tt VCPUs/number} & int & Current number of VCPUs \\ $\mathit{RO}_\mathit{run}$ & {\tt VCPUs/utilisation} & (int $\rightarrow$ float) Map & Utilisation for all of guest's current VCPUs \\ $\mathit{RO}_\mathit{ins}$ & {\tt VCPUs/features/required} & (cpu\_feature) Set & CPU features the guest demands the host supports \\ $\mathit{RO}_\mathit{ins}$ & {\tt VCPUs/features/can\_use} & (cpu\_feature) Set & CPU features the guest can use if available \\ @@ -2399,6 +2399,40 @@ int value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_VCPUs\_number} + +{\bf Overview:} +Set the VCPUs/number field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} void set_VCPUs_number (session_id s, VM ref self, int value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +{\tt int } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} From 12e12aa8f9461d0aa4fbc9bf31395b49f02fef34 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 6 Dec 2006 16:33:48 +0000 Subject: [PATCH 24/69] Added VM.set_VCPUs_features_force_on, VM.set_VCPUs_features_force_off, VM.set_otherConfig. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 102 ++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index cb3c347eaf..2facf7fec6 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -2561,6 +2561,40 @@ Get the VCPUs/features/force\_on field of the given VM. value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_VCPUs\_features\_force\_on} + +{\bf Overview:} +Set the VCPUs/features/force\_on field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} void set_VCPUs_features_force_on (session_id s, VM ref self, (cpu_feature) Set value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +{\tt (cpu\_feature) Set } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -2661,6 +2695,40 @@ Get the VCPUs/features/force\_off field of the given VM. value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_VCPUs\_features\_force\_off} + +{\bf Overview:} +Set the VCPUs/features/force\_off field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} void set_VCPUs_features_force_off (session_id s, VM ref self, (cpu_feature) Set value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +{\tt (cpu\_feature) Set } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -4009,6 +4077,40 @@ Get the otherConfig field of the given VM. value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_otherConfig} + +{\bf Overview:} +Set the otherConfig field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} void set_otherConfig (session_id s, VM ref self, (string -> string) Map value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} From dc960266aaa37386c101fcb26ca30c574d15fc5f Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 10:54:43 +0000 Subject: [PATCH 25/69] [XEND] Fix reboot for HVM domains if cdrom is empty. Signed-off-by: Alastair Tse --- tools/python/xen/xend/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 8d2aab1836..29eea9dc55 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -338,7 +338,7 @@ class HVMImageHandler(ImageHandler): for devuuid, (devtype, devinfo) in deviceConfig.items(): if devtype == 'vbd': - uname = devinfo['uname'] + uname = devinfo.get('uname') if uname is not None and 'file:' in uname: (_, vbdparam) = string.split(uname, ':', 1) if not os.path.isfile(vbdparam): From 59a3344cac1782bf3d64a5a36af49b638b7f2bf6 Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 11:12:05 +0000 Subject: [PATCH 26/69] [XEND] Update vcpu_avail when parsing configuration. Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendConfig.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 5a06f77efb..7f0da37653 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -353,10 +353,15 @@ class XendConfig(dict): if self['builder'] not in ('hvm', 'linux'): raise XendConfigError('Invalid builder configuration') + def _vcpus_sanity_check(self): + if self.get('vcpus_number') != None: + self['vcpu_avail'] = (1 << self['vcpus_number']) - 1 + def validate(self): self._memory_sanity_check() self._actions_sanity_check() self._builder_sanity_check() + self._vcpus_sanity_check() def _dominfo_to_xapi(self, dominfo): self['domid'] = dominfo['domid'] From 56e9db683be09f411dec3d0fe4f0afb433be709b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:12:52 +0000 Subject: [PATCH 27/69] [HVM] qemu: Add guest address-space mapping cache. On IA32 host or IA32 PAE host, at present, generally, we can't create an HVM guest with more than 2G memory, because generally it's almost impossible for Qemu to find a large enough and consecutive virtual address space to map an HVM guest's whole physical address space. The attached patch fixes this issue using dynamic mapping based on little blocks of memory. Signed-off-by: Jun Nakajima Signed-off-by: Dexuan Cui Signed-off-by: Keir Fraser --- tools/ioemu/target-i386-dm/cpu.h | 3 +- tools/ioemu/target-i386-dm/exec-dm.c | 17 ++- tools/ioemu/vl.c | 154 ++++++++++++++++++++------- tools/ioemu/vl.h | 20 ++++ 4 files changed, 151 insertions(+), 43 deletions(-) diff --git a/tools/ioemu/target-i386-dm/cpu.h b/tools/ioemu/target-i386-dm/cpu.h index dc016edd3e..017b8c021b 100644 --- a/tools/ioemu/target-i386-dm/cpu.h +++ b/tools/ioemu/target-i386-dm/cpu.h @@ -25,7 +25,8 @@ #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64 #else -#define TARGET_LONG_BITS 32 +/* #define TARGET_LONG_BITS 32 */ +#define TARGET_LONG_BITS 64 /* for Qemu map cache */ #endif /* target supports implicit self modifying code */ diff --git a/tools/ioemu/target-i386-dm/exec-dm.c b/tools/ioemu/target-i386-dm/exec-dm.c index be8b280dda..755d547772 100644 --- a/tools/ioemu/target-i386-dm/exec-dm.c +++ b/tools/ioemu/target-i386-dm/exec-dm.c @@ -36,6 +36,7 @@ #include "cpu.h" #include "exec-all.h" +#include "vl.h" //#define DEBUG_TB_INVALIDATE //#define DEBUG_FLUSH @@ -426,6 +427,12 @@ static inline int paddr_is_ram(target_phys_addr_t addr) #endif } +#if defined(__i386__) || defined(__x86_64__) +#define phys_ram_addr(x) (qemu_map_cache(x)) +#elif defined(__ia64__) +#define phys_ram_addr(x) (phys_ram_base + (x)) +#endif + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { @@ -438,7 +445,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK); if (l > len) l = len; - + io_index = iomem_index(addr); if (is_write) { if (io_index) { @@ -460,9 +467,10 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } else if (paddr_is_ram(addr)) { /* Reading from RAM */ - memcpy(phys_ram_base + addr, buf, l); + ptr = phys_ram_addr(addr); + memcpy(ptr, buf, l); #ifdef __ia64__ - sync_icache((unsigned long)(phys_ram_base + addr), l); + sync_icache(ptr, l); #endif } } else { @@ -485,7 +493,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } else if (paddr_is_ram(addr)) { /* Reading from RAM */ - memcpy(buf, phys_ram_base + addr, l); + ptr = phys_ram_addr(addr); + memcpy(buf, ptr, l); } else { /* Neither RAM nor known MMIO space */ memset(buf, 0xff, len); diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index a2700ef313..b65f61d8df 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -5808,6 +5808,92 @@ int set_mm_mapping(int xc_handle, uint32_t domid, return 0; } +#if defined(__i386__) || defined(__x86_64__) +static struct map_cache *mapcache_entry; +static unsigned long nr_buckets; + +static int qemu_map_cache_init(unsigned long nr_pages) +{ + unsigned long max_pages = MAX_MCACHE_SIZE >> PAGE_SHIFT; + int i; + + if (nr_pages < max_pages) + max_pages = nr_pages; + + nr_buckets = (max_pages << PAGE_SHIFT) >> MCACHE_BUCKET_SHIFT; + + fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx\n", nr_buckets); + + mapcache_entry = malloc(nr_buckets * sizeof(struct map_cache)); + if (mapcache_entry == NULL) { + errno = ENOMEM; + return -1; + } + + memset(mapcache_entry, 0, nr_buckets * sizeof(struct map_cache)); + + /* + * To avoid ENOMEM from xc_map_foreign_batch() at runtime, we + * pre-fill all the map caches in advance. + */ + for (i = 0; i < nr_buckets; i++) + (void)qemu_map_cache(((target_phys_addr_t)i) << MCACHE_BUCKET_SHIFT); + + return 0; +} + +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) +{ + struct map_cache *entry; + unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; + unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); + + /* For most cases (>99.9%), the page address is the same. */ + static unsigned long last_address_index = ~0UL; + static uint8_t *last_address_vaddr; + + if (address_index == last_address_index) + return last_address_vaddr + address_offset; + + entry = &mapcache_entry[address_index % nr_buckets]; + + if (entry->vaddr_base == NULL || entry->paddr_index != address_index) + { + /* We need to remap a bucket. */ + uint8_t *vaddr_base; + unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; + unsigned int i; + + if (entry->vaddr_base != NULL) { + errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); + if (errno) { + fprintf(logfile, "unmap fails %d\n", errno); + exit(-1); + } + } + + for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) + pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; + + vaddr_base = xc_map_foreign_batch( + xc_handle, domid, PROT_READ|PROT_WRITE, + pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); + if (vaddr_base == NULL) { + fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); + exit(-1); + } + + entry->vaddr_base = vaddr_base; + entry->paddr_index = address_index;; + } + + last_address_index = address_index; + last_address_vaddr = entry->vaddr_base; + + return last_address_vaddr + address_offset; +} +#endif + int main(int argc, char **argv) { #ifdef CONFIG_GDBSTUB @@ -6130,6 +6216,7 @@ int main(int argc, char **argv) break; case QEMU_OPTION_m: ram_size = atol(optarg) * 1024 * 1024; + ram_size = (uint64_t)atol(optarg) * 1024 * 1024; if (ram_size <= 0) help(); #ifndef CONFIG_DM @@ -6400,50 +6487,41 @@ int main(int argc, char **argv) shared_page_nr = nr_pages - 1; #endif +#if defined(__i386__) || defined(__x86_64__) + + if ( qemu_map_cache_init(tmp_nr_pages) ) + { + fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno); + exit(-1); + } + + shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, shared_page_nr); + if (shared_page == NULL) { + fprintf(logfile, "map shared IO page returned error %d\n", errno); + exit(-1); + } + + fprintf(logfile, "shared page at pfn:%lx\n", shared_page_nr); + + buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, + shared_page_nr - 2); + if (buffered_io_page == NULL) { + fprintf(logfile, "map buffered IO page returned error %d\n", errno); + exit(-1); + } + + fprintf(logfile, "buffered io page at pfn:%lx\n", shared_page_nr - 2); + +#elif defined(__ia64__) + page_array = (xen_pfn_t *)malloc(tmp_nr_pages * sizeof(xen_pfn_t)); if (page_array == NULL) { fprintf(logfile, "malloc returned error %d\n", errno); exit(-1); } -#if defined(__i386__) || defined(__x86_64__) - for ( i = 0; i < tmp_nr_pages; i++) - page_array[i] = i; - - phys_ram_base = xc_map_foreign_batch(xc_handle, domid, - PROT_READ|PROT_WRITE, page_array, - tmp_nr_pages); - if (phys_ram_base == NULL) { - fprintf(logfile, "batch map guest memory returned error %d\n", errno); - exit(-1); - } - - shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, - PROT_READ|PROT_WRITE, - page_array[shared_page_nr]); - if (shared_page == NULL) { - fprintf(logfile, "map shared IO page returned error %d\n", errno); - exit(-1); - } - - fprintf(logfile, "shared page at pfn:%lx, mfn: %"PRIx64"\n", - shared_page_nr, (uint64_t)(page_array[shared_page_nr])); - - buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, - PROT_READ|PROT_WRITE, - page_array[shared_page_nr - 2]); - if (buffered_io_page == NULL) { - fprintf(logfile, "map buffered IO page returned error %d\n", errno); - exit(-1); - } - - fprintf(logfile, "buffered io page at pfn:%lx, mfn: %"PRIx64"\n", - shared_page_nr - 2, (uint64_t)(page_array[shared_page_nr - 2])); - - free(page_array); - -#elif defined(__ia64__) - if (xc_ia64_get_pfn_list(xc_handle, domid, page_array, IO_PAGE_START >> PAGE_SHIFT, 3) != 3) { fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno); diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 3df963241c..9e4d92a17b 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -156,6 +156,26 @@ extern void *shared_vram; extern FILE *logfile; + +#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) +#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ +#define MCACHE_BUCKET_SHIFT 16 +#elif defined(__x86_64__) +#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ +#define MCACHE_BUCKET_SHIFT 20 +#endif + +#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) + +struct map_cache { + unsigned long paddr_index; + uint8_t *vaddr_base; +}; + +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr); +#endif + extern int xc_handle; extern int domid; From a490953a599fdf14f3e1a9fed85949ab0c1e0b1c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:16:17 +0000 Subject: [PATCH 28/69] [HVM] Fix reboot failure when configured 'cdrom', i.e. bug 832. Signed-off-by : Xinmei Huang --- tools/python/xen/xend/server/blkif.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index 16e2c5052d..bba11ebe1f 100644 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -124,6 +124,8 @@ class BlkifController(DevController): config['dev'] = dev if typ and params: config['uname'] = typ +':' + params + else: + config['uname'] = None if mode: config['mode'] = mode if uuid: From 03b88d57897af9feaada5f5b35dec0369ce217db Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:17:28 +0000 Subject: [PATCH 29/69] [VTPM][HVM] Transmit the locality in which the command was sent in the highest 3 bits of the 4 bytes prepended to each packet. Signed-off-by: Stefan Berger --- tools/ioemu/hw/tpm_tis.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/ioemu/hw/tpm_tis.c b/tools/ioemu/hw/tpm_tis.c index a4d07bc67f..ace469f1ec 100644 --- a/tools/ioemu/hw/tpm_tis.c +++ b/tools/ioemu/hw/tpm_tis.c @@ -132,7 +132,7 @@ typedef struct TPMState { /* local prototypes */ -static int TPM_Send(tpmState *s, tpmBuffer *buffer, char *msg); +static int TPM_Send(tpmState *s, tpmBuffer *buffer, uint8_t locty, char *msg); static int TPM_Receive(tpmState *s, tpmBuffer *buffer); static uint32_t vtpm_instance_from_xenstore(void); static void tis_poll_timer(void *opaque); @@ -271,6 +271,8 @@ static int create_local_socket(tpmState *s, uint32_t vtpm_instance) /* * the 'write' method for sending requests to the vTPM * four bytes with the vTPM instance number are prepended to each request + * the locality in which the command was sent is transmitted in the + * highest 3 bits */ static int write_local_socket(tpmState *s, const tpmBuffer *buffer) { @@ -608,7 +610,7 @@ static void tis_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) } } if (val & STS_TPM_GO) { - n = TPM_Send(s, &s->buffer,"tpm_data_write"); + n = TPM_Send(s, &s->buffer, locty, "tpm_data_write"); if (n > 0) { /* sending of data was successful */ s->offset = 0; @@ -915,7 +917,7 @@ const static unsigned char tpm_failure[] = { /* * Send a TPM request. */ -static int TPM_Send(tpmState *s, tpmBuffer *buffer, char *msg) +static int TPM_Send(tpmState *s, tpmBuffer *buffer, uint8_t locty, char *msg) { int len; uint32_t size = tpm_get_size_from_buffer(buffer->buf); @@ -945,6 +947,10 @@ static int TPM_Send(tpmState *s, tpmBuffer *buffer, char *msg) showBuff(buffer->buf, "To TPM"); #endif + /* transmit the locality in the highest 3 bits */ + buffer->instance[0] &= 0x1f; + buffer->instance[0] |= (locty << 5); + len = vTPMTransmit[s->Transmitlayer].write(s, buffer); if (len < 0) { s->Transmitlayer = -1; From 40574f04b42731e24cb00237b7c29bc8a5f45eab Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:18:38 +0000 Subject: [PATCH 30/69] VMXAssist cleanups Signed-off-by: Xin Li --- tools/firmware/vmxassist/head.S | 2 +- tools/firmware/vmxassist/setup.c | 4 +- tools/firmware/vmxassist/vm86.c | 203 ++++++++++++++----------------- 3 files changed, 94 insertions(+), 115 deletions(-) diff --git a/tools/firmware/vmxassist/head.S b/tools/firmware/vmxassist/head.S index a4cb614c68..7cb4ec1069 100644 --- a/tools/firmware/vmxassist/head.S +++ b/tools/firmware/vmxassist/head.S @@ -130,7 +130,7 @@ _start: clts /* setup my own stack */ - movl $stack_top - 4*4, %esp + movl $stack_top, %esp movl %esp, %ebp /* go ... */ diff --git a/tools/firmware/vmxassist/setup.c b/tools/firmware/vmxassist/setup.c index d1c47b2325..9f8928ff0d 100644 --- a/tools/firmware/vmxassist/setup.c +++ b/tools/firmware/vmxassist/setup.c @@ -125,7 +125,7 @@ setup_gdt(void) /* setup task state segment */ memset(&tss, 0, sizeof(tss)); tss.ss0 = DATA_SELECTOR; - tss.esp0 = (unsigned) stack_top - 4*4; + tss.esp0 = (unsigned) stack_top; tss.iomap_base = offsetof(struct tss, iomap); /* initialize gdt's tss selector */ @@ -258,7 +258,7 @@ setup_ctx(void) memset(c, 0, sizeof(*c)); c->eip = (unsigned long) switch_to_real_mode; - c->esp = (unsigned) stack_top - 4*4; + c->esp = (unsigned) stack_top; c->eflags = 0x2; /* no interrupts, please */ /* diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c index 7e37de63b8..7a76ad8b15 100644 --- a/tools/firmware/vmxassist/vm86.c +++ b/tools/firmware/vmxassist/vm86.c @@ -1,6 +1,6 @@ /* * vm86.c: A vm86 emulator. The main purpose of this emulator is to do as - * little work as possible. + * little work as possible. * * Leendert van Doorn, leendert@watson.ibm.com * Copyright (c) 2005-2006, International Business Machines Corporation. @@ -52,8 +52,8 @@ char *states[] = { static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; #endif /* DEBUG */ -#define PDE_PS (1 << 7) -#define PT_ENTRY_PRESENT 0x1 +#define PDE_PS (1 << 7) +#define PT_ENTRY_PRESENT 0x1 /* We only support access to <=4G physical memory due to 1:1 mapping */ static uint64_t @@ -136,7 +136,7 @@ address(struct regs *regs, unsigned seg, unsigned off) } if (mode == VM86_REAL || seg > oldctx.gdtr_limit || - (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg)) + (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg)) return ((seg & 0xFFFF) << 4) + off; gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base); @@ -153,13 +153,13 @@ address(struct regs *regs, unsigned seg, unsigned off) seg_limit = (entry_high & 0xF0000) | (entry_low & 0xFFFF); if (entry_high & 0x8000 && - ((entry_high & 0x800000 && off >> 12 <= seg_limit) || - (!(entry_high & 0x800000) && off <= seg_limit))) + ((entry_high & 0x800000 && off >> 12 <= seg_limit) || + (!(entry_high & 0x800000) && off <= seg_limit))) return seg_base + off; panic("should never reach here in function address():\n\t" - "entry=0x%08x%08x, mode=%d, seg=0x%08x, offset=0x%08x\n", - entry_high, entry_low, mode, seg, off); + "entry=0x%08x%08x, mode=%d, seg=0x%08x, offset=0x%08x\n", + entry_high, entry_low, mode, seg, off); return 0; } @@ -172,7 +172,7 @@ trace(struct regs *regs, int adjust, char *fmt, ...) va_list ap; if ((traceset & (1 << mode)) && - (mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) { + (mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) { /* 16-bit, seg:off addressing */ unsigned addr = address(regs, regs->cs, off); printf("0x%08x: 0x%x:0x%04x ", addr, regs->cs, off); @@ -183,7 +183,7 @@ trace(struct regs *regs, int adjust, char *fmt, ...) printf("\n"); } if ((traceset & (1 << mode)) && - (mode == VM86_PROTECTED_TO_REAL || mode == VM86_PROTECTED)) { + (mode == VM86_PROTECTED_TO_REAL || mode == VM86_PROTECTED)) { /* 16-bit, gdt addressing */ unsigned addr = address(regs, regs->cs, off); printf("0x%08x: 0x%x:0x%08x ", addr, regs->cs, off); @@ -430,7 +430,7 @@ operand(unsigned prefix, struct regs *regs, unsigned modrm) case 2: return address(regs, seg, regs->edx); case 3: return address(regs, seg, regs->ebx); case 4: return address(regs, seg, - sib(regs, mod, fetch8(regs))); + sib(regs, mod, fetch8(regs))); case 5: return address(regs, seg, fetch32(regs)); case 6: return address(regs, seg, regs->esi); case 7: return address(regs, seg, regs->edi); @@ -450,7 +450,7 @@ operand(unsigned prefix, struct regs *regs, unsigned modrm) case 2: return address(regs, seg, regs->edx + disp); case 3: return address(regs, seg, regs->ebx + disp); case 4: return address(regs, seg, - sib(regs, mod, fetch8(regs))); + sib(regs, mod, fetch8(regs))); case 5: return address(regs, seg, regs->ebp + disp); case 6: return address(regs, seg, regs->esi + disp); case 7: return address(regs, seg, regs->edi + disp); @@ -507,7 +507,7 @@ operand(unsigned prefix, struct regs *regs, unsigned modrm) } } - return 0; + return 0; } /* @@ -859,7 +859,7 @@ mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc) fail: printf("%s:%d: missed opcode %02x %02x\n", - __FUNCTION__, __LINE__, opc, modrm); + __FUNCTION__, __LINE__, opc, modrm); return 0; } @@ -896,11 +896,11 @@ load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes ((entry >> (32-16)) & 0x00FF0000) | ((entry >> ( 16)) & 0x0000FFFF)); *limit = (((entry >> (48-16)) & 0x000F0000) | - ((entry ) & 0x0000FFFF)); + (entry & 0x0000FFFF)); arbytes->bytes = 0; arbytes->fields.seg_type = (entry >> (8+32)) & 0xF; /* TYPE */ - arbytes->fields.s = (entry >> (12+32)) & 0x1; /* S */ + arbytes->fields.s = (entry >> (12+32)) & 0x1; /* S */ if (arbytes->fields.s) arbytes->fields.seg_type |= 1; /* accessed */ arbytes->fields.dpl = (entry >> (13+32)) & 0x3; /* DPL */ @@ -924,7 +924,7 @@ static void load_or_clear_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes *arbytes) { if (!load_seg(sel, base, limit, arbytes)) - load_seg(0, base, limit, arbytes); + load_seg(0, base, limit, arbytes); } @@ -988,21 +988,21 @@ real_mode(struct regs *regs) panic("%%ss 0x%lx higher than 1MB", regs->uss); regs->uss = address(regs, regs->uss, 0) >> 4; } else { - regs->uss = saved_rm_regs.uss; + regs->uss = saved_rm_regs.uss; } if (regs->vds != 0) { if (regs->vds >= HIGHMEM) panic("%%ds 0x%lx higher than 1MB", regs->vds); regs->vds = address(regs, regs->vds, 0) >> 4; } else { - regs->vds = saved_rm_regs.vds; + regs->vds = saved_rm_regs.vds; } if (regs->ves != 0) { if (regs->ves >= HIGHMEM) panic("%%es 0x%lx higher than 1MB", regs->ves); regs->ves = address(regs, regs->ves, 0) >> 4; } else { - regs->ves = saved_rm_regs.ves; + regs->ves = saved_rm_regs.ves; } /* this should get us into 16-bit mode */ @@ -1029,10 +1029,7 @@ set_mode(struct regs *regs, enum vm86_mode newmode) (mode == VM86_REAL_TO_PROTECTED)) { regs->eflags &= ~EFLAGS_TF; real_mode(regs); - break; - } else if (mode == VM86_REAL) { - break; - } else + } else if (mode != VM86_REAL) panic("unexpected real mode transition"); break; @@ -1049,25 +1046,19 @@ set_mode(struct regs *regs, enum vm86_mode newmode) oldctx.fs_sel = 0; oldctx.gs_sel = 0; oldctx.ss_sel = 0; - break; - } else if (mode == VM86_REAL_TO_PROTECTED) { - break; - } else + } else if (mode != VM86_REAL_TO_PROTECTED) panic("unexpected real-to-protected mode transition"); break; case VM86_PROTECTED_TO_REAL: - if (mode == VM86_PROTECTED) { - break; - } else + if (mode != VM86_PROTECTED) panic("unexpected protected-to-real mode transition"); break; case VM86_PROTECTED: - if (mode == VM86_REAL_TO_PROTECTED) { - protected_mode(regs); - } else + if (mode != VM86_REAL_TO_PROTECTED) panic("unexpected protected mode transition"); + protected_mode(regs); break; } @@ -1081,25 +1072,19 @@ jmpl(struct regs *regs, int prefix) unsigned n = regs->eip; unsigned cs, eip; - if (mode == VM86_REAL_TO_PROTECTED) { /* jump to protected mode */ - eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs); - cs = fetch16(regs); + eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs); + cs = fetch16(regs); - TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); + TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); - regs->cs = cs; - regs->eip = eip; + regs->cs = cs; + regs->eip = eip; + + if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */ set_mode(regs, VM86_PROTECTED); - } else if (mode == VM86_PROTECTED_TO_REAL) { /* jump to real mode */ - eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs); - cs = fetch16(regs); - - TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); - - regs->cs = cs; - regs->eip = eip; + else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */ set_mode(regs, VM86_REAL); - } else + else panic("jmpl"); } @@ -1110,29 +1095,22 @@ jmpl_indirect(struct regs *regs, int prefix, unsigned modrm) unsigned cs, eip; unsigned addr; - addr = operand(prefix, regs, modrm); + addr = operand(prefix, regs, modrm); - if (mode == VM86_REAL_TO_PROTECTED) { /* jump to protected mode */ - eip = (prefix & DATA32) ? read32(addr) : read16(addr); - addr += (prefix & DATA32) ? 4 : 2; - cs = read16(addr); + eip = (prefix & DATA32) ? read32(addr) : read16(addr); + addr += (prefix & DATA32) ? 4 : 2; + cs = read16(addr); - TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); + TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); - regs->cs = cs; - regs->eip = eip; + regs->cs = cs; + regs->eip = eip; + + if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */ set_mode(regs, VM86_PROTECTED); - } else if (mode == VM86_PROTECTED_TO_REAL) { /* jump to real mode */ - eip = (prefix & DATA32) ? read32(addr) : read16(addr); - addr += (prefix & DATA32) ? 4 : 2; - cs = read16(addr); - - TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); - - regs->cs = cs; - regs->eip = eip; + else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */ set_mode(regs, VM86_REAL); - } else + else panic("jmpl"); } @@ -1151,15 +1129,14 @@ retl(struct regs *regs, int prefix) TRACE((regs, 1, "retl (to 0x%x:0x%x)", cs, eip)); - if (mode == VM86_REAL_TO_PROTECTED) { /* jump to protected mode */ - regs->cs = cs; - regs->eip = eip; + regs->cs = cs; + regs->eip = eip; + + if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */ set_mode(regs, VM86_PROTECTED); - } else if (mode == VM86_PROTECTED_TO_REAL) { /* jump to real mode */ - regs->cs = cs; - regs->eip = eip; + else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */ set_mode(regs, VM86_REAL); - } else + else panic("retl"); } @@ -1259,8 +1236,8 @@ pushrm(struct regs *regs, int prefix, unsigned modrm) unsigned addr; unsigned data; - addr = operand(prefix, regs, modrm); - + addr = operand(prefix, regs, modrm); + if (prefix & DATA32) { data = read32(addr); push32(regs, data); @@ -1386,11 +1363,11 @@ opcode(struct regs *regs) case 0x3B: /* addr32 cmp r/m16, r16 */ if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED) goto invalid; - if ((prefix & ADDR32) == 0) - goto invalid; - if (!cmp(regs, prefix, opc)) - goto invalid; - return OPC_EMULATED; + if ((prefix & ADDR32) == 0) + goto invalid; + if (!cmp(regs, prefix, opc)) + goto invalid; + return OPC_EMULATED; case 0x3E: TRACE((regs, regs->eip - eip, "%%ds:")); @@ -1412,7 +1389,7 @@ opcode(struct regs *regs) prefix |= DATA32; continue; - case 0x67: + case 0x67: TRACE((regs, regs->eip - eip, "addr32")); prefix |= ADDR32; continue; @@ -1421,18 +1398,18 @@ opcode(struct regs *regs) case 0x8A: /* addr32 mov r/m8, r8 */ if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED) goto invalid; - if ((prefix & ADDR32) == 0) - goto invalid; - if (!movr(regs, prefix, opc)) - goto invalid; - return OPC_EMULATED; + if ((prefix & ADDR32) == 0) + goto invalid; + if (!movr(regs, prefix, opc)) + goto invalid; + return OPC_EMULATED; case 0x89: /* addr32 mov r16, r/m16 */ if (mode == VM86_PROTECTED_TO_REAL) { unsigned modrm = fetch8(regs); unsigned addr = operand(prefix, regs, modrm); unsigned val, r = (modrm >> 3) & 7; - + if (prefix & DATA32) { val = getreg16(regs, r); write32(addr, val); @@ -1447,11 +1424,11 @@ opcode(struct regs *regs) case 0x8B: /* addr32 mov r/m16, r16 */ if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED) goto invalid; - if ((prefix & ADDR32) == 0) - goto invalid; - if (!movr(regs, prefix, opc)) - goto invalid; - return OPC_EMULATED; + if ((prefix & ADDR32) == 0) + goto invalid; + if (!movr(regs, prefix, opc)) + goto invalid; + return OPC_EMULATED; case 0x8E: /* mov r16, sreg */ if (!mov_to_seg(regs, prefix, opc)) @@ -1459,11 +1436,11 @@ opcode(struct regs *regs) return OPC_EMULATED; case 0x8F: /* addr32 pop r/m16 */ - if ((prefix & ADDR32) == 0) - goto invalid; - if (!pop(regs, prefix, opc)) - goto invalid; - return OPC_EMULATED; + if ((prefix & ADDR32) == 0) + goto invalid; + if (!pop(regs, prefix, opc)) + goto invalid; + return OPC_EMULATED; case 0x90: /* nop */ TRACE((regs, regs->eip - eip, "nop")); @@ -1487,7 +1464,7 @@ opcode(struct regs *regs) regs->eflags |= EFLAGS_VM; return OPC_EMULATED; - case 0xA1: /* mov ax, r/m16 */ + case 0xA1: /* mov ax, r/m16 */ { int addr, data; int seg = segment(prefix, regs, regs->vds); @@ -1521,15 +1498,15 @@ opcode(struct regs *regs) return OPC_EMULATED; case 0xC6: /* addr32 movb $imm, r/m8 */ - if ((prefix & ADDR32) == 0) - goto invalid; - if (!movr(regs, prefix, opc)) - goto invalid; + if ((prefix & ADDR32) == 0) + goto invalid; + if (!movr(regs, prefix, opc)) + goto invalid; return OPC_EMULATED; case 0xCB: /* retl */ if ((mode == VM86_REAL_TO_PROTECTED) || - (mode == VM86_PROTECTED_TO_REAL)) { + (mode == VM86_PROTECTED_TO_REAL)) { retl(regs, prefix); return OPC_INVALID; } @@ -1567,7 +1544,7 @@ opcode(struct regs *regs) case 0xEA: /* jmpl */ if ((mode == VM86_REAL_TO_PROTECTED) || - (mode == VM86_PROTECTED_TO_REAL)) { + (mode == VM86_PROTECTED_TO_REAL)) { jmpl(regs, prefix); return OPC_INVALID; } @@ -1579,7 +1556,7 @@ opcode(struct regs *regs) switch((modrm >> 3) & 7) { case 5: /* jmpl (indirect) */ if ((mode == VM86_REAL_TO_PROTECTED) || - (mode == VM86_PROTECTED_TO_REAL)) { + (mode == VM86_PROTECTED_TO_REAL)) { jmpl_indirect(regs, prefix, modrm); return OPC_INVALID; } @@ -1596,7 +1573,7 @@ opcode(struct regs *regs) case 0xEB: /* short jump */ if ((mode == VM86_REAL_TO_PROTECTED) || - (mode == VM86_PROTECTED_TO_REAL)) { + (mode == VM86_PROTECTED_TO_REAL)) { disp = (char) fetch8(regs); TRACE((regs, 2, "jmp 0x%x", regs->eip + disp)); regs->eip += disp; @@ -1619,10 +1596,10 @@ opcode(struct regs *regs) continue; case 0xF6: /* addr32 testb $imm, r/m8 */ - if ((prefix & ADDR32) == 0) - goto invalid; - if (!test(regs, prefix, opc)) - goto invalid; + if ((prefix & ADDR32) == 0) + goto invalid; + if (!test(regs, prefix, opc)) + goto invalid; return OPC_EMULATED; case 0xFA: /* cli */ @@ -1682,6 +1659,8 @@ trap(int trapno, int errno, struct regs *regs) case 1: /* Debug */ if (regs->eflags & EFLAGS_VM) { /* emulate any 8086 instructions */ + if (mode == VM86_REAL) + return; if (mode != VM86_REAL_TO_PROTECTED) panic("not in real-to-protected mode"); emulate(regs); @@ -1702,7 +1681,7 @@ trap(int trapno, int errno, struct regs *regs) default: invalid: printf("Trap (0x%x) while in %s mode\n", - trapno, regs->eflags & EFLAGS_VM ? "real" : "protected"); + trapno, regs->eflags & EFLAGS_VM ? "real" : "protected"); if (trapno == 14) printf("Page fault address 0x%x\n", get_cr2()); dump_regs(regs); From d3f023e9ade9d28b3af1e346c63f95e73ca345c0 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:22:26 +0000 Subject: [PATCH 31/69] [XEN] Make multiboot-related code more readable. Tested on i386 and x86_64 with GRUB and PXELINUX bootmanagers. From: Christoph Egger Signed-off-by: Keir Fraser --- xen/arch/x86/boot/x86_32.S | 9 ++++++--- xen/arch/x86/boot/x86_64.S | 9 ++++++--- xen/include/xen/multiboot.h | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/boot/x86_32.S b/xen/arch/x86/boot/x86_32.S index e0f2e09643..c3466dee5f 100644 --- a/xen/arch/x86/boot/x86_32.S +++ b/xen/arch/x86/boot/x86_32.S @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,12 +18,14 @@ ENTRY(_stext) .align 4 /*** MULTIBOOT HEADER ****/ +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \ + MULTIBOOT_HEADER_WANT_MEMORY) /* Magic number indicating a Multiboot header. */ - .long 0x1BADB002 + .long MULTIBOOT_HEADER_MAGIC /* Flags to bootloader (see Multiboot spec). */ - .long 0x00000003 + .long MULTIBOOT_HEADER_FLAGS /* Checksum: must be the negated sum of the first two fields. */ - .long -0x1BADB005 + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) not_multiboot_msg: .asciz "ERR: Not a Multiboot bootloader!" diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 5a8a111b59..ce0e42987c 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -19,12 +20,14 @@ ENTRY(_stext) .org 0x004 /*** MULTIBOOT HEADER ****/ +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \ + MULTIBOOT_HEADER_WANT_MEMORY) /* Magic number indicating a Multiboot header. */ - .long 0x1BADB002 + .long MULTIBOOT_HEADER_MAGIC /* Flags to bootloader (see Multiboot spec). */ - .long 0x00000003 + .long MULTIBOOT_HEADER_FLAGS /* Checksum: must be the negated sum of the first two fields. */ - .long -0x1BADB005 + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) .Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!" .Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!" diff --git a/xen/include/xen/multiboot.h b/xen/include/xen/multiboot.h index 9473404775..86b59db1fe 100644 --- a/xen/include/xen/multiboot.h +++ b/xen/include/xen/multiboot.h @@ -18,16 +18,30 @@ #ifndef __MULTIBOOT_H__ #define __MULTIBOOT_H__ + +/* + * Multiboot header structure. + */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_HEADER_MODS_ALIGNED 0x00000001 +#define MULTIBOOT_HEADER_WANT_MEMORY 0x00000002 +#define MULTIBOOT_HEADER_HAS_VBE 0x00000004 +#define MULTIBOOT_HEADER_HAS_ADDR 0x00010000 + /* The magic number passed by a Multiboot-compliant boot loader. */ -#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 #define MBI_MEMLIMITS (1<<0) #define MBI_DRIVES (1<<1) #define MBI_CMDLINE (1<<2) #define MBI_MODULES (1<<3) +#define MBI_AOUT_SYMS (1<<4) +#define MBI_ELF_SYMS (1<<5) #define MBI_MEMMAP (1<<6) #define MBI_LOADERNAME (1<<9) +#ifndef __ASSEMBLY__ + /* The symbol table for a.out. */ typedef struct { u32 tabsize; @@ -47,16 +61,28 @@ typedef struct { /* The Multiboot information. */ typedef struct { u32 flags; + + /* Valid if flags sets MBI_MEMLIMITS */ u32 mem_lower; u32 mem_upper; + + /* Valid if flags sets MBI_DRIVES */ u32 boot_device; + + /* Valid if flags sets MBI_CMDLINE */ u32 cmdline; + + /* Valid if flags sets MBI_MODULES */ u32 mods_count; u32 mods_addr; + + /* Valid if flags sets ... */ union { - aout_symbol_table_t aout_sym; - elf_section_header_table_t elf_sec; + aout_symbol_table_t aout_sym; /* ... MBI_AOUT_SYMS */ + elf_section_header_table_t elf_sec; /* ... MBI_ELF_SYMS */ } u; + + /* Valid if flags sets MBI_MEMMAP */ u32 mmap_length; u32 mmap_addr; } multiboot_info_t; @@ -80,4 +106,7 @@ typedef struct { u32 type; } memory_map_t; + +#endif /* __ASSEMBLY__ */ + #endif /* __MULTIBOOT_H__ */ From b07ced9c1fa55ffab47e3789af1a9f9ba672ef39 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:36:26 +0000 Subject: [PATCH 32/69] [LIBXC] Add an error reporting API to the libxc library. - An 'xc_error' struct is used to pass around error details. Currently contains two members 'code' an enumeration of error types, and 'message' a free text description of the specific problem. - The xc_get_last_error() method returns a const pointer to the internal instance of this struct manged by libxc. By returning a const pointer we can add extra members to the end of the struct at any time without worrying about ABI of callers. This will let us provide more fine-grained info if needed in the future. - The xc_error instance is statically defined inside libxc and marked __thread. This ensures that errors are recorded per-thread, and that when dealing with errors we never need to call malloc - all storage needed is statically allocated. - The xc_clear_last_error() method resets any currently recorded error details - The xc_error_code_to_desc() method converts the integer error code into a generic user facing messsage. eg "Invalid kernel". Together with the 'message' field from xc_error, this provides the user visible feedback. eg "Invalid kernel: Non PAE-kernel on PAE host." - A callback can be registered with xc_set_error_handler to receive notification whenever an error is recorded, rather than querying for error details after the fact with xc_get_last_error - If built with -DDEBUG set, a default error handler will be registered which calls fprintf(stderr), thus maintaining current behaviour of logging errors to stderr during developer builds. - The python binding for libxc is updated to use xc_get_last_error to pull out error details whenever appropriate, instead of returning info based on 'errno' - The xc_set_error method is private to libxc internals, and is used for setting error details - The ERROR and PERROR macros have been updated to call xc_set_error automatically specifying XC_INTERNAL_ERROR as the error code. This gives a generic error report for all current failure points - Some uses of the ERROR macro have been replaced with explicit calls to xc_set_error to enable finer grained error reporting. In particular the code dealing with invalid kernel types uses this to report about PAE/architecture/wordsize mismatches The patch has been tested by calling xm create against a varietry of config files defining invalid kernels of various kinds. It has also been tested with libvirt talking to xend. In both cases the error messages were propagated all the way back up the stack. There is only one place where I need to do further work. The suspend & restore APIs in Xend invoke external helper programs rather than calling libxc directly. This means that error details are essentially lost. Since there is already code in XenD which scans STDERR from these programs I will investigate adapting this to extract actual error messages from these helpers. Signed-off-by: Daniel P. Berrange --- tools/libxc/xc_hvm_build.c | 16 +++-- tools/libxc/xc_linux_build.c | 12 ++-- tools/libxc/xc_load_elf.c | 95 +++++++++++++++++++++------ tools/libxc/xc_private.c | 76 ++++++++++++++++++++++ tools/libxc/xc_private.h | 19 ++---- tools/libxc/xenctrl.h | 42 ++++++++++++ tools/python/xen/lowlevel/xc/xc.c | 104 +++++++++++++++++------------- 7 files changed, 275 insertions(+), 89 deletions(-) diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 1c038755cd..21e20ffaf9 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -285,7 +285,6 @@ static int xc_hvm_build_internal(int xc_handle, if ( setup_guest(xc_handle, domid, memsize, image, image_size, &ctxt) < 0 ) { - ERROR("Error constructing guest OS"); goto error_out; } @@ -329,26 +328,30 @@ static int parseelfimage(char *elfbase, if ( !IS_ELF(*ehdr) ) { - ERROR("Kernel image does not have an ELF header."); + xc_set_error(XC_INVALID_KERNEL, + "Kernel image does not have an ELF header."); return -EINVAL; } if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize ) { - ERROR("ELF program headers extend beyond end of image."); + xc_set_error(XC_INVALID_KERNEL, + "ELF program headers extend beyond end of image."); return -EINVAL; } if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize ) { - ERROR("ELF section headers extend beyond end of image."); + xc_set_error(XC_INVALID_KERNEL, + "ELF section headers extend beyond end of image."); return -EINVAL; } /* Find the section-header strings table. */ if ( ehdr->e_shstrndx == SHN_UNDEF ) { - ERROR("ELF image has no section-header strings table (shstrtab)."); + xc_set_error(XC_INVALID_KERNEL, + "ELF image has no section-header strings table (shstrtab)."); return -EINVAL; } shdr = (Elf32_Shdr *)(elfbase + ehdr->e_shoff + @@ -370,7 +373,8 @@ static int parseelfimage(char *elfbase, (ehdr->e_entry < kernstart) || (ehdr->e_entry > kernend) ) { - ERROR("Malformed ELF image."); + xc_set_error(XC_INVALID_KERNEL, + "Malformed ELF image."); return -EINVAL; } diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 9bd4a5e3f4..edf95c0fc0 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -120,7 +120,7 @@ static int probeimageformat(const char *image, if ( probe_elf(image, image_size, load_funcs) && probe_bin(image, image_size, load_funcs) ) { - ERROR( "Unrecognized image format" ); + xc_set_error(XC_INVALID_KERNEL, "Not a valid ELF or raw kernel image"); return -EINVAL; } @@ -618,17 +618,20 @@ static int compat_check(int xc_handle, struct domain_setup_info *dsi) xen_capabilities_info_t xen_caps = ""; if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) { - ERROR("Cannot determine host capabilities."); + xc_set_error(XC_INVALID_KERNEL, + "Cannot determine host capabilities."); return 0; } if (strstr(xen_caps, "xen-3.0-x86_32p")) { if (dsi->pae_kernel == PAEKERN_no) { - ERROR("Non PAE-kernel on PAE host."); + xc_set_error(XC_INVALID_KERNEL, + "Non PAE-kernel on PAE host."); return 0; } } else if (dsi->pae_kernel != PAEKERN_no) { - ERROR("PAE-kernel on non-PAE host."); + xc_set_error(XC_INVALID_KERNEL, + "PAE-kernel on non-PAE host."); return 0; } @@ -1141,7 +1144,6 @@ static int xc_linux_build_internal(int xc_handle, console_evtchn, console_mfn, features_bitmap) < 0 ) { - ERROR("Error constructing guest OS"); goto error_out; } diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c index 9ca9759398..f8a28fb83c 100644 --- a/tools/libxc/xc_load_elf.c +++ b/tools/libxc/xc_load_elf.c @@ -29,20 +29,46 @@ loadelfsymtab( */ #if defined(__ia64__) #define ELFCLASS ELFCLASS64 +#define ELFCLASS_DESC "64-bit" + #define ELFDATA ELFDATA2LSB +#define ELFDATA_DESC "Little-Endian" + #define ELFMACHINE EM_IA_64 +#define ELFMACHINE_DESC "ia64" + + #elif defined(__i386__) #define ELFCLASS ELFCLASS32 +#define ELFCLASS_DESC "32-bit" + #define ELFDATA ELFDATA2LSB +#define ELFDATA_DESC "Little-Endian" + #define ELFMACHINE EM_386 +#define ELFMACHINE_DESC "i386" + + #elif defined(__x86_64__) #define ELFCLASS ELFCLASS64 +#define ELFCLASS_DESC "64-bit" + #define ELFDATA ELFDATA2LSB +#define ELFDATA_DESC "Little-Endian" + #define ELFMACHINE EM_X86_64 +#define ELFMACHINE_DESC "x86_64" + + #elif defined(__powerpc__) #define ELFCLASS ELFCLASS64 +#define ELFCLASS_DESC "64-bit" + #define ELFDATA ELFDATA2MSB +#define ELFDATA_DESC "Big-Endian" + #define ELFMACHINE EM_PPC64 +#define ELFMACHINE_DESC "ppc64" #endif int probe_elf(const char *image, @@ -231,7 +257,8 @@ unsigned long long xen_elfnote_numeric(struct domain_setup_info *dsi, *defined = 1; return *(uint64_t*)ELFNOTE_DESC(note); default: - ERROR("elfnotes: unknown data size %#x for numeric type note %#x\n", + xc_set_error(XC_INVALID_KERNEL, + "elfnotes: unknown data size %#x for numeric type note %#x\n", note->descsz, type); return 0; } @@ -250,35 +277,59 @@ static int parseelfimage(const char *image, if ( !IS_ELF(*ehdr) ) { - ERROR("Kernel image does not have an ELF header."); + xc_set_error(XC_INVALID_KERNEL, + "Kernel image does not have an ELF header."); return -EINVAL; } - if ( (ehdr->e_ident[EI_CLASS] != ELFCLASS) || - (ehdr->e_machine != ELFMACHINE) || - (ehdr->e_ident[EI_DATA] != ELFDATA) || - (ehdr->e_type != ET_EXEC) ) + if (ehdr->e_machine != ELFMACHINE) { - ERROR("Kernel not a Xen-compatible Elf image."); + xc_set_error(XC_INVALID_KERNEL, + "Kernel ELF architecture '%d' does not match Xen architecture '%d' (%s)", + ehdr->e_machine, ELFMACHINE, ELFMACHINE_DESC); + return -EINVAL; + } + if (ehdr->e_ident[EI_CLASS] != ELFCLASS) + { + xc_set_error(XC_INVALID_KERNEL, + "Kernel ELF wordsize '%d' does not match Xen wordsize '%d' (%s)", + ehdr->e_ident[EI_CLASS], ELFCLASS, ELFCLASS_DESC); + return -EINVAL; + } + if (ehdr->e_ident[EI_DATA] != ELFDATA) + { + xc_set_error(XC_INVALID_KERNEL, + "Kernel ELF endianness '%d' does not match Xen endianness '%d' (%s)", + ehdr->e_ident[EI_DATA], ELFDATA, ELFDATA_DESC); + return -EINVAL; + } + if (ehdr->e_type != ET_EXEC) + { + xc_set_error(XC_INVALID_KERNEL, + "Kernel ELF type '%d' does not match Xen type '%d'", + ehdr->e_type, ET_EXEC); return -EINVAL; } if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len ) { - ERROR("ELF program headers extend beyond end of image."); + xc_set_error(XC_INVALID_KERNEL, + "ELF program headers extend beyond end of image."); return -EINVAL; } if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len ) { - ERROR("ELF section headers extend beyond end of image."); + xc_set_error(XC_INVALID_KERNEL, + "ELF section headers extend beyond end of image."); return -EINVAL; } /* Find the section-header strings table. */ if ( ehdr->e_shstrndx == SHN_UNDEF ) { - ERROR("ELF image has no section-header strings table (shstrtab)."); + xc_set_error(XC_INVALID_KERNEL, + "ELF image has no section-header strings table (shstrtab)."); return -EINVAL; } shdr = (Elf_Shdr *)(image + ehdr->e_shoff + @@ -325,22 +376,25 @@ static int parseelfimage(const char *image, if ( ( loader == NULL || strncmp(loader, "generic", 7) ) && ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) ) { - ERROR("Will only load images built for the generic loader " - "or Linux images"); + xc_set_error(XC_INVALID_KERNEL, + "Will only load images built for the generic loader " + "or Linux images"); return -EINVAL; } if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) ) { - ERROR("Will only load images built for Xen v3.0"); + xc_set_error(XC_INVALID_KERNEL, + "Will only load images built for Xen v3.0"); return -EINVAL; } } else { #if defined(__x86_64__) || defined(__i386__) - ERROR("Not a Xen-ELF image: " - "No ELF notes or '__xen_guest' section found."); + xc_set_error(XC_INVALID_KERNEL, + "Not a Xen-ELF image: " + "No ELF notes or '__xen_guest' section found."); return -EINVAL; #endif } @@ -396,8 +450,9 @@ static int parseelfimage(const char *image, if ( elf_pa_off_defined && !virt_base_defined ) { - ERROR("Neither ELF_PADDR_OFFSET nor VIRT_BASE found in ELF " - " notes or __xen_guest section."); + xc_set_error(XC_INVALID_KERNEL, + "Neither ELF_PADDR_OFFSET nor VIRT_BASE found in ELF " + " notes or __xen_guest section."); return -EINVAL; } @@ -409,7 +464,8 @@ static int parseelfimage(const char *image, vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start; if ( (vaddr + phdr->p_memsz) < vaddr ) { - ERROR("ELF program header %d is too large.", h); + xc_set_error(XC_INVALID_KERNEL, + "ELF program header %d is too large.", h); return -EINVAL; } @@ -431,7 +487,8 @@ static int parseelfimage(const char *image, (dsi->v_kernentry > kernend) || (dsi->v_start > kernstart) ) { - ERROR("ELF start or entries are out of bounds."); + xc_set_error(XC_INVALID_KERNEL, + "ELF start or entries are out of bounds."); return -EINVAL; } diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index d8dbb5e0dd..3ff0b791d0 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -8,6 +8,82 @@ #include "xc_private.h" #include "xg_private.h" +#include + +static __thread xc_error last_error = { XC_ERROR_NONE, ""}; +#if DEBUG +static xc_error_handler error_handler = xc_default_error_handler; +#else +static xc_error_handler error_handler = NULL; +#endif + +void xc_default_error_handler(const xc_error const *err) +{ + const char *desc = xc_error_code_to_desc(err->code); + fprintf(stderr, "ERROR %s: %s\n", desc, err->message); +} + +const xc_error const *xc_get_last_error(void) +{ + return &last_error; +} + +void xc_clear_last_error(void) +{ + last_error.code = XC_ERROR_NONE; + last_error.message[0] = '\0'; +} + +const char *xc_error_code_to_desc(int code) +{ + /* Sync to members of xc_error_code enumeration in xenctrl.h */ + switch ( code ) + { + case XC_ERROR_NONE: + return "No error details"; + case XC_INTERNAL_ERROR: + return "Internal error"; + case XC_INVALID_KERNEL: + return "Invalid kernel"; + } + + return "Unknown error code"; +} + +xc_error_handler xc_set_error_handler(xc_error_handler handler) +{ + xc_error_handler old = error_handler; + error_handler = handler; + return old; +} + + +static void _xc_set_error(int code, const char *msg) +{ + last_error.code = code; + strncpy(last_error.message, msg, XC_MAX_ERROR_MSG_LEN - 1); + last_error.message[XC_MAX_ERROR_MSG_LEN-1] = '\0'; +} + +void xc_set_error(int code, const char *fmt, ...) +{ + int saved_errno = errno; + char msg[XC_MAX_ERROR_MSG_LEN]; + va_list args; + + va_start(args, fmt); + vsnprintf(msg, XC_MAX_ERROR_MSG_LEN-1, fmt, args); + msg[XC_MAX_ERROR_MSG_LEN-1] = '\0'; + va_end(args); + + _xc_set_error(code, msg); + + errno = saved_errno; + + if ( error_handler != NULL ) + error_handler(&last_error); +} + int lock_pages(void *addr, size_t len) { int e = 0; diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 20f7a9b445..2ddec3f988 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -59,24 +59,15 @@ #define PPRINTF(_f, _a...) #endif -#define ERROR(_m, _a...) \ -do { \ - int __saved_errno = errno; \ - DPRINTF("ERROR: " _m "\n" , ## _a ); \ - errno = __saved_errno; \ -} while (0) +void xc_set_error(int code, const char *fmt, ...); + +#define ERROR(_m, _a...) xc_set_error(XC_INTERNAL_ERROR, _m , ## _a ) +#define PERROR(_m, _a...) xc_set_error(XC_INTERNAL_ERROR, _m " (%d = %s)", \ + _m , ## _a , errno, strerror(errno)) int lock_pages(void *addr, size_t len); void unlock_pages(void *addr, size_t len); -#define PERROR(_m, _a...) \ -do { \ - int __saved_errno = errno; \ - DPRINTF("ERROR: " _m " (%d = %s)\n" , ## _a , \ - __saved_errno, strerror(__saved_errno)); \ - errno = __saved_errno; \ -} while (0) - static inline void safe_munlock(const void *addr, size_t len) { int saved_errno = errno; diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 3904cede84..d0a9f5db97 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -682,4 +682,46 @@ int xc_hvm_set_isa_irq_level( int xc_hvm_set_pci_link_route( int xc_handle, domid_t dom, uint8_t link, uint8_t isa_irq); + +typedef enum { + XC_ERROR_NONE = 0, + XC_INTERNAL_ERROR = 1, + XC_INVALID_KERNEL = 2, +} xc_error_code; + +#define XC_MAX_ERROR_MSG_LEN 1024 +typedef struct { + int code; + char message[XC_MAX_ERROR_MSG_LEN]; +} xc_error; + +/* + * Return a pointer to the last error. This pointer and the + * data pointed to are only valid until the next call to + * libxc. + */ +const xc_error const *xc_get_last_error(void); + +/* + * Clear the last error + */ +void xc_clear_last_error(void); + +typedef void (*xc_error_handler)(const xc_error const* err); + +/* + * The default error handler which prints to stderr + */ +void xc_default_error_handler(const xc_error const* err); + +/* + * Convert an error code into a text description + */ +const char *xc_error_code_to_desc(int code); + +/* + * Registers a callback to handle errors + */ +xc_error_handler xc_set_error_handler(xc_error_handler handler); + #endif diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 2eb9376426..be02bf8ed8 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -29,7 +29,7 @@ #define PKG "xen.lowlevel.xc" #define CLS "xc" -static PyObject *xc_error, *zero; +static PyObject *xc_error_obj, *zero; typedef struct { PyObject_HEAD; @@ -40,6 +40,23 @@ typedef struct { static PyObject *dom_op(XcObject *self, PyObject *args, int (*fn)(int, uint32_t)); +static PyObject *pyxc_error_to_exception(void) +{ + PyObject *pyerr; + const xc_error const *err = xc_get_last_error(); + const char *desc = xc_error_code_to_desc(err->code); + + if (err->message[1]) + pyerr = Py_BuildValue("(iss)", err->code, desc, err->message); + else + pyerr = Py_BuildValue("(is)", err->code, desc); + + xc_clear_last_error(); + + PyErr_SetObject(xc_error_obj, pyerr); + + return NULL; +} static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args) { @@ -53,7 +70,7 @@ static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args) return NULL; if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -101,13 +118,13 @@ static PyObject *pyxc_domain_create(XcObject *self, if ( (ret = xc_domain_create(self->xc_handle, ssidref, handle, flags, &dom)) < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); return PyInt_FromLong(dom); out_exception: errno = EINVAL; - PyErr_SetFromErrno(xc_error); + PyErr_SetFromErrno(xc_error_obj); return NULL; } @@ -119,7 +136,7 @@ static PyObject *pyxc_domain_max_vcpus(XcObject *self, PyObject *args) return NULL; if (xc_domain_max_vcpus(self->xc_handle, dom, max) != 0) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -164,7 +181,7 @@ static PyObject *pyxc_vcpu_setaffinity(XcObject *self, } if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -184,7 +201,7 @@ static PyObject *pyxc_domain_setcpuweight(XcObject *self, return NULL; if ( xc_domain_setcpuweight(self->xc_handle, dom, cpuweight) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -215,14 +232,13 @@ static PyObject *pyxc_domain_sethandle(XcObject *self, PyObject *args) } if (xc_domain_sethandle(self->xc_handle, dom, handle) < 0) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; out_exception: - errno = EINVAL; - PyErr_SetFromErrno(xc_error); + PyErr_SetFromErrno(xc_error_obj); return NULL; } @@ -251,7 +267,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, if (nr_doms < 0) { free(info); - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); } list = PyList_New(nr_doms); @@ -306,10 +322,10 @@ static PyObject *pyxc_vcpu_getinfo(XcObject *self, rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info); if ( rc < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); rc = xc_vcpu_getaffinity(self->xc_handle, dom, vcpu, &cpumap); if ( rc < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); info_dict = Py_BuildValue("{s:i,s:i,s:i,s:L,s:i}", "online", info.online, @@ -360,9 +376,7 @@ static PyObject *pyxc_linux_build(XcObject *self, ramdisk, cmdline, features, flags, store_evtchn, &store_mfn, console_evtchn, &console_mfn) != 0 ) { - if (!errno) - errno = EINVAL; - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); } return Py_BuildValue("{s:i,s:i}", "store_mfn", store_mfn, @@ -389,14 +403,14 @@ static PyObject *pyxc_hvm_build(XcObject *self, return NULL; if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); /* Set up the HVM info table. */ va_map = xc_map_foreign_range(self->xc_handle, dom, XC_PAGE_SIZE, PROT_READ | PROT_WRITE, HVM_INFO_PFN); if ( va_map == NULL ) - return PyErr_SetFromErrno(xc_error); + return PyErr_SetFromErrno(xc_error_obj); va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET); memset(va_hvm, 0, sizeof(*va_hvm)); strncpy(va_hvm->signature, "HVM INFO", 8); @@ -431,7 +445,7 @@ static PyObject *pyxc_evtchn_alloc_unbound(XcObject *self, return NULL; if ( (port = xc_evtchn_alloc_unbound(self->xc_handle, dom, remote_dom)) < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); return PyInt_FromLong(port); } @@ -452,7 +466,7 @@ static PyObject *pyxc_physdev_pci_access_modify(XcObject *self, ret = xc_physdev_pci_access_modify( self->xc_handle, dom, bus, dev, func, enable); if ( ret != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -474,7 +488,7 @@ static PyObject *pyxc_readconsolering(XcObject *self, ret = xc_readconsolering(self->xc_handle, &str, &count, clear); if ( ret < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); return PyString_FromStringAndSize(str, count); } @@ -504,7 +518,7 @@ static PyObject *pyxc_physinfo(XcObject *self) int i; if ( xc_physinfo(self->xc_handle, &info) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); *q=0; for(i=0;ixc_handle, XENVER_version, NULL); if ( xc_version(self->xc_handle, XENVER_extraversion, &xen_extra) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); if ( xc_version(self->xc_handle, XENVER_compile_info, &xen_cc) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); if ( xc_version(self->xc_handle, XENVER_changeset, &xen_chgset) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); if ( xc_version(self->xc_handle, XENVER_capabilities, &xen_caps) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); if ( xc_version(self->xc_handle, XENVER_platform_parameters, &p_parms) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); sprintf(str, "virt_start=0x%lx", p_parms.virt_start); xen_pagesize = xc_version(self->xc_handle, XENVER_pagesize, NULL); if (xen_pagesize < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); return Py_BuildValue("{s:i,s:i,s:s,s:s,s:i,s:s,s:s,s:s,s:s,s:s,s:s}", "xen_major", xen_version >> 16, @@ -593,7 +607,7 @@ static PyObject *pyxc_sedf_domain_set(XcObject *self, return NULL; if ( xc_sedf_domain_set(self->xc_handle, domid, period, slice, latency, extratime,weight) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -610,7 +624,7 @@ static PyObject *pyxc_sedf_domain_get(XcObject *self, PyObject *args) if (xc_sedf_domain_get(self->xc_handle, domid, &period, &slice,&latency,&extratime,&weight)) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i,s:i}", "domid", domid, @@ -638,7 +652,7 @@ static PyObject *pyxc_shadow_control(PyObject *self, if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL, 0, NULL) < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -668,7 +682,7 @@ static PyObject *pyxc_shadow_mem_control(PyObject *self, op = XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION; } if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, &mb, 0, NULL) < 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); mbarg = mb; return Py_BuildValue("i", mbarg); @@ -678,7 +692,7 @@ static PyObject *pyxc_sched_id_get(XcObject *self) { int sched_id; if (xc_sched_id(self->xc_handle, &sched_id) != 0) - return PyErr_SetFromErrno(xc_error); + return PyErr_SetFromErrno(xc_error_obj); return Py_BuildValue("i", sched_id); } @@ -704,7 +718,7 @@ static PyObject *pyxc_sched_credit_domain_set(XcObject *self, sdom.cap = cap; if ( xc_sched_credit_domain_set(self->xc_handle, domid, &sdom) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -719,7 +733,7 @@ static PyObject *pyxc_sched_credit_domain_get(XcObject *self, PyObject *args) return NULL; if ( xc_sched_credit_domain_get(self->xc_handle, domid, &sdom) != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); return Py_BuildValue("{s:H,s:H}", "weight", sdom.weight, @@ -735,7 +749,7 @@ static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args) return NULL; if (xc_domain_setmaxmem(self->xc_handle, dom, maxmem_kb) != 0) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -762,7 +776,7 @@ static PyObject *pyxc_domain_memory_increase_reservation(XcObject *self, if ( xc_domain_memory_increase_reservation(self->xc_handle, dom, nr_extents, extent_order, address_bits, NULL) ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -784,7 +798,7 @@ static PyObject *pyxc_domain_ioport_permission(XcObject *self, ret = xc_domain_ioport_permission( self->xc_handle, dom, first_port, nr_ports, allow_access); if ( ret != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -807,7 +821,7 @@ static PyObject *pyxc_domain_irq_permission(PyObject *self, ret = xc_domain_irq_permission( xc->xc_handle, dom, pirq, allow_access); if ( ret != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -830,7 +844,7 @@ static PyObject *pyxc_domain_iomem_permission(PyObject *self, ret = xc_domain_iomem_permission( xc->xc_handle, dom, first_pfn, nr_pfns, allow_access); if ( ret != 0 ) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -870,7 +884,7 @@ static PyObject *dom_op(XcObject *self, PyObject *args, return NULL; if (fn(self->xc_handle, dom) != 0) - return PyErr_SetFromErrno(xc_error); + return pyxc_error_to_exception(); Py_INCREF(zero); return zero; @@ -1199,7 +1213,7 @@ static int PyXc_init(XcObject *self, PyObject *args, PyObject *kwds) { if ((self->xc_handle = xc_interface_open()) == -1) { - PyErr_SetFromErrno(xc_error); + pyxc_error_to_exception(); return -1; } @@ -1272,7 +1286,7 @@ PyMODINIT_FUNC initxc(void) if (m == NULL) return; - xc_error = PyErr_NewException(PKG ".Error", PyExc_RuntimeError, NULL); + xc_error_obj = PyErr_NewException(PKG ".Error", PyExc_RuntimeError, NULL); zero = PyInt_FromLong(0); /* KAF: This ensures that we get debug output in a timely manner. */ @@ -1282,8 +1296,8 @@ PyMODINIT_FUNC initxc(void) Py_INCREF(&PyXcType); PyModule_AddObject(m, CLS, (PyObject *)&PyXcType); - Py_INCREF(xc_error); - PyModule_AddObject(m, "Error", xc_error); + Py_INCREF(xc_error_obj); + PyModule_AddObject(m, "Error", xc_error_obj); /* Expose some libxc constants to Python */ PyModule_AddIntConstant(m, "XEN_SCHEDULER_SEDF", XEN_SCHEDULER_SEDF); From 4393b66b51c32e1d32a4369337bb6c2e21d0979a Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 11:41:38 +0000 Subject: [PATCH 33/69] [XEND] Fix configureBootloader to work with HTTP/SEXP. Signed-off-by: Daniel P. Berrange --- tools/python/xen/xend/XendConfig.py | 1 + tools/python/xen/xend/XendDomainInfo.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 7f0da37653..1f5571b8ba 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -680,6 +680,7 @@ class XendConfig(dict): else: self[sxp_arg] = val + _set_cfg_if_exists('bootloader') _set_cfg_if_exists('shadow_memory') _set_cfg_if_exists('security') _set_cfg_if_exists('features') diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 5488b17f8f..5fda486555 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1326,7 +1326,7 @@ class XendDomainInfo: # if we have a boot loader but no image, then we need to set things # up by running the boot loader non-interactively - if self.info.get('bootloader') and self.info.get('image'): + if self.info.get('bootloader'): self._configureBootloader() if not self._infoIsSet('image'): @@ -1532,11 +1532,17 @@ class XendDomainInfo: if not self.info.get('bootloader'): return blcfg = None + # FIXME: this assumes that we want to use the first disk device - for devuuid, (devtype, devinfo) in self.info.all_devices_sxpr(): + for (devtype, devinfo) in self.info.all_devices_sxpr(): if not devtype or not devinfo or devtype not in ('vbd', 'tap'): continue - disk = devinfo.get('uname') + disk = None + for param in devinfo: + if param[0] == 'uname': + disk = param[1] + break + if disk is None: continue fn = blkdev_uname_to_file(disk) From 99280a4af4eae8ec995fb16d1115229511186690 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 7 Dec 2006 11:43:19 +0000 Subject: [PATCH 34/69] Remove unused KEXEC_RANGE_VA_XEN. KEXEC_RANGE_VA_XEN is currently unused and there is no point in exporting it. Signed-Off-By: Magnus Damm --- Applies to xen-unstable-12756 xen/common/kexec.c | 13 +++---------- xen/include/public/kexec.h | 3 +-- 2 files changed, 4 insertions(+), 12 deletions(-) --- xen/common/kexec.c | 13 +++---------- xen/include/public/kexec.h | 3 +-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/xen/common/kexec.c b/xen/common/kexec.c index 2f8b8e0de3..885afae80c 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -160,13 +160,9 @@ static int kexec_get_reserve(xen_kexec_range_t *range) extern unsigned long _text; -static int kexec_get_xen(xen_kexec_range_t *range, int get_ma) +static int kexec_get_xen(xen_kexec_range_t *range) { - if ( get_ma ) - range->start = virt_to_maddr(&_text); - else - range->start = (unsigned long) &_text; - + range->start = virt_to_maddr(&_text); range->size = (unsigned long)&_end - (unsigned long)&_text; return 0; } @@ -195,10 +191,7 @@ static int kexec_get_range(XEN_GUEST_HANDLE(void) uarg) ret = kexec_get_reserve(&range); break; case KEXEC_RANGE_MA_XEN: - ret = kexec_get_xen(&range, 1); - break; - case KEXEC_RANGE_VA_XEN: - ret = kexec_get_xen(&range, 0); + ret = kexec_get_xen(&range); break; case KEXEC_RANGE_MA_CPU: ret = kexec_get_cpu(&range); diff --git a/xen/include/public/kexec.h b/xen/include/public/kexec.h index 556aaecb3d..ca6e85b701 100644 --- a/xen/include/public/kexec.h +++ b/xen/include/public/kexec.h @@ -107,8 +107,7 @@ typedef struct xen_kexec_load { #define KEXEC_RANGE_MA_CRASH 0 /* machine address and size of crash area */ #define KEXEC_RANGE_MA_XEN 1 /* machine address and size of Xen itself */ -#define KEXEC_RANGE_VA_XEN 2 /* virtual adrress and size of Xen itself */ -#define KEXEC_RANGE_MA_CPU 3 /* machine address and size of a CPU note */ +#define KEXEC_RANGE_MA_CPU 2 /* machine address and size of a CPU note */ /* * Find the address and size of certain memory areas From df8016fc0b5f1694e0207b445780ffb2bf2155f1 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 11:45:04 +0000 Subject: [PATCH 35/69] Remove broken call to XendDomainInfo.getSsidref(), fixing the obsolete HTTP server. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/server/SrvDomainDir.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py index fe97b29aef..a134d5cbd9 100644 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ b/tools/python/xen/xend/server/SrvDomainDir.py @@ -165,10 +165,9 @@ class SrvDomainDir(SrvDir): req.write('
    ') for d in domains: req.write( - '
  • Domain %s: id = %s, memory = %d, ' - 'ssidref = %d.' + '
  • Domain %s: id = %s, memory = %d' % (url, d.getName(), d.getName(), d.getDomid(), - d.getMemoryTarget(), d.getSsidref())) + d.getMemoryTarget())) req.write('
  • ') req.write('
') From 3679c60f52c2dd0dd797269f7fcf61ffab8a64dd Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:46:07 +0000 Subject: [PATCH 36/69] [LIBXC] Python error extraction tweak. Signed-off-by: Keir Fraser --- tools/python/xen/lowlevel/xc/xc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index be02bf8ed8..e74a882fe0 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -46,7 +46,10 @@ static PyObject *pyxc_error_to_exception(void) const xc_error const *err = xc_get_last_error(); const char *desc = xc_error_code_to_desc(err->code); - if (err->message[1]) + if (err->code == XC_ERROR_NONE) + return PyErr_SetFromErrno(xc_error_obj); + + if (err->message[0] != '\0') pyerr = Py_BuildValue("(iss)", err->code, desc, err->message); else pyerr = Py_BuildValue("(is)", err->code, desc); From 948c26c48dfd89eaae34f29788ca63321be3b41f Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 11:50:11 +0000 Subject: [PATCH 37/69] [XM] Fix xm uptime TypeError exception. Signed-off-by: Masaki Kanno --- tools/python/xen/xm/main.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 95cbda9033..9151848d30 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -30,6 +30,7 @@ import socket import traceback import xmlrpclib import traceback +import time import datetime from select import select import xml.dom.minidom @@ -626,7 +627,13 @@ def parse_doms_info(info): def get_status(n, t, d): return DOM_STATES[t(sxp.child_value(info, n, d))] - + + start_time = get_info('start_time', float, -1) + if start_time == -1: + up_time = float(-1) + else: + up_time = time.time() - start_time + return { 'domid' : get_info('domid', str, ''), 'name' : get_info('name', str, '??'), @@ -634,7 +641,7 @@ def parse_doms_info(info): 'vcpus' : get_info('vcpus', int, 0), 'state' : get_info('state', str, ''), 'cpu_time' : get_info('cpu_time', float, 0), - 'up_time' : get_info('up_time', float, -1), + 'up_time' : up_time, 'seclabel' : security.get_security_printlabel(info), } @@ -1209,7 +1216,7 @@ def xm_uptime(args): for dom in doms: d = parse_doms_info(dom) - if d['domid'] > 0: + if int(d['domid']) > 0: uptime = int(round(d['up_time'])) else: f=open('/proc/uptime', 'r') @@ -1236,10 +1243,10 @@ def xm_uptime(args): if short_mode: now = datetime.datetime.now() upstring = now.strftime(" %H:%M:%S") + " up " + upstring - upstring += ", " + d['name'] + " (" + str(d['domid']) + ")" + upstring += ", " + d['name'] + " (" + d['domid'] + ")" else: upstring += ':%(seconds)02d' % vars() - upstring = ("%(name)-32s %(domid)3d " % d) + upstring + upstring = ("%(name)-32s %(domid)3s " % d) + upstring print upstring From 0bbc8c5421bea9062a7c8db102b635d24984a612 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 11:52:26 +0000 Subject: [PATCH 38/69] [HVM] qemu mouse: Adds support for USB mouse/tablet status check and restricts Universal Host Controller interrupt generating when received NAK in interrupt transfer. According to usb spec, USB mouse/tablet device returns NAK to host controller if its status does not alter in interrupt transfer. And UHC should leave a TD active when receiving NAK and execute this incompleted TD in a subseqent frame. UHC only generates an interrupt on complete after the TD with ICO bit is completed. This patch make UHC & USB mouse/tablet behave consistently with spec. Signed-off-by: Xinmei Huang --- tools/ioemu/hw/usb-hid.c | 19 +++++++++++++++---- tools/ioemu/hw/usb-uhci.c | 36 ++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/tools/ioemu/hw/usb-hid.c b/tools/ioemu/hw/usb-hid.c index 8fc0b744b7..60849a4ed0 100644 --- a/tools/ioemu/hw/usb-hid.c +++ b/tools/ioemu/hw/usb-hid.c @@ -39,6 +39,7 @@ typedef struct USBMouseState { int x, y; int kind; int mouse_grabbed; + int status_changed; } USBMouseState; /* mostly the same values as the Bochs USB Mouse device */ @@ -231,6 +232,7 @@ static void usb_mouse_event(void *opaque, s->dy += dy1; s->dz += dz1; s->buttons_state = buttons_state; + s->status_changed = 1; } static void usb_tablet_event(void *opaque, @@ -242,6 +244,7 @@ static void usb_tablet_event(void *opaque, s->y = y; s->dz += dz; s->buttons_state = buttons_state; + s->status_changed = 1; } static inline int int_clamp(int val, int vmin, int vmax) @@ -483,10 +486,16 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid, switch(pid) { case USB_TOKEN_IN: if (devep == 1) { - if (s->kind == USB_MOUSE) - ret = usb_mouse_poll(s, data, len); - else if (s->kind == USB_TABLET) - ret = usb_tablet_poll(s, data, len); + if (s->kind == USB_MOUSE) + ret = usb_mouse_poll(s, data, len); + else if (s->kind == USB_TABLET) + ret = usb_tablet_poll(s, data, len); + + if (!s->status_changed) + ret = USB_RET_NAK; + else + s->status_changed = 0; + } else { goto fail; } @@ -523,6 +532,7 @@ USBDevice *usb_tablet_init(void) s->dev.handle_data = usb_mouse_handle_data; s->dev.handle_destroy = usb_mouse_handle_destroy; s->kind = USB_TABLET; + s->status_changed = 0; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); @@ -544,6 +554,7 @@ USBDevice *usb_mouse_init(void) s->dev.handle_data = usb_mouse_handle_data; s->dev.handle_destroy = usb_mouse_handle_destroy; s->kind = USB_MOUSE; + s->status_changed = 0; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); diff --git a/tools/ioemu/hw/usb-uhci.c b/tools/ioemu/hw/usb-uhci.c index 4b8db28717..9503c51c3e 100644 --- a/tools/ioemu/hw/usb-uhci.c +++ b/tools/ioemu/hw/usb-uhci.c @@ -424,12 +424,10 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask) uint8_t buf[2048]; int len, max_len, err, ret; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; + if (!(td->ctrl & TD_CTRL_ACTIVE)){ + ret = 1; + goto out; } - - if (!(td->ctrl & TD_CTRL_ACTIVE)) - return 1; /* TD is active */ max_len = ((td->token >> 21) + 1) & 0x7ff; @@ -467,7 +465,8 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask) /* invalid pid : frame interrupted */ s->status |= UHCI_STS_HCPERR; uhci_update_irq(s); - return -1; + ret = -1; + goto out; } if (td->ctrl & TD_CTRL_IOS) td->ctrl &= ~TD_CTRL_ACTIVE; @@ -479,10 +478,12 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask) len < max_len) { *int_mask |= 0x02; /* short packet: do not update QH */ - return 1; + ret = 1; + goto out; } else { /* success */ - return 0; + ret = 0; + goto out; } } else { switch(ret) { @@ -501,23 +502,34 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask) } td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | (err << TD_CTRL_ERROR_SHIFT); - return 1; + ret = 1; + goto out; case USB_RET_NAK: td->ctrl |= TD_CTRL_NAK; if (pid == USB_TOKEN_SETUP) goto do_timeout; - return 1; + ret = 1; + goto out; case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; td->ctrl &= ~TD_CTRL_ACTIVE; - return 1; + ret = 1; + goto out; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; td->ctrl &= ~TD_CTRL_ACTIVE; /* frame interrupted */ - return -1; + ret = -1; + goto out; } } + +out: + /* If TD is inactive and IOC bit set to 1 then update int_mask */ + if ((td->ctrl & TD_CTRL_IOC) && (!(td->ctrl & TD_CTRL_ACTIVE))) { + *int_mask |= 0x01; + } + return ret; } static void uhci_frame_timer(void *opaque) From 09ddbb1ce580051ada4dd96c6667fbd3e6f10499 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 12:07:53 +0000 Subject: [PATCH 39/69] The HTTP service used for SEXPR based RPC calls currently serializes all incoming client requests. Since some requests can take non-trivial time blocking out other clients in this way has bad consequences. The attached patch makes XenD spawn a new thread to handle each incoming HTTP request. This same approach is already taken in the XML-RPC service in XenD so I don't anticipate any multi-thread issues (at least none which don't already exist). Signed-off-by: Daniel P. Berrange --- tools/python/xen/web/httpserver.py | 44 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/tools/python/xen/web/httpserver.py b/tools/python/xen/web/httpserver.py index bcf5dbd6b1..2326a2b875 100644 --- a/tools/python/xen/web/httpserver.py +++ b/tools/python/xen/web/httpserver.py @@ -264,7 +264,32 @@ class HttpServerRequest(http.HttpRequest): s += x + "/" self.write(' %s/' % (s, x)) self.write("") - + +class HttpServerClient: + + def __init__(self, server, sock, addr): + self.server = server + self.sock = sock + self.addr = addr + + def process(self): + thread = threading.Thread(target=self.doProcess) + thread.setDaemon(True) + thread.start() + + def doProcess(self): + try: + rp = RequestProcessor(self.server, self.sock, self.addr) + rp.process() + except SystemExit: + raise + except Exception, ex: + print 'HttpServer>processRequest> exception: ', ex + try: + self.sock.close() + except: + pass + class HttpServer: backlog = 5 @@ -286,8 +311,8 @@ class HttpServer: while not self.closed: (sock, addr) = self.accept() - self.processRequest(sock, addr) - + cl = HttpServerClient(self, sock, addr) + cl.process() def stop(self): self.close() @@ -314,19 +339,6 @@ class HttpServer: except: pass - def processRequest(self, sock, addr): - try: - rp = RequestProcessor(self, sock, addr) - rp.process() - except SystemExit: - raise - except Exception, ex: - print 'HttpServer>processRequest> exception: ', ex - try: - sock.close() - except: - pass - def getServerAddr(self): return (socket.gethostname(), self.port) From a2b0be52481960535db8749d3a148194aa749628 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 12:11:40 +0000 Subject: [PATCH 40/69] Do an explicit check for bootloader path existence prior to the one for executable permissions. Also print out the path being tested. Signed-off-by: Daniel P, Berrange --- tools/python/xen/xm/create.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index c081560f8e..aa0c03cac3 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -704,8 +704,10 @@ def configure_hvm(config_image, vals): config_image.append(['vncpasswd', vals.vncpasswd]) def run_bootloader(vals, config_image): + if not os.access(vals.bootloader, os.F_OK): + err("Bootloader '%s' does not exist" % vals.bootloader) if not os.access(vals.bootloader, os.X_OK): - err("Bootloader isn't executable") + err("Bootloader '%s' isn't executable" % vals.bootloader) if len(vals.disk) < 1: err("No disks configured and boot loader requested") (uname, dev, mode, backend) = vals.disk[0] From 504c725be09c53962aa5e5ada544895de02c1757 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 12:14:22 +0000 Subject: [PATCH 41/69] Scrub VNC passwords from the logs. Signed-off-by: Daniel P. Berrange --- tools/python/xen/xend/XendConfig.py | 37 +++++++++++++++++++++++-- tools/python/xen/xend/XendDomainInfo.py | 19 +++++++------ 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 1f5571b8ba..c8ab727d6b 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -42,6 +42,39 @@ def reverse_dict(adict): def bool0(v): return v != '0' and bool(v) +# Recursively copy a data struct, scrubbing out VNC passwords. +# Will scrub any dict entry with a key of 'vncpasswd' or any +# 2-element list whose first member is 'vncpasswd'. It will +# also scrub a string matching '(vncpasswd XYZ)'. Everything +# else is no-op passthrough +def scrub_password(data): + if type(data) == dict or type(data) == XendConfig: + scrubbed = {} + for key in data.keys(): + if key == "vncpasswd": + scrubbed[key] = "XXXXXXXX" + else: + scrubbed[key] = scrub_password(data[key]) + return scrubbed + elif type(data) == list: + if len(data) == 2 and type(data[0]) == str and data[0] == 'vncpasswd': + return ['vncpasswd', 'XXXXXXXX'] + else: + scrubbed = [] + for entry in data: + scrubbed.append(scrub_password(entry)) + return scrubbed + elif type(data) == tuple: + scrubbed = [] + for entry in data: + scrubbed.append(scrub_password(entry)) + return tuple(scrubbed) + elif type(data) == str: + return re.sub(r'\(vncpasswd\s+[^\)]+\)','(vncpasswd XXXXXX)', data) + else: + return data + + # Mapping from XendConfig configuration keys to the old # legacy configuration keys that map directly. @@ -269,7 +302,7 @@ class XendConfig(dict): # output from xc.domain_getinfo self._dominfo_to_xapi(dominfo) - log.debug('XendConfig.init: %s' % self) + log.debug('XendConfig.init: %s' % scrub_password(self)) # validators go here self.validate() @@ -478,7 +511,7 @@ class XendConfig(dict): else: for opt, val in config[1:]: dev_info[opt] = val - log.debug("XendConfig: reading device: %s" % dev_info) + log.debug("XendConfig: reading device: %s" % scrub_password(dev_info)) # create uuid if it doesn't dev_uuid = dev_info.get('uuid', uuid.createString()) dev_info['uuid'] = dev_uuid diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 5fda486555..a86518ab40 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -40,6 +40,7 @@ from xen.util import security from xen.xend import balloon, sxp, uuid, image, arch from xen.xend import XendRoot, XendNode, XendConfig +from xen.xend.XendConfig import scrub_password from xen.xend.XendBootloader import bootloader from xen.xend.XendError import XendError, VmError from xen.xend.XendDevices import XendDevices @@ -148,7 +149,7 @@ def create(config): @raise VmError: Invalid configuration or failure to start. """ - log.debug("XendDomainInfo.create(%s)", config) + log.debug("XendDomainInfo.create(%s)", scrub_password(config)) vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config)) try: vm.start() @@ -175,7 +176,7 @@ def recreate(info, priv): @raise XendError: Errors with configuration. """ - log.debug("XendDomainInfo.recreate(%s)", info) + log.debug("XendDomainInfo.recreate(%s)", scrub_password(info)) assert not info['dying'] @@ -257,7 +258,7 @@ def restore(config): @raise XendError: Errors with configuration. """ - log.debug("XendDomainInfo.restore(%s)", config) + log.debug("XendDomainInfo.restore(%s)", scrub_password(config)) vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config), resume = True) try: @@ -280,7 +281,7 @@ def createDormant(domconfig): @raise XendError: Errors with configuration. """ - log.debug("XendDomainInfo.createDormant(%s)", domconfig) + log.debug("XendDomainInfo.createDormant(%s)", scrub_password(domconfig)) # domid does not make sense for non-running domains. domconfig.pop('domid', None) @@ -520,11 +521,11 @@ class XendDomainInfo: @param dev_config: device configuration @type dev_config: SXP object (parsed config) """ - log.debug("XendDomainInfo.device_create: %s" % dev_config) + log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config)) dev_type = sxp.name(dev_config) dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config) dev_config_dict = self.info['devices'][dev_uuid][1] - log.debug("XendDomainInfo.device_create: %s" % dev_config_dict) + log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict)) devid = self._createDevice(dev_type, dev_config_dict) self._waitForDevice(dev_type, devid) return self.getDeviceController(dev_type).sxpr(devid) @@ -746,7 +747,7 @@ class XendDomainInfo: to_store.update(self._vcpuDomDetails()) - log.debug("Storing domain details: %s", to_store) + log.debug("Storing domain details: %s", scrub_password(to_store)) self._writeDom(to_store) @@ -1188,7 +1189,7 @@ class XendDomainInfo: """ for (devclass, config) in self.info.get('devices', {}).values(): if devclass in XendDevices.valid_devices(): - log.info("createDevice: %s : %s" % (devclass, config)) + log.info("createDevice: %s : %s" % (devclass, scrub_password(config))) self._createDevice(devclass, config) if self.image: @@ -1667,7 +1668,7 @@ class XendDomainInfo: if not self._readVm('xend/restart_count'): to_store['xend/restart_count'] = str(0) - log.debug("Storing VM details: %s", to_store) + log.debug("Storing VM details: %s", scrub_password(to_store)) self._writeVm(to_store) self._setVmPermissions() From b744adfbba82cc16fbdd6285b068b07436e600fe Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 12:15:30 +0000 Subject: [PATCH 42/69] The new lifecycle patches in xen-unstable added 3 new operations which can be performed on domains - new, start and delete. libvirt has had no-op stub implementations of these APIs for a while & thus we'd enable their use for Xen 3.0.4 builds. The new APIs are not currently exposed via the existing SEXPR protocol, and since the new Xen-API protocol is unsupported tech-preview for 3.0.4 we don't want to re-write against that just yet. Thus the attached patch adds the 3 neccessary bindings for the SEXPR protocol to allow the lifecycle functionality to be invoked. It also allows the 'state' parameter to be specified when listing domains, so we can explicitly request inactive domains if we know we're running against a 3.0.4 era XenD Signed-off-by: Daniel P. Berrange --- tools/python/xen/xend/server/SrvDomain.py | 13 +++++++ tools/python/xen/xend/server/SrvDomainDir.py | 37 +++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index 82998e4d98..00c18c9386 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -21,6 +21,7 @@ from xen.web import http from xen.xend import sxp from xen.xend import XendDomain from xen.xend.Args import FormFn +from xen.xend.XendLogging import log from xen.web.SrvDir import SrvDir @@ -63,6 +64,18 @@ class SrvDomain(SrvDir): self.acceptCommand(req) return self.dom.shutdown(req.args['reason'][0]) + def op_delete(self, _, req): + self.acceptCommand(req) + return self.xd.domain_delete(self.dom.getName()) + + def op_start(self, _, req): + self.acceptCommand(req) + paused = False + if 'paused' in req.args and req.args['paused'] == [1]: + paused = True + log.debug("Starting domain " + self.dom.getName() + " " + str(paused)) + return self.xd.domain_start(self.dom.getName(), paused) + def op_sysrq(self, _, req): self.acceptCommand(req) return self.dom.send_sysrq(int(req.args['key'][0])) diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py index a134d5cbd9..950b26316d 100644 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ b/tools/python/xen/xend/server/SrvDomainDir.py @@ -25,6 +25,8 @@ from xen.xend import XendDomain from xen.xend.XendDomainInfo import XendDomainInfo from xen.xend.Args import FormFn from xen.xend.XendError import XendError +from xen.xend.XendLogging import log +from xen.xend.XendConstants import DOM_STATE_RUNNING from xen.web.SrvDir import SrvDir from SrvDomain import SrvDomain @@ -101,6 +103,35 @@ class SrvDomainDir(SrvDir): out.close() return val + def op_new(self, _, req): + """Define a new domain. + Expects the domain config in request parameter 'config' in SXP format. + """ + ok = 0 + errmsg = '' + try: + configstring = req.args.get('config')[0] + #print 'op_create>', 'config:', configstring + pin = sxp.Parser() + pin.input(configstring) + pin.input_eof() + config = pin.get_val() + ok = 1 + except sxp.ParseError, ex: + errmsg = 'Invalid configuration ' + str(ex) + except Exception, ex: + print 'op_create> Exception in config', ex + traceback.print_exc() + errmsg = 'Configuration error ' + str(ex) + if not ok: + raise XendError(errmsg) + try: + self.xd.domain_new(config) + except Exception, ex: + print 'op_create> Exception creating domain:' + traceback.print_exc() + raise XendError("Error creating domain: " + str(ex)) + def op_restore(self, op, req): """Restore a domain from file. @@ -159,7 +190,11 @@ class SrvDomainDir(SrvDir): if detail: sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req) else: - sxp.show(self.xd.list_names(), out=req) + state = DOM_STATE_RUNNING + if 'state' in req.args and len(req.args['state']) > 0: + state = req.args['state'][0] + log.debug("Listing domains in state " + str(state)) + sxp.show(self.xd.list_names(state), out=req) else: domains = self.xd.list_sorted() req.write('
    ') From a1aafcf306ab3daecc10e56fd1e857417403960c Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 12:23:35 +0000 Subject: [PATCH 43/69] This patch checks the contents of XENDOMAINS_SAVE before the restore process begins, and prevents xendomains from attempting to start any domain that appears there, whether the domain started successfully or not. Signed off by: Hugh Brock --- tools/examples/init.d/xendomains | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/examples/init.d/xendomains b/tools/examples/init.d/xendomains index b3722882d6..7aca157bc9 100644 --- a/tools/examples/init.d/xendomains +++ b/tools/examples/init.d/xendomains @@ -204,12 +204,14 @@ start() return; fi + saved_domains=" " if [ "$XENDOMAINS_RESTORE" = "true" ] && contains_something "$XENDOMAINS_SAVE" then mkdir -p $(dirname "$LOCKFILE") touch $LOCKFILE echo -n "Restoring Xen domains:" + saved_domains=`ls $XENDOMAINS_SAVE` for dom in $XENDOMAINS_SAVE/*; do echo -n " ${dom##*/}" xm restore $dom @@ -234,9 +236,14 @@ start() # Create all domains with config files in XENDOMAINS_AUTO. # TODO: We should record which domain name belongs # so we have the option to selectively shut down / migrate later + # If a domain statefile from $XENDOMAINS_SAVE matches a domain name + # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't + # restore correctly it requires administrative attention. for dom in $XENDOMAINS_AUTO/*; do echo -n " ${dom##*/}" - if is_running $dom; then + shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p') + echo $saved_domains | grep -w $shortdom > /dev/null + if [ $? -eq 0 ] || is_running $dom; then echo -n "(skip)" else xm create --quiet --defconfig $dom From 9ca50215eebbf159c905235f4d5de945b9b446e2 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 7 Dec 2006 13:14:44 +0000 Subject: [PATCH 44/69] [XEN] Init pae_l3_cache lock earlier In particular, before hvm_vcpu_initialise causes a CR3 update. Signed-off-by: Tim Deegan --- xen/arch/x86/domain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 75d5284aeb..9171b394ae 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -134,6 +134,8 @@ int vcpu_initialise(struct vcpu *v) v->arch.flags = TF_kernel_mode; + pae_l3_cache_init(&v->arch.pae_l3_cache); + if ( is_hvm_domain(d) ) { if ( (rc = hvm_vcpu_initialise(v)) != 0 ) @@ -155,8 +157,6 @@ int vcpu_initialise(struct vcpu *v) v->arch.perdomain_ptes = d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT); - pae_l3_cache_init(&v->arch.pae_l3_cache); - return 0; } From e150713e686a554fedfc97102cdc0d920d1c5bbb Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 13:47:13 +0000 Subject: [PATCH 45/69] [XEND] Fix resume for managed domains. Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendCheckpoint.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 707a9c5c3c..21a323cdcc 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -137,7 +137,6 @@ def restore(xd, fd, dominfo = None, paused = False): vmconfig = p.get_val() if dominfo: - dominfo.update(XendConfig(sxp_obj = vmconfig), refresh = False) dominfo.resume() else: dominfo = xd.restore_(vmconfig) From bd52f01c26803f7346e636b5cc599811050af116 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 14:03:54 +0000 Subject: [PATCH 46/69] [XEN] Early page fault handler to deal with spurious page faults. Signed-off-by: Keir Fraser --- xen/arch/x86/crash.c | 12 ++---------- xen/arch/x86/setup.c | 11 ++++++----- xen/arch/x86/traps.c | 31 +++++++++++++++++++++++++++++++ xen/arch/x86/x86_32/domain_page.c | 26 -------------------------- xen/arch/x86/x86_32/entry.S | 8 ++++++++ xen/arch/x86/x86_64/entry.S | 6 ++++++ xen/include/xen/domain_page.h | 9 --------- 7 files changed, 53 insertions(+), 50 deletions(-) diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c index 3389174a7a..a5b0aeedf1 100644 --- a/xen/arch/x86/crash.c +++ b/xen/arch/x86/crash.c @@ -27,7 +27,6 @@ #include #include -#ifdef CONFIG_SMP static atomic_t waiting_for_crash_ipi; static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu) @@ -71,9 +70,7 @@ static void nmi_shootdown_cpus(void) atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); /* Would it be better to replace the trap vector here? */ set_nmi_callback(crash_nmi_callback); - /* Ensure the new callback function is set before sending - * out the NMI - */ + /* Ensure the new callback function is set before sending out the NMI. */ wmb(); smp_send_nmi_allbutself(); @@ -88,7 +85,6 @@ static void nmi_shootdown_cpus(void) /* Leave the nmi callback set */ disable_local_APIC(); } -#endif static void crash_save_xen_notes(void) { @@ -102,16 +98,12 @@ static void crash_save_xen_notes(void) void machine_crash_shutdown(void) { - printk("machine_crash_shutdown: %d\n", smp_processor_id()); local_irq_disable(); -#ifdef CONFIG_SMP nmi_shootdown_cpus(); -#endif -#ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); -#endif + hvm_disable(); crash_save_xen_notes(); diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 391a50eb05..8d9f6f9e08 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -305,6 +305,9 @@ void __init __start_xen(multiboot_info_t *mbi) .stop_bits = 1 }; + extern void early_page_fault(void); + set_intr_gate(TRAP_page_fault, &early_page_fault); + /* Parse the command-line options. */ if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) cmdline = __va(mbi->cmdline); @@ -501,21 +504,19 @@ void __init __start_xen(multiboot_info_t *mbi) kdump_start >>= PAGE_SHIFT; kdump_size >>= PAGE_SHIFT; - /* allocate pages for Kdump memory area */ + /* Allocate pages for Kdump memory area. */ k = alloc_boot_pages_at(kdump_size, kdump_start); - if ( k != kdump_start ) panic("Unable to reserve Kdump memory\n"); - /* allocate pages for relocated initial images */ + /* Allocate pages for relocated initial images. */ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0; k += (initial_images_end - initial_images_start) >> PAGE_SHIFT; k = alloc_boot_pages(k, 1); - - if ( !k ) + if ( k == 0 ) panic("Unable to allocate initial images memory\n"); move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end); diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 3e6ab2856d..11960e56fb 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -935,6 +935,37 @@ asmlinkage int do_page_fault(struct cpu_user_regs *regs) return 0; } +/* + * Early handler to deal with spurious page faults. For example, consider a + * routine that uses a mapping immediately after installing it (making it + * present). The CPU may speculatively execute the memory access before + * executing the PTE write. The instruction will then be marked to cause a + * page fault when it is retired, despite the fact that the PTE is present and + * correct at that point in time. + */ +asmlinkage int do_early_page_fault(struct cpu_user_regs *regs) +{ + static int stuck; + static unsigned long prev_eip, prev_cr2; + unsigned long cr2 = read_cr2(); + + BUG_ON(smp_processor_id() != 0); + + if ( (regs->eip != prev_eip) || (cr2 != prev_cr2) ) + { + prev_eip = regs->eip; + prev_cr2 = cr2; + stuck = 0; + return EXCRET_not_a_fault; + } + + if ( stuck++ == 1000 ) + panic("Early fatal page fault at %04x:%p (cr2=%p, ec=%04x)\n", + regs->cs, _p(regs->eip), _p(cr2), regs->error_code); + + return EXCRET_not_a_fault; +} + long do_fpu_taskswitch(int set) { struct vcpu *v = current; diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 2b760ce704..93cd2379a7 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -252,29 +252,3 @@ void unmap_domain_page_global(void *va) idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT; set_bit(idx, garbage); } - -paddr_t maddr_from_mapped_domain_page(void *va) -{ - unsigned long __va = (unsigned long)va; - l2_pgentry_t *pl2e; - l1_pgentry_t *pl1e; - unsigned int idx; - struct mapcache *cache; - unsigned long mfn; - - if ( (__va >= MAPCACHE_VIRT_START) && (__va < MAPCACHE_VIRT_END) ) - { - cache = &mapcache_current_vcpu()->domain->arch.mapcache; - idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT; - mfn = l1e_get_pfn(cache->l1tab[idx]); - } - else - { - ASSERT(__va >= IOREMAP_VIRT_START); - pl2e = virt_to_xen_l2e(__va); - pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va); - mfn = l1e_get_pfn(*pl1e); - } - - return ((paddr_t)mfn << PAGE_SHIFT) | ((unsigned long)va & ~PAGE_MASK); -} diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 566f4d4279..454e963fe3 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -536,6 +536,14 @@ ENTRY(spurious_interrupt_bug) pushl $TRAP_spurious_int<<16 jmp handle_exception +ENTRY(early_page_fault) + SAVE_ALL_NOSEGREGS(a) + movl %esp,%edx + pushl %edx + call do_early_page_fault + addl $4,%esp + jmp restore_all_xen + ENTRY(nmi) #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL # NMI entry protocol is incompatible with guest kernel in ring 0. diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 87602a3d86..b28b644c33 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -478,6 +478,12 @@ ENTRY(double_fault) call do_double_fault ud2 +ENTRY(early_page_fault) + SAVE_ALL + movq %rsp,%rdi + call do_early_page_fault + jmp restore_all_xen + ENTRY(nmi) pushq $0 SAVE_ALL diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index 3f83b2a6db..7067f33ff7 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -34,13 +34,6 @@ void unmap_domain_page(void *va); void *map_domain_page_global(unsigned long mfn); void unmap_domain_page_global(void *va); -/* - * Convert a VA (within a page previously mapped in the context of the - * currently-executing VCPU via a call to map_domain_page(), or via a - * previous call to map_domain_page_global()) to the mapped machine address. - */ -paddr_t maddr_from_mapped_domain_page(void *va); - #define DMCACHE_ENTRY_VALID 1U #define DMCACHE_ENTRY_HELD 2U @@ -109,8 +102,6 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache) #define map_domain_page_global(mfn) maddr_to_virt((mfn)< Date: Thu, 7 Dec 2006 14:38:16 +0000 Subject: [PATCH 47/69] [XEND] Prevent None values from appearing in Device SXP Signed-off-by: Alastair Tse --- tools/python/xen/xend/server/DevController.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 646e19d9de..b8dc8f4763 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -226,9 +226,11 @@ class DevController: for key, val in configDict.items(): if isinstance(val, (types.ListType, types.TupleType)): for v in val: - sxpr.append([key, v]) + if v != None: + sxpr.append([key, v]) else: - sxpr.append([key, val]) + if val != None: + sxpr.append([key, val]) return sxpr def sxprs(self): From dee1d9ba0c760f68519f2354d1660f80d7447dfb Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 14:40:13 +0000 Subject: [PATCH 48/69] [XEND] Make SXP parsing re-use device_add in XendConfig This will fix the IP address configuration problem for vifs. Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendConfig.py | 38 ++++++++++++++++++----------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index c8ab727d6b..526e8836a5 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -509,14 +509,8 @@ class XendConfig(dict): log.debug("XendConfig: reading device: %s" % pci_devs) else: - for opt, val in config[1:]: - dev_info[opt] = val + self.device_add(dev_type, cfg_sxp = config, target = cfg) log.debug("XendConfig: reading device: %s" % scrub_password(dev_info)) - # create uuid if it doesn't - dev_uuid = dev_info.get('uuid', uuid.createString()) - dev_info['uuid'] = dev_uuid - cfg['devices'][dev_uuid] = (dev_type, dev_info) - # Extract missing data from configuration entries image_sxp = sxp.child_value(sxp_cfg, 'image', []) @@ -867,7 +861,8 @@ class XendConfig(dict): return sxpr - def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None): + def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None, + target = None): """Add a device configuration in SXP format or XenAPI struct format. For SXP, it could be either: @@ -882,9 +877,14 @@ class XendConfig(dict): @param cfg_sxp: SXP configuration object @type cfg_xenapi: dict @param cfg_xenapi: A device configuration from Xen API (eg. vbd,vif) + @param target: write device information to + @type target: None or a dictionary @rtype: string @return: Assigned UUID of the device. """ + if target == None: + target = self + if dev_type not in XendDevices.valid_devices() and \ dev_type not in XendDevices.pseudo_devices(): raise XendConfigError("XendConfig: %s not a valid device type" % @@ -914,15 +914,18 @@ class XendConfig(dict): except ValueError: pass # SXP has no options for this device - - def _get_config_ipaddr(config): + + # Special handling for certain device parameters. + + def _get_config_ipaddr(cfg): val = [] - for ipaddr in sxp.children(config, elt='ip'): + for ipaddr in sxp.children(cfg, elt='ip'): val.append(sxp.child0(ipaddr)) return val if dev_type == 'vif' and 'ip' in dev_info: dev_info['ip'] = _get_config_ipaddr(config) + log.debug('XendConfig: IP Address: %s' % dev_info['ip']) if dev_type == 'vbd': if dev_info.get('dev', '').startswith('ioemu:'): @@ -936,11 +939,18 @@ class XendConfig(dict): dev_info['uuid'] = dev_uuid # store dev references by uuid for certain device types - self['devices'][dev_uuid] = (dev_type, dev_info) + target['devices'][dev_uuid] = (dev_type, dev_info) if dev_type in ('vif', 'vbd', 'vtpm'): - self['%s_refs' % dev_type].append(dev_uuid) + param = '%s_refs' % dev_type + if param not in target: + target[param] = [] + if dev_uuid in target[param]: + target[param].append(dev_uuid) elif dev_type in ('tap',): - self['vbd_refs'].append(dev_uuid) + if 'vbd_refs' not in target: + target['vbd_refs'] = [] + if dev_uuid in target['vbd_refs']: + target['vbd_refs'].append(dev_uuid) return dev_uuid From 0be2a505dd7a4c7a544f8c561b3fb0ba5ad2ed80 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 14:57:14 +0000 Subject: [PATCH 49/69] [XEN] Add new safe pte update macros and use as necessary when updating active pagetables. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 54 +++++++++++++----------- xen/arch/x86/mm/shadow/multi.c | 2 + xen/arch/x86/x86_32/domain_page.c | 10 ++--- xen/arch/x86/x86_32/mm.c | 33 ++++++++------- xen/arch/x86/x86_64/mm.c | 31 +++++++------- xen/include/asm-x86/page.h | 15 +++++-- xen/include/asm-x86/x86_32/page-2level.h | 3 +- xen/include/asm-x86/x86_32/page-3level.h | 7 +++ xen/include/asm-x86/x86_64/page.h | 3 +- 9 files changed, 94 insertions(+), 64 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 48dea7cffb..9a965f982b 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -335,7 +335,7 @@ void make_cr3(struct vcpu *v, unsigned long mfn) cache->high_mfn = mfn; /* Map the guest L3 table and copy to the chosen low-memory cache. */ - *(fix_pae_highmem_pl1e - cpu) = l1e_from_pfn(mfn, __PAGE_HYPERVISOR); + l1e_write(fix_pae_highmem_pl1e-cpu, l1e_from_pfn(mfn, __PAGE_HYPERVISOR)); /* First check the previous high mapping can't be in the TLB. * (i.e. have we loaded CR3 since we last did this?) */ if ( unlikely(this_cpu(make_cr3_timestamp) == this_cpu(tlbflush_time)) ) @@ -343,7 +343,7 @@ void make_cr3(struct vcpu *v, unsigned long mfn) highmem_l3tab = (l3_pgentry_t *)fix_to_virt(FIX_PAE_HIGHMEM_0 + cpu); lowmem_l3tab = cache->table[cache->inuse_idx]; memcpy(lowmem_l3tab, highmem_l3tab, sizeof(cache->table[0])); - *(fix_pae_highmem_pl1e - cpu) = l1e_empty(); + l1e_write(fix_pae_highmem_pl1e-cpu, l1e_empty()); this_cpu(make_cr3_timestamp) = this_cpu(tlbflush_time); v->arch.cr3 = __pa(lowmem_l3tab); @@ -380,7 +380,7 @@ void invalidate_shadow_ldt(struct vcpu *v) { pfn = l1e_get_pfn(v->arch.perdomain_ptes[i]); if ( pfn == 0 ) continue; - v->arch.perdomain_ptes[i] = l1e_empty(); + l1e_write(&v->arch.perdomain_ptes[i], l1e_empty()); page = mfn_to_page(pfn); ASSERT_PAGE_IS_TYPE(page, PGT_ldt_page); ASSERT_PAGE_IS_DOMAIN(page, v->domain); @@ -449,7 +449,7 @@ int map_ldt_shadow_page(unsigned int off) nl1e = l1e_from_pfn(mfn, l1e_get_flags(l1e) | _PAGE_RW); - v->arch.perdomain_ptes[off + 16] = nl1e; + l1e_write(&v->arch.perdomain_ptes[off + 16], nl1e); v->arch.shadow_ldt_mapcnt++; return 1; @@ -851,7 +851,7 @@ static int alloc_l1_table(struct page_info *page) static int create_pae_xen_mappings(l3_pgentry_t *pl3e) { struct page_info *page; - l2_pgentry_t *pl2e; + l2_pgentry_t *pl2e, l2e; l3_pgentry_t l3e3; int i; @@ -892,15 +892,19 @@ static int create_pae_xen_mappings(l3_pgentry_t *pl3e) &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT], L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t)); for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) - pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] = - l2e_from_page( - virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt) + i, - __PAGE_HYPERVISOR); + { + l2e = l2e_from_page( + virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt) + i, + __PAGE_HYPERVISOR); + l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i], l2e); + } for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ ) - pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] = - (l3e_get_flags(pl3e[i]) & _PAGE_PRESENT) ? - l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR) : - l2e_empty(); + { + l2e = l2e_empty(); + if ( l3e_get_flags(pl3e[i]) & _PAGE_PRESENT ) + l2e = l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR); + l2e_write(&pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i], l2e); + } unmap_domain_page(pl2e); return 1; @@ -2760,7 +2764,7 @@ void destroy_gdt(struct vcpu *v) { if ( (pfn = l1e_get_pfn(v->arch.perdomain_ptes[i])) != 0 ) put_page_and_type(mfn_to_page(pfn)); - v->arch.perdomain_ptes[i] = l1e_empty(); + l1e_write(&v->arch.perdomain_ptes[i], l1e_empty()); v->arch.guest_context.gdt_frames[i] = 0; } } @@ -2794,8 +2798,8 @@ long set_gdt(struct vcpu *v, for ( i = 0; i < nr_pages; i++ ) { v->arch.guest_context.gdt_frames[i] = frames[i]; - v->arch.perdomain_ptes[i] = - l1e_from_pfn(frames[i], __PAGE_HYPERVISOR); + l1e_write(&v->arch.perdomain_ptes[i], + l1e_from_pfn(frames[i], __PAGE_HYPERVISOR)); } return 0; @@ -3298,8 +3302,8 @@ int map_pages_to_xen( !map_small_pages ) { /* Super-page mapping. */ - ol2e = *pl2e; - *pl2e = l2e_from_pfn(mfn, flags|_PAGE_PSE); + ol2e = *pl2e; + l2e_write(pl2e, l2e_from_pfn(mfn, flags|_PAGE_PSE)); if ( (l2e_get_flags(ol2e) & _PAGE_PRESENT) ) { @@ -3319,22 +3323,24 @@ int map_pages_to_xen( { pl1e = page_to_virt(alloc_xen_pagetable()); clear_page(pl1e); - *pl2e = l2e_from_page(virt_to_page(pl1e), __PAGE_HYPERVISOR); + l2e_write(pl2e, l2e_from_page(virt_to_page(pl1e), + __PAGE_HYPERVISOR)); } else if ( l2e_get_flags(*pl2e) & _PAGE_PSE ) { pl1e = page_to_virt(alloc_xen_pagetable()); for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) - pl1e[i] = l1e_from_pfn( - l2e_get_pfn(*pl2e) + i, - l2e_get_flags(*pl2e) & ~_PAGE_PSE); - *pl2e = l2e_from_page(virt_to_page(pl1e), __PAGE_HYPERVISOR); + l1e_write(&pl1e[i], + l1e_from_pfn(l2e_get_pfn(*pl2e) + i, + l2e_get_flags(*pl2e) & ~_PAGE_PSE)); + l2e_write(pl2e, l2e_from_page(virt_to_page(pl1e), + __PAGE_HYPERVISOR)); local_flush_tlb_pge(); } pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(virt); ol1e = *pl1e; - *pl1e = l1e_from_pfn(mfn, flags); + l1e_write(pl1e, l1e_from_pfn(mfn, flags)); if ( (l1e_get_flags(ol1e) & _PAGE_PRESENT) ) local_flush_tlb_one(virt); diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 98ff07ace4..211b98b2ed 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -851,7 +851,9 @@ static inline void safe_write_entry(void *dst, void *src) * then writing the high word before the low word. */ BUILD_BUG_ON(sizeof (shadow_l1e_t) != 2 * sizeof (unsigned long)); d[0] = 0; + wmb(); d[1] = s[1]; + wmb(); d[0] = s[0]; #else /* In 32-bit and 64-bit, sizeof(pte) == sizeof(ulong) == 1 word, diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 93cd2379a7..9080de1a87 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -107,7 +107,7 @@ void *map_domain_page(unsigned long mfn) spin_unlock(&cache->lock); - cache->l1tab[idx] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR); + l1e_write(&cache->l1tab[idx], l1e_from_pfn(mfn, __PAGE_HYPERVISOR)); out: va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT); @@ -147,7 +147,7 @@ void unmap_domain_page(void *va) { /* /First/, zap the PTE. */ ASSERT(l1e_get_pfn(cache->l1tab[hashent->idx]) == hashent->mfn); - cache->l1tab[hashent->idx] = l1e_empty(); + l1e_write(&cache->l1tab[hashent->idx], l1e_empty()); /* /Second/, mark as garbage. */ set_bit(hashent->idx, cache->garbage); } @@ -159,7 +159,7 @@ void unmap_domain_page(void *va) else { /* /First/, zap the PTE. */ - cache->l1tab[idx] = l1e_empty(); + l1e_write(&cache->l1tab[idx], l1e_empty()); /* /Second/, mark as garbage. */ set_bit(idx, cache->garbage); } @@ -229,7 +229,7 @@ void *map_domain_page_global(unsigned long mfn) pl2e = virt_to_xen_l2e(va); pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(va); - *pl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR); + l1e_write(pl1e, l1e_from_pfn(mfn, __PAGE_HYPERVISOR)); return (void *)va; } @@ -246,7 +246,7 @@ void unmap_domain_page_global(void *va) /* /First/, we zap the PTE. */ pl2e = virt_to_xen_l2e(__va); pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va); - *pl1e = l1e_empty(); + l1e_write(pl1e, l1e_empty()); /* /Second/, we add to the garbage map. */ idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT; diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index 116228a53d..4978b82dad 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -99,11 +99,12 @@ void __init paging_init(void) { if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL ) panic("Not enough memory to bootstrap Xen.\n"); - idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i] = - l2e_from_page(pg, PAGE_HYPERVISOR | _PAGE_PSE); + l2e_write(&idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i], + l2e_from_page(pg, PAGE_HYPERVISOR | _PAGE_PSE)); /* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. */ - idle_pg_table_l2[l2_linear_offset(RO_MPT_VIRT_START) + i] = - l2e_from_page(pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW); + l2e_write(&idle_pg_table_l2[l2_linear_offset(RO_MPT_VIRT_START) + i], + l2e_from_page( + pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW)); } /* Fill with an obvious debug pattern. */ @@ -115,8 +116,8 @@ void __init paging_init(void) { ioremap_pt = alloc_xenheap_page(); clear_page(ioremap_pt); - idle_pg_table_l2[l2_linear_offset(IOREMAP_VIRT_START) + i] = - l2e_from_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR); + l2e_write(&idle_pg_table_l2[l2_linear_offset(IOREMAP_VIRT_START) + i], + l2e_from_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR)); } } @@ -125,10 +126,10 @@ void __init setup_idle_pagetable(void) int i; for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) - idle_pg_table_l2[l2_linear_offset(PERDOMAIN_VIRT_START) + i] = - l2e_from_page(virt_to_page(idle_vcpu[0]->domain-> - arch.mm_perdomain_pt) + i, - __PAGE_HYPERVISOR); + l2e_write(&idle_pg_table_l2[l2_linear_offset(PERDOMAIN_VIRT_START)+i], + l2e_from_page(virt_to_page(idle_vcpu[0]->domain-> + arch.mm_perdomain_pt) + i, + __PAGE_HYPERVISOR)); } void __init zap_low_mappings(l2_pgentry_t *base) @@ -136,14 +137,16 @@ void __init zap_low_mappings(l2_pgentry_t *base) int i; u32 addr; - for (i = 0; ; i++) { - addr = (i << L2_PAGETABLE_SHIFT); - if (addr >= HYPERVISOR_VIRT_START) + for ( i = 0; ; i++ ) + { + addr = i << L2_PAGETABLE_SHIFT; + if ( addr >= HYPERVISOR_VIRT_START ) break; - if (l2e_get_paddr(base[i]) != addr) + if ( l2e_get_paddr(base[i]) != addr ) continue; - base[i] = l2e_empty(); + l2e_write(&base[i], l2e_empty()); } + flush_tlb_all_pge(); } diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index c2783e897d..e14d266e12 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -59,7 +59,7 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned long v) { pl3e = page_to_virt(alloc_xen_pagetable()); clear_page(pl3e); - *pl4e = l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR); + l4e_write(pl4e, l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR)); } pl3e = l4e_to_l3e(*pl4e) + l3_table_offset(v); @@ -67,7 +67,7 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned long v) { pl2e = page_to_virt(alloc_xen_pagetable()); clear_page(pl2e); - *pl3e = l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR); + l3e_write(pl3e, l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR)); } pl2e = l3e_to_l2e(*pl3e) + l2_table_offset(v); @@ -85,8 +85,8 @@ void __init paging_init(void) if ( (l2_pg = alloc_domheap_page(NULL)) == NULL ) goto nomem; l3_ro_mpt = clear_page(page_to_virt(l2_pg)); - idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)] = - l4e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER); + l4e_write(&idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)], + l4e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER)); /* * Allocate and map the machine-to-phys table. @@ -111,18 +111,19 @@ void __init paging_init(void) goto nomem; va = RO_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT); l2_ro_mpt = clear_page(page_to_virt(l2_pg)); - l3_ro_mpt[l3_table_offset(va)] = - l3e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER); + l3e_write(&l3_ro_mpt[l3_table_offset(va)], + l3e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER)); l2_ro_mpt += l2_table_offset(va); } /* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. */ - *l2_ro_mpt++ = l2e_from_page( - l1_pg, /*_PAGE_GLOBAL|*/_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT); + l2e_write(l2_ro_mpt, l2e_from_page( + l1_pg, /*_PAGE_GLOBAL|*/_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT)); + l2_ro_mpt++; } /* Set up linear page table mapping. */ - idle_pg_table[l4_table_offset(LINEAR_PT_VIRT_START)] = - l4e_from_paddr(__pa(idle_pg_table), __PAGE_HYPERVISOR); + l4e_write(&idle_pg_table[l4_table_offset(LINEAR_PT_VIRT_START)], + l4e_from_paddr(__pa(idle_pg_table), __PAGE_HYPERVISOR)); return; nomem: @@ -132,15 +133,15 @@ void __init paging_init(void) void __init setup_idle_pagetable(void) { /* Install per-domain mappings for idle domain. */ - idle_pg_table[l4_table_offset(PERDOMAIN_VIRT_START)] = - l4e_from_page( - virt_to_page(idle_vcpu[0]->domain->arch.mm_perdomain_l3), - __PAGE_HYPERVISOR); + l4e_write(&idle_pg_table[l4_table_offset(PERDOMAIN_VIRT_START)], + l4e_from_page( + virt_to_page(idle_vcpu[0]->domain->arch.mm_perdomain_l3), + __PAGE_HYPERVISOR)); } void __init zap_low_mappings(void) { - idle_pg_table[0] = l4e_empty(); + l4e_write(&idle_pg_table[0], l4e_empty()); flush_tlb_all_pge(); } diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index b9c921a5cd..d384d34d65 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -33,9 +33,18 @@ /* Write a pte atomically to memory. */ #define l1e_write_atomic(l1ep, l1e) pte_write_atomic(l1ep, l1e_get_intpte(l1e)) -#define l2e_write_atomic(l2ep, l2e) pte_write_atomic(l2ep, l1e_get_intpte(l2e)) -#define l3e_write_atomic(l3ep, l3e) pte_write_atomic(l3ep, l1e_get_intpte(l3e)) -#define l4e_write_atomic(l4ep, l4e) pte_write_atomic(l4ep, l1e_get_intpte(l4e)) +#define l2e_write_atomic(l2ep, l2e) pte_write_atomic(l2ep, l2e_get_intpte(l2e)) +#define l3e_write_atomic(l3ep, l3e) pte_write_atomic(l3ep, l3e_get_intpte(l3e)) +#define l4e_write_atomic(l4ep, l4e) pte_write_atomic(l4ep, l4e_get_intpte(l4e)) + +/* + * Write a pte safely but non-atomically to memory. + * The PTE may become temporarily not-present during the update. + */ +#define l1e_write(l1ep, l1e) pte_write(l1ep, l1e_get_intpte(l1e)) +#define l2e_write(l2ep, l2e) pte_write(l2ep, l2e_get_intpte(l2e)) +#define l3e_write(l3ep, l3e) pte_write(l3ep, l3e_get_intpte(l3e)) +#define l4e_write(l4ep, l4e) pte_write(l4ep, l4e_get_intpte(l4e)) /* Get direct integer representation of a pte's contents (intpte_t). */ #define l1e_get_intpte(x) ((x).l1) diff --git a/xen/include/asm-x86/x86_32/page-2level.h b/xen/include/asm-x86/x86_32/page-2level.h index a022b12087..86e8dbe30f 100644 --- a/xen/include/asm-x86/x86_32/page-2level.h +++ b/xen/include/asm-x86/x86_32/page-2level.h @@ -29,7 +29,8 @@ typedef l2_pgentry_t root_pgentry_t; #endif /* !__ASSEMBLY__ */ #define pte_read_atomic(ptep) (*(intpte_t *)(ptep)) -#define pte_write_atomic(ptep, pte) (*(intpte_t *)(ptep)) = (pte)) +#define pte_write_atomic(ptep, pte) ((*(intpte_t *)(ptep)) = (pte)) +#define pte_write(ptep, pte) ((*(intpte_t *)(ptep)) = (pte)) /* root table */ #define root_get_pfn l2e_get_pfn diff --git a/xen/include/asm-x86/x86_32/page-3level.h b/xen/include/asm-x86/x86_32/page-3level.h index 08864255ad..41bc5b0cff 100644 --- a/xen/include/asm-x86/x86_32/page-3level.h +++ b/xen/include/asm-x86/x86_32/page-3level.h @@ -48,6 +48,13 @@ typedef l3_pgentry_t root_pgentry_t; while ( (__npte = cmpxchg((intpte_t *)(ptep), __pte, (pte))) != __pte ) \ __pte = __npte; \ } while ( 0 ) +#define pte_write(ptep, pte) do { \ + *((u32 *)(ptep)+0) = 0; \ + wmb(); \ + *((u32 *)(ptep)+1) = (pte) >> 32; \ + wmb(); \ + *((u32 *)(ptep)+0) = (pte) >> 0; \ +} while ( 0 ) /* root table */ #define root_get_pfn l3e_get_pfn diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h index e52097d73e..fca1173c1e 100644 --- a/xen/include/asm-x86/x86_64/page.h +++ b/xen/include/asm-x86/x86_64/page.h @@ -44,7 +44,8 @@ typedef l4_pgentry_t root_pgentry_t; #endif /* !__ASSEMBLY__ */ #define pte_read_atomic(ptep) (*(intpte_t *)(ptep)) -#define pte_write_atomic(ptep, pte) (*(intpte_t *)(ptep)) = (pte)) +#define pte_write_atomic(ptep, pte) ((*(intpte_t *)(ptep)) = (pte)) +#define pte_write(ptep, pte) ((*(intpte_t *)(ptep)) = (pte)) /* Given a virtual address, get an entry offset into a linear page table. */ #define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> L1_PAGETABLE_SHIFT) From 69370cc992643992941d7d65d591f26cc2bf0cc3 Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 16:08:44 +0000 Subject: [PATCH 50/69] [XEND] Sync Xen API with newer VDB and VIF specification. Fix breakage with storing VIF and VBD refs, remove extraneous debugging. Also fixing some type errors in default values for Xen API if things are missing in XendConfig. Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendAPI.py | 11 +++--- tools/python/xen/xend/XendConfig.py | 5 ++- tools/python/xen/xend/XendDomainInfo.py | 46 +++++++------------------ 3 files changed, 19 insertions(+), 43 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 0b4e35b8ce..f59153e68b 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1036,8 +1036,8 @@ class XendAPI: # regular xm created VBDs VBD_attr_ro = ['image', - 'IO_bandwidth_incoming_kbs', - 'IO_bandwidth_outgoing_kbs'] + 'io_read_kbs', + 'io_write_kbs'] VBD_attr_rw = ['VM', 'VDI', 'device', @@ -1113,10 +1113,8 @@ class XendAPI: # Xen API: Class VIF # ---------------------------------------------------------------- - VIF_attr_ro = ['network_read_kbs', - 'network_write_kbs', - 'IO_bandwidth_incoming_kbs', - 'IO_bandwidth_outgoing_kbs'] + VIF_attr_ro = ['io_read_kbs', + 'io_write_kbs'] VIF_attr_rw = ['name', 'type', 'device', @@ -1138,6 +1136,7 @@ class XendAPI: return xen_api_error(XEND_ERROR_VIF_INVALID) valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \ self.Base_attr_ro + self.Base_attr_rw + for k in cfg.keys(): if k not in valid_vif_keys: del cfg[k] diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 526e8836a5..74ff06284d 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -925,7 +925,6 @@ class XendConfig(dict): if dev_type == 'vif' and 'ip' in dev_info: dev_info['ip'] = _get_config_ipaddr(config) - log.debug('XendConfig: IP Address: %s' % dev_info['ip']) if dev_type == 'vbd': if dev_info.get('dev', '').startswith('ioemu:'): @@ -944,12 +943,12 @@ class XendConfig(dict): param = '%s_refs' % dev_type if param not in target: target[param] = [] - if dev_uuid in target[param]: + if dev_uuid not in target[param]: target[param].append(dev_uuid) elif dev_type in ('tap',): if 'vbd_refs' not in target: target['vbd_refs'] = [] - if dev_uuid in target['vbd_refs']: + if dev_uuid not in target['vbd_refs']: target['vbd_refs'].append(dev_uuid) return dev_uuid diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index a86518ab40..3716be8462 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1780,13 +1780,13 @@ class XendDomainInfo: return dom_uuid def get_memory_static_max(self): - return self.info.get('memory_static_max') + return self.info.get('memory_static_max', 0) def get_memory_static_min(self): - return self.info.get('memory_static_min') + return self.info.get('memory_static_min', 0) def get_memory_dynamic_max(self): - return self.info.get('memory_dynamic_min') + return self.info.get('memory_dynamic_min', 0) def get_memory_dynamic_min(self): - return self.info.get('memory_dynamic_max') + return self.info.get('memory_dynamic_max', 0) def get_vcpus_policy(self): @@ -1820,7 +1820,7 @@ class XendDomainInfo: def get_builder(self): return self.info.get('builder', 0) def get_boot_method(self): - return self.info.get('boot_method', '') + return self.info.get('boot_method', XEN_API_BOOT_TYPE[2]) def get_kernel_image(self): return self.info.get('kernel_kernel', '') def get_kernel_initrd(self): @@ -1830,7 +1830,7 @@ class XendDomainInfo: def get_grub_cmdline(self): return '' # TODO def get_pci_bus(self): - return 0 # TODO + return '' # TODO def get_tools_version(self): return {} # TODO def get_other_config(self): @@ -1925,18 +1925,16 @@ class XendDomainInfo: config['network'] = '' # Invalid for Xend config['MTU'] = 1500 # TODO - config['network_read_kbs'] = 0.0 - config['network_write_kbs'] = 0.0 - config['IO_bandwidth_incoming_kbs'] = 0.0 - config['IO_bandwidth_outgoing_kbs'] = 0.0 + config['io_read_kbs'] = 0.0 + config['io_write_kbs'] = 0.0 if dev_class == 'vbd': - config['VDI'] = '' # TODO + config['VDI'] = config.get('VDI', '') config['device'] = config.get('dev', '') config['driver'] = 'paravirtualised' # TODO config['image'] = config.get('uname', '') - config['IO_bandwidth_incoming_kbs'] = 0.0 - config['IO_bandwidth_outgoing_kbs'] = 0.0 + config['io_read_kbs'] = 0.0 + config['io_write_kbs'] = 0.0 if config['mode'] == 'r': config['mode'] = 'RO' else: @@ -2050,27 +2048,7 @@ class XendDomainInfo: return dev_uuid def has_device(self, dev_class, dev_uuid): - return (dev_uuid in self.info['%s_refs' % dev_class]) - - """ - def stateChar(name): - if name in self.info: - if self.info[name]: - return name[0] - else: - return '-' - else: - return '?' - - state = reduce(lambda x, y: x + y, map(stateChar, DOM_STATES_OLD)) - - sxpr.append(['state', state]) - - if self.store_mfn: - sxpr.append(['store_mfn', self.store_mfn]) - if self.console_mfn: - sxpr.append(['console_mfn', self.console_mfn]) - """ + return (dev_uuid in self.info['%s_refs' % dev_class.lower()]) def __str__(self): return '' % \ From a8b5e33ac829c0adb072c2acd67993fc1a77be39 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 7 Dec 2006 16:43:08 +0000 Subject: [PATCH 51/69] [LINUX] Fail gracefully if we run out of spare IRQs. Signed-off-by: Keir Fraser --- .../arch/i386/kernel/time-xen.c | 24 ++++--- .../drivers/xen/core/evtchn.c | 38 ++++++++--- .../drivers/xen/core/smpboot.c | 68 ++++++++++++------- .../drivers/xen/netback/netback.c | 13 ++-- 4 files changed, 93 insertions(+), 50 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index 93388ea67a..816b890050 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -1047,9 +1047,9 @@ void time_resume(void) #ifdef CONFIG_SMP static char timer_name[NR_CPUS][15]; -void local_setup_timer(unsigned int cpu) +int local_setup_timer(unsigned int cpu) { - int seq; + int seq, irq; BUG_ON(cpu == 0); @@ -1062,15 +1062,17 @@ void local_setup_timer(unsigned int cpu) } while (read_seqretry(&xtime_lock, seq)); sprintf(timer_name[cpu], "timer%d", cpu); - per_cpu(timer_irq, cpu) = - bind_virq_to_irqhandler( - VIRQ_TIMER, - cpu, - timer_interrupt, - SA_INTERRUPT, - timer_name[cpu], - NULL); - BUG_ON(per_cpu(timer_irq, cpu) < 0); + irq = bind_virq_to_irqhandler(VIRQ_TIMER, + cpu, + timer_interrupt, + SA_INTERRUPT, + timer_name[cpu], + NULL); + if (irq < 0) + return irq; + per_cpu(timer_irq, cpu) = irq; + + return 0; } void local_teardown_timer(unsigned int cpu) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c index b455a3b10a..d596da3888 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c @@ -251,8 +251,15 @@ static int find_unbound_irq(void) if (irq_bindcount[irq] == 0) break; - if (irq == NR_IRQS) - panic("No available IRQ to bind to: increase NR_IRQS!\n"); + if (irq == NR_IRQS) { + static int warned; + if (!warned) { + warned = 1; + printk(KERN_WARNING "No available IRQ to bind to: " + "increase NR_IRQS!\n"); + } + return -ENOSPC; + } return irq; } @@ -264,15 +271,17 @@ static int bind_evtchn_to_irq(unsigned int evtchn) spin_lock(&irq_mapping_update_lock); if ((irq = evtchn_to_irq[evtchn]) == -1) { - irq = find_unbound_irq(); + if ((irq = find_unbound_irq()) < 0) + goto out; + evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); } irq_bindcount[irq]++; + out: spin_unlock(&irq_mapping_update_lock); - return irq; } @@ -284,6 +293,9 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) spin_lock(&irq_mapping_update_lock); if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { + if ((irq = find_unbound_irq()) < 0) + goto out; + bind_virq.virq = virq; bind_virq.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, @@ -291,7 +303,6 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) BUG(); evtchn = bind_virq.port; - irq = find_unbound_irq(); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); @@ -302,8 +313,8 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) irq_bindcount[irq]++; + out: spin_unlock(&irq_mapping_update_lock); - return irq; } @@ -315,13 +326,15 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) spin_lock(&irq_mapping_update_lock); if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) { + if ((irq = find_unbound_irq()) < 0) + goto out; + bind_ipi.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0) BUG(); evtchn = bind_ipi.port; - irq = find_unbound_irq(); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); @@ -332,8 +345,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) irq_bindcount[irq]++; + out: spin_unlock(&irq_mapping_update_lock); - return irq; } @@ -383,6 +396,9 @@ int bind_evtchn_to_irqhandler( int retval; irq = bind_evtchn_to_irq(evtchn); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); @@ -405,6 +421,9 @@ int bind_virq_to_irqhandler( int retval; irq = bind_virq_to_irq(virq, cpu); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); @@ -427,6 +446,9 @@ int bind_ipi_to_irqhandler( int retval; irq = bind_ipi_to_irq(ipi, cpu); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); diff --git a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c index 2538791d0e..36d5a884d4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c @@ -33,7 +33,7 @@ extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *); extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *); -extern void local_setup_timer(unsigned int cpu); +extern int local_setup_timer(unsigned int cpu); extern void local_teardown_timer(unsigned int cpu); extern void hypervisor_callback(void); @@ -110,32 +110,45 @@ set_cpu_sibling_map(int cpu) cpu_data[cpu].booted_cores = 1; } -static void xen_smp_intr_init(unsigned int cpu) +static int xen_smp_intr_init(unsigned int cpu) { + int rc; + + per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1; + sprintf(resched_name[cpu], "resched%d", cpu); - per_cpu(resched_irq, cpu) = - bind_ipi_to_irqhandler( - RESCHEDULE_VECTOR, - cpu, - smp_reschedule_interrupt, - SA_INTERRUPT, - resched_name[cpu], - NULL); - BUG_ON(per_cpu(resched_irq, cpu) < 0); + rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, + cpu, + smp_reschedule_interrupt, + SA_INTERRUPT, + resched_name[cpu], + NULL); + if (rc < 0) + goto fail; + per_cpu(resched_irq, cpu) = rc; sprintf(callfunc_name[cpu], "callfunc%d", cpu); - per_cpu(callfunc_irq, cpu) = - bind_ipi_to_irqhandler( - CALL_FUNCTION_VECTOR, - cpu, - smp_call_function_interrupt, - SA_INTERRUPT, - callfunc_name[cpu], - NULL); - BUG_ON(per_cpu(callfunc_irq, cpu) < 0); + rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR, + cpu, + smp_call_function_interrupt, + SA_INTERRUPT, + callfunc_name[cpu], + NULL); + if (rc < 0) + goto fail; + per_cpu(callfunc_irq, cpu) = rc; - if (cpu != 0) - local_setup_timer(cpu); + if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0)) + goto fail; + + return 0; + + fail: + if (per_cpu(resched_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); + if (per_cpu(callfunc_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); + return rc; } #ifdef CONFIG_HOTPLUG_CPU @@ -253,7 +266,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) set_cpu_sibling_map(0); - xen_smp_intr_init(0); + if (xen_smp_intr_init(0)) + BUG(); /* Restrict the possible_map according to max_cpus. */ while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) { @@ -419,7 +433,13 @@ int __devinit __cpu_up(unsigned int cpu) set_cpu_sibling_map(cpu); wmb(); - xen_smp_intr_init(cpu); + + rc = xen_smp_intr_init(cpu); + if (rc) { + remove_siblinginfo(cpu); + return rc; + } + cpu_set(cpu, cpu_online_map); rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index 1d24fc9b88..f05802aa2e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -1506,13 +1506,12 @@ static int __init netback_init(void) netif_xenbus_init(); #ifdef NETBE_DEBUG_INTERRUPT - (void)bind_virq_to_irqhandler( - VIRQ_DEBUG, - 0, - netif_be_dbg, - SA_SHIRQ, - "net-be-dbg", - &netif_be_dbg); + (void)bind_virq_to_irqhandler(VIRQ_DEBUG, + 0, + netif_be_dbg, + SA_SHIRQ, + "net-be-dbg", + &netif_be_dbg); #endif return 0; From eee69a2a82227a8491c69fd3b11c77bf2f543e90 Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Thu, 7 Dec 2006 16:43:22 +0000 Subject: [PATCH 52/69] [XEND] Only return valid VIF and VBD parameters via Xen API. Also fix typo for memory_dynamic_{min,max}. Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendAPI.py | 19 +++++++++++++++---- tools/python/xen/xend/XendDomainInfo.py | 4 ++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index f59153e68b..e2640589ec 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1057,7 +1057,16 @@ class XendAPI: cfg = vm.get_dev_xenapi_config('vbd', vbd_ref) if not cfg: return xen_api_error(XEND_ERROR_VBD_INVALID) - return xen_api_success(cfg) + + valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \ + self.Base_attr_ro + self.Base_attr_rw + + return_cfg = {} + for k in cfg.keys(): + if k in valid_vbd_keys: + return_cfg[k] = cfg[k] + + return xen_api_success(return_cfg) def VBD_media_change(self, session, vbd_ref, vdi_ref): return xen_api_error(XEND_ERROR_UNSUPPORTED) @@ -1134,14 +1143,16 @@ class XendAPI: cfg = vm.get_dev_xenapi_config('vif', vif_ref) if not cfg: return xen_api_error(XEND_ERROR_VIF_INVALID) + valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \ self.Base_attr_ro + self.Base_attr_rw + return_cfg = {} for k in cfg.keys(): - if k not in valid_vif_keys: - del cfg[k] + if k in valid_vif_keys: + return_cfg[k] = cfg[k] - return xen_api_success(cfg) + return xen_api_success(return_cfg) # class methods def VIF_create(self, session, vif_struct): diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 3716be8462..29ce17083c 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1784,9 +1784,9 @@ class XendDomainInfo: def get_memory_static_min(self): return self.info.get('memory_static_min', 0) def get_memory_dynamic_max(self): - return self.info.get('memory_dynamic_min', 0) - def get_memory_dynamic_min(self): return self.info.get('memory_dynamic_max', 0) + def get_memory_dynamic_min(self): + return self.info.get('memory_dynamic_min', 0) def get_vcpus_policy(self): From 4f2a113ba67dbdae178b2beb12a39dbaf0e70ff6 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 17:47:43 +0000 Subject: [PATCH 53/69] Diagnose bad config files. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 9151848d30..6850061908 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -335,17 +335,22 @@ all_commands = (domain_commands + host_commands + scheduler_commands + # Configuration File Parsing ## +config = None if os.path.isfile(XM_CONFIG_FILE): - config = xml.dom.minidom.parse(XM_CONFIG_FILE) -else: - config = None + try: + config = xml.dom.minidom.parse(XM_CONFIG_FILE) + except: + print >>sys.stderr, ('Ignoring invalid configuration file %s.' % + XM_CONFIG_FILE) def parseServer(): if config: server = config.getElementsByTagName('server') if server: st = server[0].getAttribute('type') - if st != SERVER_XEN_API: + if st != SERVER_XEN_API and st != SERVER_LEGACY_XMLRPC: + print >>sys.stderr, ('Invalid server type %s; using %s.' % + (st, SERVER_LEGACY_XMLRPC)) st = SERVER_LEGACY_XMLRPC return (st, server[0].getAttribute('uri')) From ff3ba258ad75c5bcf4ffb837c05104314c586c7d Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 7 Dec 2006 17:48:35 +0000 Subject: [PATCH 54/69] Fix PERROR. Signed-off-by: Ewan Mellor --- tools/libxc/xc_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 2ddec3f988..f087e7de69 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -63,7 +63,7 @@ void xc_set_error(int code, const char *fmt, ...); #define ERROR(_m, _a...) xc_set_error(XC_INTERNAL_ERROR, _m , ## _a ) #define PERROR(_m, _a...) xc_set_error(XC_INTERNAL_ERROR, _m " (%d = %s)", \ - _m , ## _a , errno, strerror(errno)) + ## _a , errno, strerror(errno)) int lock_pages(void *addr, size_t len); void unlock_pages(void *addr, size_t len); From e80c00aa787316a5080496b47418d91eaf3dccf5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 09:19:37 +0000 Subject: [PATCH 55/69] [LINUX] Clean up and clarify find_unbound_irq(). Signed-off-by: Keir Fraser --- .../drivers/xen/core/evtchn.c | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c index d596da3888..445cacf785 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c @@ -244,24 +244,22 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) static int find_unbound_irq(void) { - int irq; + static int warned; + int dynirq, irq; - /* Only allocate from dynirq range */ - for (irq = DYNIRQ_BASE; irq < NR_IRQS; irq++) + for (dynirq = 0; dynirq < NR_DYNIRQS; dynirq++) { + irq = dynirq_to_irq(dynirq); if (irq_bindcount[irq] == 0) - break; - - if (irq == NR_IRQS) { - static int warned; - if (!warned) { - warned = 1; - printk(KERN_WARNING "No available IRQ to bind to: " - "increase NR_IRQS!\n"); - } - return -ENOSPC; + return irq; } - return irq; + if (!warned) { + warned = 1; + printk(KERN_WARNING "No available IRQ to bind to: " + "increase NR_DYNIRQS.\n"); + } + + return -ENOSPC; } static int bind_evtchn_to_irq(unsigned int evtchn) From 27c982df5e2b051941188900874b664092a0482c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 09:27:39 +0000 Subject: [PATCH 56/69] [LINUX] Make xb_waitq static. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c | 2 +- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c index f0e42ba715..e5af661c87 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @@ -52,7 +52,7 @@ extern void xenbus_probe(void *); extern int xenstored_ready; static DECLARE_WORK(probe_work, xenbus_probe, NULL); -DECLARE_WAIT_QUEUE_HEAD(xb_waitq); +static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs) { diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h index 9599d037c4..b54d168cbb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h @@ -38,7 +38,6 @@ int xb_init_comms(void); int xb_write(const void *data, unsigned len); int xb_read(void *data, unsigned len); int xs_input_avail(void); -extern wait_queue_head_t xb_waitq; extern struct xenstore_domain_interface *xen_store_interface; extern int xen_store_evtchn; From 03ba7e6e162e8f5fa1532dad3eff40e3ce027a22 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 09:32:42 +0000 Subject: [PATCH 57/69] Make XEN_DOMCTL_getdomaininfo return shared_info_frame in gmfn not mfn. Signed-off-by: Isaku Yamahata --- xen/common/domctl.c | 2 +- xen/include/public/domctl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index bf6b8473aa..b05ecd1099 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -126,7 +126,7 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info) info->tot_pages = d->tot_pages; info->max_pages = d->max_pages; - info->shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT; + info->shared_info_frame = mfn_to_gmfn(d, __pa(d->shared_info)>>PAGE_SHIFT); memcpy(info->handle, d->handle, sizeof(xen_domain_handle_t)); } diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 37618ad827..da0b5b2868 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -93,7 +93,7 @@ struct xen_domctl_getdomaininfo { uint32_t flags; /* XEN_DOMINF_* */ uint64_t tot_pages; uint64_t max_pages; - uint64_t shared_info_frame; /* MFN of shared_info struct */ + uint64_t shared_info_frame; /* GMFN of shared_info struct */ uint64_t cpu_time; uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */ From ebeefe4ef6c680c49f84f059265ec4b7f6b0d250 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 09:34:24 +0000 Subject: [PATCH 58/69] [LINUX] Make CONFIG_XEN_FRAMEBUFFER=m build properly. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c index 0111e8e3a2..a11140bda0 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @@ -289,6 +289,7 @@ int xenbus_free_evtchn(struct xenbus_device *dev, int port) return err; } +EXPORT_SYMBOL_GPL(xenbus_free_evtchn); enum xenbus_state xenbus_read_driver_state(const char *path) From 7953e4aa37ebcdb7ad6603512d798de0dd5df77e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 09:35:00 +0000 Subject: [PATCH 59/69] [LINUX] CONFIG_XEN_BACKEND=m build properly. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile | 10 +++------- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile index ce5acc2457..d7091dcbcb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile @@ -1,13 +1,9 @@ -obj-y += xenbus.o +obj-y += xenbus_client.o xenbus_comms.o xenbus_xs.o xenbus_probe.o obj-$(CONFIG_XEN_BACKEND) += xenbus_be.o xenbus_be-objs = xenbus_be-objs += xenbus_backend_client.o -xenbus-objs = -xenbus-objs += xenbus_client.o -xenbus-objs += xenbus_comms.o -xenbus-objs += xenbus_xs.o -xenbus-objs += xenbus_probe.o -obj-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o +xenbus-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o +obj-y += $(xenbus-y) $(xenbus-m) obj-$(CONFIG_XEN_XENBUS_DEV) += xenbus_dev.o diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h index 2d2e567826..417b23e184 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h @@ -34,7 +34,7 @@ #ifndef _XENBUS_PROBE_H #define _XENBUS_PROBE_H -#ifdef CONFIG_XEN_BACKEND +#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE) extern void xenbus_backend_suspend(int (*fn)(struct device *, void *)); extern void xenbus_backend_resume(int (*fn)(struct device *, void *)); extern void xenbus_backend_probe_and_watch(void); From e0abcedc4994deeb7119eeed4f709713e46ab2cc Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 8 Dec 2006 10:32:48 +0000 Subject: [PATCH 60/69] Download and symlink the i386 version of the ramdisk when running on x86_64. This means that people don't need to explicitly set BR_ARCH. Signed-off-by: Ewan Mellor --- tools/xm-test/ramdisk/Makefile.am | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/xm-test/ramdisk/Makefile.am b/tools/xm-test/ramdisk/Makefile.am index 14bfc9267c..b6c59d60e5 100644 --- a/tools/xm-test/ramdisk/Makefile.am +++ b/tools/xm-test/ramdisk/Makefile.am @@ -34,6 +34,7 @@ HVM_SCRIPT = bin/create_disk_image XMTEST_MAJ_VER = $(shell echo @PACKAGE_VERSION@ | perl -pe 's/(\d+)\.(\d+)\.\d+/\1.\2/') XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER)-$(BR_ARCH).img +XMTEST_DL_IMG = $(shell echo $(XMTEST_VER_IMG) | sed -e 's/x86_64/i386/g') EXTRA_ROOT_DIRS = sys @@ -83,7 +84,12 @@ disk.img: existing existing: @if [ -n "$(INITRD)" ] && [ ! -f $(XMTEST_VER_IMG) ] ; then \ - wget $(INITRD)/$(XMTEST_VER_IMG); \ + if [ ! -f $(XMTEST_DL_IMG) ] ; then \ + wget $(INITRD)/$(XMTEST_DL_IMG); \ + fi; \ + if [ "$(XMTEST_DL_IMG)" != "$(XMTEST_VER_IMG)" ] ; then \ + ln -s $(XMTEST_DL_IMG) $(XMTEST_VER_IMG); \ + fi \ fi @if [ -f $(XMTEST_VER_IMG) ] ; then \ ln -sf $(XMTEST_VER_IMG) initrd.img; \ From 9ccd4175a4c9611870e1aa0fabaf965fde72bd9d Mon Sep 17 00:00:00 2001 From: Steven Hand Date: Fri, 8 Dec 2006 10:48:46 +0000 Subject: [PATCH 61/69] Fix potential minor memory leak. Signed-off-by: Steven Hand --- xen/arch/x86/mm/shadow/multi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 211b98b2ed..d9d9bd1c70 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2762,6 +2762,7 @@ static int sh_page_fault(struct vcpu *v, * shadow_set_l*e(), which will have crashed the guest. * Get out of the fault handler immediately. */ ASSERT(test_bit(_DOMF_dying, &d->domain_flags)); + unmap_walk(v, &gw); shadow_unlock(d); return 0; } From a3b9408bafc6cd2a23c0e41676d1abab5a906c9a Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Fri, 8 Dec 2006 11:08:26 +0000 Subject: [PATCH 62/69] [XEND] Fix xm vcpu-set when decrementing VCPU count Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendConfig.py | 5 ++++- tools/python/xen/xend/XendDomainInfo.py | 14 +++++++++++--- tools/python/xen/xm/main.py | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 74ff06284d..9896254f32 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -632,6 +632,9 @@ class XendConfig(dict): self['memory_dynamic_max'] = self['memory_static_max'] self['memory_dynamic_min'] = self['memory_static_min'] + # make sure max_vcpu_id is set correctly + self['max_vcpu_id'] = self['vcpus_number'] - 1 + # set device references in the configuration self['devices'] = cfg.get('devices', {}) @@ -714,7 +717,7 @@ class XendConfig(dict): _set_cfg_if_exists('on_xend_stop') _set_cfg_if_exists('on_xend_start') _set_cfg_if_exists('vcpu_avail') - _set_cfg_if_exists('max_vcpu_id') # TODO, deprecated? + _set_cfg_if_exists('max_vcpu_id') # needed for vcpuDomDetails # Parse and store runtime configuration _set_cfg_if_exists('start_time') diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 29ce17083c..c0a66aaf67 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -876,10 +876,18 @@ class XendDomainInfo: def setVCpuCount(self, vcpus): self.info['vcpu_avail'] = (1 << vcpus) - 1 - self.info['vcpus_number'] = vcpus self.storeVm('vcpu_avail', self.info['vcpu_avail']) - self.storeVm('vcpus', self.info['vcpus_number']) - self._writeDom(self._vcpuDomDetails()) + # update dom differently depending on whether we are adjusting + # vcpu number up or down, otherwise _vcpuDomDetails does not + # disable the vcpus + if self.info['vcpus_number'] > vcpus: + # decreasing + self._writeDom(self._vcpuDomDetails()) + self.info['vcpus_number'] = vcpus + else: + # same or increasing + self.info['vcpus_number'] = vcpus + self._writeDom(self._vcpuDomDetails()) def getLabel(self): return security.get_security_info(self.info, 'label') diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 6850061908..dff8253639 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -643,7 +643,7 @@ def parse_doms_info(info): 'domid' : get_info('domid', str, ''), 'name' : get_info('name', str, '??'), 'mem' : get_info('memory_dynamic_min', int, 0), - 'vcpus' : get_info('vcpus', int, 0), + 'vcpus' : get_info('online_vcpus', int, 0), 'state' : get_info('state', str, ''), 'cpu_time' : get_info('cpu_time', float, 0), 'up_time' : up_time, From 43ff8f0aefb427bc6390c872e5c2a3a800189e1f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 11:30:30 +0000 Subject: [PATCH 63/69] [XEN] Implement XENMEM_set_memory_map, which specifies memory map to be returned by XENMEM_memory_map. Hook this into the domain builder. Based on a patch by Glauber de Oliveira Costa Signed-off-by: Keir Fraser --- tools/libxc/xc_domain.c | 46 ++++++++++++++++++++++++++++++ tools/libxc/xenctrl.h | 4 +++ tools/python/xen/lowlevel/xc/xc.c | 23 +++++++++++++++ tools/python/xen/xend/image.py | 10 ++++++- xen/arch/x86/mm.c | 47 ++++++++++++++++++++++++++++++- xen/include/asm-x86/domain.h | 10 +++---- xen/include/public/memory.h | 17 ++++++++++- 7 files changed, 149 insertions(+), 8 deletions(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index b63e172a22..82aef99ccc 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -316,6 +316,52 @@ int xc_domain_setmaxmem(int xc_handle, return do_domctl(xc_handle, &domctl); } +#if defined(__i386__) || defined(__x86_64__) +#include +int xc_domain_set_memmap_limit(int xc_handle, + uint32_t domid, + unsigned long map_limitkb) +{ + int rc; + + struct xen_foreign_memory_map fmap = { + .domid = domid, + .map = { .nr_entries = 1 } + }; + + struct e820entry e820 = { + .addr = 0, + .size = (uint64_t)map_limitkb << 10, + .type = E820_RAM + }; + + set_xen_guest_handle(fmap.map.buffer, &e820); + + if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) ) + { + PERROR("Could not lock memory for Xen hypercall"); + rc = -1; + goto out; + } + + rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap); + + out: + unlock_pages(&fmap, sizeof(fmap)); + unlock_pages(&e820, sizeof(e820)); + return rc; +} +#else +int xc_domain_set_memmap_limit(int xc_handle, + uint32_t domid, + unsigned long map_limitkb) +{ + PERROR("Function not implemented"); + errno = ENOSYS; + return -1; +} +#endif + int xc_domain_set_time_offset(int xc_handle, uint32_t domid, int32_t time_offset_seconds) diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index d0a9f5db97..00fa713562 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -419,6 +419,10 @@ int xc_domain_setmaxmem(int xc_handle, uint32_t domid, unsigned int max_memkb); +int xc_domain_set_memmap_limit(int xc_handle, + uint32_t domid, + unsigned long map_limitkb); + int xc_domain_set_time_offset(int xc_handle, uint32_t domid, int32_t time_offset_seconds); diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index e74a882fe0..0d68d89f28 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -758,6 +758,21 @@ static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args) return zero; } +static PyObject *pyxc_domain_set_memmap_limit(XcObject *self, PyObject *args) +{ + uint32_t dom; + unsigned int maplimit_kb; + + if ( !PyArg_ParseTuple(args, "ii", &dom, &maplimit_kb) ) + return NULL; + + if ( xc_domain_set_memmap_limit(self->xc_handle, dom, maplimit_kb) != 0 ) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; +} + static PyObject *pyxc_domain_memory_increase_reservation(XcObject *self, PyObject *args, PyObject *kwds) @@ -1141,6 +1156,14 @@ static PyMethodDef pyxc_methods[] = { " maxmem_kb [int]: .\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_set_memmap_limit", + (PyCFunction)pyxc_domain_set_memmap_limit, + METH_VARARGS, "\n" + "Set a domain's physical memory mappping limit\n" + " dom [int]: Identifier of domain.\n" + " map_limitkb [int]: .\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_memory_increase_reservation", (PyCFunction)pyxc_domain_memory_increase_reservation, METH_VARARGS | METH_KEYWORDS, "\n" diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 29eea9dc55..2ccc8615e9 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -548,6 +548,14 @@ class X86_HVM_ImageHandler(HVMImageHandler): return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)), shadow_mem_kb) +class X86_Linux_ImageHandler(LinuxImageHandler): + + def buildDomain(self): + # set physical mapping limit + # add an 8MB slack to balance backend allocations. + mem_kb = self.getRequiredInitialReservation() + (8 * 1024) + xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb) + return LinuxImageHandler.buildDomain(self) _handlers = { "powerpc": { @@ -558,7 +566,7 @@ _handlers = { "hvm": IA64_HVM_ImageHandler, }, "x86": { - "linux": LinuxImageHandler, + "linux": X86_Linux_ImageHandler, "hvm": X86_HVM_ImageHandler, }, } diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 9a965f982b..4fd69400f3 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2978,9 +2978,54 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) break; } + case XENMEM_set_memory_map: + { + struct xen_foreign_memory_map fmap; + struct domain *d; + int rc; + + if ( copy_from_guest(&fmap, arg, 1) ) + return -EFAULT; + + if ( fmap.map.nr_entries > ARRAY_SIZE(d->arch.e820) ) + return -EINVAL; + + if ( fmap.domid == DOMID_SELF ) + { + d = current->domain; + get_knownalive_domain(d); + } + else if ( !IS_PRIV(current->domain) ) + return -EPERM; + else if ( (d = find_domain_by_id(fmap.domid)) == NULL ) + return -ESRCH; + + rc = copy_from_guest(&d->arch.e820[0], fmap.map.buffer, + fmap.map.nr_entries) ? -EFAULT : 0; + d->arch.nr_e820 = fmap.map.nr_entries; + + put_domain(d); + return rc; + } + case XENMEM_memory_map: { - return -ENOSYS; + struct xen_memory_map map; + struct domain *d = current->domain; + + /* Backwards compatibility. */ + if ( d->arch.nr_e820 == 0 ) + return -ENOSYS; + + if ( copy_from_guest(&map, arg, 1) ) + return -EFAULT; + + map.nr_entries = min(map.nr_entries, d->arch.nr_e820); + if ( copy_to_guest(map.buffer, &d->arch.e820[0], map.nr_entries) || + copy_to_guest(arg, &map, 1) ) + return -EFAULT; + + return 0; } case XENMEM_machine_memory_map: diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 20793910ba..efda6dd263 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -5,6 +5,7 @@ #include #include #include +#include struct trap_bounce { unsigned long error_code; @@ -100,11 +101,7 @@ struct arch_domain /* I/O-port admin-specified access capabilities. */ struct rangeset *ioport_caps; - /* HVM stuff */ - struct hvm_domain hvm_domain; - - /* Shadow-translated guest: Pseudophys base address of reserved area. */ - unsigned long first_reserved_pfn; + struct hvm_domain hvm_domain; struct shadow_domain shadow; @@ -113,6 +110,9 @@ struct arch_domain /* Highest guest frame that's ever been mapped in the p2m */ unsigned long max_mapped_pfn; + /* Pseudophysical e820 map (XENMEM_memory_map). */ + struct e820entry e820[3]; + unsigned int nr_e820; } __cacheline_aligned; #ifdef CONFIG_X86_PAE diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index e28ed12620..acbc89b7e7 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -222,7 +222,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_translate_gpfn_list_t); /* * Returns the pseudo-physical memory map as it was when the domain - * was started. + * was started (specified by XENMEM_set_memory_map). + * arg == addr of xen_memory_map_t. */ #define XENMEM_memory_map 9 struct xen_memory_map { @@ -245,9 +246,23 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t); /* * Returns the real physical memory map. Passes the same structure as * XENMEM_memory_map. + * arg == addr of xen_memory_map_t. */ #define XENMEM_machine_memory_map 10 +/* + * Set the pseudo-physical memory map of a domain, as returned by + * XENMEM_memory_map. + * arg == addr of xen_foreign_memory_map_t. + */ +#define XENMEM_set_memory_map 13 +struct xen_foreign_memory_map { + domid_t domid; + struct xen_memory_map map; +}; +typedef struct xen_foreign_memory_map xen_foreign_memory_map_t; +DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t); + #endif /* __XEN_PUBLIC_MEMORY_H__ */ /* From e793ba7d4ead6b2a55a984d4f5c23da971bbfc67 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Dec 2006 11:46:48 +0000 Subject: [PATCH 64/69] [LINUX] Kexec: Do not bug if a kexec hypercall fails. This is non fatal since we can recover and boot without kexec functionality. Signed-off-by: Ian Campbell --- .../drivers/xen/core/machine_kexec.c | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c index 1f4a828e55..5e6b58b390 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c @@ -20,7 +20,7 @@ void xen_machine_kexec_setup_resources(void) { xen_kexec_range_t range; struct resource *res; - int err, k = 0; + int k = 0; if (!is_initial_xendomain()) return; @@ -32,26 +32,21 @@ void xen_machine_kexec_setup_resources(void) range.range = KEXEC_RANGE_MA_CPU; range.nr = k; - /* - * Anything other than EINVAL or success indictates - * that we are not running on a hypervisor which - * supports kexec. - */ - err = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range); - if (err == -EINVAL) + if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range)) break; - else if (err) - return; k++; } + if (k == 0) + return; + xen_max_nr_phys_cpus = k; /* allocate xen_phys_cpus */ xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource)); - BUG_ON(!xen_phys_cpus); + BUG_ON(xen_phys_cpus == NULL); /* fill in xen_phys_cpus with per-cpu crash note information */ @@ -61,7 +56,7 @@ void xen_machine_kexec_setup_resources(void) range.nr = k; if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range)) - BUG(); + goto err; res = xen_phys_cpus + k; @@ -78,7 +73,7 @@ void xen_machine_kexec_setup_resources(void) range.range = KEXEC_RANGE_MA_XEN; if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range)) - BUG(); + goto err; xen_hypervisor_res.name = "Hypervisor code and data"; xen_hypervisor_res.start = range.start; @@ -91,12 +86,23 @@ void xen_machine_kexec_setup_resources(void) range.range = KEXEC_RANGE_MA_CRASH; if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range)) - BUG(); + return; if (range.size) { crashk_res.start = range.start; crashk_res.end = range.start + range.size - 1; } + + return; + + err: + /* + * It isn't possible to free xen_phys_cpus this early in the + * boot. Since failure at this stage is unexpected and the + * amount is small we leak the memory. + */ + xen_max_nr_phys_cpus = 0; + return; } void xen_machine_kexec_register_resources(struct resource *res) From 5a4af387e35b5e86c5e2b4a53e8f1784125c5dd8 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Dec 2006 11:47:09 +0000 Subject: [PATCH 65/69] [LINUX] kexec: remove patches which are not straight backports. Their contents will be added to the sparse tree in a subsequent patch. Changes to kernel/sys.c in kexec-generic.patch remain for now. These will be taken care of in a later patch. Signed-off-by: Ian Campbell --- patches/linux-2.6.16.33/kexec-generic.patch | 213 ----------------- .../linux-2.6.19-rc1-kexec-xen-i386.patch | 108 --------- .../linux-2.6.19-rc1-kexec-xen-x86_64.patch | 219 ------------------ patches/linux-2.6.16.33/series | 2 - 4 files changed, 542 deletions(-) delete mode 100644 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch delete mode 100644 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch diff --git a/patches/linux-2.6.16.33/kexec-generic.patch b/patches/linux-2.6.16.33/kexec-generic.patch index 2e01a7aab0..a85d546e4d 100644 --- a/patches/linux-2.6.16.33/kexec-generic.patch +++ b/patches/linux-2.6.16.33/kexec-generic.patch @@ -1,216 +1,3 @@ ---- 0001/include/linux/kexec.h -+++ work/include/linux/kexec.h -@@ -31,6 +31,13 @@ - #error KEXEC_ARCH not defined - #endif - -+#ifndef KEXEC_ARCH_HAS_PAGE_MACROS -+#define kexec_page_to_pfn(page) page_to_pfn(page) -+#define kexec_pfn_to_page(pfn) pfn_to_page(pfn) -+#define kexec_virt_to_phys(addr) virt_to_phys(addr) -+#define kexec_phys_to_virt(addr) phys_to_virt(addr) -+#endif -+ - /* - * This structure is used to hold the arguments that are used when loading - * kernel binaries. -@@ -91,6 +98,13 @@ struct kimage { - extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET; - extern int machine_kexec_prepare(struct kimage *image); - extern void machine_kexec_cleanup(struct kimage *image); -+#ifdef CONFIG_XEN -+extern int xen_machine_kexec_load(struct kimage *image); -+extern void xen_machine_kexec_unload(struct kimage *image); -+extern NORET_TYPE void xen_machine_kexec(struct kimage *image) ATTRIB_NORET; -+extern void xen_machine_kexec_setup_resources(void); -+extern void xen_machine_kexec_register_resources(struct resource *res); -+#endif - extern asmlinkage long sys_kexec_load(unsigned long entry, - unsigned long nr_segments, - struct kexec_segment __user *segments, ---- 0001/kernel/kexec.c -+++ work/kernel/kexec.c -@@ -403,7 +403,7 @@ static struct page *kimage_alloc_normal_ - pages = kimage_alloc_pages(GFP_KERNEL, order); - if (!pages) - break; -- pfn = page_to_pfn(pages); -+ pfn = kexec_page_to_pfn(pages); - epfn = pfn + count; - addr = pfn << PAGE_SHIFT; - eaddr = epfn << PAGE_SHIFT; -@@ -437,6 +437,7 @@ static struct page *kimage_alloc_normal_ - return pages; - } - -+#ifndef CONFIG_XEN - static struct page *kimage_alloc_crash_control_pages(struct kimage *image, - unsigned int order) - { -@@ -490,7 +491,7 @@ static struct page *kimage_alloc_crash_c - } - /* If I don't overlap any segments I have found my hole! */ - if (i == image->nr_segments) { -- pages = pfn_to_page(hole_start >> PAGE_SHIFT); -+ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT); - break; - } - } -@@ -517,6 +518,13 @@ struct page *kimage_alloc_control_pages( - - return pages; - } -+#else /* !CONFIG_XEN */ -+struct page *kimage_alloc_control_pages(struct kimage *image, -+ unsigned int order) -+{ -+ return kimage_alloc_normal_control_pages(image, order); -+} -+#endif - - static int kimage_add_entry(struct kimage *image, kimage_entry_t entry) - { -@@ -532,7 +540,7 @@ static int kimage_add_entry(struct kimag - return -ENOMEM; - - ind_page = page_address(page); -- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION; -+ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION; - image->entry = ind_page; - image->last_entry = ind_page + - ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1); -@@ -593,13 +601,13 @@ static int kimage_terminate(struct kimag - #define for_each_kimage_entry(image, ptr, entry) \ - for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ - ptr = (entry & IND_INDIRECTION)? \ -- phys_to_virt((entry & PAGE_MASK)): ptr +1) -+ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1) - - static void kimage_free_entry(kimage_entry_t entry) - { - struct page *page; - -- page = pfn_to_page(entry >> PAGE_SHIFT); -+ page = kexec_pfn_to_page(entry >> PAGE_SHIFT); - kimage_free_pages(page); - } - -@@ -611,6 +619,10 @@ static void kimage_free(struct kimage *i - if (!image) - return; - -+#ifdef CONFIG_XEN -+ xen_machine_kexec_unload(image); -+#endif -+ - kimage_free_extra_pages(image); - for_each_kimage_entry(image, ptr, entry) { - if (entry & IND_INDIRECTION) { -@@ -686,7 +698,7 @@ static struct page *kimage_alloc_page(st - * have a match. - */ - list_for_each_entry(page, &image->dest_pages, lru) { -- addr = page_to_pfn(page) << PAGE_SHIFT; -+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT; - if (addr == destination) { - list_del(&page->lru); - return page; -@@ -701,12 +713,12 @@ static struct page *kimage_alloc_page(st - if (!page) - return NULL; - /* If the page cannot be used file it away */ -- if (page_to_pfn(page) > -+ if (kexec_page_to_pfn(page) > - (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { - list_add(&page->lru, &image->unuseable_pages); - continue; - } -- addr = page_to_pfn(page) << PAGE_SHIFT; -+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT; - - /* If it is the destination page we want use it */ - if (addr == destination) -@@ -729,7 +741,7 @@ static struct page *kimage_alloc_page(st - struct page *old_page; - - old_addr = *old & PAGE_MASK; -- old_page = pfn_to_page(old_addr >> PAGE_SHIFT); -+ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT); - copy_highpage(page, old_page); - *old = addr | (*old & ~PAGE_MASK); - -@@ -779,7 +791,7 @@ static int kimage_load_normal_segment(st - result = -ENOMEM; - goto out; - } -- result = kimage_add_page(image, page_to_pfn(page) -+ result = kimage_add_page(image, kexec_page_to_pfn(page) - << PAGE_SHIFT); - if (result < 0) - goto out; -@@ -811,6 +823,7 @@ out: - return result; - } - -+#ifndef CONFIG_XEN - static int kimage_load_crash_segment(struct kimage *image, - struct kexec_segment *segment) - { -@@ -833,7 +846,7 @@ static int kimage_load_crash_segment(str - char *ptr; - size_t uchunk, mchunk; - -- page = pfn_to_page(maddr >> PAGE_SHIFT); -+ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT); - if (page == 0) { - result = -ENOMEM; - goto out; -@@ -881,6 +894,13 @@ static int kimage_load_segment(struct ki - - return result; - } -+#else /* CONFIG_XEN */ -+static int kimage_load_segment(struct kimage *image, -+ struct kexec_segment *segment) -+{ -+ return kimage_load_normal_segment(image, segment); -+} -+#endif - - /* - * Exec Kernel system call: for obvious reasons only root may call it. -@@ -991,6 +1011,11 @@ asmlinkage long sys_kexec_load(unsigned - if (result) - goto out; - } -+#ifdef CONFIG_XEN -+ result = xen_machine_kexec_load(image); -+ if (result) -+ goto out; -+#endif - /* Install the new kernel, and Uninstall the old */ - image = xchg(dest_image, image); - -@@ -1045,7 +1070,6 @@ void crash_kexec(struct pt_regs *regs) - struct kimage *image; - int locked; - -- - /* Take the kexec_lock here to prevent sys_kexec_load - * running on one cpu from replacing the crash kernel - * we are using after a panic on a different cpu. -@@ -1061,7 +1085,11 @@ void crash_kexec(struct pt_regs *regs) - struct pt_regs fixed_regs; - crash_setup_regs(&fixed_regs, regs); - machine_crash_shutdown(&fixed_regs); -+#ifdef CONFIG_XEN -+ xen_machine_kexec(image); -+#else - machine_kexec(image); -+#endif - } - xchg(&kexec_lock, 0); - } --- 0002/kernel/sys.c +++ work/kernel/sys.c @@ -435,8 +435,12 @@ void kernel_kexec(void) diff --git a/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch b/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch deleted file mode 100644 index 93480f9528..0000000000 --- a/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch +++ /dev/null @@ -1,108 +0,0 @@ ---- 0001/arch/i386/kernel/crash.c -+++ work/arch/i386/kernel/crash.c -@@ -90,6 +90,7 @@ static void crash_save_self(struct pt_re - crash_save_this_cpu(regs, cpu); - } - -+#ifndef CONFIG_XEN - #ifdef CONFIG_SMP - static atomic_t waiting_for_crash_ipi; - -@@ -158,6 +159,7 @@ static void nmi_shootdown_cpus(void) - /* There are no cpus to shootdown */ - } - #endif -+#endif /* CONFIG_XEN */ - - void machine_crash_shutdown(struct pt_regs *regs) - { -@@ -174,10 +176,12 @@ void machine_crash_shutdown(struct pt_re - - /* Make a note of crashing cpu. Will be used in NMI callback.*/ - crashing_cpu = smp_processor_id(); -+#ifndef CONFIG_XEN - nmi_shootdown_cpus(); - lapic_shutdown(); - #if defined(CONFIG_X86_IO_APIC) - disable_IO_APIC(); - #endif -+#endif /* CONFIG_XEN */ - crash_save_self(regs); - } ---- 0007/arch/i386/kernel/machine_kexec.c -+++ work/arch/i386/kernel/machine_kexec.c -@@ -19,6 +19,10 @@ - #include - #include - -+#ifdef CONFIG_XEN -+#include -+#endif -+ - #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) - static u32 kexec_pgd[1024] PAGE_ALIGNED; - #ifdef CONFIG_X86_PAE -@@ -28,6 +32,40 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED - static u32 kexec_pte0[1024] PAGE_ALIGNED; - static u32 kexec_pte1[1024] PAGE_ALIGNED; - -+#ifdef CONFIG_XEN -+ -+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT) -+ -+#if PAGES_NR > KEXEC_XEN_NO_PAGES -+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break -+#endif -+ -+#if PA_CONTROL_PAGE != 0 -+#error PA_CONTROL_PAGE is non zero - Xen support will break -+#endif -+ -+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image) -+{ -+ void *control_page; -+ -+ memset(xki->page_list, 0, sizeof(xki->page_list)); -+ -+ control_page = page_address(image->control_code_page); -+ memcpy(control_page, relocate_kernel, PAGE_SIZE); -+ -+ xki->page_list[PA_CONTROL_PAGE] = __ma(control_page); -+ xki->page_list[PA_PGD] = __ma(kexec_pgd); -+#ifdef CONFIG_X86_PAE -+ xki->page_list[PA_PMD_0] = __ma(kexec_pmd0); -+ xki->page_list[PA_PMD_1] = __ma(kexec_pmd1); -+#endif -+ xki->page_list[PA_PTE_0] = __ma(kexec_pte0); -+ xki->page_list[PA_PTE_1] = __ma(kexec_pte1); -+ -+} -+ -+#endif /* CONFIG_XEN */ -+ - /* - * A architecture hook called to validate the - * proposed image and prepare the control pages ---- 0006/include/asm-i386/kexec.h -+++ work/include/asm-i386/kexec.h -@@ -98,6 +98,20 @@ relocate_kernel(unsigned long indirectio - unsigned long start_address, - unsigned int has_pae) ATTRIB_NORET; - -+ -+/* Under Xen we need to work with machine addresses. These macros give the -+ * machine address of a certain page to the generic kexec code instead of -+ * the pseudo physical address which would be given by the default macros. -+ */ -+ -+#ifdef CONFIG_XEN -+#define KEXEC_ARCH_HAS_PAGE_MACROS -+#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page)) -+#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn)) -+#define kexec_virt_to_phys(addr) virt_to_machine(addr) -+#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr)) -+#endif -+ - #endif /* __ASSEMBLY__ */ - - #endif /* _I386_KEXEC_H */ diff --git a/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch b/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch deleted file mode 100644 index c387519889..0000000000 --- a/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch +++ /dev/null @@ -1,219 +0,0 @@ ---- 0001/arch/x86_64/kernel/crash.c -+++ work/arch/x86_64/kernel/crash.c -@@ -92,6 +92,7 @@ static void crash_save_self(struct pt_re - crash_save_this_cpu(regs, cpu); - } - -+#ifndef CONFIG_XEN - #ifdef CONFIG_SMP - static atomic_t waiting_for_crash_ipi; - -@@ -156,6 +157,7 @@ static void nmi_shootdown_cpus(void) - /* There are no cpus to shootdown */ - } - #endif -+#endif /* CONFIG_XEN */ - - void machine_crash_shutdown(struct pt_regs *regs) - { -@@ -173,6 +175,8 @@ void machine_crash_shutdown(struct pt_re - - /* Make a note of crashing cpu. Will be used in NMI callback.*/ - crashing_cpu = smp_processor_id(); -+ -+#ifndef CONFIG_XEN - nmi_shootdown_cpus(); - - if(cpu_has_apic) -@@ -181,6 +185,6 @@ void machine_crash_shutdown(struct pt_re - #if defined(CONFIG_X86_IO_APIC) - disable_IO_APIC(); - #endif -- -+#endif /* CONFIG_XEN */ - crash_save_self(regs); - } ---- 0010/arch/x86_64/kernel/machine_kexec.c -+++ work/arch/x86_64/kernel/machine_kexec.c -@@ -24,6 +24,104 @@ static u64 kexec_pud1[512] PAGE_ALIGNED; - static u64 kexec_pmd1[512] PAGE_ALIGNED; - static u64 kexec_pte1[512] PAGE_ALIGNED; - -+#ifdef CONFIG_XEN -+ -+/* In the case of Xen, override hypervisor functions to be able to create -+ * a regular identity mapping page table... -+ */ -+ -+#include -+#include -+ -+#define x__pmd(x) ((pmd_t) { (x) } ) -+#define x__pud(x) ((pud_t) { (x) } ) -+#define x__pgd(x) ((pgd_t) { (x) } ) -+ -+#define x_pmd_val(x) ((x).pmd) -+#define x_pud_val(x) ((x).pud) -+#define x_pgd_val(x) ((x).pgd) -+ -+static inline void x_set_pmd(pmd_t *dst, pmd_t val) -+{ -+ x_pmd_val(*dst) = x_pmd_val(val); -+} -+ -+static inline void x_set_pud(pud_t *dst, pud_t val) -+{ -+ x_pud_val(*dst) = phys_to_machine(x_pud_val(val)); -+} -+ -+static inline void x_pud_clear (pud_t *pud) -+{ -+ x_pud_val(*pud) = 0; -+} -+ -+static inline void x_set_pgd(pgd_t *dst, pgd_t val) -+{ -+ x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val)); -+} -+ -+static inline void x_pgd_clear (pgd_t * pgd) -+{ -+ x_pgd_val(*pgd) = 0; -+} -+ -+#define X__PAGE_KERNEL_LARGE_EXEC \ -+ _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE -+#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY -+ -+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT) -+ -+#if PAGES_NR > KEXEC_XEN_NO_PAGES -+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break -+#endif -+ -+#if PA_CONTROL_PAGE != 0 -+#error PA_CONTROL_PAGE is non zero - Xen support will break -+#endif -+ -+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image) -+{ -+ void *control_page; -+ void *table_page; -+ -+ memset(xki->page_list, 0, sizeof(xki->page_list)); -+ -+ control_page = page_address(image->control_code_page) + PAGE_SIZE; -+ memcpy(control_page, relocate_kernel, PAGE_SIZE); -+ -+ table_page = page_address(image->control_code_page); -+ -+ xki->page_list[PA_CONTROL_PAGE] = __ma(control_page); -+ xki->page_list[PA_TABLE_PAGE] = __ma(table_page); -+ -+ xki->page_list[PA_PGD] = __ma(kexec_pgd); -+ xki->page_list[PA_PUD_0] = __ma(kexec_pud0); -+ xki->page_list[PA_PUD_1] = __ma(kexec_pud1); -+ xki->page_list[PA_PMD_0] = __ma(kexec_pmd0); -+ xki->page_list[PA_PMD_1] = __ma(kexec_pmd1); -+ xki->page_list[PA_PTE_0] = __ma(kexec_pte0); -+ xki->page_list[PA_PTE_1] = __ma(kexec_pte1); -+} -+ -+#else /* CONFIG_XEN */ -+ -+#define x__pmd(x) __pmd(x) -+#define x__pud(x) __pud(x) -+#define x__pgd(x) __pgd(x) -+ -+#define x_set_pmd(x, y) set_pmd(x, y) -+#define x_set_pud(x, y) set_pud(x, y) -+#define x_set_pgd(x, y) set_pgd(x, y) -+ -+#define x_pud_clear(x) pud_clear(x) -+#define x_pgd_clear(x) pgd_clear(x) -+ -+#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC -+#define X_KERNPG_TABLE _KERNPG_TABLE -+ -+#endif /* CONFIG_XEN */ -+ - static void init_level2_page(pmd_t *level2p, unsigned long addr) - { - unsigned long end_addr; -@@ -31,7 +129,7 @@ static void init_level2_page(pmd_t *leve - addr &= PAGE_MASK; - end_addr = addr + PUD_SIZE; - while (addr < end_addr) { -- set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); -+ x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC)); - addr += PMD_SIZE; - } - } -@@ -56,12 +154,12 @@ static int init_level3_page(struct kimag - } - level2p = (pmd_t *)page_address(page); - init_level2_page(level2p, addr); -- set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE)); -+ x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE)); - addr += PUD_SIZE; - } - /* clear the unused entries */ - while (addr < end_addr) { -- pud_clear(level3p++); -+ x_pud_clear(level3p++); - addr += PUD_SIZE; - } - out: -@@ -92,12 +190,12 @@ static int init_level4_page(struct kimag - if (result) { - goto out; - } -- set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); -+ x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE)); - addr += PGDIR_SIZE; - } - /* clear the unused entries */ - while (addr < end_addr) { -- pgd_clear(level4p++); -+ x_pgd_clear(level4p++); - addr += PGDIR_SIZE; - } - out: -@@ -108,8 +206,14 @@ out: - static int init_pgtable(struct kimage *image, unsigned long start_pgtable) - { - pgd_t *level4p; -+ unsigned long x_end_pfn = end_pfn; -+ -+#ifdef CONFIG_XEN -+ x_end_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL); -+#endif -+ - level4p = (pgd_t *)__va(start_pgtable); -- return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT); -+ return init_level4_page(image, level4p, 0, x_end_pfn << PAGE_SHIFT); - } - - int machine_kexec_prepare(struct kimage *image) ---- 0009/include/asm-x86_64/kexec.h -+++ work/include/asm-x86_64/kexec.h -@@ -91,6 +91,19 @@ relocate_kernel(unsigned long indirectio - unsigned long page_list, - unsigned long start_address) ATTRIB_NORET; - -+/* Under Xen we need to work with machine addresses. These macros give the -+ * machine address of a certain page to the generic kexec code instead of -+ * the pseudo physical address which would be given by the default macros. -+ */ -+ -+#ifdef CONFIG_XEN -+#define KEXEC_ARCH_HAS_PAGE_MACROS -+#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page)) -+#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn)) -+#define kexec_virt_to_phys(addr) virt_to_machine(addr) -+#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr)) -+#endif -+ - #endif /* __ASSEMBLY__ */ - - #endif /* _X86_64_KEXEC_H */ diff --git a/patches/linux-2.6.16.33/series b/patches/linux-2.6.16.33/series index 1f01b4033f..604aed27e9 100644 --- a/patches/linux-2.6.16.33/series +++ b/patches/linux-2.6.16.33/series @@ -3,10 +3,8 @@ git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch linux-2.6.19-rc1-kexec-move_segment_code-i386.patch -linux-2.6.19-rc1-kexec-xen-i386.patch git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch -linux-2.6.19-rc1-kexec-xen-x86_64.patch blktap-aio-16_03_06.patch device_bind.patch fix-hz-suspend.patch From 24a9aad534dd075c8ed0619fb2fa02c33b86754a Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Dec 2006 11:47:09 +0000 Subject: [PATCH 66/69] [LINUX] Kexec: add kexec files to sparse tree. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/arch/i386/kernel/crash.c | 183 +++ .../arch/i386/kernel/machine_kexec.c | 89 ++ .../arch/x86_64/kernel/crash.c | 186 +++ .../arch/x86_64/kernel/machine_kexec.c | 173 +++ linux-2.6-xen-sparse/include/asm-i386/kexec.h | 103 ++ .../include/asm-x86_64/kexec.h | 96 ++ linux-2.6-xen-sparse/include/linux/kexec.h | 139 +++ linux-2.6-xen-sparse/kernel/kexec.c | 1081 +++++++++++++++++ 8 files changed, 2050 insertions(+) create mode 100644 linux-2.6-xen-sparse/arch/i386/kernel/crash.c create mode 100644 linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c create mode 100644 linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c create mode 100644 linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c create mode 100644 linux-2.6-xen-sparse/include/asm-i386/kexec.h create mode 100644 linux-2.6-xen-sparse/include/asm-x86_64/kexec.h create mode 100644 linux-2.6-xen-sparse/include/linux/kexec.h create mode 100644 linux-2.6-xen-sparse/kernel/kexec.c diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/crash.c b/linux-2.6-xen-sparse/arch/i386/kernel/crash.c new file mode 100644 index 0000000000..d49dbe8dc9 --- /dev/null +++ b/linux-2.6-xen-sparse/arch/i386/kernel/crash.c @@ -0,0 +1,183 @@ +/* + * Architecture specific (i386) functions for kexec based crash dumps. + * + * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) + * + * Copyright (C) IBM Corporation, 2004. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* This keeps a track of which one is crashing cpu. */ +static int crashing_cpu; + +static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, + size_t data_len) +{ + struct elf_note note; + + note.n_namesz = strlen(name) + 1; + note.n_descsz = data_len; + note.n_type = type; + memcpy(buf, ¬e, sizeof(note)); + buf += (sizeof(note) +3)/4; + memcpy(buf, name, note.n_namesz); + buf += (note.n_namesz + 3)/4; + memcpy(buf, data, note.n_descsz); + buf += (note.n_descsz + 3)/4; + + return buf; +} + +static void final_note(u32 *buf) +{ + struct elf_note note; + + note.n_namesz = 0; + note.n_descsz = 0; + note.n_type = 0; + memcpy(buf, ¬e, sizeof(note)); +} + +static void crash_save_this_cpu(struct pt_regs *regs, int cpu) +{ + struct elf_prstatus prstatus; + u32 *buf; + + if ((cpu < 0) || (cpu >= NR_CPUS)) + return; + + /* Using ELF notes here is opportunistic. + * I need a well defined structure format + * for the data I pass, and I need tags + * on the data to indicate what information I have + * squirrelled away. ELF notes happen to provide + * all of that that no need to invent something new. + */ + buf = (u32*)per_cpu_ptr(crash_notes, cpu); + if (!buf) + return; + memset(&prstatus, 0, sizeof(prstatus)); + prstatus.pr_pid = current->pid; + elf_core_copy_regs(&prstatus.pr_reg, regs); + buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, + sizeof(prstatus)); + final_note(buf); +} + +static void crash_save_self(struct pt_regs *regs) +{ + int cpu; + + cpu = smp_processor_id(); + crash_save_this_cpu(regs, cpu); +} + +#ifdef CONFIG_SMP +static atomic_t waiting_for_crash_ipi; + +static int crash_nmi_callback(struct pt_regs *regs, int cpu) +{ + struct pt_regs fixed_regs; + + /* Don't do anything if this handler is invoked on crashing cpu. + * Otherwise, system will completely hang. Crashing cpu can get + * an NMI if system was initially booted with nmi_watchdog parameter. + */ + if (cpu == crashing_cpu) + return 1; + local_irq_disable(); + + if (!user_mode(regs)) { + crash_fixup_ss_esp(&fixed_regs, regs); + regs = &fixed_regs; + } + crash_save_this_cpu(regs, cpu); + disable_local_APIC(); + atomic_dec(&waiting_for_crash_ipi); + /* Assume hlt works */ + halt(); + for(;;); + + return 1; +} + +/* + * By using the NMI code instead of a vector we just sneak thru the + * word generator coming out with just what we want. AND it does + * not matter if clustered_apic_mode is set or not. + */ +static void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} + +static void nmi_shootdown_cpus(void) +{ + unsigned long msecs; + + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); + /* Would it be better to replace the trap vector here? */ + set_nmi_callback(crash_nmi_callback); + /* Ensure the new callback function is set before sending + * out the NMI + */ + wmb(); + + smp_send_nmi_allbutself(); + + msecs = 1000; /* Wait at most a second for the other cpus to stop */ + while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { + mdelay(1); + msecs--; + } + + /* Leave the nmi callback set */ + disable_local_APIC(); +} +#else +static void nmi_shootdown_cpus(void) +{ + /* There are no cpus to shootdown */ +} +#endif + +void machine_crash_shutdown(struct pt_regs *regs) +{ + /* This function is only called after the system + * has paniced or is otherwise in a critical state. + * The minimum amount of code to allow a kexec'd kernel + * to run successfully needs to happen here. + * + * In practice this means shooting down the other cpus in + * an SMP system. + */ + /* The kernel is broken so disable interrupts */ + local_irq_disable(); + + /* Make a note of crashing cpu. Will be used in NMI callback.*/ + crashing_cpu = smp_processor_id(); + nmi_shootdown_cpus(); + lapic_shutdown(); +#if defined(CONFIG_X86_IO_APIC) + disable_IO_APIC(); +#endif + crash_save_self(regs); +} diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c b/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c new file mode 100644 index 0000000000..00e1c189fc --- /dev/null +++ b/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c @@ -0,0 +1,89 @@ +/* + * machine_kexec.c - handle transition of Linux booting another kernel + * Copyright (C) 2002-2005 Eric Biederman + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) +static u32 kexec_pgd[1024] PAGE_ALIGNED; +#ifdef CONFIG_X86_PAE +static u32 kexec_pmd0[1024] PAGE_ALIGNED; +static u32 kexec_pmd1[1024] PAGE_ALIGNED; +#endif +static u32 kexec_pte0[1024] PAGE_ALIGNED; +static u32 kexec_pte1[1024] PAGE_ALIGNED; + +/* + * A architecture hook called to validate the + * proposed image and prepare the control pages + * as needed. The pages for KEXEC_CONTROL_CODE_SIZE + * have been allocated, but the segments have yet + * been copied into the kernel. + * + * Do what every setup is needed on image and the + * reboot code buffer to allow us to avoid allocations + * later. + * + * Currently nothing. + */ +int machine_kexec_prepare(struct kimage *image) +{ + return 0; +} + +/* + * Undo anything leftover by machine_kexec_prepare + * when an image is freed. + */ +void machine_kexec_cleanup(struct kimage *image) +{ +} + +/* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. + */ +NORET_TYPE void machine_kexec(struct kimage *image) +{ + unsigned long page_list[PAGES_NR]; + void *control_page; + + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + control_page = page_address(image->control_code_page); + memcpy(control_page, relocate_kernel, PAGE_SIZE); + + page_list[PA_CONTROL_PAGE] = __pa(control_page); + page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; + page_list[PA_PGD] = __pa(kexec_pgd); + page_list[VA_PGD] = (unsigned long)kexec_pgd; +#ifdef CONFIG_X86_PAE + page_list[PA_PMD_0] = __pa(kexec_pmd0); + page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; + page_list[PA_PMD_1] = __pa(kexec_pmd1); + page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; +#endif + page_list[PA_PTE_0] = __pa(kexec_pte0); + page_list[VA_PTE_0] = (unsigned long)kexec_pte0; + page_list[PA_PTE_1] = __pa(kexec_pte1); + page_list[VA_PTE_1] = (unsigned long)kexec_pte1; + + relocate_kernel((unsigned long)image->head, (unsigned long)page_list, + image->start, cpu_has_pae); +} diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c new file mode 100644 index 0000000000..4e6c3b729e --- /dev/null +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c @@ -0,0 +1,186 @@ +/* + * Architecture specific (x86_64) functions for kexec based crash dumps. + * + * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) + * + * Copyright (C) IBM Corporation, 2004. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* This keeps a track of which one is crashing cpu. */ +static int crashing_cpu; + +static u32 *append_elf_note(u32 *buf, char *name, unsigned type, + void *data, size_t data_len) +{ + struct elf_note note; + + note.n_namesz = strlen(name) + 1; + note.n_descsz = data_len; + note.n_type = type; + memcpy(buf, ¬e, sizeof(note)); + buf += (sizeof(note) +3)/4; + memcpy(buf, name, note.n_namesz); + buf += (note.n_namesz + 3)/4; + memcpy(buf, data, note.n_descsz); + buf += (note.n_descsz + 3)/4; + + return buf; +} + +static void final_note(u32 *buf) +{ + struct elf_note note; + + note.n_namesz = 0; + note.n_descsz = 0; + note.n_type = 0; + memcpy(buf, ¬e, sizeof(note)); +} + +static void crash_save_this_cpu(struct pt_regs *regs, int cpu) +{ + struct elf_prstatus prstatus; + u32 *buf; + + if ((cpu < 0) || (cpu >= NR_CPUS)) + return; + + /* Using ELF notes here is opportunistic. + * I need a well defined structure format + * for the data I pass, and I need tags + * on the data to indicate what information I have + * squirrelled away. ELF notes happen to provide + * all of that that no need to invent something new. + */ + + buf = (u32*)per_cpu_ptr(crash_notes, cpu); + + if (!buf) + return; + + memset(&prstatus, 0, sizeof(prstatus)); + prstatus.pr_pid = current->pid; + elf_core_copy_regs(&prstatus.pr_reg, regs); + buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, + sizeof(prstatus)); + final_note(buf); +} + +static void crash_save_self(struct pt_regs *regs) +{ + int cpu; + + cpu = smp_processor_id(); + crash_save_this_cpu(regs, cpu); +} + +#ifdef CONFIG_SMP +static atomic_t waiting_for_crash_ipi; + +static int crash_nmi_callback(struct pt_regs *regs, int cpu) +{ + /* + * Don't do anything if this handler is invoked on crashing cpu. + * Otherwise, system will completely hang. Crashing cpu can get + * an NMI if system was initially booted with nmi_watchdog parameter. + */ + if (cpu == crashing_cpu) + return 1; + local_irq_disable(); + + crash_save_this_cpu(regs, cpu); + disable_local_APIC(); + atomic_dec(&waiting_for_crash_ipi); + /* Assume hlt works */ + for(;;) + asm("hlt"); + + return 1; +} + +static void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} + +/* + * This code is a best effort heuristic to get the + * other cpus to stop executing. So races with + * cpu hotplug shouldn't matter. + */ + +static void nmi_shootdown_cpus(void) +{ + unsigned long msecs; + + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); + set_nmi_callback(crash_nmi_callback); + + /* + * Ensure the new callback function is set before sending + * out the NMI + */ + wmb(); + + smp_send_nmi_allbutself(); + + msecs = 1000; /* Wait at most a second for the other cpus to stop */ + while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { + mdelay(1); + msecs--; + } + /* Leave the nmi callback set */ + disable_local_APIC(); +} +#else +static void nmi_shootdown_cpus(void) +{ + /* There are no cpus to shootdown */ +} +#endif + +void machine_crash_shutdown(struct pt_regs *regs) +{ + /* + * This function is only called after the system + * has paniced or is otherwise in a critical state. + * The minimum amount of code to allow a kexec'd kernel + * to run successfully needs to happen here. + * + * In practice this means shooting down the other cpus in + * an SMP system. + */ + /* The kernel is broken so disable interrupts */ + local_irq_disable(); + + /* Make a note of crashing cpu. Will be used in NMI callback.*/ + crashing_cpu = smp_processor_id(); + nmi_shootdown_cpus(); + + if(cpu_has_apic) + disable_local_APIC(); + +#if defined(CONFIG_X86_IO_APIC) + disable_IO_APIC(); +#endif + + crash_save_self(regs); +} diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c new file mode 100644 index 0000000000..52e5171181 --- /dev/null +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c @@ -0,0 +1,173 @@ +/* + * machine_kexec.c - handle transition of Linux booting another kernel + * Copyright (C) 2002-2005 Eric Biederman + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) +static u64 kexec_pgd[512] PAGE_ALIGNED; +static u64 kexec_pud0[512] PAGE_ALIGNED; +static u64 kexec_pmd0[512] PAGE_ALIGNED; +static u64 kexec_pte0[512] PAGE_ALIGNED; +static u64 kexec_pud1[512] PAGE_ALIGNED; +static u64 kexec_pmd1[512] PAGE_ALIGNED; +static u64 kexec_pte1[512] PAGE_ALIGNED; + +static void init_level2_page(pmd_t *level2p, unsigned long addr) +{ + unsigned long end_addr; + + addr &= PAGE_MASK; + end_addr = addr + PUD_SIZE; + while (addr < end_addr) { + set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); + addr += PMD_SIZE; + } +} + +static int init_level3_page(struct kimage *image, pud_t *level3p, + unsigned long addr, unsigned long last_addr) +{ + unsigned long end_addr; + int result; + + result = 0; + addr &= PAGE_MASK; + end_addr = addr + PGDIR_SIZE; + while ((addr < last_addr) && (addr < end_addr)) { + struct page *page; + pmd_t *level2p; + + page = kimage_alloc_control_pages(image, 0); + if (!page) { + result = -ENOMEM; + goto out; + } + level2p = (pmd_t *)page_address(page); + init_level2_page(level2p, addr); + set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE)); + addr += PUD_SIZE; + } + /* clear the unused entries */ + while (addr < end_addr) { + pud_clear(level3p++); + addr += PUD_SIZE; + } +out: + return result; +} + + +static int init_level4_page(struct kimage *image, pgd_t *level4p, + unsigned long addr, unsigned long last_addr) +{ + unsigned long end_addr; + int result; + + result = 0; + addr &= PAGE_MASK; + end_addr = addr + (PTRS_PER_PGD * PGDIR_SIZE); + while ((addr < last_addr) && (addr < end_addr)) { + struct page *page; + pud_t *level3p; + + page = kimage_alloc_control_pages(image, 0); + if (!page) { + result = -ENOMEM; + goto out; + } + level3p = (pud_t *)page_address(page); + result = init_level3_page(image, level3p, addr, last_addr); + if (result) { + goto out; + } + set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); + addr += PGDIR_SIZE; + } + /* clear the unused entries */ + while (addr < end_addr) { + pgd_clear(level4p++); + addr += PGDIR_SIZE; + } +out: + return result; +} + + +static int init_pgtable(struct kimage *image, unsigned long start_pgtable) +{ + pgd_t *level4p; + level4p = (pgd_t *)__va(start_pgtable); + return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT); +} + +int machine_kexec_prepare(struct kimage *image) +{ + unsigned long start_pgtable; + int result; + + /* Calculate the offsets */ + start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; + + /* Setup the identity mapped 64bit page table */ + result = init_pgtable(image, start_pgtable); + if (result) + return result; + + return 0; +} + +void machine_kexec_cleanup(struct kimage *image) +{ + return; +} + +/* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. + */ +NORET_TYPE void machine_kexec(struct kimage *image) +{ + unsigned long page_list[PAGES_NR]; + void *control_page; + + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + control_page = page_address(image->control_code_page) + PAGE_SIZE; + memcpy(control_page, relocate_kernel, PAGE_SIZE); + + page_list[PA_CONTROL_PAGE] = __pa(control_page); + page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; + page_list[PA_PGD] = __pa(kexec_pgd); + page_list[VA_PGD] = (unsigned long)kexec_pgd; + page_list[PA_PUD_0] = __pa(kexec_pud0); + page_list[VA_PUD_0] = (unsigned long)kexec_pud0; + page_list[PA_PMD_0] = __pa(kexec_pmd0); + page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; + page_list[PA_PTE_0] = __pa(kexec_pte0); + page_list[VA_PTE_0] = (unsigned long)kexec_pte0; + page_list[PA_PUD_1] = __pa(kexec_pud1); + page_list[VA_PUD_1] = (unsigned long)kexec_pud1; + page_list[PA_PMD_1] = __pa(kexec_pmd1); + page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; + page_list[PA_PTE_1] = __pa(kexec_pte1); + page_list[VA_PTE_1] = (unsigned long)kexec_pte1; + + page_list[PA_TABLE_PAGE] = + (unsigned long)__pa(page_address(image->control_code_page)); + + relocate_kernel((unsigned long)image->head, (unsigned long)page_list, + image->start); +} diff --git a/linux-2.6-xen-sparse/include/asm-i386/kexec.h b/linux-2.6-xen-sparse/include/asm-i386/kexec.h new file mode 100644 index 0000000000..4dfc9f5ed0 --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-i386/kexec.h @@ -0,0 +1,103 @@ +#ifndef _I386_KEXEC_H +#define _I386_KEXEC_H + +#define PA_CONTROL_PAGE 0 +#define VA_CONTROL_PAGE 1 +#define PA_PGD 2 +#define VA_PGD 3 +#define PA_PTE_0 4 +#define VA_PTE_0 5 +#define PA_PTE_1 6 +#define VA_PTE_1 7 +#ifdef CONFIG_X86_PAE +#define PA_PMD_0 8 +#define VA_PMD_0 9 +#define PA_PMD_1 10 +#define VA_PMD_1 11 +#define PAGES_NR 12 +#else +#define PAGES_NR 8 +#endif + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +/* + * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. + * I.e. Maximum page that is mapped directly into kernel memory, + * and kmap is not required. + * + * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct + * calculation for the amount of memory directly mappable into the + * kernel memory space. + */ + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) +/* Maximum address we can use for the control code buffer */ +#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE + +#define KEXEC_CONTROL_CODE_SIZE 4096 + +/* The native architecture */ +#define KEXEC_ARCH KEXEC_ARCH_386 + +#define MAX_NOTE_BYTES 1024 + +/* CPU does not save ss and esp on stack if execution is already + * running in kernel mode at the time of NMI occurrence. This code + * fixes it. + */ +static inline void crash_fixup_ss_esp(struct pt_regs *newregs, + struct pt_regs *oldregs) +{ + memcpy(newregs, oldregs, sizeof(*newregs)); + newregs->esp = (unsigned long)&(oldregs->esp); + __asm__ __volatile__( + "xorl %%eax, %%eax\n\t" + "movw %%ss, %%ax\n\t" + :"=a"(newregs->xss)); +} + +/* + * This function is responsible for capturing register states if coming + * via panic otherwise just fix up the ss and esp if coming via kernel + * mode exception. + */ +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) +{ + if (oldregs) + crash_fixup_ss_esp(newregs, oldregs); + else { + __asm__ __volatile__("movl %%ebx,%0" : "=m"(newregs->ebx)); + __asm__ __volatile__("movl %%ecx,%0" : "=m"(newregs->ecx)); + __asm__ __volatile__("movl %%edx,%0" : "=m"(newregs->edx)); + __asm__ __volatile__("movl %%esi,%0" : "=m"(newregs->esi)); + __asm__ __volatile__("movl %%edi,%0" : "=m"(newregs->edi)); + __asm__ __volatile__("movl %%ebp,%0" : "=m"(newregs->ebp)); + __asm__ __volatile__("movl %%eax,%0" : "=m"(newregs->eax)); + __asm__ __volatile__("movl %%esp,%0" : "=m"(newregs->esp)); + __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(newregs->xss)); + __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(newregs->xcs)); + __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(newregs->xds)); + __asm__ __volatile__("movw %%es, %%ax;" :"=a"(newregs->xes)); + __asm__ __volatile__("pushfl; popl %0" :"=m"(newregs->eflags)); + + newregs->eip = (unsigned long)current_text_addr(); + } +} +asmlinkage NORET_TYPE void +relocate_kernel(unsigned long indirection_page, + unsigned long control_page, + unsigned long start_address, + unsigned int has_pae) ATTRIB_NORET; + +#endif /* __ASSEMBLY__ */ + +#endif /* _I386_KEXEC_H */ diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h b/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h new file mode 100644 index 0000000000..5fab957e10 --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h @@ -0,0 +1,96 @@ +#ifndef _X86_64_KEXEC_H +#define _X86_64_KEXEC_H + +#define PA_CONTROL_PAGE 0 +#define VA_CONTROL_PAGE 1 +#define PA_PGD 2 +#define VA_PGD 3 +#define PA_PUD_0 4 +#define VA_PUD_0 5 +#define PA_PMD_0 6 +#define VA_PMD_0 7 +#define PA_PTE_0 8 +#define VA_PTE_0 9 +#define PA_PUD_1 10 +#define VA_PUD_1 11 +#define PA_PMD_1 12 +#define VA_PMD_1 13 +#define PA_PTE_1 14 +#define VA_PTE_1 15 +#define PA_TABLE_PAGE 16 +#define PAGES_NR 17 + +#ifndef __ASSEMBLY__ + +#include + +#include +#include + +/* + * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. + * I.e. Maximum page that is mapped directly into kernel memory, + * and kmap is not required. + * + * So far x86_64 is limited to 40 physical address bits. + */ + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (0xFFFFFFFFFFUL) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (0xFFFFFFFFFFUL) +/* Maximum address we can use for the control pages */ +#define KEXEC_CONTROL_MEMORY_LIMIT (0xFFFFFFFFFFUL) + +/* Allocate one page for the pdp and the second for the code */ +#define KEXEC_CONTROL_CODE_SIZE (4096UL + 4096UL) + +/* The native architecture */ +#define KEXEC_ARCH KEXEC_ARCH_X86_64 + +#define MAX_NOTE_BYTES 1024 + +/* + * Saving the registers of the cpu on which panic occured in + * crash_kexec to save a valid sp. The registers of other cpus + * will be saved in machine_crash_shutdown while shooting down them. + */ + +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) +{ + if (oldregs) + memcpy(newregs, oldregs, sizeof(*newregs)); + else { + __asm__ __volatile__("movq %%rbx,%0" : "=m"(newregs->rbx)); + __asm__ __volatile__("movq %%rcx,%0" : "=m"(newregs->rcx)); + __asm__ __volatile__("movq %%rdx,%0" : "=m"(newregs->rdx)); + __asm__ __volatile__("movq %%rsi,%0" : "=m"(newregs->rsi)); + __asm__ __volatile__("movq %%rdi,%0" : "=m"(newregs->rdi)); + __asm__ __volatile__("movq %%rbp,%0" : "=m"(newregs->rbp)); + __asm__ __volatile__("movq %%rax,%0" : "=m"(newregs->rax)); + __asm__ __volatile__("movq %%rsp,%0" : "=m"(newregs->rsp)); + __asm__ __volatile__("movq %%r8,%0" : "=m"(newregs->r8)); + __asm__ __volatile__("movq %%r9,%0" : "=m"(newregs->r9)); + __asm__ __volatile__("movq %%r10,%0" : "=m"(newregs->r10)); + __asm__ __volatile__("movq %%r11,%0" : "=m"(newregs->r11)); + __asm__ __volatile__("movq %%r12,%0" : "=m"(newregs->r12)); + __asm__ __volatile__("movq %%r13,%0" : "=m"(newregs->r13)); + __asm__ __volatile__("movq %%r14,%0" : "=m"(newregs->r14)); + __asm__ __volatile__("movq %%r15,%0" : "=m"(newregs->r15)); + __asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss)); + __asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs)); + __asm__ __volatile__("pushfq; popq %0" :"=m"(newregs->eflags)); + + newregs->rip = (unsigned long)current_text_addr(); + } +} + +NORET_TYPE void +relocate_kernel(unsigned long indirection_page, + unsigned long page_list, + unsigned long start_address) ATTRIB_NORET; + +#endif /* __ASSEMBLY__ */ + +#endif /* _X86_64_KEXEC_H */ diff --git a/linux-2.6-xen-sparse/include/linux/kexec.h b/linux-2.6-xen-sparse/include/linux/kexec.h new file mode 100644 index 0000000000..cfb3410e32 --- /dev/null +++ b/linux-2.6-xen-sparse/include/linux/kexec.h @@ -0,0 +1,139 @@ +#ifndef LINUX_KEXEC_H +#define LINUX_KEXEC_H + +#ifdef CONFIG_KEXEC +#include +#include +#include +#include +#include +#include + +/* Verify architecture specific macros are defined */ + +#ifndef KEXEC_SOURCE_MEMORY_LIMIT +#error KEXEC_SOURCE_MEMORY_LIMIT not defined +#endif + +#ifndef KEXEC_DESTINATION_MEMORY_LIMIT +#error KEXEC_DESTINATION_MEMORY_LIMIT not defined +#endif + +#ifndef KEXEC_CONTROL_MEMORY_LIMIT +#error KEXEC_CONTROL_MEMORY_LIMIT not defined +#endif + +#ifndef KEXEC_CONTROL_CODE_SIZE +#error KEXEC_CONTROL_CODE_SIZE not defined +#endif + +#ifndef KEXEC_ARCH +#error KEXEC_ARCH not defined +#endif + +/* + * This structure is used to hold the arguments that are used when loading + * kernel binaries. + */ + +typedef unsigned long kimage_entry_t; +#define IND_DESTINATION 0x1 +#define IND_INDIRECTION 0x2 +#define IND_DONE 0x4 +#define IND_SOURCE 0x8 + +#define KEXEC_SEGMENT_MAX 16 +struct kexec_segment { + void __user *buf; + size_t bufsz; + unsigned long mem; /* User space sees this as a (void *) ... */ + size_t memsz; +}; + +#ifdef CONFIG_COMPAT +struct compat_kexec_segment { + compat_uptr_t buf; + compat_size_t bufsz; + compat_ulong_t mem; /* User space sees this as a (void *) ... */ + compat_size_t memsz; +}; +#endif + +struct kimage { + kimage_entry_t head; + kimage_entry_t *entry; + kimage_entry_t *last_entry; + + unsigned long destination; + + unsigned long start; + struct page *control_code_page; + + unsigned long nr_segments; + struct kexec_segment segment[KEXEC_SEGMENT_MAX]; + + struct list_head control_pages; + struct list_head dest_pages; + struct list_head unuseable_pages; + + /* Address of next control page to allocate for crash kernels. */ + unsigned long control_page; + + /* Flags to indicate special processing */ + unsigned int type : 1; +#define KEXEC_TYPE_DEFAULT 0 +#define KEXEC_TYPE_CRASH 1 +}; + + + +/* kexec interface functions */ +extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET; +extern int machine_kexec_prepare(struct kimage *image); +extern void machine_kexec_cleanup(struct kimage *image); +extern asmlinkage long sys_kexec_load(unsigned long entry, + unsigned long nr_segments, + struct kexec_segment __user *segments, + unsigned long flags); +#ifdef CONFIG_COMPAT +extern asmlinkage long compat_sys_kexec_load(unsigned long entry, + unsigned long nr_segments, + struct compat_kexec_segment __user *segments, + unsigned long flags); +#endif +extern struct page *kimage_alloc_control_pages(struct kimage *image, + unsigned int order); +extern void crash_kexec(struct pt_regs *); +int kexec_should_crash(struct task_struct *); +extern struct kimage *kexec_image; + +#define KEXEC_ON_CRASH 0x00000001 +#define KEXEC_ARCH_MASK 0xffff0000 + +/* These values match the ELF architecture values. + * Unless there is a good reason that should continue to be the case. + */ +#define KEXEC_ARCH_DEFAULT ( 0 << 16) +#define KEXEC_ARCH_386 ( 3 << 16) +#define KEXEC_ARCH_X86_64 (62 << 16) +#define KEXEC_ARCH_PPC (20 << 16) +#define KEXEC_ARCH_PPC64 (21 << 16) +#define KEXEC_ARCH_IA_64 (50 << 16) +#define KEXEC_ARCH_S390 (22 << 16) +#define KEXEC_ARCH_SH (42 << 16) + +#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */ + +/* Location of a reserved region to hold the crash kernel. + */ +extern struct resource crashk_res; +typedef u32 note_buf_t[MAX_NOTE_BYTES/4]; +extern note_buf_t *crash_notes; + +#else /* !CONFIG_KEXEC */ +struct pt_regs; +struct task_struct; +static inline void crash_kexec(struct pt_regs *regs) { } +static inline int kexec_should_crash(struct task_struct *p) { return 0; } +#endif /* CONFIG_KEXEC */ +#endif /* LINUX_KEXEC_H */ diff --git a/linux-2.6-xen-sparse/kernel/kexec.c b/linux-2.6-xen-sparse/kernel/kexec.c new file mode 100644 index 0000000000..bf39d28e4c --- /dev/null +++ b/linux-2.6-xen-sparse/kernel/kexec.c @@ -0,0 +1,1081 @@ +/* + * kexec.c - kexec system call + * Copyright (C) 2002-2004 Eric Biederman + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Per cpu memory for storing cpu states in case of system crash. */ +note_buf_t* crash_notes; + +/* Location of the reserved area for the crash kernel */ +struct resource crashk_res = { + .name = "Crash kernel", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +int kexec_should_crash(struct task_struct *p) +{ + if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops) + return 1; + return 0; +} + +/* + * When kexec transitions to the new kernel there is a one-to-one + * mapping between physical and virtual addresses. On processors + * where you can disable the MMU this is trivial, and easy. For + * others it is still a simple predictable page table to setup. + * + * In that environment kexec copies the new kernel to its final + * resting place. This means I can only support memory whose + * physical address can fit in an unsigned long. In particular + * addresses where (pfn << PAGE_SHIFT) > ULONG_MAX cannot be handled. + * If the assembly stub has more restrictive requirements + * KEXEC_SOURCE_MEMORY_LIMIT and KEXEC_DEST_MEMORY_LIMIT can be + * defined more restrictively in . + * + * The code for the transition from the current kernel to the + * the new kernel is placed in the control_code_buffer, whose size + * is given by KEXEC_CONTROL_CODE_SIZE. In the best case only a single + * page of memory is necessary, but some architectures require more. + * Because this memory must be identity mapped in the transition from + * virtual to physical addresses it must live in the range + * 0 - TASK_SIZE, as only the user space mappings are arbitrarily + * modifiable. + * + * The assembly stub in the control code buffer is passed a linked list + * of descriptor pages detailing the source pages of the new kernel, + * and the destination addresses of those source pages. As this data + * structure is not used in the context of the current OS, it must + * be self-contained. + * + * The code has been made to work with highmem pages and will use a + * destination page in its final resting place (if it happens + * to allocate it). The end product of this is that most of the + * physical address space, and most of RAM can be used. + * + * Future directions include: + * - allocating a page table with the control code buffer identity + * mapped, to simplify machine_kexec and make kexec_on_panic more + * reliable. + */ + +/* + * KIMAGE_NO_DEST is an impossible destination address..., for + * allocating pages whose destination address we do not care about. + */ +#define KIMAGE_NO_DEST (-1UL) + +static int kimage_is_destination_range(struct kimage *image, + unsigned long start, unsigned long end); +static struct page *kimage_alloc_page(struct kimage *image, + gfp_t gfp_mask, + unsigned long dest); + +static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, + unsigned long nr_segments, + struct kexec_segment __user *segments) +{ + size_t segment_bytes; + struct kimage *image; + unsigned long i; + int result; + + /* Allocate a controlling structure */ + result = -ENOMEM; + image = kmalloc(sizeof(*image), GFP_KERNEL); + if (!image) + goto out; + + memset(image, 0, sizeof(*image)); + image->head = 0; + image->entry = &image->head; + image->last_entry = &image->head; + image->control_page = ~0; /* By default this does not apply */ + image->start = entry; + image->type = KEXEC_TYPE_DEFAULT; + + /* Initialize the list of control pages */ + INIT_LIST_HEAD(&image->control_pages); + + /* Initialize the list of destination pages */ + INIT_LIST_HEAD(&image->dest_pages); + + /* Initialize the list of unuseable pages */ + INIT_LIST_HEAD(&image->unuseable_pages); + + /* Read in the segments */ + image->nr_segments = nr_segments; + segment_bytes = nr_segments * sizeof(*segments); + result = copy_from_user(image->segment, segments, segment_bytes); + if (result) + goto out; + + /* + * Verify we have good destination addresses. The caller is + * responsible for making certain we don't attempt to load + * the new image into invalid or reserved areas of RAM. This + * just verifies it is an address we can use. + * + * Since the kernel does everything in page size chunks ensure + * the destination addreses are page aligned. Too many + * special cases crop of when we don't do this. The most + * insidious is getting overlapping destination addresses + * simply because addresses are changed to page size + * granularity. + */ + result = -EADDRNOTAVAIL; + for (i = 0; i < nr_segments; i++) { + unsigned long mstart, mend; + + mstart = image->segment[i].mem; + mend = mstart + image->segment[i].memsz; + if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK)) + goto out; + if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT) + goto out; + } + + /* Verify our destination addresses do not overlap. + * If we alloed overlapping destination addresses + * through very weird things can happen with no + * easy explanation as one segment stops on another. + */ + result = -EINVAL; + for (i = 0; i < nr_segments; i++) { + unsigned long mstart, mend; + unsigned long j; + + mstart = image->segment[i].mem; + mend = mstart + image->segment[i].memsz; + for (j = 0; j < i; j++) { + unsigned long pstart, pend; + pstart = image->segment[j].mem; + pend = pstart + image->segment[j].memsz; + /* Do the segments overlap ? */ + if ((mend > pstart) && (mstart < pend)) + goto out; + } + } + + /* Ensure our buffer sizes are strictly less than + * our memory sizes. This should always be the case, + * and it is easier to check up front than to be surprised + * later on. + */ + result = -EINVAL; + for (i = 0; i < nr_segments; i++) { + if (image->segment[i].bufsz > image->segment[i].memsz) + goto out; + } + + result = 0; +out: + if (result == 0) + *rimage = image; + else + kfree(image); + + return result; + +} + +static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, + unsigned long nr_segments, + struct kexec_segment __user *segments) +{ + int result; + struct kimage *image; + + /* Allocate and initialize a controlling structure */ + image = NULL; + result = do_kimage_alloc(&image, entry, nr_segments, segments); + if (result) + goto out; + + *rimage = image; + + /* + * Find a location for the control code buffer, and add it + * the vector of segments so that it's pages will also be + * counted as destination pages. + */ + result = -ENOMEM; + image->control_code_page = kimage_alloc_control_pages(image, + get_order(KEXEC_CONTROL_CODE_SIZE)); + if (!image->control_code_page) { + printk(KERN_ERR "Could not allocate control_code_buffer\n"); + goto out; + } + + result = 0; + out: + if (result == 0) + *rimage = image; + else + kfree(image); + + return result; +} + +static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, + unsigned long nr_segments, + struct kexec_segment __user *segments) +{ + int result; + struct kimage *image; + unsigned long i; + + image = NULL; + /* Verify we have a valid entry point */ + if ((entry < crashk_res.start) || (entry > crashk_res.end)) { + result = -EADDRNOTAVAIL; + goto out; + } + + /* Allocate and initialize a controlling structure */ + result = do_kimage_alloc(&image, entry, nr_segments, segments); + if (result) + goto out; + + /* Enable the special crash kernel control page + * allocation policy. + */ + image->control_page = crashk_res.start; + image->type = KEXEC_TYPE_CRASH; + + /* + * Verify we have good destination addresses. Normally + * the caller is responsible for making certain we don't + * attempt to load the new image into invalid or reserved + * areas of RAM. But crash kernels are preloaded into a + * reserved area of ram. We must ensure the addresses + * are in the reserved area otherwise preloading the + * kernel could corrupt things. + */ + result = -EADDRNOTAVAIL; + for (i = 0; i < nr_segments; i++) { + unsigned long mstart, mend; + + mstart = image->segment[i].mem; + mend = mstart + image->segment[i].memsz - 1; + /* Ensure we are within the crash kernel limits */ + if ((mstart < crashk_res.start) || (mend > crashk_res.end)) + goto out; + } + + /* + * Find a location for the control code buffer, and add + * the vector of segments so that it's pages will also be + * counted as destination pages. + */ + result = -ENOMEM; + image->control_code_page = kimage_alloc_control_pages(image, + get_order(KEXEC_CONTROL_CODE_SIZE)); + if (!image->control_code_page) { + printk(KERN_ERR "Could not allocate control_code_buffer\n"); + goto out; + } + + result = 0; +out: + if (result == 0) + *rimage = image; + else + kfree(image); + + return result; +} + +static int kimage_is_destination_range(struct kimage *image, + unsigned long start, + unsigned long end) +{ + unsigned long i; + + for (i = 0; i < image->nr_segments; i++) { + unsigned long mstart, mend; + + mstart = image->segment[i].mem; + mend = mstart + image->segment[i].memsz; + if ((end > mstart) && (start < mend)) + return 1; + } + + return 0; +} + +static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order) +{ + struct page *pages; + + pages = alloc_pages(gfp_mask, order); + if (pages) { + unsigned int count, i; + pages->mapping = NULL; + set_page_private(pages, order); + count = 1 << order; + for (i = 0; i < count; i++) + SetPageReserved(pages + i); + } + + return pages; +} + +static void kimage_free_pages(struct page *page) +{ + unsigned int order, count, i; + + order = page_private(page); + count = 1 << order; + for (i = 0; i < count; i++) + ClearPageReserved(page + i); + __free_pages(page, order); +} + +static void kimage_free_page_list(struct list_head *list) +{ + struct list_head *pos, *next; + + list_for_each_safe(pos, next, list) { + struct page *page; + + page = list_entry(pos, struct page, lru); + list_del(&page->lru); + kimage_free_pages(page); + } +} + +static struct page *kimage_alloc_normal_control_pages(struct kimage *image, + unsigned int order) +{ + /* Control pages are special, they are the intermediaries + * that are needed while we copy the rest of the pages + * to their final resting place. As such they must + * not conflict with either the destination addresses + * or memory the kernel is already using. + * + * The only case where we really need more than one of + * these are for architectures where we cannot disable + * the MMU and must instead generate an identity mapped + * page table for all of the memory. + * + * At worst this runs in O(N) of the image size. + */ + struct list_head extra_pages; + struct page *pages; + unsigned int count; + + count = 1 << order; + INIT_LIST_HEAD(&extra_pages); + + /* Loop while I can allocate a page and the page allocated + * is a destination page. + */ + do { + unsigned long pfn, epfn, addr, eaddr; + + pages = kimage_alloc_pages(GFP_KERNEL, order); + if (!pages) + break; + pfn = page_to_pfn(pages); + epfn = pfn + count; + addr = pfn << PAGE_SHIFT; + eaddr = epfn << PAGE_SHIFT; + if ((epfn >= (KEXEC_CONTROL_MEMORY_LIMIT >> PAGE_SHIFT)) || + kimage_is_destination_range(image, addr, eaddr)) { + list_add(&pages->lru, &extra_pages); + pages = NULL; + } + } while (!pages); + + if (pages) { + /* Remember the allocated page... */ + list_add(&pages->lru, &image->control_pages); + + /* Because the page is already in it's destination + * location we will never allocate another page at + * that address. Therefore kimage_alloc_pages + * will not return it (again) and we don't need + * to give it an entry in image->segment[]. + */ + } + /* Deal with the destination pages I have inadvertently allocated. + * + * Ideally I would convert multi-page allocations into single + * page allocations, and add everyting to image->dest_pages. + * + * For now it is simpler to just free the pages. + */ + kimage_free_page_list(&extra_pages); + + return pages; +} + +static struct page *kimage_alloc_crash_control_pages(struct kimage *image, + unsigned int order) +{ + /* Control pages are special, they are the intermediaries + * that are needed while we copy the rest of the pages + * to their final resting place. As such they must + * not conflict with either the destination addresses + * or memory the kernel is already using. + * + * Control pages are also the only pags we must allocate + * when loading a crash kernel. All of the other pages + * are specified by the segments and we just memcpy + * into them directly. + * + * The only case where we really need more than one of + * these are for architectures where we cannot disable + * the MMU and must instead generate an identity mapped + * page table for all of the memory. + * + * Given the low demand this implements a very simple + * allocator that finds the first hole of the appropriate + * size in the reserved memory region, and allocates all + * of the memory up to and including the hole. + */ + unsigned long hole_start, hole_end, size; + struct page *pages; + + pages = NULL; + size = (1 << order) << PAGE_SHIFT; + hole_start = (image->control_page + (size - 1)) & ~(size - 1); + hole_end = hole_start + size - 1; + while (hole_end <= crashk_res.end) { + unsigned long i; + + if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT) + break; + if (hole_end > crashk_res.end) + break; + /* See if I overlap any of the segments */ + for (i = 0; i < image->nr_segments; i++) { + unsigned long mstart, mend; + + mstart = image->segment[i].mem; + mend = mstart + image->segment[i].memsz - 1; + if ((hole_end >= mstart) && (hole_start <= mend)) { + /* Advance the hole to the end of the segment */ + hole_start = (mend + (size - 1)) & ~(size - 1); + hole_end = hole_start + size - 1; + break; + } + } + /* If I don't overlap any segments I have found my hole! */ + if (i == image->nr_segments) { + pages = pfn_to_page(hole_start >> PAGE_SHIFT); + break; + } + } + if (pages) + image->control_page = hole_end; + + return pages; +} + + +struct page *kimage_alloc_control_pages(struct kimage *image, + unsigned int order) +{ + struct page *pages = NULL; + + switch (image->type) { + case KEXEC_TYPE_DEFAULT: + pages = kimage_alloc_normal_control_pages(image, order); + break; + case KEXEC_TYPE_CRASH: + pages = kimage_alloc_crash_control_pages(image, order); + break; + } + + return pages; +} + +static int kimage_add_entry(struct kimage *image, kimage_entry_t entry) +{ + if (*image->entry != 0) + image->entry++; + + if (image->entry == image->last_entry) { + kimage_entry_t *ind_page; + struct page *page; + + page = kimage_alloc_page(image, GFP_KERNEL, KIMAGE_NO_DEST); + if (!page) + return -ENOMEM; + + ind_page = page_address(page); + *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION; + image->entry = ind_page; + image->last_entry = ind_page + + ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1); + } + *image->entry = entry; + image->entry++; + *image->entry = 0; + + return 0; +} + +static int kimage_set_destination(struct kimage *image, + unsigned long destination) +{ + int result; + + destination &= PAGE_MASK; + result = kimage_add_entry(image, destination | IND_DESTINATION); + if (result == 0) + image->destination = destination; + + return result; +} + + +static int kimage_add_page(struct kimage *image, unsigned long page) +{ + int result; + + page &= PAGE_MASK; + result = kimage_add_entry(image, page | IND_SOURCE); + if (result == 0) + image->destination += PAGE_SIZE; + + return result; +} + + +static void kimage_free_extra_pages(struct kimage *image) +{ + /* Walk through and free any extra destination pages I may have */ + kimage_free_page_list(&image->dest_pages); + + /* Walk through and free any unuseable pages I have cached */ + kimage_free_page_list(&image->unuseable_pages); + +} +static int kimage_terminate(struct kimage *image) +{ + if (*image->entry != 0) + image->entry++; + + *image->entry = IND_DONE; + + return 0; +} + +#define for_each_kimage_entry(image, ptr, entry) \ + for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ + ptr = (entry & IND_INDIRECTION)? \ + phys_to_virt((entry & PAGE_MASK)): ptr +1) + +static void kimage_free_entry(kimage_entry_t entry) +{ + struct page *page; + + page = pfn_to_page(entry >> PAGE_SHIFT); + kimage_free_pages(page); +} + +static void kimage_free(struct kimage *image) +{ + kimage_entry_t *ptr, entry; + kimage_entry_t ind = 0; + + if (!image) + return; + + kimage_free_extra_pages(image); + for_each_kimage_entry(image, ptr, entry) { + if (entry & IND_INDIRECTION) { + /* Free the previous indirection page */ + if (ind & IND_INDIRECTION) + kimage_free_entry(ind); + /* Save this indirection page until we are + * done with it. + */ + ind = entry; + } + else if (entry & IND_SOURCE) + kimage_free_entry(entry); + } + /* Free the final indirection page */ + if (ind & IND_INDIRECTION) + kimage_free_entry(ind); + + /* Handle any machine specific cleanup */ + machine_kexec_cleanup(image); + + /* Free the kexec control pages... */ + kimage_free_page_list(&image->control_pages); + kfree(image); +} + +static kimage_entry_t *kimage_dst_used(struct kimage *image, + unsigned long page) +{ + kimage_entry_t *ptr, entry; + unsigned long destination = 0; + + for_each_kimage_entry(image, ptr, entry) { + if (entry & IND_DESTINATION) + destination = entry & PAGE_MASK; + else if (entry & IND_SOURCE) { + if (page == destination) + return ptr; + destination += PAGE_SIZE; + } + } + + return NULL; +} + +static struct page *kimage_alloc_page(struct kimage *image, + gfp_t gfp_mask, + unsigned long destination) +{ + /* + * Here we implement safeguards to ensure that a source page + * is not copied to its destination page before the data on + * the destination page is no longer useful. + * + * To do this we maintain the invariant that a source page is + * either its own destination page, or it is not a + * destination page at all. + * + * That is slightly stronger than required, but the proof + * that no problems will not occur is trivial, and the + * implementation is simply to verify. + * + * When allocating all pages normally this algorithm will run + * in O(N) time, but in the worst case it will run in O(N^2) + * time. If the runtime is a problem the data structures can + * be fixed. + */ + struct page *page; + unsigned long addr; + + /* + * Walk through the list of destination pages, and see if I + * have a match. + */ + list_for_each_entry(page, &image->dest_pages, lru) { + addr = page_to_pfn(page) << PAGE_SHIFT; + if (addr == destination) { + list_del(&page->lru); + return page; + } + } + page = NULL; + while (1) { + kimage_entry_t *old; + + /* Allocate a page, if we run out of memory give up */ + page = kimage_alloc_pages(gfp_mask, 0); + if (!page) + return NULL; + /* If the page cannot be used file it away */ + if (page_to_pfn(page) > + (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { + list_add(&page->lru, &image->unuseable_pages); + continue; + } + addr = page_to_pfn(page) << PAGE_SHIFT; + + /* If it is the destination page we want use it */ + if (addr == destination) + break; + + /* If the page is not a destination page use it */ + if (!kimage_is_destination_range(image, addr, + addr + PAGE_SIZE)) + break; + + /* + * I know that the page is someones destination page. + * See if there is already a source page for this + * destination page. And if so swap the source pages. + */ + old = kimage_dst_used(image, addr); + if (old) { + /* If so move it */ + unsigned long old_addr; + struct page *old_page; + + old_addr = *old & PAGE_MASK; + old_page = pfn_to_page(old_addr >> PAGE_SHIFT); + copy_highpage(page, old_page); + *old = addr | (*old & ~PAGE_MASK); + + /* The old page I have found cannot be a + * destination page, so return it. + */ + addr = old_addr; + page = old_page; + break; + } + else { + /* Place the page on the destination list I + * will use it later. + */ + list_add(&page->lru, &image->dest_pages); + } + } + + return page; +} + +static int kimage_load_normal_segment(struct kimage *image, + struct kexec_segment *segment) +{ + unsigned long maddr; + unsigned long ubytes, mbytes; + int result; + unsigned char __user *buf; + + result = 0; + buf = segment->buf; + ubytes = segment->bufsz; + mbytes = segment->memsz; + maddr = segment->mem; + + result = kimage_set_destination(image, maddr); + if (result < 0) + goto out; + + while (mbytes) { + struct page *page; + char *ptr; + size_t uchunk, mchunk; + + page = kimage_alloc_page(image, GFP_HIGHUSER, maddr); + if (page == 0) { + result = -ENOMEM; + goto out; + } + result = kimage_add_page(image, page_to_pfn(page) + << PAGE_SHIFT); + if (result < 0) + goto out; + + ptr = kmap(page); + /* Start with a clear page */ + memset(ptr, 0, PAGE_SIZE); + ptr += maddr & ~PAGE_MASK; + mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK); + if (mchunk > mbytes) + mchunk = mbytes; + + uchunk = mchunk; + if (uchunk > ubytes) + uchunk = ubytes; + + result = copy_from_user(ptr, buf, uchunk); + kunmap(page); + if (result) { + result = (result < 0) ? result : -EIO; + goto out; + } + ubytes -= uchunk; + maddr += mchunk; + buf += mchunk; + mbytes -= mchunk; + } +out: + return result; +} + +static int kimage_load_crash_segment(struct kimage *image, + struct kexec_segment *segment) +{ + /* For crash dumps kernels we simply copy the data from + * user space to it's destination. + * We do things a page at a time for the sake of kmap. + */ + unsigned long maddr; + unsigned long ubytes, mbytes; + int result; + unsigned char __user *buf; + + result = 0; + buf = segment->buf; + ubytes = segment->bufsz; + mbytes = segment->memsz; + maddr = segment->mem; + while (mbytes) { + struct page *page; + char *ptr; + size_t uchunk, mchunk; + + page = pfn_to_page(maddr >> PAGE_SHIFT); + if (page == 0) { + result = -ENOMEM; + goto out; + } + ptr = kmap(page); + ptr += maddr & ~PAGE_MASK; + mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK); + if (mchunk > mbytes) + mchunk = mbytes; + + uchunk = mchunk; + if (uchunk > ubytes) { + uchunk = ubytes; + /* Zero the trailing part of the page */ + memset(ptr + uchunk, 0, mchunk - uchunk); + } + result = copy_from_user(ptr, buf, uchunk); + kunmap(page); + if (result) { + result = (result < 0) ? result : -EIO; + goto out; + } + ubytes -= uchunk; + maddr += mchunk; + buf += mchunk; + mbytes -= mchunk; + } +out: + return result; +} + +static int kimage_load_segment(struct kimage *image, + struct kexec_segment *segment) +{ + int result = -ENOMEM; + + switch (image->type) { + case KEXEC_TYPE_DEFAULT: + result = kimage_load_normal_segment(image, segment); + break; + case KEXEC_TYPE_CRASH: + result = kimage_load_crash_segment(image, segment); + break; + } + + return result; +} + +/* + * Exec Kernel system call: for obvious reasons only root may call it. + * + * This call breaks up into three pieces. + * - A generic part which loads the new kernel from the current + * address space, and very carefully places the data in the + * allocated pages. + * + * - A generic part that interacts with the kernel and tells all of + * the devices to shut down. Preventing on-going dmas, and placing + * the devices in a consistent state so a later kernel can + * reinitialize them. + * + * - A machine specific part that includes the syscall number + * and the copies the image to it's final destination. And + * jumps into the image at entry. + * + * kexec does not sync, or unmount filesystems so if you need + * that to happen you need to do that yourself. + */ +struct kimage *kexec_image = NULL; +static struct kimage *kexec_crash_image = NULL; +/* + * A home grown binary mutex. + * Nothing can wait so this mutex is safe to use + * in interrupt context :) + */ +static int kexec_lock = 0; + +asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, + struct kexec_segment __user *segments, + unsigned long flags) +{ + struct kimage **dest_image, *image; + int locked; + int result; + + /* We only trust the superuser with rebooting the system. */ + if (!capable(CAP_SYS_BOOT)) + return -EPERM; + + /* + * Verify we have a legal set of flags + * This leaves us room for future extensions. + */ + if ((flags & KEXEC_FLAGS) != (flags & ~KEXEC_ARCH_MASK)) + return -EINVAL; + + /* Verify we are on the appropriate architecture */ + if (((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH) && + ((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT)) + return -EINVAL; + + /* Put an artificial cap on the number + * of segments passed to kexec_load. + */ + if (nr_segments > KEXEC_SEGMENT_MAX) + return -EINVAL; + + image = NULL; + result = 0; + + /* Because we write directly to the reserved memory + * region when loading crash kernels we need a mutex here to + * prevent multiple crash kernels from attempting to load + * simultaneously, and to prevent a crash kernel from loading + * over the top of a in use crash kernel. + * + * KISS: always take the mutex. + */ + locked = xchg(&kexec_lock, 1); + if (locked) + return -EBUSY; + + dest_image = &kexec_image; + if (flags & KEXEC_ON_CRASH) + dest_image = &kexec_crash_image; + if (nr_segments > 0) { + unsigned long i; + + /* Loading another kernel to reboot into */ + if ((flags & KEXEC_ON_CRASH) == 0) + result = kimage_normal_alloc(&image, entry, + nr_segments, segments); + /* Loading another kernel to switch to if this one crashes */ + else if (flags & KEXEC_ON_CRASH) { + /* Free any current crash dump kernel before + * we corrupt it. + */ + kimage_free(xchg(&kexec_crash_image, NULL)); + result = kimage_crash_alloc(&image, entry, + nr_segments, segments); + } + if (result) + goto out; + + result = machine_kexec_prepare(image); + if (result) + goto out; + + for (i = 0; i < nr_segments; i++) { + result = kimage_load_segment(image, &image->segment[i]); + if (result) + goto out; + } + result = kimage_terminate(image); + if (result) + goto out; + } + /* Install the new kernel, and Uninstall the old */ + image = xchg(dest_image, image); + +out: + xchg(&kexec_lock, 0); /* Release the mutex */ + kimage_free(image); + + return result; +} + +#ifdef CONFIG_COMPAT +asmlinkage long compat_sys_kexec_load(unsigned long entry, + unsigned long nr_segments, + struct compat_kexec_segment __user *segments, + unsigned long flags) +{ + struct compat_kexec_segment in; + struct kexec_segment out, __user *ksegments; + unsigned long i, result; + + /* Don't allow clients that don't understand the native + * architecture to do anything. + */ + if ((flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_DEFAULT) + return -EINVAL; + + if (nr_segments > KEXEC_SEGMENT_MAX) + return -EINVAL; + + ksegments = compat_alloc_user_space(nr_segments * sizeof(out)); + for (i=0; i < nr_segments; i++) { + result = copy_from_user(&in, &segments[i], sizeof(in)); + if (result) + return -EFAULT; + + out.buf = compat_ptr(in.buf); + out.bufsz = in.bufsz; + out.mem = in.mem; + out.memsz = in.memsz; + + result = copy_to_user(&ksegments[i], &out, sizeof(out)); + if (result) + return -EFAULT; + } + + return sys_kexec_load(entry, nr_segments, ksegments, flags); +} +#endif + +void crash_kexec(struct pt_regs *regs) +{ + struct kimage *image; + int locked; + + + /* Take the kexec_lock here to prevent sys_kexec_load + * running on one cpu from replacing the crash kernel + * we are using after a panic on a different cpu. + * + * If the crash kernel was not located in a fixed area + * of memory the xchg(&kexec_crash_image) would be + * sufficient. But since I reuse the memory... + */ + locked = xchg(&kexec_lock, 1); + if (!locked) { + image = xchg(&kexec_crash_image, NULL); + if (image) { + struct pt_regs fixed_regs; + crash_setup_regs(&fixed_regs, regs); + machine_crash_shutdown(&fixed_regs); + machine_kexec(image); + } + xchg(&kexec_lock, 0); + } +} + +static int __init crash_notes_memory_init(void) +{ + /* Allocate memory for saving cpu registers. */ + crash_notes = alloc_percpu(note_buf_t); + if (!crash_notes) { + printk("Kexec: Memory allocation for saving cpu register" + " states failed\n"); + return -ENOMEM; + } + return 0; +} +module_init(crash_notes_memory_init) From 69f0c953b4257eb4f3956b6240278f834b7e8ba1 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Dec 2006 11:47:09 +0000 Subject: [PATCH 67/69] [LINUX] Kexec: Reapply kexec patches to sparse tree. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/arch/i386/kernel/crash.c | 4 + .../arch/i386/kernel/machine_kexec.c | 38 ++++++ .../arch/x86_64/kernel/crash.c | 6 +- .../arch/x86_64/kernel/machine_kexec.c | 116 +++++++++++++++++- linux-2.6-xen-sparse/include/asm-i386/kexec.h | 14 +++ .../include/asm-x86_64/kexec.h | 13 ++ linux-2.6-xen-sparse/include/linux/kexec.h | 14 +++ linux-2.6-xen-sparse/kernel/kexec.c | 52 ++++++-- 8 files changed, 238 insertions(+), 19 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/crash.c b/linux-2.6-xen-sparse/arch/i386/kernel/crash.c index d49dbe8dc9..75aab8ef35 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/crash.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/crash.c @@ -90,6 +90,7 @@ static void crash_save_self(struct pt_regs *regs) crash_save_this_cpu(regs, cpu); } +#ifndef CONFIG_XEN #ifdef CONFIG_SMP static atomic_t waiting_for_crash_ipi; @@ -158,6 +159,7 @@ static void nmi_shootdown_cpus(void) /* There are no cpus to shootdown */ } #endif +#endif /* CONFIG_XEN */ void machine_crash_shutdown(struct pt_regs *regs) { @@ -174,10 +176,12 @@ void machine_crash_shutdown(struct pt_regs *regs) /* Make a note of crashing cpu. Will be used in NMI callback.*/ crashing_cpu = smp_processor_id(); +#ifndef CONFIG_XEN nmi_shootdown_cpus(); lapic_shutdown(); #if defined(CONFIG_X86_IO_APIC) disable_IO_APIC(); #endif +#endif /* CONFIG_XEN */ crash_save_self(regs); } diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c b/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c index 00e1c189fc..f9ebc85481 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c @@ -19,6 +19,10 @@ #include #include +#ifdef CONFIG_XEN +#include +#endif + #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) static u32 kexec_pgd[1024] PAGE_ALIGNED; #ifdef CONFIG_X86_PAE @@ -28,6 +32,40 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED; static u32 kexec_pte0[1024] PAGE_ALIGNED; static u32 kexec_pte1[1024] PAGE_ALIGNED; +#ifdef CONFIG_XEN + +#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT) + +#if PAGES_NR > KEXEC_XEN_NO_PAGES +#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break +#endif + +#if PA_CONTROL_PAGE != 0 +#error PA_CONTROL_PAGE is non zero - Xen support will break +#endif + +void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image) +{ + void *control_page; + + memset(xki->page_list, 0, sizeof(xki->page_list)); + + control_page = page_address(image->control_code_page); + memcpy(control_page, relocate_kernel, PAGE_SIZE); + + xki->page_list[PA_CONTROL_PAGE] = __ma(control_page); + xki->page_list[PA_PGD] = __ma(kexec_pgd); +#ifdef CONFIG_X86_PAE + xki->page_list[PA_PMD_0] = __ma(kexec_pmd0); + xki->page_list[PA_PMD_1] = __ma(kexec_pmd1); +#endif + xki->page_list[PA_PTE_0] = __ma(kexec_pte0); + xki->page_list[PA_PTE_1] = __ma(kexec_pte1); + +} + +#endif /* CONFIG_XEN */ + /* * A architecture hook called to validate the * proposed image and prepare the control pages diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c index 4e6c3b729e..3263b5942a 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/crash.c @@ -92,6 +92,7 @@ static void crash_save_self(struct pt_regs *regs) crash_save_this_cpu(regs, cpu); } +#ifndef CONFIG_XEN #ifdef CONFIG_SMP static atomic_t waiting_for_crash_ipi; @@ -156,6 +157,7 @@ static void nmi_shootdown_cpus(void) /* There are no cpus to shootdown */ } #endif +#endif /* CONFIG_XEN */ void machine_crash_shutdown(struct pt_regs *regs) { @@ -173,6 +175,8 @@ void machine_crash_shutdown(struct pt_regs *regs) /* Make a note of crashing cpu. Will be used in NMI callback.*/ crashing_cpu = smp_processor_id(); + +#ifndef CONFIG_XEN nmi_shootdown_cpus(); if(cpu_has_apic) @@ -181,6 +185,6 @@ void machine_crash_shutdown(struct pt_regs *regs) #if defined(CONFIG_X86_IO_APIC) disable_IO_APIC(); #endif - +#endif /* CONFIG_XEN */ crash_save_self(regs); } diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c index 52e5171181..f598578b0c 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c @@ -24,6 +24,104 @@ static u64 kexec_pud1[512] PAGE_ALIGNED; static u64 kexec_pmd1[512] PAGE_ALIGNED; static u64 kexec_pte1[512] PAGE_ALIGNED; +#ifdef CONFIG_XEN + +/* In the case of Xen, override hypervisor functions to be able to create + * a regular identity mapping page table... + */ + +#include +#include + +#define x__pmd(x) ((pmd_t) { (x) } ) +#define x__pud(x) ((pud_t) { (x) } ) +#define x__pgd(x) ((pgd_t) { (x) } ) + +#define x_pmd_val(x) ((x).pmd) +#define x_pud_val(x) ((x).pud) +#define x_pgd_val(x) ((x).pgd) + +static inline void x_set_pmd(pmd_t *dst, pmd_t val) +{ + x_pmd_val(*dst) = x_pmd_val(val); +} + +static inline void x_set_pud(pud_t *dst, pud_t val) +{ + x_pud_val(*dst) = phys_to_machine(x_pud_val(val)); +} + +static inline void x_pud_clear (pud_t *pud) +{ + x_pud_val(*pud) = 0; +} + +static inline void x_set_pgd(pgd_t *dst, pgd_t val) +{ + x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val)); +} + +static inline void x_pgd_clear (pgd_t * pgd) +{ + x_pgd_val(*pgd) = 0; +} + +#define X__PAGE_KERNEL_LARGE_EXEC \ + _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE +#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY + +#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT) + +#if PAGES_NR > KEXEC_XEN_NO_PAGES +#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break +#endif + +#if PA_CONTROL_PAGE != 0 +#error PA_CONTROL_PAGE is non zero - Xen support will break +#endif + +void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image) +{ + void *control_page; + void *table_page; + + memset(xki->page_list, 0, sizeof(xki->page_list)); + + control_page = page_address(image->control_code_page) + PAGE_SIZE; + memcpy(control_page, relocate_kernel, PAGE_SIZE); + + table_page = page_address(image->control_code_page); + + xki->page_list[PA_CONTROL_PAGE] = __ma(control_page); + xki->page_list[PA_TABLE_PAGE] = __ma(table_page); + + xki->page_list[PA_PGD] = __ma(kexec_pgd); + xki->page_list[PA_PUD_0] = __ma(kexec_pud0); + xki->page_list[PA_PUD_1] = __ma(kexec_pud1); + xki->page_list[PA_PMD_0] = __ma(kexec_pmd0); + xki->page_list[PA_PMD_1] = __ma(kexec_pmd1); + xki->page_list[PA_PTE_0] = __ma(kexec_pte0); + xki->page_list[PA_PTE_1] = __ma(kexec_pte1); +} + +#else /* CONFIG_XEN */ + +#define x__pmd(x) __pmd(x) +#define x__pud(x) __pud(x) +#define x__pgd(x) __pgd(x) + +#define x_set_pmd(x, y) set_pmd(x, y) +#define x_set_pud(x, y) set_pud(x, y) +#define x_set_pgd(x, y) set_pgd(x, y) + +#define x_pud_clear(x) pud_clear(x) +#define x_pgd_clear(x) pgd_clear(x) + +#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC +#define X_KERNPG_TABLE _KERNPG_TABLE + +#endif /* CONFIG_XEN */ + static void init_level2_page(pmd_t *level2p, unsigned long addr) { unsigned long end_addr; @@ -31,7 +129,7 @@ static void init_level2_page(pmd_t *level2p, unsigned long addr) addr &= PAGE_MASK; end_addr = addr + PUD_SIZE; while (addr < end_addr) { - set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); + x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC)); addr += PMD_SIZE; } } @@ -56,12 +154,12 @@ static int init_level3_page(struct kimage *image, pud_t *level3p, } level2p = (pmd_t *)page_address(page); init_level2_page(level2p, addr); - set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE)); + x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE)); addr += PUD_SIZE; } /* clear the unused entries */ while (addr < end_addr) { - pud_clear(level3p++); + x_pud_clear(level3p++); addr += PUD_SIZE; } out: @@ -92,12 +190,12 @@ static int init_level4_page(struct kimage *image, pgd_t *level4p, if (result) { goto out; } - set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); + x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE)); addr += PGDIR_SIZE; } /* clear the unused entries */ while (addr < end_addr) { - pgd_clear(level4p++); + x_pgd_clear(level4p++); addr += PGDIR_SIZE; } out: @@ -108,8 +206,14 @@ out: static int init_pgtable(struct kimage *image, unsigned long start_pgtable) { pgd_t *level4p; + unsigned long x_end_pfn = end_pfn; + +#ifdef CONFIG_XEN + x_end_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL); +#endif + level4p = (pgd_t *)__va(start_pgtable); - return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT); + return init_level4_page(image, level4p, 0, x_end_pfn << PAGE_SHIFT); } int machine_kexec_prepare(struct kimage *image) diff --git a/linux-2.6-xen-sparse/include/asm-i386/kexec.h b/linux-2.6-xen-sparse/include/asm-i386/kexec.h index 4dfc9f5ed0..4610897c78 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/kexec.h +++ b/linux-2.6-xen-sparse/include/asm-i386/kexec.h @@ -98,6 +98,20 @@ relocate_kernel(unsigned long indirection_page, unsigned long start_address, unsigned int has_pae) ATTRIB_NORET; + +/* Under Xen we need to work with machine addresses. These macros give the + * machine address of a certain page to the generic kexec code instead of + * the pseudo physical address which would be given by the default macros. + */ + +#ifdef CONFIG_XEN +#define KEXEC_ARCH_HAS_PAGE_MACROS +#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page)) +#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn)) +#define kexec_virt_to_phys(addr) virt_to_machine(addr) +#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr)) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _I386_KEXEC_H */ diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h b/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h index 5fab957e10..3e112d941b 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h @@ -91,6 +91,19 @@ relocate_kernel(unsigned long indirection_page, unsigned long page_list, unsigned long start_address) ATTRIB_NORET; +/* Under Xen we need to work with machine addresses. These macros give the + * machine address of a certain page to the generic kexec code instead of + * the pseudo physical address which would be given by the default macros. + */ + +#ifdef CONFIG_XEN +#define KEXEC_ARCH_HAS_PAGE_MACROS +#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page)) +#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn)) +#define kexec_virt_to_phys(addr) virt_to_machine(addr) +#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr)) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _X86_64_KEXEC_H */ diff --git a/linux-2.6-xen-sparse/include/linux/kexec.h b/linux-2.6-xen-sparse/include/linux/kexec.h index cfb3410e32..b51072d4ed 100644 --- a/linux-2.6-xen-sparse/include/linux/kexec.h +++ b/linux-2.6-xen-sparse/include/linux/kexec.h @@ -31,6 +31,13 @@ #error KEXEC_ARCH not defined #endif +#ifndef KEXEC_ARCH_HAS_PAGE_MACROS +#define kexec_page_to_pfn(page) page_to_pfn(page) +#define kexec_pfn_to_page(pfn) pfn_to_page(pfn) +#define kexec_virt_to_phys(addr) virt_to_phys(addr) +#define kexec_phys_to_virt(addr) phys_to_virt(addr) +#endif + /* * This structure is used to hold the arguments that are used when loading * kernel binaries. @@ -91,6 +98,13 @@ struct kimage { extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET; extern int machine_kexec_prepare(struct kimage *image); extern void machine_kexec_cleanup(struct kimage *image); +#ifdef CONFIG_XEN +extern int xen_machine_kexec_load(struct kimage *image); +extern void xen_machine_kexec_unload(struct kimage *image); +extern NORET_TYPE void xen_machine_kexec(struct kimage *image) ATTRIB_NORET; +extern void xen_machine_kexec_setup_resources(void); +extern void xen_machine_kexec_register_resources(struct resource *res); +#endif extern asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment __user *segments, diff --git a/linux-2.6-xen-sparse/kernel/kexec.c b/linux-2.6-xen-sparse/kernel/kexec.c index bf39d28e4c..1dd4096967 100644 --- a/linux-2.6-xen-sparse/kernel/kexec.c +++ b/linux-2.6-xen-sparse/kernel/kexec.c @@ -403,7 +403,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image, pages = kimage_alloc_pages(GFP_KERNEL, order); if (!pages) break; - pfn = page_to_pfn(pages); + pfn = kexec_page_to_pfn(pages); epfn = pfn + count; addr = pfn << PAGE_SHIFT; eaddr = epfn << PAGE_SHIFT; @@ -437,6 +437,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image, return pages; } +#ifndef CONFIG_XEN static struct page *kimage_alloc_crash_control_pages(struct kimage *image, unsigned int order) { @@ -490,7 +491,7 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image, } /* If I don't overlap any segments I have found my hole! */ if (i == image->nr_segments) { - pages = pfn_to_page(hole_start >> PAGE_SHIFT); + pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT); break; } } @@ -517,6 +518,13 @@ struct page *kimage_alloc_control_pages(struct kimage *image, return pages; } +#else /* !CONFIG_XEN */ +struct page *kimage_alloc_control_pages(struct kimage *image, + unsigned int order) +{ + return kimage_alloc_normal_control_pages(image, order); +} +#endif static int kimage_add_entry(struct kimage *image, kimage_entry_t entry) { @@ -532,7 +540,7 @@ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry) return -ENOMEM; ind_page = page_address(page); - *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION; + *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION; image->entry = ind_page; image->last_entry = ind_page + ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1); @@ -593,13 +601,13 @@ static int kimage_terminate(struct kimage *image) #define for_each_kimage_entry(image, ptr, entry) \ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ ptr = (entry & IND_INDIRECTION)? \ - phys_to_virt((entry & PAGE_MASK)): ptr +1) + kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1) static void kimage_free_entry(kimage_entry_t entry) { struct page *page; - page = pfn_to_page(entry >> PAGE_SHIFT); + page = kexec_pfn_to_page(entry >> PAGE_SHIFT); kimage_free_pages(page); } @@ -611,6 +619,10 @@ static void kimage_free(struct kimage *image) if (!image) return; +#ifdef CONFIG_XEN + xen_machine_kexec_unload(image); +#endif + kimage_free_extra_pages(image); for_each_kimage_entry(image, ptr, entry) { if (entry & IND_INDIRECTION) { @@ -686,7 +698,7 @@ static struct page *kimage_alloc_page(struct kimage *image, * have a match. */ list_for_each_entry(page, &image->dest_pages, lru) { - addr = page_to_pfn(page) << PAGE_SHIFT; + addr = kexec_page_to_pfn(page) << PAGE_SHIFT; if (addr == destination) { list_del(&page->lru); return page; @@ -701,12 +713,12 @@ static struct page *kimage_alloc_page(struct kimage *image, if (!page) return NULL; /* If the page cannot be used file it away */ - if (page_to_pfn(page) > + if (kexec_page_to_pfn(page) > (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { list_add(&page->lru, &image->unuseable_pages); continue; } - addr = page_to_pfn(page) << PAGE_SHIFT; + addr = kexec_page_to_pfn(page) << PAGE_SHIFT; /* If it is the destination page we want use it */ if (addr == destination) @@ -729,7 +741,7 @@ static struct page *kimage_alloc_page(struct kimage *image, struct page *old_page; old_addr = *old & PAGE_MASK; - old_page = pfn_to_page(old_addr >> PAGE_SHIFT); + old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT); copy_highpage(page, old_page); *old = addr | (*old & ~PAGE_MASK); @@ -779,7 +791,7 @@ static int kimage_load_normal_segment(struct kimage *image, result = -ENOMEM; goto out; } - result = kimage_add_page(image, page_to_pfn(page) + result = kimage_add_page(image, kexec_page_to_pfn(page) << PAGE_SHIFT); if (result < 0) goto out; @@ -811,6 +823,7 @@ out: return result; } +#ifndef CONFIG_XEN static int kimage_load_crash_segment(struct kimage *image, struct kexec_segment *segment) { @@ -833,7 +846,7 @@ static int kimage_load_crash_segment(struct kimage *image, char *ptr; size_t uchunk, mchunk; - page = pfn_to_page(maddr >> PAGE_SHIFT); + page = kexec_pfn_to_page(maddr >> PAGE_SHIFT); if (page == 0) { result = -ENOMEM; goto out; @@ -881,6 +894,13 @@ static int kimage_load_segment(struct kimage *image, return result; } +#else /* CONFIG_XEN */ +static int kimage_load_segment(struct kimage *image, + struct kexec_segment *segment) +{ + return kimage_load_normal_segment(image, segment); +} +#endif /* * Exec Kernel system call: for obvious reasons only root may call it. @@ -991,6 +1011,11 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, if (result) goto out; } +#ifdef CONFIG_XEN + result = xen_machine_kexec_load(image); + if (result) + goto out; +#endif /* Install the new kernel, and Uninstall the old */ image = xchg(dest_image, image); @@ -1045,7 +1070,6 @@ void crash_kexec(struct pt_regs *regs) struct kimage *image; int locked; - /* Take the kexec_lock here to prevent sys_kexec_load * running on one cpu from replacing the crash kernel * we are using after a panic on a different cpu. @@ -1061,7 +1085,11 @@ void crash_kexec(struct pt_regs *regs) struct pt_regs fixed_regs; crash_setup_regs(&fixed_regs, regs); machine_crash_shutdown(&fixed_regs); +#ifdef CONFIG_XEN + xen_machine_kexec(image); +#else machine_kexec(image); +#endif } xchg(&kexec_lock, 0); } From c720eb6ab76d4b6699d022182daf014df3507d97 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 8 Dec 2006 11:47:09 +0000 Subject: [PATCH 68/69] [LINUX] Kexec: Remove remainder of kexec-generic.patch Rename xen_machine_kexec() to just machine_kexec() and only compile in the Xen or native version as appropriate. Signed-off-by: Ian Campbell --- .../arch/i386/kernel/machine_kexec.c | 2 ++ .../arch/x86_64/kernel/machine_kexec.c | 2 ++ .../drivers/xen/core/machine_kexec.c | 2 +- linux-2.6-xen-sparse/include/linux/kexec.h | 1 - linux-2.6-xen-sparse/kernel/kexec.c | 4 ---- patches/linux-2.6.16.33/kexec-generic.patch | 15 --------------- patches/linux-2.6.16.33/series | 1 - 7 files changed, 5 insertions(+), 22 deletions(-) delete mode 100644 patches/linux-2.6.16.33/kexec-generic.patch diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c b/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c index f9ebc85481..d3979a6531 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c @@ -92,6 +92,7 @@ void machine_kexec_cleanup(struct kimage *image) { } +#ifndef CONFIG_XEN /* * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. @@ -125,3 +126,4 @@ NORET_TYPE void machine_kexec(struct kimage *image) relocate_kernel((unsigned long)image->head, (unsigned long)page_list, image->start, cpu_has_pae); } +#endif diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c index f598578b0c..f1d9583880 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c @@ -237,6 +237,7 @@ void machine_kexec_cleanup(struct kimage *image) return; } +#ifndef CONFIG_XEN /* * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. @@ -275,3 +276,4 @@ NORET_TYPE void machine_kexec(struct kimage *image) relocate_kernel((unsigned long)image->head, (unsigned long)page_list, image->start); } +#endif diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c index 5e6b58b390..a16e9d9a22 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c @@ -163,7 +163,7 @@ void xen_machine_kexec_unload(struct kimage *image) * stop all CPUs and kexec. That is it combines machine_shutdown() * and machine_kexec() in Linux kexec terms. */ -NORET_TYPE void xen_machine_kexec(struct kimage *image) +NORET_TYPE void machine_kexec(struct kimage *image) { xen_kexec_exec_t xke; diff --git a/linux-2.6-xen-sparse/include/linux/kexec.h b/linux-2.6-xen-sparse/include/linux/kexec.h index b51072d4ed..8f4fccf63c 100644 --- a/linux-2.6-xen-sparse/include/linux/kexec.h +++ b/linux-2.6-xen-sparse/include/linux/kexec.h @@ -101,7 +101,6 @@ extern void machine_kexec_cleanup(struct kimage *image); #ifdef CONFIG_XEN extern int xen_machine_kexec_load(struct kimage *image); extern void xen_machine_kexec_unload(struct kimage *image); -extern NORET_TYPE void xen_machine_kexec(struct kimage *image) ATTRIB_NORET; extern void xen_machine_kexec_setup_resources(void); extern void xen_machine_kexec_register_resources(struct resource *res); #endif diff --git a/linux-2.6-xen-sparse/kernel/kexec.c b/linux-2.6-xen-sparse/kernel/kexec.c index 1dd4096967..9a1dbb6ae3 100644 --- a/linux-2.6-xen-sparse/kernel/kexec.c +++ b/linux-2.6-xen-sparse/kernel/kexec.c @@ -1085,11 +1085,7 @@ void crash_kexec(struct pt_regs *regs) struct pt_regs fixed_regs; crash_setup_regs(&fixed_regs, regs); machine_crash_shutdown(&fixed_regs); -#ifdef CONFIG_XEN - xen_machine_kexec(image); -#else machine_kexec(image); -#endif } xchg(&kexec_lock, 0); } diff --git a/patches/linux-2.6.16.33/kexec-generic.patch b/patches/linux-2.6.16.33/kexec-generic.patch deleted file mode 100644 index a85d546e4d..0000000000 --- a/patches/linux-2.6.16.33/kexec-generic.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- 0002/kernel/sys.c -+++ work/kernel/sys.c -@@ -435,8 +435,12 @@ void kernel_kexec(void) - kernel_restart_prepare(NULL); - printk(KERN_EMERG "Starting new kernel\n"); - machine_shutdown(); -+#ifdef CONFIG_XEN -+ xen_machine_kexec(image); -+#else - machine_kexec(image); - #endif -+#endif - } - EXPORT_SYMBOL_GPL(kernel_kexec); - diff --git a/patches/linux-2.6.16.33/series b/patches/linux-2.6.16.33/series index 604aed27e9..28fabf00ff 100644 --- a/patches/linux-2.6.16.33/series +++ b/patches/linux-2.6.16.33/series @@ -1,4 +1,3 @@ -kexec-generic.patch git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch From b65f717688423c3b3f770d38d63ad681a53121c4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 8 Dec 2006 11:57:06 +0000 Subject: [PATCH 69/69] [LIBXC] Clean up use of sterror(). Define a thread-safe version which uses strerror_r(), and tries to cope with the POSIX and GNU versions of that function. Signed-off-by: Keir Fraser --- tools/libxc/ia64/xc_ia64_linux_save.c | 2 +- tools/libxc/xc_core.c | 4 ++-- tools/libxc/xc_linux_build.c | 4 ++-- tools/libxc/xc_private.c | 13 +++++++++++++ tools/libxc/xc_private.h | 3 ++- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c index 42ec21c802..d98725445a 100644 --- a/tools/libxc/ia64/xc_ia64_linux_save.c +++ b/tools/libxc/ia64/xc_ia64_linux_save.c @@ -353,7 +353,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, It will be remarked dirty. FIXME: to be tracked. */ fprintf(stderr, "cannot map page %lx: %s\n", - page_array[N], strerror (errno)); + page_array[N], safe_strerror(errno)); continue; } diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 550d5691e1..035bf301e5 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -140,7 +140,7 @@ static int local_file_dump(void *args, char *buffer, unsigned int length) bytes = write(da->fd, &buffer[offset], length-offset); if ( bytes <= 0 ) { - PERROR("Failed to write buffer: %s", strerror(errno)); + PERROR("Failed to write buffer"); return -errno; } } @@ -158,7 +158,7 @@ xc_domain_dumpcore(int xc_handle, if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 ) { - PERROR("Could not open corefile %s: %s", corename, strerror(errno)); + PERROR("Could not open corefile %s", corename); return -errno; } diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index edf95c0fc0..a2b5274083 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -593,8 +593,8 @@ static int setup_guest(int xc_handle, /* shared_info page starts its life empty. */ shared_info = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame); - printf("shared_info = %p, err=%s frame=%lx\n", - shared_info, strerror (errno), shared_info_frame); + printf("shared_info = %p frame=%lx\n", + shared_info, shared_info_frame); //memset(shared_info, 0, PAGE_SIZE); /* Mask all upcalls... */ for ( i = 0; i < MAX_VIRT_CPUS; i++ ) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 3ff0b791d0..ed76cf003c 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -483,6 +483,19 @@ unsigned long xc_make_page_below_4G( return new_mfn; } +char *safe_strerror(int errcode) +{ + static __thread char errbuf[32]; +#ifdef __GLIBC__ + /* Broken GNU definition of strerror_r may not use our supplied buffer. */ + return strerror_r(errcode, errbuf, sizeof(errbuf)); +#else + /* Assume we have the POSIX definition of strerror_r. */ + strerror_r(errcode, errbuf, sizeof(errbuf)); + return errbuf; +#endif +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index f087e7de69..6dfbdead7a 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -59,11 +59,12 @@ #define PPRINTF(_f, _a...) #endif +char *safe_strerror(int errcode); void xc_set_error(int code, const char *fmt, ...); #define ERROR(_m, _a...) xc_set_error(XC_INTERNAL_ERROR, _m , ## _a ) #define PERROR(_m, _a...) xc_set_error(XC_INTERNAL_ERROR, _m " (%d = %s)", \ - ## _a , errno, strerror(errno)) + ## _a , errno, safe_strerror(errno)) int lock_pages(void *addr, size_t len); void unlock_pages(void *addr, size_t len);