xen/xend-traditional-qemu.patch
2013-06-20 17:01:24 +00:00

6059 lines
212 KiB
Diff

From 9ca313aa0824f2d350a7a6c9b1ef6c47e0408f1d Mon Sep 17 00:00:00 2001
From: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Date: Sat, 23 Aug 2008 23:27:37 +0000
Subject: [PATCH] VNC: Support for ExtendedKeyEvent client message
This patch adds support for the ExtendedKeyEvent client message. This message
allows a client to send raw scan codes directly to the server. If the client
and server are using the same keymap, then it's unnecessary to use the '-k'
option with QEMU when this extension is supported.
This is extension is currently only implemented by gtk-vnc based clients
(gvncviewer, virt-manager, vinagre, etc.).
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5076 c046a42c-6fe2-441c-8c8c-71466251a162
---
vnc.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 50 insertions(+), 9 deletions(-)
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/vnc.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/vnc.c
@@ -1285,35 +1285,22 @@ static void press_key_altgr_down(VncStat
}
}
-static void do_key_event(VncState *vs, int down, uint32_t sym)
+static void do_key_event(VncState *vs, int down, int keycode, int sym, int shift)
{
- int keycode;
int shift_keys = 0;
- int shift = 0;
int keypad = 0;
int altgr = 0;
int altgr_keys = 0;
if (is_graphic_console()) {
- if (sym >= 'A' && sym <= 'Z') {
- sym = sym - 'A' + 'a';
- shift = 1;
- }
- else {
+ if (!shift)
shift = keysym_is_shift(vs->kbd_layout, sym & 0xFFFF);
- }
altgr = keysym_is_altgr(vs->kbd_layout, sym & 0xFFFF);
}
shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
altgr_keys = vs->modifiers_state[0xb8];
- keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
- if (keycode == 0) {
- fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
- return;
- }
-
/* QEMU console switch */
switch(keycode) {
case 0x2a: /* Left Shift */
@@ -1342,6 +1329,11 @@ static void do_key_event(VncState *vs, i
}
break;
case 0x3a: /* CapsLock */
+ if(!down){
+ vs->modifiers_state[keycode] ^= 1;
+ kbd_put_keycode(keycode | 0x80);
+ }
+ return;
case 0x45: /* NumLock */
if (down) {
kbd_put_keycode(keycode & 0x7f);
@@ -1445,7 +1437,28 @@ static void do_key_event(VncState *vs, i
static void key_event(VncState *vs, int down, uint32_t sym)
{
- do_key_event(vs, down, sym);
+ int keycode;
+ int shift = 0;
+
+ if ( sym == 0xffea && keyboard_layout && !strcmp(keyboard_layout,"es") )
+ sym = 0xffe9;
+
+ if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) {
+ sym = sym - 'A' + 'a';
+ shift = 1;
+ }
+ keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
+ do_key_event(vs, down, keycode, sym, shift);
+}
+
+static void ext_key_event(VncState *vs, int down,
+ uint32_t sym, uint16_t keycode)
+{
+ /* if the user specifies a keyboard layout, always use it */
+ if (keyboard_layout)
+ key_event(vs, down, sym);
+ else
+ do_key_event(vs, down, keycode, sym, 0);
}
static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
@@ -1534,6 +1547,15 @@ static void framebuffer_update_request(V
qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
}
+static void send_ext_key_event_ack(VncState *vs)
+{
+ vnc_write_u8(vs, 0);
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1);
+ vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -258);
+ vnc_flush(vs);
+}
+
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
{
int i;
@@ -1562,6 +1584,9 @@ static void set_encodings(VncState *vs,
case -257:
vs->has_pointer_type_change = 1;
break;
+ case -258:
+ send_ext_key_event_ack(vs);
+ break;
case 0x574D5669:
vs->has_WMVi = 1;
default:
@@ -1734,6 +1759,25 @@ static int protocol_client_msg(VncState
}
set_encodings(vs, (int32_t *)(data + 4), limit);
+
+ /*
+ * The initialization of a VNC connection can race with xenfb changing
+ * the resolution. This happens when the VNC connection is already
+ * established, but the client has not yet advertised has_resize, so it
+ * won't get notified of the switch.
+ *
+ * Therefore we resend the resolution as soon as the client has sent its
+ * encodings.
+ */
+ if (vs->has_resize) {
+ /* Resize the VNC window */
+ vnc_write_u8(vs, 0); /* msg id */
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+ vnc_framebuffer_update(vs, 0, 0, vs->serverds.width, vs->serverds.height, -223);
+
+ vnc_flush(vs);
+ }
break;
case 3:
if (len == 1)
@@ -1774,6 +1818,24 @@ static int protocol_client_msg(VncState
client_cut_text(vs, read_u32(data, 4), (char *)(data + 8));
break;
+ case 255:
+ if (len == 1)
+ return 2;
+
+ switch (read_u8(data, 1)) {
+ case 0:
+ if (len == 2)
+ return 12;
+
+ ext_key_event(vs, read_u16(data, 2),
+ read_u32(data, 4), read_u32(data, 8));
+ break;
+ default:
+ printf("Msg: %d\n", read_u16(data, 0));
+ vnc_client_error(vs);
+ break;
+ }
+ break;
default:
printf("Msg: %d\n", data[0]);
vnc_client_error(vs);
@@ -2445,10 +2507,11 @@ void vnc_display_init(DisplayState *ds)
vs->ds = ds;
- if (!keyboard_layout)
- keyboard_layout = "en-us";
+ if (keyboard_layout)
+ vs->kbd_layout = init_keyboard_layout(keyboard_layout);
+ else
+ vs->kbd_layout = init_keyboard_layout("en-us");
- vs->kbd_layout = init_keyboard_layout(keyboard_layout);
if (!vs->kbd_layout)
exit(1);
vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
@@ -2564,6 +2627,7 @@ int vnc_display_password(DisplayState *d
if (password && password[0]) {
if (!(vs->password = qemu_strdup(password)))
return -1;
+ vs->auth = VNC_AUTH_VNC;
}
return 0;
Index: xen-4.3.0-testing/tools/hotplug/Linux/init.d/sysconfig.xendomains
===================================================================
--- xen-4.3.0-testing.orig/tools/hotplug/Linux/init.d/sysconfig.xendomains
+++ xen-4.3.0-testing/tools/hotplug/Linux/init.d/sysconfig.xendomains
@@ -98,7 +98,6 @@ XENDOMAINS_RESTORE=true
# Note that the script tries to be clever if both RESTORE and AUTO are
# set: It will first restore saved domains and then only start domains
# in AUTO which are not running yet.
-# Note that the name matching is somewhat fuzzy.
#
XENDOMAINS_AUTO=/etc/xen/auto
Index: xen-4.3.0-testing/tools/examples/xend-config.sxp
===================================================================
--- xen-4.3.0-testing.orig/tools/examples/xend-config.sxp
+++ xen-4.3.0-testing/tools/examples/xend-config.sxp
@@ -58,11 +58,12 @@
#(xend-http-server no)
-#(xend-unix-server no)
+(xend-unix-server yes)
#(xend-tcp-xmlrpc-server no)
#(xend-unix-xmlrpc-server yes)
+# Only enable xend-relocation-server on trusted networks as it lacks
+# encryption and authentication.
#(xend-relocation-server no)
-(xend-relocation-server yes)
#(xend-relocation-ssl-server no)
#(xend-udev-event-server no)
@@ -170,7 +171,12 @@
# two fake interfaces per guest domain. To do things like this, write
# yourself a wrapper script, and call network-bridge from it, as appropriate.
#
-(network-script network-bridge)
+# SuSE users note:
+# On openSUSE >= 11.1 and SLES >= 11, networks should be configured using
+# native platform tool - YaST. vif-bridge and qemu-ifup can be used to
+# connect vifs to the YaST-managed networks.
+#(network-script network-bridge)
+(network-script )
# The script used to control virtual interfaces. This can be overridden on a
# per-vif basis when creating a domain or a configuring a new vif. The
@@ -194,6 +200,26 @@
#(network-script network-route)
#(vif-script vif-route)
+# SuSE users note:
+# If using a routed network configuration it is advised to NOT use
+# network-route and vif-route scripts but instead use sysconfig scripts
+# in dom0 and vif-route-ifup script to "connect" the domU vif to dom0.
+# Since this configuration requires a vif sysconfig script in dom0, a static
+# vif name must be used. E.g. in dom0 the vif sysconfig script
+# (/etc/sysconfig/network/ifcfg-xen1.0) may contain
+#
+# NAME='XEN vm 1 virtual interface 0'
+# BOOTPROTO='static'
+# STARTMODE='hotplug'
+# ...
+#
+# The corresponding domain vif configuration would contain e.g.
+# vif=[ 'mac=00:16:3e:aa:bb:cc,script=vif-route-ifup,vifname=xen1.0', ]
+#
+# If the vif-route-ifup script will be used for all domains, it can be
+# set here as the default vif script, alleviating the need for
+# 'script=' in domain vif configuration.
+#(vif-script vif-route-ifup)
## Use the following if network traffic is routed with NAT, as an alternative
# to the settings for bridged networking given above.
@@ -203,7 +229,7 @@
# dom0-min-mem is the lowest permissible memory level (in MB) for dom0.
# This is a minimum both for auto-ballooning (as enabled by
# enable-dom0-ballooning below) and for xm mem-set when applied to dom0.
-(dom0-min-mem 196)
+(dom0-min-mem 512)
# Whether to enable auto-ballooning of dom0 to allow domUs to be created.
# If enable-dom0-ballooning = no, dom0 will never balloon out.
@@ -224,6 +250,9 @@
(dom0-cpus 0)
# Whether to enable core-dumps when domains crash.
+# This setting overrides the per-domain dump value 'on_crash' and causes a
+# core dump on all crashed domains. For finer grain control, it is best to
+# disable this setting (which is default) and use the per-domain controls.
#(enable-dump no)
# The tool used for initiating virtual TPM migration
@@ -295,6 +324,70 @@
# device assignment could really work properly even after we do this.
#(pci-passthrough-strict-check yes)
+# Domain Locking
+# In a multihost environment, domain locking provides a simple mechanism that
+# prevents simultaneously running a domain on more than one host.
+#
+# If enabled, xend will execute a external lock utility (defined below)
+# on each domain start and stop event. Disabled by default. Set to yes
+# to enable domain locking.
+#
+#(xend-domain-lock no)
+
+# Path where domain lock is stored if xend-domain-lock is enabled.
+# Note: This path must be accessible to all VM Servers participating
+# in domain locking, e.g. by specifying a shared mount point.
+# Lock is placed in /<xend-domain-lock-path>/<domain-uuid>.
+# Default is /var/lib/xen/images/vm_locks/
+#
+#(xend-domain-lock-path /var/lib/images/vm_locks)
+
+# External locking utility called by xend for acquiring/releasing
+# domain lock. By default /etc/xen/scripts/domain-lock will be used
+# if xend-domain-lock is set to yes. Set to path of custom locking
+# utility to override the default.
+#
+# Synopsis of lock-util:
+# lock-util [-l|-u] -n <vm name> -i <vm uuid> -p <physical host> path"
+# -l Acquire (create) lock
+# -u Remove lock
+# -n vm-name Name of domain
+# -i vm-id Id or UUID of domain
+# -p phy-host Name of physical host (dom0)
+# path /<xend-domain-lock-path>/<vm-uuid>
+# Return 0 on success, non-zero on error.
+#
+# lock-util [-s] -i <vm uuid> path"
+# -s Lock status. If lock is acquired, print any contents
+# on stdout and return 0. Return non-zero if lock is
+# available.
+# path /<xend-domain-lock-path>/<vm-uuid>
+# If lock is acquired, print any contents on stdout and return 0.
+# Return non-zero if lock is available.
+#
+# Default lock-util behavior:
+# On domain start event, domain-lock will create and flock(1)
+# /<xend-domain-lock-path>/<vm-uuid>/lock. Every two seconds it
+# will write <vm-name>, <vm-id>, <vm-host>, and <tick> to the lock.
+# <tick> is running counter.
+# On domain stop event, domain-lock will unlock and remove
+# /<xend-domain-lock-path>/<vm-uuid>/lock.
+#
+# Note: If xend-domain-lock-path is a cluster-unaware file system,
+# administrator intervention may be required to remove stale
+# locks. Consider two hosts using NFS for xend-domain-lock-path
+# when HostA, running vm1, crashes. HostB could not acquire a
+# lock for vm1 since the NFS server holds an exclusive lock
+# acquired by HostA. The lock file must be manually removed
+# before starting vm1 on HostB.
+#
+#(xend-domain-lock-utility domain-lock)
+
+# Some locking mechanism provide cluster wide locking service like sfex.
+# And that requires a shared locking device.
+#(xend-domain-lock-utility domain-lock-sfex)
+#(xend-domain-lock-device "/dev/iwmvg/hbdevice")
+
# If we have a very big scsi device configuration, start of xend is slow,
# because xend scans all the device paths to build its internal PSCSI device
# list. If we need only a few devices for assigning to a guest, we can reduce
Index: xen-4.3.0-testing/tools/python/xen/xm/create.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xm/create.py
+++ xen-4.3.0-testing/tools/python/xen/xm/create.py
@@ -36,7 +36,7 @@ from xen.xend.server.DevConstants import
from xen.util import blkif
from xen.util import vscsi_util
import xen.util.xsm.xsm as security
-from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
+from xen.xm.main import serverType, SERVER_XEN_API, SERVER_LEGACY_XMLRPC, get_single_vm
from xen.util import utils, auxbin
from xen.util.pci import dev_dict_to_sxp, \
parse_pci_name_extended, PciDeviceParseError
@@ -73,7 +73,7 @@ gopts.opt('quiet', short='q',
use="Quiet.")
gopts.opt('path', val='PATH',
- fn=set_value, default='.:' + auxbin.xen_configdir(),
+ fn=set_value, default='.:' + auxbin.xen_configdir() + "/vm",
use="Search path for configuration scripts. "
"The value of PATH is a colon-separated directory list.")
@@ -242,6 +242,10 @@ gopts.var('viridian', val='VIRIDIAN',
use="""Expose Viridian interface to x86 HVM guest?
(Default is 0).""")
+gopts.var('extid', val='EXTID',
+ fn=set_int, default=0,
+ use="Specify extention ID for a HVM domain.")
+
gopts.var('acpi', val='ACPI',
fn=set_int, default=1,
use="Disable or enable ACPI of HVM domain.")
@@ -473,6 +477,26 @@ gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
+gopts.var('smbios_firmware', val='FILE',
+ fn=set_value, default=None,
+ use="Path to a file that contains extra SMBIOS firmware structures.")
+
+gopts.var('acpi_firmware', val='FILE',
+ fn=set_value, default=None,
+ use="Path to a file that contains extra ACPI firmware tables.")
+
+gopts.var('actmem', val='NUM',
+ fn=set_value, default='0',
+ use="Number of pages to swap.")
+
+gopts.var('xenpaging_file', val='PATH',
+ fn=set_value, default=None,
+ use="pagefile to use (optional)")
+
+gopts.var('xenpaging_extra', val='string1,string2',
+ fn=append_value, default=[],
+ use="additional args for xenpaging (optional)")
+
gopts.var('device_model', val='FILE',
fn=set_value, default=None,
use="Path to device model program.")
@@ -517,6 +541,21 @@ gopts.var('usbdevice', val='NAME',
fn=set_value, default='',
use="Name of USB device to add?")
+gopts.var('watchdog', val='NAME',
+ fn=set_value, default='',
+ use="Watchdog device to use. May be ib700 or i6300esb")
+
+gopts.var('watchdog_action', val='reset|shutdown|poweroff|pause|none|dump',
+ fn=set_value, default="reset",
+ use="""Action when watchdog timer expires:
+ - reset: Default, forcefully reset the guest;
+ - shutdown: Gracefully shutdown the guest (not recommended);
+ - poweroff: Forcefully power off the guest;
+ - pause: Pause the guest;
+ - none: Do nothing;
+ - dump: Automatically dump the guest;
+ """)
+
gopts.var('description', val='NAME',
fn=set_value, default='',
use="Description of a domain")
@@ -1032,7 +1071,11 @@ def configure_hvm(config_image, vals):
args = [ 'acpi', 'apic',
'boot',
'cpuid', 'cpuid_check',
+ 'actmem',
+ 'xenpaging_file',
+ 'xenpaging_extra',
'device_model', 'display',
+ 'smbios_firmware', 'acpi_firmware',
'fda', 'fdb',
'gfx_passthru', 'guest_os_type',
'hap', 'hpet',
@@ -1047,7 +1090,8 @@ def configure_hvm(config_image, vals):
'timer_mode',
'usb', 'usbdevice',
'vcpus', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten',
- 'vncunused', 'viridian', 'vpt_align',
+ 'vncunused', 'vpt_align',
+ 'watchdog', 'watchdog_action',
'xauthority', 'xen_extended_power_mgmt', 'xen_platform_pci',
'memory_sharing' ]
@@ -1056,6 +1100,10 @@ def configure_hvm(config_image, vals):
config_image.append([a, vals.__dict__[a]])
if vals.vncpasswd is not None:
config_image.append(['vncpasswd', vals.vncpasswd])
+ if vals.extid and vals.extid == 1:
+ config_image.append(['viridian', vals.extid])
+ elif vals.viridian:
+ config_image.append(['viridian', vals.viridian])
def make_config(vals):
@@ -1274,9 +1322,8 @@ def preprocess_access_control(vals):
def preprocess_ip(vals):
if vals.ip or vals.dhcp != 'off':
- dummy_nfs_server = '127.0.255.255'
ip = (vals.ip
- + ':' + (vals.nfs_server or dummy_nfs_server)
+ + ':' + (vals.nfs_server or '')
+ ':' + vals.gateway
+ ':' + vals.netmask
+ ':' + vals.hostname
@@ -1465,7 +1512,7 @@ def main(argv):
except IOError, exn:
raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
- if serverType == SERVER_XEN_API:
+ if serverType == SERVER_XEN_API or serverType == SERVER_LEGACY_XMLRPC:
from xen.xm.xenapi_create import sxp2xml
sxp2xml_inst = sxp2xml()
doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
@@ -1473,7 +1520,7 @@ def main(argv):
if opts.vals.dryrun and not opts.is_xml:
SXPPrettyPrint.prettyprint(config)
- if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
+ if opts.vals.xmldryrun:
print doc.toprettyxml()
if opts.vals.dryrun or opts.vals.xmldryrun:
Index: xen-4.3.0-testing/docs/man/xm.pod.1
===================================================================
--- xen-4.3.0-testing.orig/docs/man/xm.pod.1
+++ xen-4.3.0-testing/docs/man/xm.pod.1
@@ -79,7 +79,7 @@ in the config file. See L<xmdomain.cfg>
format, and possible options used in either the configfile or for I<vars>.
I<configfile> can either be an absolute path to a file, or a relative
-path to a file located in /etc/xen.
+path to a file located in /etc/xen/vm.
Create will return B<as soon> as the domain is started. This B<does
not> mean the guest OS in the domain has actually booted, or is
@@ -160,7 +160,7 @@ B<EXAMPLES>
xm create Fedora4
-This creates a domain with the file /etc/xen/Fedora4, and returns as
+This creates a domain with the file /etc/xen/vm/Fedora4, and returns as
soon as it is run.
=item I<without config file>
@@ -299,7 +299,8 @@ scheduling by the Xen hypervisor.
=item B<s - shutdown>
-FIXME: Why would you ever see this state?
+The guest has requested to be shutdown, rebooted or suspended, and the
+domain is in the process of being destroyed in response.
=item B<c - crashed>
@@ -312,8 +313,6 @@ restart on crash. See L<xmdomain.cfg> f
The domain is in process of dying, but hasn't completely shutdown or
crashed.
-FIXME: Is this right?
-
=back
B<NOTES>
@@ -737,8 +736,6 @@ Xen ships with a number of domain schedu
time with the B<sched=> parameter on the Xen command line. By
default B<credit> is used for scheduling.
-FIXME: we really need a scheduler expert to write up this section.
-
=over 4
=item B<sched-credit> [ B<-d> I<domain-id> [ B<-w>[B<=>I<WEIGHT>] | B<-c>[B<=>I<CAP>] ] ]
@@ -801,8 +798,6 @@ The normal EDF scheduling usage in nanos
The normal EDF scheduling usage in nanoseconds
-FIXME: these are lame, should explain more.
-
=item I<latency-hint>
Scaled period if domain is doing heavy I/O.
@@ -952,9 +947,6 @@ the default setting in xend-config.sxp f
Passes the specified IP Address to the adapter on creation.
-FIXME: this currently appears to be B<broken>. I'm not sure under what
-circumstances this should actually work.
-
=item B<mac=>I<macaddr>
The MAC address that the domain will see on its Ethernet device. If
@@ -980,9 +972,6 @@ Removes the network device from the doma
I<devid> is the virtual interface device number within the domain
(i.e. the 3 in vif22.3).
-FIXME: this is currently B<broken>. Network devices aren't completely
-removed from domain 0.
-
=item B<network-list> [B<-l>|B<--long>]> I<domain-id>
List virtual network interfaces for a domain. The returned output is
Index: xen-4.3.0-testing/docs/man/xmdomain.cfg.pod.5
===================================================================
--- xen-4.3.0-testing.orig/docs/man/xmdomain.cfg.pod.5
+++ xen-4.3.0-testing/docs/man/xmdomain.cfg.pod.5
@@ -4,9 +4,9 @@ xmdomain.cfg - xm domain config file for
=head1 SYNOPSIS
- /etc/xen/myxendomain
- /etc/xen/myxendomain2
- /etc/xen/auto/myxenautostarted
+ /etc/xen/auto/
+ /etc/xen/examples/
+ /etc/xen/vm/
=head1 DESCRIPTION
@@ -14,14 +14,14 @@ The B<xm>(1) program uses python executa
domains to create from scratch. Each of these config files needs to
contain a number of required options, and may specify many more.
-Domain configuration files live in /etc/xen by default, if you store
+Domain configuration files live in /etc/xen/vm by default. If you store
config files anywhere else the full path to the config file must be
specified in the I<xm create> command.
/etc/xen/auto is a special case. Domain config files in that
directory will be started automatically at system boot if the
xendomain init script is enabled. The contents of /etc/xen/auto
-should be symlinks to files in /etc/xen to allow I<xm create> to be
+should be symlinks to files in /etc/xen/vm to allow I<xm create> to be
used without full paths.
Options are specified by I<name = value> statements in the
@@ -243,6 +243,25 @@ this the xen kernel must be compiled wit
This defaults to 1, meaning running the domain as a UP.
+=item B<acpi_firmware>
+
+Specify a path to a file that contains extra ACPI firmware tables to pass in to
+a guest. The file can contain several tables in their binary AML form
+concatenated together. Each table self describes its length so no additional
+information is needed. These tables will be added to the ACPI table set in the
+guest. Note that existing tables cannot be overridden by this feature. For
+example this cannot be used to override tables like DSDT, FADT, etc.
+
+=item B<smbios_firmware>
+
+Specify a path to a file that contains extra SMBIOS firmware structures to pass
+in to a guest. The file can contain a set DMTF predefined structures which will
+override the internal defaults. Not all predefined structures can be overridden,
+only the following types: 0, 1, 2, 3, 11, 22, 39. The file can also contain any
+number of vendor defined SMBIOS structures (type 128 - 255). Since SMBIOS
+structures do not present their overall size, each entry in the file must be
+preceded by a 32b integer indicating the size of the next structure.
+
=back
=head1 DOMAIN SHUTDOWN OPTIONS
@@ -333,16 +352,10 @@ at hda1, which is the root filesystem.
=item I<NFS Root>
-FIXME: write me
-
=item I<LVM Root>
-FIXME: write me
-
=item I<Two Networks>
-FIXME: write me
-
=back
=head1 SEE ALSO
Index: xen-4.3.0-testing/tools/python/xen/xend/server/DevController.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/DevController.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/DevController.py
@@ -149,13 +149,16 @@ class DevController:
(status, err) = self.waitForBackend(devid)
if status == Timeout:
- self.destroyDevice(devid, False)
+ #Clean timeout backend resource
+ dev = self.convertToDeviceNumber(devid)
+ self.writeBackend(dev, HOTPLUG_STATUS_NODE, HOTPLUG_STATUS_ERROR)
+ self.destroyDevice(devid, True)
raise VmError("Device %s (%s) could not be connected. "
"Hotplug scripts not working." %
(devid, self.deviceClass))
elif status == Error:
- self.destroyDevice(devid, False)
+ self.destroyDevice(devid, True)
if err is None:
raise VmError("Device %s (%s) could not be connected. "
"Backend device not found." %
@@ -554,7 +557,17 @@ class DevController:
xswatch(statusPath, hotplugStatusCallback, ev, result)
- ev.wait(DEVICE_CREATE_TIMEOUT)
+ for i in range(1, 50):
+ ev.wait(DEVICE_CREATE_TIMEOUT/50)
+ status = xstransact.Read(statusPath)
+ if status is not None:
+ if status == HOTPLUG_STATUS_ERROR:
+ result['status'] = Error
+ elif status == HOTPLUG_STATUS_BUSY:
+ result['status'] = Busy
+ else:
+ result['status'] = Connected
+ break
err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)
@@ -571,7 +584,12 @@ class DevController:
xswatch(statusPath, deviceDestroyCallback, ev, result)
- ev.wait(DEVICE_DESTROY_TIMEOUT)
+ for i in range(1, 50):
+ ev.wait(DEVICE_DESTROY_TIMEOUT/50)
+ status = xstransact.Read(statusPath)
+ if status is None:
+ result['status'] = Disconnected
+ break
return result['status']
@@ -592,6 +610,31 @@ class DevController:
return (Missing, None)
+ def waitForFrontend(self, devid):
+ def frontendStatusCallback(statusPath, ev, result):
+ status = xstransact.Read(statusPath)
+ log.debug("frontendStatusCallback %s = %s" % (statusPath, status))
+ try:
+ status = int(status)
+ if status == xenbusState['Connected']:
+ result['status'] = Connected
+ elif status == xenbusState['Closed']:
+ result['status'] = Error
+ else:
+ raise
+ except:
+ return 1
+ ev.set()
+ return 0
+ frontpath = self.frontendPath(devid)
+ statusPath = frontpath + '/state'
+ ev = Event()
+ result = { 'status': Timeout }
+ xswatch(statusPath, frontendStatusCallback, ev, result)
+ ev.wait(5)
+ return result['status']
+
+
def backendPath(self, backdom, devid):
"""Construct backend path given the backend domain and device id.
Index: xen-4.3.0-testing/tools/python/xen/xend/XendBootloader.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendBootloader.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendBootloader.py
@@ -12,7 +12,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
-import os, select, errno, stat, signal, tty
+import os, select, errno, stat, signal, tty, time
import random
import shlex
from xen.xend import sxp
@@ -38,8 +38,25 @@ def bootloader(blexec, disk, dom, quiet
msg = "Bootloader isn't executable"
log.error(msg)
raise VmError(msg)
- if not os.access(disk, os.R_OK):
- msg = "Disk isn't accessible"
+
+ # domUloader requires '--entry=foo' in blargs, which is derived from
+ # 'bootargs' entry in domain configuration file. Ensure it exists
+ # here so a reasonable error message can be returned.
+ if blexec.find('domUloader.py') != -1:
+ if blargs.find('entry') == -1:
+ msg = "domUloader requires specification of bootargs"
+ log.error(msg)
+ raise VmError(msg)
+
+ avail = False
+ for i in xrange(1, 500):
+ avail = os.access(disk, os.R_OK)
+ if avail:
+ break
+ time.sleep(.1)
+
+ if not avail:
+ msg = "Disk '%s' isn't accessible" % disk
log.error(msg)
raise VmError(msg)
Index: xen-4.3.0-testing/tools/python/xen/xend/XendDomainInfo.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendDomainInfo.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendDomainInfo.py
@@ -74,7 +74,7 @@ from xen.xend.XendPSCSI import XendPSCSI
from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA
MIGRATE_TIMEOUT = 30.0
-BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
+BOOTLOADER_LOOPBACK_DEVICES = ['/dev/xvd' + chr(x) for x in range(ord('z'), ord('d'), -1)]
xc = xen.lowlevel.xc.xc()
xoptions = XendOptions.instance()
@@ -303,7 +303,8 @@ def dom_get(dom):
return None
from xen.xend.server.pciif import parse_pci_name, PciDevice,\
- get_assigned_pci_devices, get_all_assigned_pci_devices
+ get_assigned_pci_devices, get_all_assigned_pci_devices,\
+ prepare_host_pci_devices, reattach_host_pci_devices
def do_FLR(domid, is_hvm):
@@ -317,6 +318,20 @@ def do_FLR(domid, is_hvm):
"parse it's resources - "+str(e))
dev.do_FLR(is_hvm, xoptions.get_pci_dev_assign_strict_check())
+def prepare_domain_pci_devices(domconfig):
+ ordered_refs = domconfig.ordered_device_refs()
+ for dev_uuid in ordered_refs:
+ devclass, devconfig = domconfig['devices'][dev_uuid]
+ if devclass == 'pci':
+ prepare_host_pci_devices(devconfig)
+
+def reattach_domain_pci_devices(domconfig):
+ ordered_refs = domconfig.ordered_device_refs()
+ for dev_uuid in ordered_refs:
+ devclass, devconfig = domconfig['devices'][dev_uuid]
+ if devclass == 'pci':
+ reattach_host_pci_devices(devconfig)
+
class XendDomainInfo:
"""An object represents a domain.
@@ -470,6 +485,8 @@ class XendDomainInfo:
if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED, XEN_API_VM_POWER_STATE_CRASHED):
try:
+ prepare_domain_pci_devices(self.info);
+ self.acquire_running_lock();
XendTask.log_progress(0, 30, self._constructDomain)
XendTask.log_progress(31, 60, self._initDomain)
@@ -496,6 +513,7 @@ class XendDomainInfo:
state = self._stateGet()
if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED):
try:
+ prepare_domain_pci_devices(self.info)
self._constructDomain()
try:
@@ -712,6 +730,8 @@ class XendDomainInfo:
the device.
"""
+ if self.domid is None:
+ return
self.iommu_check_pod_mode()
# Test whether the devices can be assigned
@@ -851,6 +871,9 @@ class XendDomainInfo:
if self.domid is not None:
try:
+ if dev_type == 'pci':
+ prepare_host_pci_devices(dev_config_dict)
+
dev_config_dict['devid'] = devid = \
self._createDevice(dev_type, dev_config_dict)
if dev_type == 'tap2':
@@ -864,6 +887,7 @@ class XendDomainInfo:
if dev_type == 'pci':
for dev in dev_config_dict['devs']:
XendAPIStore.deregister(dev['uuid'], 'DPCI')
+ reattach_host_pci_devices(dev_config_dict)
elif dev_type == 'vscsi':
for dev in dev_config_dict['devs']:
XendAPIStore.deregister(dev['uuid'], 'DSCSI')
@@ -908,6 +932,10 @@ class XendDomainInfo:
dev_config = pci_convert_sxp_to_dict(dev_sxp)
dev = dev_config['devs'][0]
+ # For attach only. For boot, prepare work has been done already in earlier stage.
+ if self.domid is not None and pci_state == 'Initialising' and pci_sub_state != 'Booting':
+ prepare_host_pci_devices(dev_config)
+
stubdomid = self.getStubdomDomid()
# Do HVM specific processing
if self.info.is_hvm():
@@ -984,6 +1012,9 @@ class XendDomainInfo:
new_dev_sxp = dev_control.configuration(devid)
self.info.device_update(dev_uuid, new_dev_sxp)
+ if pci_state == 'Closing':
+ reattach_host_pci_devices(dev_config)
+
# If there is no device left, destroy pci and remove config.
if num_devs == 0:
if self.info.is_hvm():
@@ -1203,6 +1234,9 @@ class XendDomainInfo:
except ValueError:
pass
devid = dev_control.convertToDeviceNumber(dev)
+ else:
+ # devid could be a name, e.g. hdc
+ devid = dev_control.convertToDeviceNumber(devid)
dev_info = self._getDeviceInfo_vbd(devid)
if dev_info is None:
raise VmError("Device %s not connected" % devid)
@@ -1295,8 +1329,15 @@ class XendDomainInfo:
frontpath = self.getDeviceController(deviceClass).frontendPath(dev)
backpath = xstransact.Read(frontpath, "backend")
thread.start_new_thread(self.getDeviceController(deviceClass).finishDeviceCleanup, (backpath, path))
-
- rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
+ if deviceClass =='vusb':
+ dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
+ state = self.getDeviceController(deviceClass).readBackend(dev, 'state')
+ if state == '1':
+ rc = self.getDeviceController(deviceClass).destroyDevice(devid, True)
+ else:
+ rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
+ else:
+ rc = self.getDeviceController(deviceClass).destroyDevice(devid, force)
if not force and rm_cfg:
# The backend path, other than the device itself,
# has to be passed because its accompanied frontend
@@ -1459,6 +1500,52 @@ class XendDomainInfo:
pci_conf = self.info['devices'][dev_uuid][1]
return map(pci_dict_to_bdf_str, pci_conf['devs'])
+ def capAndSetMemoryTarget(self, target):
+ """Potentially lowers the requested target to the largest possible
+ value (i.e., caps it), and then sets the memory target of this domain
+ to that value.
+ @param target in MiB.
+ """
+ max_target = 0
+ if self.domid == 0:
+ try:
+ from balloon import get_dom0_max_target
+ max_target = get_dom0_max_target() / 1024
+ except:
+ # It's nice to cap the max at sane values, but harmless to set
+ # them high. Carry on.
+ pass
+ if max_target and target > max_target:
+ log.debug("Requested memory target %d MiB; maximum reasonable is %d MiB.",
+ target, max_target)
+ target = max_target
+ self.setMemoryTarget(target)
+
+ def chgvncpasswd(self, passwd):
+ if self._stateGet() != DOM_STATE_HALTED:
+ path = '/local/domain/0/backend/vfb/%u/0/' % self.getDomid()
+ xstransact.Write(path, 'vncpasswd', passwd)
+ self.image.signalDeviceModel("chgvncpasswd", "vncpasswdchged")
+
+ for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
+ if dev_type == 'vfb':
+ dev_info['vncpasswd'] = passwd
+ dev_info['other_config']['vncpasswd'] = passwd
+ self.info.device_update(dev_uuid, cfg_xenapi = dev_info)
+ break
+ xen.xend.XendDomain.instance().managed_config_save(self)
+
+ def setSwapTarget(self, target):
+ """Set the swap target of this domain.
+ @param target: In MiB.
+ """
+ log.debug("Setting swap target of domain %s (%s) to %d MiB.",
+ self.info['name_label'], str(self.domid), target)
+
+ if self.domid > 0:
+ self.storeDom("memory/target-tot_pages", target * 1024)
+ self.info['platform']['actmem'] = str(target)
+
def setMemoryTarget(self, target):
"""Set the memory target of this domain.
@param target: In MiB.
@@ -1923,6 +2010,8 @@ class XendDomainInfo:
self.info['name_label'] = name
if to_store:
self.storeVm("name", name)
+ if self.dompath:
+ self.storeDom("name", name)
def getName(self):
return self.info['name_label']
@@ -2247,6 +2336,8 @@ class XendDomainInfo:
self.info['name_label'], self.domid, self.info['uuid'],
new_name, new_uuid)
self._unwatchVm()
+ if self.image:
+ self.image.destroyXenPaging()
self._releaseDevices()
# Remove existing vm node in xenstore
self._removeVm()
@@ -2283,7 +2374,7 @@ class XendDomainInfo:
# To prohibit directory traversal
based_name = os.path.basename(self.info['name_label'])
- coredir = "/var/xen/dump/%s" % (based_name)
+ coredir = "/var/lib/xen/dump/%s" % (based_name)
if not os.path.exists(coredir):
try:
mkdir.parents(coredir, stat.S_IRWXU)
@@ -2333,6 +2424,10 @@ class XendDomainInfo:
deviceClass, config = self.info['devices'].get(dev_uuid)
self._waitForDevice(deviceClass, config['devid'])
+ def _waitForDeviceFrontUUID(self, dev_uuid):
+ deviceClass, config = self.info['devices'].get(dev_uuid)
+ self.getDeviceController(deviceClass).waitForFrontend(config['devid'])
+
def _waitForDevice_destroy(self, deviceClass, devid, backpath):
return self.getDeviceController(deviceClass).waitForDevice_destroy(
devid, backpath)
@@ -2734,7 +2829,10 @@ class XendDomainInfo:
from xen.xend import XendDomain
doms = XendDomain.instance().list('all')
for dom in filter (lambda d: d.domid != self.domid, doms):
- cpuinfo = dom.getVCPUInfo()
+ try:
+ cpuinfo = dom.getVCPUInfo()
+ except:
+ continue
for vcpu in sxp.children(cpuinfo, 'vcpu'):
if sxp.child_value(vcpu, 'online') == 0: continue
cpumap = list(sxp.child_value(vcpu,'cpumap'))
@@ -2884,7 +2982,7 @@ class XendDomainInfo:
self.guest_bitsize = self.image.getBitSize()
# Make sure there's enough RAM available for the domain
- balloon.free(memory + shadow + vtd_mem, self)
+ balloon.free(memory + shadow + vtd_mem + 512, self)
# Set up the shadow memory
shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024)
@@ -2919,6 +3017,9 @@ class XendDomainInfo:
self._createDevices()
+ if self.image:
+ self.image.createXenPaging()
+
self.image.cleanupTmpImages()
self.info['start_time'] = time.time()
@@ -2943,6 +3044,8 @@ class XendDomainInfo:
self.refresh_shutdown_lock.acquire()
try:
self.unwatchShutdown()
+ if self.image:
+ self.image.destroyXenPaging()
self._releaseDevices()
bootloader_tidy(self)
@@ -2956,6 +3059,11 @@ class XendDomainInfo:
self._stateSet(DOM_STATE_HALTED)
self.domid = None # Do not push into _stateSet()!
+
+ try:
+ self.release_running_lock()
+ except:
+ log.exception("Failed to release domain lock.")
finally:
self.refresh_shutdown_lock.release()
@@ -3011,7 +3119,7 @@ class XendDomainInfo:
# TODO: recategorise - called from XendCheckpoint
#
- def completeRestore(self, store_mfn, console_mfn):
+ def completeRestore(self, store_mfn, console_mfn, console_port):
log.debug("XendDomainInfo.completeRestore")
@@ -3022,6 +3130,8 @@ class XendDomainInfo:
self.image = image.create(self, self.info)
if self.image:
self.image.createDeviceModel(True)
+ self.image.createXenPaging()
+ self.console_port = console_port
self._storeDomDetails()
self._registerWatches()
self.refreshShutdown()
@@ -3099,9 +3209,15 @@ class XendDomainInfo:
log.debug("%s KiB need to add to Memory pool" %self.alloc_mem)
MemoryPool.instance().increase_memory(self.alloc_mem)
+ reattach_domain_pci_devices(self.info)
self._cleanup_phantom_devs(paths)
self._cleanupVm()
+ if "change_home_server" in self.info:
+ chs = self.info["change_home_server"]
+ if (type(chs) is str and chs == "False") or \
+ (type(chs) is bool and chs is False):
+ self.setChangeHomeServer(None)
if ("transient" in self.info["other_config"] and \
bool(self.info["other_config"]["transient"])) or \
("change_home_server" in self.info and \
@@ -3157,6 +3273,8 @@ class XendDomainInfo:
# could also fetch a parsed note from xenstore
fast = self.info.get_notes().get('SUSPEND_CANCEL') and 1 or 0
if not fast:
+ if self.image:
+ self.image.destroyXenPaging()
self._releaseDevices()
self.testDeviceComplete()
self.testvifsComplete()
@@ -3172,6 +3290,8 @@ class XendDomainInfo:
self._storeDomDetails()
self._createDevices()
+ if self.image:
+ self.image.createXenPaging()
log.debug("XendDomainInfo.resumeDomain: devices created")
xc.domain_resume(self.domid, fast)
@@ -3271,32 +3391,38 @@ class XendDomainInfo:
# This is a file, not a device. pygrub can cope with a
# file if it's raw, but if it's QCOW or other such formats
# used through blktap, then we need to mount it first.
-
- log.info("Mounting %s on %s." %
- (fn, BOOTLOADER_LOOPBACK_DEVICE))
-
- vbd = {
- 'mode': 'RO',
- 'device': BOOTLOADER_LOOPBACK_DEVICE,
- }
-
- from xen.xend import XendDomain
- dom0 = XendDomain.instance().privilegedDomain()
- mounted_vbd_uuid = dom0.create_vbd(vbd, disk);
- dom0._waitForDeviceUUID(mounted_vbd_uuid)
- fn = BOOTLOADER_LOOPBACK_DEVICE
-
+ # Try all possible loopback_devices
+ for loopback_device in BOOTLOADER_LOOPBACK_DEVICES:
+ log.info("Mounting %s on %s." % (fn, loopback_device))
+ vbd = { 'mode' : 'RW', 'device' : loopback_device, }
+ try:
+ from xen.xend import XendDomain
+ dom0 = XendDomain.instance().privilegedDomain()
+ mounted_vbd_uuid = dom0.create_vbd(vbd, disk)
+ dom0._waitForDeviceFrontUUID(mounted_vbd_uuid)
+ fn = loopback_device
+ break
+ except VmError, e:
+ if str(e).find('already connected.') != -1:
+ continue
+ elif str(e).find('isn\'t accessible') != -1:
+ dom0.destroyDevice('vbd', loopback_device, force = True, rm_cfg = True)
+ continue
+ else:
+ raise
+ else:
+ raise
try:
blcfg = bootloader(blexec, fn, self, False,
bootloader_args, kernel, ramdisk, args)
finally:
if mounted:
log.info("Unmounting %s from %s." %
- (fn, BOOTLOADER_LOOPBACK_DEVICE))
- _, vbd_info = dom0.info['devices'][mounted_vbd_uuid]
- dom0.destroyDevice(dom0.getBlockDeviceClass(vbd_info['devid']),
- BOOTLOADER_LOOPBACK_DEVICE, force = True)
-
+ (fn, loopback_device))
+ if devtype in ['tap', 'tap2']:
+ dom0.destroyDevice('tap', loopback_device, rm_cfg = True)
+ else:
+ dom0.destroyDevice('vbd', loopback_device, rm_cfg = True)
if blcfg is None:
msg = "Had a bootloader specified, but can't find disk"
log.error(msg)
@@ -3908,6 +4034,14 @@ class XendDomainInfo:
else:
config['mode'] = 'RW'
+ if dev_class == 'console':
+ if not config.has_key('protocol'):
+ con_type = config.get('type', '')
+ if con_type == 'vnc':
+ config['protocol'] = 'rfb'
+ elif con_type == 'sdl':
+ config['protocol'] = 'rdp'
+
return config
def get_dev_property(self, dev_class, dev_uuid, field):
@@ -4415,6 +4549,91 @@ class XendDomainInfo:
def has_device(self, dev_class, dev_uuid):
return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
+ # Return name of host contained in lock file.
+ def get_lock_host(self, path):
+ lock_cmd = '%s -s -i %s ' % \
+ (xoptions.get_xend_domain_lock_utility(), \
+ self.info['uuid'])
+ lock_dev = xoptions.get_xend_domain_lock_device()
+ if lock_dev:
+ lock_cmd += '-x %d ' % lock_dev
+ lock_cmd += path
+ fin = os.popen(lock_cmd, 'r')
+ hostname = "unknown"
+
+ try:
+ tokens = fin.readline().split()
+ for token in tokens:
+ item = token.split('=')
+ if item[0] == 'host':
+ hostname = item[1]
+ return hostname
+ finally:
+ fin.close()
+
+ # Acquire a lock for the domain. No-op if domain locking is turned off.
+ def acquire_running_lock(self):
+ if not xoptions.get_xend_domain_lock():
+ return
+
+ log.debug("Acquiring lock for domain %s" % self.info['name_label'])
+ path = xoptions.get_xend_domain_lock_path()
+ path = os.path.join(path, self.get_uuid())
+
+ lock_cmd = '%s -l -p %s -n %s -i %s ' % \
+ (xoptions.get_xend_domain_lock_utility(), \
+ XendNode.instance().get_name(), \
+ self.info['name_label'], \
+ self.info['uuid'])
+ lock_dev = xoptions.get_xend_domain_lock_device()
+ if lock_dev:
+ lock_cmd += '-x %d ' % lock_dev
+ lock_cmd += path
+
+ try:
+ if not os.path.exists(path):
+ mkdir.parents(path, stat.S_IRWXU)
+ except:
+ log.exception("%s could not be created." % path)
+ raise XendError("%s could not be created." % path)
+
+ status = os.system(lock_cmd) >> 8
+ if status != 0:
+ log.debug("Failed to aqcuire lock: status = %d" % status)
+ raise XendError("The VM is locked and appears to be running on host %s." % self.get_lock_host(path))
+
+ # Release lock for domain. No-op if domain locking is turned off.
+ def release_running_lock(self, name = None):
+ if not xoptions.get_xend_domain_lock():
+ return
+
+ dom_name = self.info['name_label']
+ if name:
+ dom_name = name
+ log.debug("Releasing lock for domain %s" % dom_name)
+
+ path = xoptions.get_xend_domain_lock_path()
+ path = os.path.join(path, self.get_uuid())
+
+ lock_cmd = '%s -u -p %s -n %s -i %s ' % \
+ (xoptions.get_xend_domain_lock_utility(), \
+ XendNode.instance().get_name(), \
+ dom_name, \
+ self.info['uuid'])
+ lock_dev = xoptions.get_xend_domain_lock_device()
+ if lock_dev:
+ lock_cmd += '-x %d ' % lock_dev
+ lock_cmd += path
+
+ status = os.system(lock_cmd) >> 8
+ if status != 0:
+ log.exception("Failed to release lock: status = %s" % status)
+ try:
+ if len(os.listdir(path)) == 0:
+ shutil.rmtree(path)
+ except:
+ log.exception("Failed to remove unmanaged directory %s." % path)
+
def __str__(self):
return '<domain id=%s name=%s memory=%s state=%s>' % \
(str(self.domid), self.info['name_label'],
Index: xen-4.3.0-testing/tools/python/xen/xm/main.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xm/main.py
+++ xen-4.3.0-testing/tools/python/xen/xm/main.py
@@ -21,6 +21,7 @@
"""Grand unified management application for Xen.
"""
+import getpass
import atexit
import cmd
import os
@@ -114,6 +115,8 @@ SUBCOMMAND_HELP = {
'Set the maximum amount reservation for a domain.'),
'mem-set' : ('<Domain> <Mem>',
'Set the current memory usage for a domain.'),
+ 'mem-swap-target' : ('<Domain> <Mem>',
+ 'Set the memory usage for a domain.'),
'migrate' : ('<Domain> <Host>',
'Migrate a domain to another machine.'),
'pause' : ('<Domain>', 'Pause execution of a domain.'),
@@ -121,7 +124,7 @@ SUBCOMMAND_HELP = {
'reset' : ('<Domain>', 'Reset a domain.'),
'restore' : ('<CheckpointFile> [-p]',
'Restore a domain from a saved state.'),
- 'save' : ('[-c] <Domain> <CheckpointFile>',
+ 'save' : ('[-c|-f] <Domain> <CheckpointFile>',
'Save a domain state to restore later.'),
'shutdown' : ('<Domain> [-waRH]', 'Shutdown a domain.'),
'top' : ('', 'Monitor a host and the domains in real time.'),
@@ -280,6 +283,9 @@ SUBCOMMAND_HELP = {
'getenforce' : ('', 'Returns the current enforcing mode for the Flask XSM module (Enforcing,Permissive)'),
'setenforce' : ('[ (Enforcing|1) | (Permissive|0) ]',
'Modifies the current enforcing mode for the Flask XSM module'),
+ #change vnc password
+ 'change-vnc-passwd' : ('<Domain>',\
+ 'Change vnc password'),
}
SUBCOMMAND_OPTIONS = {
@@ -341,6 +347,7 @@ SUBCOMMAND_OPTIONS = {
),
'save': (
('-c', '--checkpoint', 'Leave domain running after creating snapshot'),
+ ('-f', '--force', 'Force to overwrite exist file'),
),
'restore': (
('-p', '--paused', 'Do not unpause domain after restoring it'),
@@ -404,6 +411,7 @@ common_commands = [
"usb-del",
"domstate",
"vcpu-set",
+ "change-vnc-passwd",
]
domain_commands = [
@@ -441,6 +449,7 @@ domain_commands = [
"vcpu-list",
"vcpu-pin",
"vcpu-set",
+ "change-vnc-passwd",
]
host_commands = [
@@ -862,18 +871,21 @@ def xm_event_monitor(args):
def xm_save(args):
- arg_check(args, "save", 2, 3)
+ arg_check(args, "save", 2, 4)
try:
- (options, params) = getopt.gnu_getopt(args, 'c', ['checkpoint'])
+ (options, params) = getopt.gnu_getopt(args, 'cf', ['checkpoint', 'force'])
except getopt.GetoptError, opterr:
err(opterr)
usage('save')
checkpoint = False
+ force = False
for (k, v) in options:
if k in ['-c', '--checkpoint']:
checkpoint = True
+ if k in ['-f', '--force']:
+ force = True
if len(params) != 2:
err("Wrong number of parameters")
@@ -887,9 +899,9 @@ def xm_save(args):
sys.exit(1)
if serverType == SERVER_XEN_API:
- server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
+ server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint, force)
else:
- server.xend.domain.save(dom, savefile, checkpoint)
+ server.xend.domain.save(dom, savefile, checkpoint, force)
def xm_restore(args):
arg_check(args, "restore", 1, 2)
@@ -1580,6 +1592,17 @@ def xm_mem_set(args):
mem_target = int_unit(args[1], 'm')
server.xend.domain.setMemoryTarget(dom, mem_target)
+def xm_mem_swap_target(args):
+ arg_check(args, "mem-swap-target", 2)
+
+ dom = args[0]
+
+ if serverType == SERVER_XEN_API:
+ err("xenapi not supported")
+ else:
+ swap_target = int_unit(args[1], 'm')
+ server.xend.domain.swaptarget_set(dom, swap_target)
+
def xm_usb_add(args):
arg_check(args, "usb-add", 2)
server.xend.domain.usb_add(args[0],args[1])
@@ -2199,6 +2222,10 @@ def xm_debug_keys(args):
def xm_top(args):
arg_check(args, "top", 0)
+ # A hack to get a clear error message if ran as non-root
+ if os.geteuid() != 0:
+ raise IOError()
+
os.system('xentop')
def xm_dmesg(args):
@@ -2586,10 +2613,22 @@ def xm_usb_list(args):
ni = parse_dev_info(x[1])
ni['idx'] = int(x[0])
usbver = sxp.child_value(x[1], 'usb-ver')
+
+ substr = re.search("^\d{1,}", usbver)
+ if substr:
+ usbver = substr.group()
+ else:
+ print "Unknown usb-ver"
+ continue
+
if int(usbver) == 1:
ni['usb-ver'] = 'USB1.1'
- else:
+ elif int(usbver) == 2:
ni['usb-ver'] = 'USB2.0'
+ else:
+ print "Unknown usb-ver"
+ continue
+
print "%(idx)-3d %(backend-id)-3d %(state)-5d %(usb-ver)-7s %(be-path)-30s " % ni
ports = sxp.child(x[1], 'port')
@@ -3751,6 +3790,10 @@ def xm_cpupool_migrate(args):
else:
server.xend.cpu_pool.migrate(domname, poolname)
+def xm_chgvncpasswd(args):
+ arg_check(args, "change-vnc-passwd", 1)
+ pwd = getpass.getpass("Enter new password: ")
+ server.xend.domain.chgvncpasswd(args[0], pwd)
commands = {
"shell": xm_shell,
@@ -3782,6 +3825,7 @@ commands = {
# memory commands
"mem-max": xm_mem_max,
"mem-set": xm_mem_set,
+ "mem-swap-target": xm_mem_swap_target,
# cpu commands
"vcpu-pin": xm_vcpu_pin,
"vcpu-list": xm_vcpu_list,
@@ -3857,6 +3901,8 @@ commands = {
"usb-del": xm_usb_del,
#domstate
"domstate": xm_domstate,
+ #change vnc password:
+ "change-vnc-passwd": xm_chgvncpasswd,
}
## The commands supported by a separate argument parser in xend.xm.
Index: xen-4.3.0-testing/tools/python/xen/xend/XendNode.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendNode.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendNode.py
@@ -162,6 +162,7 @@ class XendNode:
self._init_cpu_pools()
+ self._init_lock_devices()
def _init_networks(self):
# Initialise networks
@@ -382,6 +383,17 @@ class XendNode:
XendCPUPool.recreate_active_pools()
+ def _init_lock_devices(self):
+ if xendoptions().get_xend_domain_lock():
+ if xendoptions().get_xend_domain_lock_utility().endswith("domain-lock-sfex"):
+ lock_device = xendoptions().get_xend_domain_lock_device()
+ if not lock_device:
+ raise XendError("The block device for sfex is not properly configured")
+ status = os.system("lvchange -ay %s" % lock_device) >> 8
+ if status != 0:
+ raise XendError("The block device for sfex could not be initialized")
+
+
def add_network(self, interface):
# TODO
log.debug("add_network(): Not implemented.")
@@ -949,11 +961,35 @@ class XendNode:
info['cpu_mhz'] = info['cpu_khz'] / 1000
- # physinfo is in KiB, need it in MiB
- info['total_memory'] = info['total_memory'] / 1024
- info['free_memory'] = info['free_memory'] / 1024
+ configured_floor = xendoptions().get_dom0_min_mem() * 1024
+ from xen.xend import balloon
+ try:
+ kernel_floor = balloon.get_dom0_min_target()
+ except:
+ kernel_floor = 0
+ dom0_min_mem = max(configured_floor, kernel_floor)
+ dom0_mem = balloon.get_dom0_current_alloc()
+ extra_mem = 0
+ if dom0_min_mem > 0 and dom0_mem > dom0_min_mem:
+ extra_mem = dom0_mem - dom0_min_mem
+ info['free_memory'] = info['free_memory'] + info['scrub_memory']
+ info['max_free_memory'] = info['free_memory'] + extra_mem
info['free_cpus'] = len(XendCPUPool.unbound_cpus())
+ # Convert KiB to MiB, rounding down to be conservative
+ info['total_memory'] = info['total_memory'] / 1024
+ info['free_memory'] = info['free_memory'] / 1024
+ info['max_free_memory'] = info['max_free_memory'] / 1024
+
+ # FIXME: These are hard-coded to be the inverse of the getXenMemory
+ # functions in image.py. Find a cleaner way.
+ info['max_para_memory'] = info['max_free_memory'] - 4
+ if info['max_para_memory'] < 0:
+ info['max_para_memory'] = 0
+ info['max_hvm_memory'] = int((info['max_free_memory']-12) * (1-2.4/1024))
+ if info['max_hvm_memory'] < 0:
+ info['max_hvm_memory'] = 0
+
ITEM_ORDER = ['nr_cpus',
'nr_nodes',
'cores_per_socket',
@@ -964,6 +1000,9 @@ class XendNode:
'total_memory',
'free_memory',
'free_cpus',
+ 'max_free_memory',
+ 'max_para_memory',
+ 'max_hvm_memory',
]
if show_numa != 0:
Index: xen-4.3.0-testing/tools/python/xen/xend/balloon.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/balloon.py
+++ xen-4.3.0-testing/tools/python/xen/xend/balloon.py
@@ -43,6 +43,8 @@ SLEEP_TIME_GROWTH = 0.1
# label actually shown in the PROC_XEN_BALLOON file.
#labels = { 'current' : 'Current allocation',
# 'target' : 'Requested target',
+# 'min-target' : 'Minimum target',
+# 'max-target' : 'Maximum target',
# 'low-balloon' : 'Low-mem balloon',
# 'high-balloon' : 'High-mem balloon',
# 'limit' : 'Xen hard limit' }
@@ -69,6 +71,23 @@ def get_dom0_target_alloc():
raise VmError('Failed to query target memory allocation of dom0.')
return kb
+def get_dom0_min_target():
+ """Returns the minimum amount of memory (in KiB) that dom0 will accept."""
+
+ kb = _get_proc_balloon('min-target')
+ if kb == None:
+ raise VmError('Failed to query minimum target memory allocation of dom0.')
+ return kb
+
+def get_dom0_max_target():
+ """Returns the maximum amount of memory (in KiB) that is potentially
+ visible to dom0."""
+
+ kb = _get_proc_balloon('max-target')
+ if kb == None:
+ raise VmError('Failed to query maximum target memory allocation of dom0.')
+ return kb
+
def free(need_mem, dominfo):
"""Balloon out memory from the privileged domain so that there is the
specified required amount (in KiB) free.
Index: xen-4.3.0-testing/tools/python/xen/xend/server/SrvDomain.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/SrvDomain.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/SrvDomain.py
@@ -187,7 +187,7 @@ class SrvDomain(SrvDir):
def op_mem_target_set(self, _, req):
- return self.call(self.dom.setMemoryTarget,
+ return self.call(self.dom.capAndSetMemoryTarget,
[['target', 'int']],
req)
Index: xen-4.3.0-testing/tools/python/xen/xend/osdep.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/osdep.py
+++ xen-4.3.0-testing/tools/python/xen/xend/osdep.py
@@ -42,6 +42,8 @@ def _linux_balloon_stat_proc(label):
xend2linux_labels = { 'current' : 'Current allocation',
'target' : 'Requested target',
+ 'min-target' : 'Minimum target',
+ 'max-target' : 'Maximum target',
'low-balloon' : 'Low-mem balloon',
'high-balloon' : 'High-mem balloon',
'limit' : 'Xen hard limit' }
@@ -141,10 +143,14 @@ def _linux_get_cpuinfo():
d = {}
for line in f:
keyvalue = line.split(':')
- if len(keyvalue) != 2:
+ if len(keyvalue) < 2:
continue
key = keyvalue[0].strip()
- val = keyvalue[1].strip()
+ for i in range(1, len(keyvalue)):
+ if i == 1:
+ val = keyvalue[i].lstrip()
+ else:
+ val = val + ":" + keyvalue[i]
if key == 'processor':
if p != -1:
cpuinfo[p] = d
Index: xen-4.3.0-testing/tools/hotplug/Linux/Makefile
===================================================================
--- xen-4.3.0-testing.orig/tools/hotplug/Linux/Makefile
+++ xen-4.3.0-testing/tools/hotplug/Linux/Makefile
@@ -11,7 +11,7 @@ XENCOMMONS_SYSCONFIG = init.d/sysconfig.
# Xen script dir and scripts to go there.
XEN_SCRIPTS = network-bridge vif-bridge
-XEN_SCRIPTS += network-route vif-route
+XEN_SCRIPTS += network-route vif-route vif-route-ifup
XEN_SCRIPTS += network-nat vif-nat
XEN_SCRIPTS += vif-openvswitch
XEN_SCRIPTS += vif2
@@ -23,6 +23,8 @@ XEN_SCRIPTS += xen-hotplug-cleanup
XEN_SCRIPTS += external-device-migrate
XEN_SCRIPTS += vscsi
XEN_SCRIPTS += block-iscsi
+XEN_SCRIPTS += domain-lock vm-monitor
+XEN_SCRIPTS += domain-lock-sfex
XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
XEN_SCRIPT_DATA += block-common.sh
Index: xen-4.3.0-testing/tools/hotplug/Linux/vif-route-ifup
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/hotplug/Linux/vif-route-ifup
@@ -0,0 +1,34 @@
+#!/bin/bash
+#============================================================================
+# /etc/xen/vif-route-ifup
+#
+# Script for configuring a vif in routed mode.
+# The hotplugging system will call this script if it is specified either in
+# the device configuration given to Xend, or the default Xend configuration
+# in /etc/xen/xend-config.sxp. If the script is specified in neither of those
+# places, then vif-bridge is the default.
+#
+# Usage:
+# vif-route-ifup (add|remove|online|offline)
+#
+# Environment vars:
+# dev vif interface name (required).
+#============================================================================
+
+dir=$(dirname "$0")
+. "$dir/vif-common.sh"
+
+case "$command" in
+ online)
+ ifup ${dev}
+ ;;
+ offline)
+ do_without_error ifdown ${dev}
+ ;;
+esac
+
+log debug "Successful vif-route-ifup $command for ${dev}."
+if [ "$command" = "online" ]
+then
+ success
+fi
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/net.h
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/net.h
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/net.h
@@ -107,8 +107,8 @@ void net_host_device_add(const char *dev
void net_host_device_remove(int vlan_id, const char *device);
#ifndef DEFAULT_NETWORK_SCRIPT
-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
+#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
+#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/xen/qemu-ifdown"
#endif
#ifdef __sun__
#define SMBD_COMMAND "/usr/sfw/sbin/smbd"
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/net.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/net.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/net.c
@@ -1759,9 +1759,10 @@ int net_client_init(const char *device,
}
if (get_param_value(script_arg, sizeof(script_arg), "scriptarg", p) == 0 &&
get_param_value(script_arg, sizeof(script_arg), "bridge", p) == 0) { /* deprecated; for xend compatibility */
- pstrcpy(script_arg, sizeof(script_arg), "");
+ ret = net_tap_init(vlan, device, name, ifname, setup_script, NULL, NULL);
+ } else {
+ ret = net_tap_init(vlan, device, name, ifname, setup_script, down_script, script_arg);
}
- ret = net_tap_init(vlan, device, name, ifname, setup_script, down_script, script_arg);
}
} else
#endif
Index: xen-4.3.0-testing/tools/python/xen/xend/image.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/image.py
+++ xen-4.3.0-testing/tools/python/xen/xend/image.py
@@ -17,7 +17,7 @@
#============================================================================
-import os, os.path, string
+import os, os.path, string, struct, stat
import re
import math
import time
@@ -122,7 +122,13 @@ class ImageHandler:
self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } )
self.device_model = vmConfig['platform'].get('device_model')
+ self.actmem = str(vmConfig['platform'].get('actmem'))
+ self.xenpaging_file = str(vmConfig['platform'].get('xenpaging_file'))
+ self.xenpaging_extra = vmConfig['platform'].get('xenpaging_extra')
+ self.xenpaging_pid = None
+ self.smbios_firmware =(str(vmConfig['platform'].get('smbios_firmware')))
+ self.acpi_firmware =(str(vmConfig['platform'].get('acpi_firmware')))
self.display = vmConfig['platform'].get('display')
self.xauthority = vmConfig['platform'].get('xauthority')
self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0))
@@ -392,6 +398,87 @@ class ImageHandler:
sentinel_fifos_inuse[sentinel_path_fifo] = 1
self.sentinel_path_fifo = sentinel_path_fifo
+ def createXenPaging(self):
+ if not self.vm.info.is_hvm():
+ return
+ if self.actmem == "0":
+ return
+ if self.xenpaging_pid:
+ return
+ xenpaging_bin = auxbin.pathTo("xenpaging")
+ args = [xenpaging_bin]
+ args = args + ([ "-f", "/var/lib/xen/xenpaging/%s.%d.paging" % (str(self.vm.info['name_label']), self.vm.getDomid())])
+ if self.xenpaging_extra:
+ args = args + (self.xenpaging_extra)
+ args = args + ([ "-d", "%d" % self.vm.getDomid()])
+ self.xenpaging_logfile = "/var/log/xen/xenpaging-%s.log" % str(self.vm.info['name_label'])
+ logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND|os.O_TRUNC
+ null = os.open("/dev/null", os.O_RDONLY)
+ try:
+ os.unlink(self.xenpaging_logfile)
+ except:
+ pass
+ logfd = os.open(self.xenpaging_logfile, logfile_mode, 0644)
+ sys.stderr.flush()
+ contract = osdep.prefork("%s:%d" % (self.vm.getName(), self.vm.getDomid()))
+ xenpaging_pid = os.fork()
+ if xenpaging_pid == 0: #child
+ try:
+ osdep.postfork(contract)
+ os.dup2(null, 0)
+ os.dup2(logfd, 1)
+ os.dup2(logfd, 2)
+ try:
+ env = dict(os.environ)
+ log.info("starting %s" % args)
+ os.execve(xenpaging_bin, args, env)
+ except Exception, e:
+ log.warn('failed to execute xenpaging: %s' % utils.exception_string(e))
+ os._exit(126)
+ except:
+ log.warn("starting xenpaging failed")
+ os._exit(127)
+ else:
+ osdep.postfork(contract, abandon=True)
+ self.xenpaging_pid = xenpaging_pid
+ os.close(null)
+ os.close(logfd)
+ self.vm.storeDom("xenpaging/xenpaging-pid", self.xenpaging_pid)
+ self.vm.storeDom("memory/target-tot_pages", int(self.actmem) * 1024)
+
+ def destroyXenPaging(self):
+ if self.actmem == "0":
+ return
+ if self.xenpaging_pid:
+ try:
+ os.kill(self.xenpaging_pid, signal.SIGHUP)
+ except OSError, exn:
+ log.exception(exn)
+ for i in xrange(100):
+ try:
+ (p, rv) = os.waitpid(self.xenpaging_pid, os.WNOHANG)
+ if p == self.xenpaging_pid:
+ break
+ except OSError:
+ # This is expected if Xend has been restarted within
+ # the life of this domain. In this case, we can kill
+ # the process, but we can't wait for it because it's
+ # not our child. We continue this loop, and after it is
+ # terminated make really sure the process is going away
+ # (SIGKILL).
+ pass
+ time.sleep(0.1)
+ else:
+ log.warning("xenpaging %d took more than 10s "
+ "to terminate: sending SIGKILL" % self.xenpaging_pid)
+ try:
+ os.kill(self.xenpaging_pid, signal.SIGKILL)
+ os.waitpid(self.xenpaging_pid, 0)
+ except OSError:
+ # This happens if the process doesn't exist.
+ pass
+ self.xenpaging_pid = None
+
def createDeviceModel(self, restore = False):
if self.device_model is None:
return
@@ -828,6 +915,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
+ self.extid = int(vmConfig['platform'].get('extid', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
self.memory_sharing = int(vmConfig['memory_sharing'])
try:
@@ -855,7 +943,8 @@ class HVMImageHandler(ImageHandler):
dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
'localtime', 'serial', 'stdvga', 'isa',
- 'acpi', 'usb', 'usbdevice', 'gfx_passthru' ]
+ 'acpi', 'usb', 'usbdevice', 'gfx_passthru',
+ 'watchdog', 'watchdog_action' ]
for a in dmargs:
v = vmConfig['platform'].get(a)
@@ -863,6 +952,7 @@ class HVMImageHandler(ImageHandler):
# python doesn't allow '-' in variable names
if a == 'stdvga': a = 'std-vga'
if a == 'keymap': a = 'k'
+ if a == 'watchdog_action': a = 'watchdog-action'
# Handle booleans gracefully
if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']:
@@ -912,11 +1002,13 @@ class HVMImageHandler(ImageHandler):
mac = devinfo.get('mac')
if mac is None:
raise VmError("MAC address not specified or generated.")
- bridge = devinfo.get('bridge', 'xenbr0')
+ bridge = devinfo.get('bridge', None)
model = devinfo.get('model', 'rtl8139')
ret.append("-net")
- ret.append("nic,vlan=%d,macaddr=%s,model=%s" %
- (nics, mac, model))
+ net = "nic,vlan=%d,macaddr=%s,model=%s" % (nics, mac, model)
+ if bridge:
+ net += ",bridge=%s" % bridge
+ ret.append(net)
vifname = "vif%d.%d-emu" % (self.vm.getDomid(), nics-1)
ret.append("-net")
if osdep.tapif_script is not None:
@@ -941,6 +1033,38 @@ class HVMImageHandler(ImageHandler):
self.vm.getDomid() ])
return args
+ def _readFirmwareFile(self, filename):
+ # Sanity check
+ if filename is None or filename.strip() == "":
+ size = struct.pack('i', int(0))
+ return size + ""
+
+ log.debug("Reading firmware file %s", filename)
+ # Open
+ try:
+ fd = os.open(filename, os.O_RDONLY)
+ except Exception, e:
+ raise VmError('Unable to open firmware file %s' % filename)
+
+ # Validate file size
+ statinfo = os.fstat(fd)
+ if statinfo.st_size == 0 or statinfo.st_size > sys.maxint:
+ os.close(fd)
+ raise VmError('Firmware file %s is an invalid size' % filename)
+ if not stat.S_ISREG(statinfo.st_mode):
+ os.close(fd)
+ raise VmError('Firmware file %s is an invalid file type' % filename)
+ size = struct.pack('i', statinfo.st_size)
+
+ # Read entire file
+ try:
+ buf = os.read(fd, statinfo.st_size)
+ except Exception, e:
+ os.close(fd)
+ raise VmError('Failed reading firmware file %s' % filename)
+ os.close(fd)
+ return size+buf
+
def buildDomain(self):
store_evtchn = self.vm.getStorePort()
@@ -956,6 +1080,8 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpu_avail = %li", self.vm.getVCpuAvail())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("smbios_firmware= %s", self.smbios_firmware)
+ log.debug("acpi_firmware = %s", self.acpi_firmware)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
@@ -964,7 +1090,9 @@ class HVMImageHandler(ImageHandler):
vcpus = self.vm.getVCpuCount(),
vcpu_avail = self.vm.getVCpuAvail(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ smbios_firmware= self._readFirmwareFile(self.smbios_firmware),
+ acpi_firmware = self._readFirmwareFile(self.acpi_firmware))
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
@@ -1036,7 +1164,7 @@ class X86_HVM_ImageHandler(HVMImageHandl
def configure(self, vmConfig):
HVMImageHandler.configure(self, vmConfig)
- self.pae = int(vmConfig['platform'].get('pae', 0))
+ self.pae = int(vmConfig['platform'].get('pae', 1))
self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
def buildDomain(self):
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/i386-dm/qemu-ifup-Linux
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/i386-dm/qemu-ifup-Linux
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/i386-dm/qemu-ifup-Linux
@@ -1,36 +1,22 @@
#!/bin/sh
-#. /etc/rc.d/init.d/functions
-#ulimit -c unlimited
-
echo 'config qemu network with xen bridge for ' $*
+# If bridge is not specified, try device with default route.
bridge=$2
+if [ -z "$bridge" ]; then
+ bridge=$(ip route list | awk '/^default / { print $NF }')
+fi
-#
-# Old style bridge setup with netloop, used to have a bridge name
-# of xenbrX, enslaving pethX and vif0.X, and then configuring
-# eth0.
-#
-# New style bridge setup does not use netloop, so the bridge name
-# is ethX and the physical device is enslaved pethX
-#
-# So if...
-#
-# - User asks for xenbrX
-# - AND xenbrX doesn't exist
-# - AND there is a ethX device which is a bridge
-#
-# ..then we translate xenbrX to ethX
-#
-# This lets old config files work without modification
-#
-if [ ! -e "/sys/class/net/$bridge" ] && [ -z "${bridge##xenbr*}" ]
+# Exit if $bridge is not a bridge. Exit with 0 status
+# so qemu-dm process is not terminated. No networking in
+# vm is bad but not catastrophic. The vm could still run
+# cpu and disk IO workloads.
+# Include an useful error message in qemu-dm log file.
+if [ ! -e "/sys/class/net/${bridge}/bridge" ]
then
- if [ -e "/sys/class/net/eth${bridge#xenbr}/bridge" ]
- then
- bridge="eth${bridge#xenbr}"
- fi
+ echo "WARNING! ${bridge} is not a bridge. qemu-ifup exiting. VM may not have a functioning networking stack."
+ exit 0
fi
ifconfig $1 0.0.0.0 up
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/monitor.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/monitor.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/monitor.c
@@ -26,6 +26,7 @@
#include "hw/pcmcia.h"
#include "hw/pc.h"
#include "hw/pci.h"
+#include "hw/watchdog.h"
#include "gdbstub.h"
#include "net.h"
#include "qemu-char.h"
@@ -531,6 +532,13 @@ static void do_gdbserver(const char *por
}
#endif
+static void do_watchdog_action(const char *action)
+{
+ if (select_watchdog_action(action) == -1) {
+ qemu_printf("Unknown watchdog action '%s'\n", action);
+ }
+}
+
static void term_printc(int c)
{
term_printf("'");
@@ -1497,6 +1505,7 @@ static const term_cmd_t term_cmds[] = {
"device|all", "commit changes to the disk images (if -snapshot is used) or backing files" },
{ "info", "s?", do_info,
"subcommand", "show various information about the system state" },
+#ifdef CONFIG_TRUSTED_CLIENT
{ "q|quit", "", do_quit,
"", "quit the emulator" },
{ "eject", "-fB", do_eject,
@@ -1509,6 +1518,7 @@ static const term_cmd_t term_cmds[] = {
"filename", "output logs to 'filename'" },
{ "log", "s", do_log,
"item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
+#endif
{ "savevm", "s?", do_savevm,
"tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" },
{ "loadvm", "s", do_loadvm,
@@ -1538,8 +1548,10 @@ static const term_cmd_t term_cmds[] = {
"", "reset the system" },
{ "system_powerdown", "", do_system_powerdown,
"", "send system power down event" },
+#ifdef CONFIG_TRUSTED_CLIENT
{ "sum", "ii", do_sum,
"addr size", "compute the checksum of a memory region" },
+#endif
{ "usb_add", "s", do_usb_add,
"device", "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')" },
{ "usb_del", "s", do_usb_del,
@@ -1558,6 +1570,7 @@ static const term_cmd_t term_cmds[] = {
"state", "change mouse button state (1=L, 2=M, 4=R)" },
{ "mouse_set", "i", do_mouse_set,
"index", "set which mouse device receives events" },
+#ifdef CONFIG_TRUSTED_CLIENT
#ifdef HAS_AUDIO
{ "wavcapture", "si?i?i?", do_wav_capture,
"path [frequency bits channels]",
@@ -1565,6 +1578,7 @@ static const term_cmd_t term_cmds[] = {
#endif
{ "stopcapture", "i", do_stop_capture,
"capture index", "stop capture" },
+#endif
{ "memsave", "lis", do_memory_save,
"addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
{ "pmemsave", "lis", do_physical_memory_save,
@@ -1599,6 +1613,8 @@ static const term_cmd_t term_cmds[] = {
"target", "request VM to change it's memory allocation (in MB)" },
{ "set_link", "ss", do_set_link,
"name [up|down]", "change the link status of a network adapter" },
+ { "watchdog_action", "s", do_watchdog_action,
+ "[reset|shutdown|poweroff|pause|debug|none]", "change watchdog action" },
{ "cpu_set", "is", do_cpu_set_nr,
"cpu [online|offline]", "change cpu state" },
{ NULL, NULL, },
@@ -1646,6 +1662,7 @@ static const term_cmd_t info_cmds[] = {
"", "show KVM information", },
{ "usb", "", usb_info,
"", "show guest USB devices", },
+#ifdef CONFIG_TRUSTED_CLIENT
{ "usbhost", "", usb_host_info,
"", "show host USB devices", },
{ "profile", "", do_info_profile,
@@ -1677,6 +1694,7 @@ static const term_cmd_t info_cmds[] = {
{ "migrate", "", do_info_migrate, "", "show migration status" },
{ "balloon", "", do_info_balloon,
"", "show balloon information" },
+#endif
{ NULL, NULL, },
};
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ne2000.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ne2000.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ne2000.c
@@ -218,7 +218,7 @@ static int ne2000_can_receive(void *opaq
NE2000State *s = opaque;
if (s->cmd & E8390_STOP)
- return 1;
+ return 0;
return !ne2000_buffer_full(s);
}
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/pc.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/pc.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/pc.c
@@ -41,6 +41,7 @@
#include "virtio-balloon.h"
#include "virtio-console.h"
#include "hpet_emul.h"
+#include "watchdog.h"
#ifdef CONFIG_PASSTHROUGH
#include "pass-through.h"
@@ -413,7 +414,8 @@ static void bochs_bios_write(void *opaqu
case 0x400:
case 0x401:
fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
- exit(1);
+ /* according to documentation, these can be safely ignored */
+ break;
case 0x402:
case 0x403:
#ifdef DEBUG_BIOS
@@ -436,8 +438,9 @@ static void bochs_bios_write(void *opaqu
/* LGPL'ed VGA BIOS messages */
case 0x501:
case 0x502:
+ /* according to documentation, these can be safely ignored */
fprintf(stderr, "VGA BIOS panic, line %d\n", val);
- exit(1);
+ break;
case 0x500:
case 0x503:
#ifdef DEBUG_BIOS
@@ -472,45 +475,28 @@ static void bochs_bios_init(void)
/* Generate an initial boot sector which sets state and jump to
a specified vector */
-static void generate_bootsect(uint8_t *option_rom,
- uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
+static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
{
- uint8_t rom[512], *p, *reloc;
- uint8_t sum;
+ uint8_t bootsect[512], *p;
int i;
+ int hda;
- memset(rom, 0, sizeof(rom));
+ hda = drive_get_index(IF_IDE, 0, 0);
+ if (hda == -1) {
+ fprintf(stderr, "A disk image must be given for 'hda' when booting "
+ "a Linux kernel\n(if you really don't want it, use /dev/zero)\n");
+ exit(1);
+ }
+ memset(bootsect, 0, sizeof(bootsect));
- p = rom;
- /* Make sure we have an option rom signature */
- *p++ = 0x55;
- *p++ = 0xaa;
-
- /* ROM size in sectors*/
- *p++ = 1;
-
- /* Hook int19 */
-
- *p++ = 0x50; /* push ax */
- *p++ = 0x1e; /* push ds */
- *p++ = 0x31; *p++ = 0xc0; /* xor ax, ax */
- *p++ = 0x8e; *p++ = 0xd8; /* mov ax, ds */
-
- *p++ = 0xc7; *p++ = 0x06; /* movvw _start,0x64 */
- *p++ = 0x64; *p++ = 0x00;
- reloc = p;
- *p++ = 0x00; *p++ = 0x00;
-
- *p++ = 0x8c; *p++ = 0x0e; /* mov cs,0x66 */
- *p++ = 0x66; *p++ = 0x00;
-
- *p++ = 0x1f; /* pop ds */
- *p++ = 0x58; /* pop ax */
- *p++ = 0xcb; /* lret */
-
- /* Actual code */
- *reloc = (p - rom);
+ /* Copy the MSDOS partition table if possible */
+ bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1);
+ /* Make sure we have a partition signature */
+ bootsect[510] = 0x55;
+ bootsect[511] = 0xaa;
+ /* Actual code */
+ p = bootsect;
*p++ = 0xfa; /* CLI */
*p++ = 0xfc; /* CLD */
@@ -540,13 +526,7 @@ static void generate_bootsect(uint8_t *o
*p++ = segs[1]; /* CS */
*p++ = segs[1] >> 8;
- /* sign rom */
- sum = 0;
- for (i = 0; i < (sizeof(rom) - 1); i++)
- sum += rom[i];
- rom[sizeof(rom) - 1] = -sum;
-
- memcpy(option_rom, rom, sizeof(rom));
+ bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect));
}
static long get_file_size(FILE *f)
@@ -563,8 +543,7 @@ static long get_file_size(FILE *f)
return size;
}
-static void load_linux(uint8_t *option_rom,
- const char *kernel_filename,
+static void load_linux(const char *kernel_filename,
const char *initrd_filename,
const char *kernel_cmdline)
{
@@ -630,7 +609,9 @@ static void load_linux(uint8_t *option_r
/* Special pages are placed at end of low RAM: pick an arbitrary one and
* subtract a suitably large amount of padding (64kB) to skip BIOS data. */
- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram);
+ //xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram);
+ /* BUFIO Page beyond last_pfn, use 0x7ffc instead. Fix ME. */
+ end_low_ram = 0x7ffc;
end_low_ram = (end_low_ram << 12) - (64*1024);
/* highest address for loading the initrd */
@@ -719,7 +700,7 @@ static void load_linux(uint8_t *option_r
memset(gpr, 0, sizeof gpr);
gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */
- generate_bootsect(option_rom, gpr, seg, 0);
+ generate_bootsect(gpr, seg, 0);
#endif
}
@@ -930,14 +911,6 @@ vga_bios_error:
int size, offset;
offset = 0;
- if (linux_boot) {
- option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE);
- load_linux(phys_ram_base + option_rom_offset,
- kernel_filename, initrd_filename, kernel_cmdline);
- cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE,
- option_rom_offset | IO_MEM_ROM);
- offset = TARGET_PAGE_SIZE;
- }
for (i = 0; i < nb_option_roms; i++) {
size = get_image_size(option_rom[i]);
@@ -971,6 +944,9 @@ vga_bios_error:
bochs_bios_init();
+ if (linux_boot)
+ load_linux(kernel_filename, initrd_filename, kernel_cmdline);
+
cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
i8259 = i8259_init(cpu_irq[0]);
ferr_irq = i8259[13];
@@ -1075,6 +1051,8 @@ vga_bios_error:
}
}
+ watchdog_pc_init(pci_bus);
+
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
Index: xen-4.3.0-testing/tools/python/xen/xend/server/HalDaemon.py
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/python/xen/xend/server/HalDaemon.py
@@ -0,0 +1,243 @@
+#!/usr/bin/env python
+# -*- mode: python; -*-
+#============================================================================
+# 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) 2007 Pat Campbell <plc@novell.com>
+# Copyright (C) 2007 Novell Inc.
+#============================================================================
+
+"""hald (Hardware Abstraction Layer Daemon) watcher for Xen management
+ of removable block device media.
+
+"""
+
+import gobject
+import dbus
+import dbus.glib
+import os
+import types
+import sys
+import signal
+import traceback
+from xen.xend.xenstore.xstransact import xstransact, complete
+from xen.xend.xenstore.xsutil import xshandle
+from xen.xend import PrettyPrint
+from xen.xend import XendLogging
+from xen.xend.XendLogging import log
+
+DEVICE_TYPES = ['vbd', 'tap']
+
+class HalDaemon:
+ """The Hald block device watcher for XEN
+ """
+
+ """Default path to the log file. """
+ logfile_default = "/var/log/xen/hald.log"
+
+ """Default level of information to be logged."""
+ loglevel_default = 'INFO'
+
+
+ def __init__(self):
+
+ XendLogging.init(self.logfile_default, self.loglevel_default)
+ log.debug( "%s", "__init__")
+
+ self.udi_dict = {}
+ self.debug = 0
+ self.dbpath = "/local/domain/0/backend"
+ self.bus = dbus.SystemBus()
+ self.hal_manager_obj = self.bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
+ self.hal_manager = dbus.Interface( self.hal_manager_obj, 'org.freedesktop.Hal.Manager')
+ self.gatherBlockDevices()
+ self.registerDeviceCallbacks()
+
+ def run(self):
+ log.debug( "%s", "In new run" );
+ try:
+ self.mainloop = gobject.MainLoop()
+ self.mainloop.run()
+ except KeyboardInterrupt, ex:
+ log.debug('Keyboard exception handler: %s', ex )
+ self.mainloop.quit()
+ except Exception, ex:
+ log.debug('Generic exception handler: %s', ex )
+ self.mainloop.quit()
+
+ def __del__(self):
+ log.debug( "%s", "In del " );
+ self.unRegisterDeviceCallbacks()
+ self.mainloop.quit()
+
+ def shutdown(self):
+ log.debug( "%s", "In shutdown now " );
+ self.unRegisterDeviceCallbacks()
+ self.mainloop.quit()
+
+ def stop(self):
+ log.debug( "%s", "In stop now " );
+ self.unRegisterDeviceCallbacks()
+ self.mainloop.quit()
+
+ def gatherBlockDevices(self):
+
+ # Get all the current devices from hal and save in a dictionary
+ try:
+ device_names = self.hal_manager.GetAllDevices()
+ i = 0;
+ for name in device_names:
+ #log.debug("device name, device=%s",name)
+ dev_obj = self.bus.get_object ('org.freedesktop.Hal', name)
+ dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
+ dev_properties = dev_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device")
+ if dev_properties.has_key('block.device'):
+ dev_str = dev_properties['block.device']
+ dev_major = dev_properties['block.major']
+ dev_minor = dev_properties['block.minor']
+ udi_info = {}
+ udi_info['device'] = dev_str
+ udi_info['major'] = dev_major
+ udi_info['minor'] = dev_minor
+ udi_info['udi'] = name
+ self.udi_dict[i] = udi_info
+ i = i + 1
+ except Exception, ex:
+ print >>sys.stderr, 'Exception gathering block devices:', ex
+ log.warn("Exception gathering block devices (%s)",ex)
+
+ #
+ def registerDeviceCallbacks(self):
+ # setup the callbacks for when the gdl changes
+ self.hal_manager.connect_to_signal('DeviceAdded', self.device_added_callback)
+ self.hal_manager.connect_to_signal('DeviceRemoved', self.device_removed_callback)
+
+ #
+ def unRegisterDeviceCallbacks(self):
+ # setup the callbacks for when the gdl changes
+ self.hal_manager.remove_signal_receiver(self.device_added_callback,'DeviceAdded')
+ self.hal_manager.remove_signal_receiver(self.device_removed_callback,'DeviceRemoved')
+
+ #
+ def device_removed_callback(self,udi):
+ log.debug('UDI %s was removed',udi)
+ self.show_dict(self.udi_dict)
+ for key in self.udi_dict:
+ udi_info = self.udi_dict[key]
+ if udi_info['udi'] == udi:
+ device = udi_info['device']
+ major = udi_info['major']
+ minor = udi_info['minor']
+ self.change_xenstore( "remove", device, major, minor)
+
+ # Adds device to dictionary if not already there
+ def device_added_callback(self,udi):
+ log.debug('UDI %s was added', udi)
+ self.show_dict(self.udi_dict)
+ dev_obj = self.bus.get_object ('org.freedesktop.Hal', udi)
+ dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device')
+ device = dev.GetProperty ('block.device')
+ major = dev.GetProperty ('block.major')
+ minor = dev.GetProperty ('block.minor')
+ udi_info = {}
+ udi_info['device'] = device
+ udi_info['major'] = major
+ udi_info['minor'] = minor
+ udi_info['udi'] = udi
+ already = 0
+ cnt = 0;
+ for key in self.udi_dict:
+ info = self.udi_dict[key]
+ if info['udi'] == udi:
+ already = 1
+ break
+ cnt = cnt + 1
+ if already == 0:
+ self.udi_dict[cnt] = udi_info;
+ log.debug('UDI %s was added, device:%s major:%s minor:%s index:%d\n', udi, device, major, minor, cnt)
+ self.change_xenstore( "add", device, major, minor)
+
+ # Debug helper, shows dictionary contents
+ def show_dict(self,dict=None):
+ if self.debug == 0 :
+ return
+ if dict == None :
+ dict = self.udi_dict
+ for key in dict:
+ log.debug('udi_info %s udi_info:%s',key,dict[key])
+
+ # Set or clear xenstore media-present depending on the action argument
+ # for every vbd that has this block device
+ def change_xenstore(self,action, device, major, minor):
+ for type in DEVICE_TYPES:
+ path = self.dbpath + '/' + type
+ domains = xstransact.List(path)
+ log.debug('domains: %s', domains)
+ for domain in domains: # for each domain
+ devices = xstransact.List( path + '/' + domain)
+ log.debug('devices: %s',devices)
+ for device in devices: # for each vbd device
+ str = device.split('/')
+ vbd_type = None;
+ vbd_physical_device = None
+ vbd_media = None
+ vbd_device_path = path + '/' + domain + '/' + device
+ listing = xstransact.List(vbd_device_path)
+ for entry in listing: # for each entry
+ item = path + '/' + entry
+ value = xstransact.Read( vbd_device_path + '/' + entry)
+ log.debug('%s=%s',item,value)
+ if item.find('media-present') != -1:
+ vbd_media = item;
+ vbd_media_path = item
+ if item.find('physical-device') != -1:
+ vbd_physical_device = value;
+ if item.find('type') != -1:
+ vbd_type = value;
+ if vbd_type is not None and vbd_physical_device is not None and vbd_media is not None :
+ inode = vbd_physical_device.split(':')
+ imajor = parse_hex(inode[0])
+ iminor = parse_hex(inode[1])
+ log.debug("action:%s major:%s- minor:%s- imajor:%s- iminor:%s- inode: %s",
+ action,major,minor, imajor, iminor, inode)
+ if int(imajor) == int(major) and int(iminor) == int(minor):
+ if action == "add":
+ xs_dict = {'media': "1"}
+ xstransact.Write(vbd_device_path, 'media-present', "1" )
+ log.debug("wrote xenstore media-present 1 path:%s",vbd_media_path)
+ else:
+ xstransact.Write(vbd_device_path, 'media-present', "0" )
+ log.debug("wrote xenstore media 0 path:%s",vbd_media_path)
+
+def mylog( fmt, *args):
+ f = open('/tmp/haldaemon.log', 'a')
+ print >>f, "HalDaemon ", fmt % args
+ f.close()
+
+
+def parse_hex(val):
+ try:
+ if isinstance(val, types.StringTypes):
+ return int(val, 16)
+ else:
+ return val
+ except ValueError:
+ return None
+
+if __name__ == "__main__":
+ watcher = HalDaemon()
+ watcher.run()
+ print 'Falling off end'
+
+
Index: xen-4.3.0-testing/tools/python/xen/xend/server/Hald.py
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/python/xen/xend/server/Hald.py
@@ -0,0 +1,125 @@
+#============================================================================
+# 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) 2007 Pat Campbell <plc@novell.com>
+# Copyright (C) 2007 Novell Inc.
+#============================================================================
+
+import errno
+import types
+import os
+import sys
+import time
+import signal
+from traceback import print_exc
+
+from xen.xend.XendLogging import log
+
+class Hald:
+ def __init__(self):
+ self.ready = False
+ self.running = True
+
+ def run(self):
+ """Starts the HalDaemon process
+ """
+ self.ready = True
+ try:
+ myfile = self.find("xen/xend/server/HalDaemon.py")
+ args = (["python", myfile ])
+ self.pid = self.daemonize("python", args )
+ #log.debug( "%s %s pid:%d", "Hald.py starting ", args, self.pid )
+ except:
+ self.pid = -1
+ log.debug("Unable to start HalDaemon process")
+
+ def shutdown(self):
+ """Shutdown the HalDaemon process
+ """
+ log.debug("%s pid:%d", "Hald.shutdown()", self.pid)
+ self.running = False
+ self.ready = False
+ if self.pid != -1:
+ try:
+ os.kill(self.pid, signal.SIGINT)
+ except:
+ print_exc()
+
+ def daemonize(self,prog, args):
+ """Runs a program as a daemon with the list of arguments. Returns the PID
+ of the daemonized program, or returns 0 on error.
+ Copied from xm/create.py instead of importing to reduce coupling
+ """
+ r, w = os.pipe()
+ pid = os.fork()
+
+ if pid == 0:
+ os.close(r)
+ w = os.fdopen(w, 'w')
+ os.setsid()
+ try:
+ pid2 = os.fork()
+ except:
+ pid2 = None
+ if pid2 == 0:
+ os.chdir("/")
+ env = os.environ.copy()
+ env['PYTHONPATH'] = self.getpythonpath()
+ for fd in range(0, 256):
+ try:
+ os.close(fd)
+ except:
+ pass
+ os.open("/dev/null", os.O_RDWR)
+ os.dup2(0, 1)
+ os.dup2(0, 2)
+ os.execvpe(prog, args, env)
+ os._exit(1)
+ else:
+ w.write(str(pid2 or 0))
+ w.close()
+ os._exit(0)
+ os.close(w)
+ r = os.fdopen(r)
+ daemon_pid = int(r.read())
+ r.close()
+ os.waitpid(pid, 0)
+ #log.debug( "daemon_pid: %d", daemon_pid )
+ return daemon_pid
+
+ def getpythonpath(self):
+ str = " "
+ for p in sys.path:
+ if str != " ":
+ str = str + ":" + p
+ else:
+ if str != "":
+ str = p
+ return str
+
+ def find(self,path, matchFunc=os.path.isfile):
+ """Find a module in the sys.path
+ From web page: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52224
+ """
+ for dirname in sys.path:
+ candidate = os.path.join(dirname, path)
+ if matchFunc(candidate):
+ return candidate
+ raise Error("Can't find file %s" % path)
+
+if __name__ == "__main__":
+ watcher = Hald()
+ watcher.run()
+ time.sleep(10)
+ watcher.shutdown()
Index: xen-4.3.0-testing/tools/python/xen/xend/server/SrvServer.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/SrvServer.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/SrvServer.py
@@ -57,6 +57,7 @@ from xen.web.SrvDir import SrvDir
from SrvRoot import SrvRoot
from XMLRPCServer import XMLRPCServer
+from xen.xend.server.Hald import Hald
xoptions = XendOptions.instance()
@@ -252,6 +253,8 @@ def _loadConfig(servers, root, reload):
if xoptions.get_xend_unix_xmlrpc_server():
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
+ servers.add(Hald())
+
def create():
root = SrvDir()
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/xenstore.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/xenstore.c
@@ -18,12 +18,14 @@
#include "exec-all.h"
#include "sysemu.h"
+#include "console.h"
#include "hw.h"
#include "pci.h"
#include "qemu-timer.h"
#include "qemu-xen.h"
#include "xen_backend.h"
+extern DisplayState *display_state;
struct xs_handle *xsh = NULL;
static char *media_filename[MAX_DRIVES+1];
static QEMUTimer *insert_timer = NULL;
@@ -133,7 +135,8 @@ static void insert_media(void *opaque)
else
format = &bdrv_raw;
- bdrv_open2(bs, media_filename[i], 0, format);
+ /* Temporary BDRV_O_RDWR */
+ bdrv_open2(bs, media_filename[i], BDRV_O_RDWR, format);
#ifdef CONFIG_STUBDOM
{
char *buf, *backend, *params_path, *params;
@@ -443,13 +446,13 @@ void xenstore_init(void)
}
}
-void xenstore_parse_domain_config(int hvm_domid)
+void xenstore_parse_domain_config(int hvm_domid, QEMUMachine *machine)
{
char **e_danger = NULL;
char *buf = NULL;
- char *fpath = NULL, *bpath = NULL,
+ char *fpath = NULL, *bpath = NULL, *btype = NULL,
*dev = NULL, *params = NULL, *drv = NULL;
- int i, ret;
+ int i, j, ret, is_tap;
unsigned int len, num, hd_index, pci_devid = 0;
BlockDriverState *bs;
BlockDriver *format;
@@ -486,6 +489,14 @@ void xenstore_parse_domain_config(int hv
e_danger[i]);
if (bpath == NULL)
continue;
+ /* check to see if type is tap or not */
+ if (pasprintf(&buf, "%s/type", bpath) == -1)
+ continue;
+ free(btype);
+ btype = xs_read(xsh, XBT_NULL, buf, &len);
+ if (btype == NULL)
+ continue;
+ is_tap = !strncmp(btype, "tap", 3);
/* read the name of the device */
if (pasprintf(&buf, "%s/dev", bpath) == -1)
continue;
@@ -500,7 +511,8 @@ void xenstore_parse_domain_config(int hv
}
for (i = 0; i < num; i++) {
- format = NULL; /* don't know what the format is yet */
+ flags = 0;
+ format = NULL; /* don't know what the format is yet */
/* read the backend path */
xenstore_get_backend_path(&bpath, "vbd", danger_path, hvm_domid, e_danger[i]);
if (bpath == NULL)
@@ -525,12 +537,7 @@ void xenstore_parse_domain_config(int hv
continue;
free(danger_type);
danger_type = xs_read(xsh, XBT_NULL, danger_buf, &len);
- if (pasprintf(&buf, "%s/params", bpath) == -1)
- continue;
- free(params);
- params = xs_read(xsh, XBT_NULL, buf, &len);
- if (params == NULL)
- continue;
+
/* read the name of the device */
if (pasprintf(&buf, "%s/type", bpath) == -1)
continue;
@@ -538,6 +545,35 @@ void xenstore_parse_domain_config(int hv
drv = xs_read(xsh, XBT_NULL, buf, &len);
if (drv == NULL)
continue;
+
+ free(params);
+ if (!strcmp(drv,"iscsi") || !strcmp(drv, "npiv") ||
+ !strcmp(drv,"dmmd")) {
+ if (pasprintf(&buf, "%s/node", bpath) == -1)
+ continue;
+
+ /* wait for block-[iscsi|npiv|dmmd] script to complete and populate the
+ * node entry. try 30 times (30 secs) */
+ for (j = 0; j < 30; j++) {
+ params = xs_read(xsh, XBT_NULL, buf, &len);
+ if (params != NULL)
+ break;
+ sleep(1);
+ }
+ if (params == NULL) {
+ fprintf(stderr, "qemu: %s device not found -- timed out \n", drv);
+ continue;
+ }
+ }
+ else
+ {
+ if (pasprintf(&buf, "%s/params", bpath) == -1)
+ continue;
+ params = xs_read(xsh, XBT_NULL, buf, &len);
+ if (params == NULL)
+ continue;
+ }
+
/* Obtain blktap sub-type prefix */
if ((!strcmp(drv, "tap") || !strcmp(drv, "qdisk")) && params[0]) {
char *offset = strchr(params, ':');
@@ -562,6 +598,17 @@ void xenstore_parse_domain_config(int hv
format = &bdrv_raw;
}
+ /* read the mode of the device */
+ if (pasprintf(&buf, "%s/mode", bpath) == -1)
+ continue;
+ free(mode);
+ mode = xs_read(xsh, XBT_NULL, buf, &len);
+
+ if (!strcmp(mode, "r") || !strcmp(mode, "ro"))
+ flags |= BDRV_O_RDONLY;
+ if (!strcmp(mode, "w") || !strcmp(mode, "rw"))
+ flags |= BDRV_O_RDWR;
+
#if 0
/* Phantom VBDs are disabled because the use of paths
* from guest-controlled areas in xenstore is unsafe.
@@ -596,6 +643,21 @@ void xenstore_parse_domain_config(int hv
#endif
bs = bdrv_new(dev);
+
+ /* if cdrom physical put a watch on media-present */
+ if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
+ if (drv && !strcmp(drv, "phy")) {
+ if (pasprintf(&buf, "%s/media-present", bpath) != -1) {
+ if (bdrv_is_inserted(bs))
+ xs_write(xsh, XBT_NULL, buf, "1", strlen("1"));
+ else {
+ xs_write(xsh, XBT_NULL, buf, "0", strlen("0"));
+ }
+ xs_watch(xsh, buf, "media-present");
+ }
+ }
+ }
+
/* check if it is a cdrom */
if (danger_type && !strcmp(danger_type, "cdrom")) {
bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
@@ -614,7 +676,7 @@ void xenstore_parse_domain_config(int hv
#ifdef CONFIG_STUBDOM
if (pasprintf(&danger_buf, "%s/device/vbd/%s", danger_path, e_danger[i]) == -1)
continue;
- if (bdrv_open2(bs, danger_buf, BDRV_O_CACHE_WB /* snapshot and write-back */, &bdrv_raw) == 0) {
+ if (bdrv_open2(bs, danger_buf, flags|BDRV_O_CACHE_WB /* snapshot and write-back */, &bdrv_raw) == 0) {
if (pasprintf(&buf, "%s/params", bpath) == -1)
continue;
free(params);
@@ -640,6 +702,12 @@ void xenstore_parse_domain_config(int hv
format = &bdrv_host_device;
else
format = &bdrv_raw;
+ } else if (!strcmp(drv,"iscsi")) {
+ format = &bdrv_raw;
+ } else if (!strcmp(drv,"npiv")) {
+ format = &bdrv_raw;
+ } else if (!strcmp(drv,"dmmd")) {
+ format = &bdrv_raw;
} else {
format = bdrv_find_format(drv);
if (!format) {
@@ -672,11 +740,19 @@ void xenstore_parse_domain_config(int hv
#endif
- drives_table[nb_drives].bdrv = bs;
- drives_table[nb_drives].used = 1;
- media_filename[nb_drives] = strdup(bs->filename);
- nb_drives++;
-
+ if (machine == &xenfv_machine) {
+ drives_table[nb_drives].bdrv = bs;
+ drives_table[nb_drives].used = 1;
+#ifdef CONFIG_STUBDOM
+ media_filename[nb_drives] = strdup(danger_buf);
+#else
+ media_filename[nb_drives] = strdup(bs->filename);
+#endif
+ nb_drives++;
+ } else {
+ qemu_aio_flush();
+ bdrv_close(bs);
+ }
}
#ifdef CONFIG_STUBDOM
@@ -762,6 +838,7 @@ void xenstore_parse_domain_config(int hv
free(mode);
free(params);
free(dev);
+ free(btype);
free(bpath);
free(buf);
free(danger_buf);
@@ -872,6 +949,19 @@ static void xenstore_process_dm_command_
} else if (!strncmp(command, "continue", len)) {
fprintf(logfile, "dm-command: continue after state save\n");
xen_pause_requested = 0;
+ } else if (!strncmp(command, "chgvncpasswd", len)) {
+ fprintf(logfile, "dm-command: change vnc passwd\n");
+ if (pasprintf(&path,
+ "/local/domain/0/backend/vfb/%u/0/vncpasswd", domid) == -1) {
+ fprintf(logfile, "out of memory reading dm command parameter\n");
+ goto out;
+ }
+ par = xs_read(xsh, XBT_NULL, path, &len);
+ if (!par)
+ goto out;
+ if (vnc_display_password(display_state, par) == 0)
+ xenstore_record_dm_state("vncpasswdchged");
+ free(par);
} else if (!strncmp(command, "usb-add", len)) {
fprintf(logfile, "dm-command: usb-add a usb device\n");
if (pasprintf(&path,
@@ -930,6 +1020,9 @@ static void xenstore_process_dm_command_
do_pci_add(par);
free(par);
#endif
+ } else if (!strncmp(command, "flush-cache", len)) {
+ fprintf(logfile, "dm-command: flush caches\n");
+ qemu_invalidate_map_cache();
} else {
fprintf(logfile, "dm-command: unknown command\"%*s\"\n", len, command);
}
@@ -1086,6 +1179,50 @@ static void xenstore_process_vcpu_set_ev
return;
}
+static void xenstore_process_media_change_event(char **vec)
+{
+ char *media_present = NULL;
+ unsigned int len;
+
+ media_present = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
+
+ if (media_present) {
+ BlockDriverState *bs;
+ char *buf = NULL, *cp = NULL, *path = NULL, *dev = NULL;
+
+ path = strdup(vec[XS_WATCH_PATH]);
+ cp = strstr(path, "media-present");
+ if (cp){
+ *(cp-1) = '\0';
+ pasprintf(&buf, "%s/dev", path);
+ dev = xs_read(xsh, XBT_NULL, buf, &len);
+ if (dev) {
+ if ( !strncmp(dev, "xvd", 3)) {
+ memmove(dev, dev+1, strlen(dev));
+ dev[0] = 'h';
+ dev[1] = 'd';
+ }
+ bs = bdrv_find(dev);
+ if (!bs) {
+ term_printf("device not found\n");
+ return;
+ }
+ if (strcmp(media_present, "0") == 0 && bs) {
+ bdrv_close(bs);
+ }
+ else if (strcmp(media_present, "1") == 0 &&
+ bs != NULL && bs->drv == NULL) {
+ if (bdrv_open(bs, bs->filename, 0 /* snapshot */) < 0) {
+ fprintf(logfile, "%s() qemu: could not open cdrom disk '%s'\n",
+ __func__, bs->filename);
+ }
+ bs->media_changed = 1;
+ }
+ }
+ }
+ }
+}
+
void xenstore_process_event(void *opaque)
{
char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
@@ -1121,6 +1258,11 @@ void xenstore_process_event(void *opaque
xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
xenstore_watch_callbacks[i].opaque);
+ if (!strcmp(vec[XS_WATCH_TOKEN], "media-present")) {
+ xenstore_process_media_change_event(vec);
+ goto out;
+ }
+
hd_index = drive_name_to_index(vec[XS_WATCH_TOKEN]);
if (hd_index == -1) {
fprintf(stderr,"medium change watch on `%s' -"
Index: xen-4.3.0-testing/tools/python/xen/xend/XendAuthSessions.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendAuthSessions.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendAuthSessions.py
@@ -84,7 +84,7 @@ class XendAuthSessions:
# if PAM doesn't exist, let's ignore it
return False
- pam_auth.start("login")
+ pam_auth.start("xen-api")
pam_auth.set_item(PAM.PAM_USER, username)
def _pam_conv(auth, query_list, user_data = None):
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/Makefile
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/Makefile
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/Makefile
@@ -46,14 +46,6 @@ $(filter %-user,$(SUBDIR_RULES)): libqem
recurse-all: $(SUBDIR_RULES)
-CPPFLAGS += -I$(XEN_ROOT)/tools/libxc
-CPPFLAGS += -I$(XEN_ROOT)/tools/blktap/lib
-CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
-CPPFLAGS += -I$(XEN_ROOT)/tools/include
-
-tapdisk-ioemu: tapdisk-ioemu.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c hw/xen_blktap.c osdep.c
- $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
-
#######################################################################
# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
@@ -72,6 +64,21 @@ endif
BLOCK_OBJS += block-raw-posix.o
endif
+#######################################################################
+# tapdisk-ioemu
+
+hw/tapdisk-xen_blktap.o: hw/xen_blktap.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_IMG -DQEMU_TOOL -c -o $@ $<
+tapdisk-ioemu.o: tapdisk-ioemu.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_IMG -DQEMU_TOOL -c -o $@ $<
+
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/libxc
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/blktap/lib
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
+tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/include
+tapdisk-ioemu: tapdisk-ioemu.o $(BLOCK_OBJS) qemu-tool.o hw/tapdisk-xen_blktap.o
+ $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS)
+
######################################################################
# libqemu_common.a: Target independent part of system emulation. The
# long term path is to suppress *all* target specific code in case of
@@ -243,7 +250,7 @@ endif
install: all $(if $(BUILD_DOCS),install-doc)
mkdir -p "$(DESTDIR)$(bindir)"
ifneq ($(TOOLS),)
- $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
+ $(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)"
endif
ifneq ($(BLOBS),)
mkdir -p "$(DESTDIR)$(datadir)"
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/Makefile.target
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/Makefile.target
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/Makefile.target
@@ -580,6 +580,10 @@ OBJS += e1000.o
# Serial mouse
OBJS += msmouse.o
+# Generic watchdog support and some watchdog devices
+OBJS += watchdog.o
+OBJS += wdt_ib700.o wdt_i6300esb.o
+
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
ifdef CONFIG_AUDIO
@@ -755,7 +759,7 @@ clean:
install: all install-hook
ifneq ($(PROGS),)
- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
+ $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
endif
# Include automatically generated dependency files
Index: xen-4.3.0-testing/tools/python/xen/xend/XendCheckpoint.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendCheckpoint.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendCheckpoint.py
@@ -123,6 +123,11 @@ def save(fd, dominfo, network, live, dst
str(int(live) | (int(hvm) << 2)) ]
log.debug("[xc_save]: %s", string.join(cmd))
+ # It is safe to release the domain lock at this point if not
+ # checkpointing
+ if checkpoint == False:
+ dominfo.release_running_lock(domain_name)
+
def saveInputHandler(line, tochild):
log.debug("In saveInputHandler %s", line)
if line == "suspend":
@@ -172,7 +177,10 @@ def save(fd, dominfo, network, live, dst
dominfo.destroy()
dominfo.testDeviceComplete()
try:
- dominfo.setName(domain_name, False)
+ if checkpoint:
+ dominfo.setName(domain_name)
+ else:
+ dominfo.setName(domain_name, False)
except VmError:
# Ignore this. The name conflict (hopefully) arises because we
# are doing localhost migration; if we are doing a suspend of a
@@ -184,6 +192,9 @@ def save(fd, dominfo, network, live, dst
log.exception("Save failed on domain %s (%s) - resuming.", domain_name,
dominfo.getDomid())
dominfo.resumeDomain()
+ # Reacquire the domain lock
+ if checkpoint == False:
+ dominfo.acquire_running_lock()
try:
dominfo.setName(domain_name)
@@ -326,8 +337,7 @@ def restore(xd, fd, dominfo = None, paus
restore_image.setCpuid()
# xc_restore will wait for source to close connection
-
- dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
+ dominfo.completeRestore(handler.store_mfn, handler.console_mfn, console_port)
#
# We shouldn't hold the domains_lock over a waitForDevices
@@ -351,6 +361,7 @@ def restore(xd, fd, dominfo = None, paus
if not paused:
dominfo.unpause()
+ dominfo.acquire_running_lock()
return dominfo
except Exception, exn:
dominfo.destroy()
Index: xen-4.3.0-testing/tools/python/xen/xend/XendAPI.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendAPI.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendAPI.py
@@ -1941,10 +1941,10 @@ class XendAPI(object):
bool(live), port, node, ssl, bool(chs))
return xen_api_success_void()
- def VM_save(self, _, vm_ref, dest, checkpoint):
+ def VM_save(self, _, vm_ref, dest, checkpoint, force):
xendom = XendDomain.instance()
xeninfo = xendom.get_vm_by_uuid(vm_ref)
- xendom.domain_save(xeninfo.getDomid(), dest, checkpoint)
+ xendom.domain_save(xeninfo.getDomid(), dest, checkpoint, force)
return xen_api_success_void()
def VM_restore(self, _, src, paused):
Index: xen-4.3.0-testing/tools/python/xen/xend/XendDomain.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendDomain.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendDomain.py
@@ -1505,7 +1505,7 @@ class XendDomain:
pass
sock.close()
- def domain_save(self, domid, dst, checkpoint=False):
+ def domain_save(self, domid, dst, checkpoint=False, force=False):
"""Start saving a domain to file.
@param domid: Domain ID or Name
@@ -1521,6 +1521,9 @@ class XendDomain:
if not dominfo:
raise XendInvalidDomain(str(domid))
+ if os.access(dst, os.F_OK) and not force:
+ raise XendError("Save file:%s exist!\n" % dst)
+
if dominfo.getDomid() == DOM0_ID:
raise XendError("Cannot save privileged domain %s" % str(domid))
if dominfo._stateGet() != DOM_STATE_RUNNING:
@@ -1832,6 +1835,21 @@ class XendDomain:
log.exception(ex)
raise XendError(str(ex))
+ def domain_swaptarget_set(self, domid, mem):
+ """Set the memory limit for a domain.
+
+ @param domid: Domain ID or Name
+ @type domid: int or string.
+ @param mem: memory limit (in MiB)
+ @type mem: int
+ @raise XendError: fail to set memory
+ @rtype: 0
+ """
+ dominfo = self.domain_lookup_nr(domid)
+ if not dominfo:
+ raise XendInvalidDomain(str(domid))
+ dominfo.setSwapTarget(mem)
+
def domain_maxmem_set(self, domid, mem):
"""Set the memory limit for a domain.
Index: xen-4.3.0-testing/tools/python/xen/xend/XendAPIConstants.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendAPIConstants.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendAPIConstants.py
@@ -45,8 +45,10 @@ XEN_API_ON_NORMAL_EXIT = [
XEN_API_ON_CRASH_BEHAVIOUR = [
'destroy',
'coredump_and_destroy',
+ 'coredump_destroy',
'restart',
'coredump_and_restart',
+ 'coredump_restart',
'preserve',
'rename_restart'
]
Index: xen-4.3.0-testing/tools/python/xen/xend/XendConfig.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendConfig.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendConfig.py
@@ -147,6 +147,11 @@ XENAPI_PLATFORM_CFG_TYPES = {
'apic': int,
'boot': str,
'device_model': str,
+ 'actmem': str,
+ 'xenpaging_file': str,
+ 'xenpaging_extra': str,
+ 'smbios_firmware': str,
+ 'acpi_firmware': str,
'loader': str,
'display' : str,
'fda': str,
@@ -159,6 +164,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'nographic': int,
'nomigrate': int,
'pae' : int,
+ 'extid': int,
'rtc_timeoffset': int,
'parallel': str,
'serial': str,
@@ -192,6 +198,8 @@ XENAPI_PLATFORM_CFG_TYPES = {
'xen_platform_pci': int,
"gfx_passthru": int,
'oos' : int,
+ 'watchdog': str,
+ 'watchdog_action': str,
}
# Xen API console 'other_config' keys.
@@ -512,8 +520,20 @@ class XendConfig(dict):
self['platform']['nomigrate'] = 0
if self.is_hvm():
+ if 'actmem' not in self['platform']:
+ self['platform']['actmem'] = "0"
+ if 'xenpaging_file' not in self['platform']:
+ self['platform']['xenpaging_file'] = ""
+ if 'xenpaging_extra' not in self['platform']:
+ self['platform']['xenpaging_extra'] = []
+ if 'smbios_firmware' not in self['platform']:
+ self['platform']['smbios_firmware'] = ""
+ if 'acpi_firmware' not in self['platform']:
+ self['platform']['acpi_firmware'] = ""
if 'timer_mode' not in self['platform']:
self['platform']['timer_mode'] = 1
+ if 'extid' in self['platform'] and int(self['platform']['extid']) == 1:
+ self['platform']['viridian'] = 1
if 'viridian' not in self['platform']:
self['platform']['viridian'] = 0
if 'rtc_timeoffset' not in self['platform']:
@@ -1865,7 +1885,14 @@ class XendConfig(dict):
ports = sxp.child(dev_sxp, 'port')
for port in ports[1:]:
try:
- num, bus = port
+ # When ['port' ['1','']] is saved into sxp file, it will become (port (1 ))
+ # If using this sxp file, here variable "port" will be port=1,
+ # we should process it, otherwise, it will report error.
+ if len(port) == 1:
+ num = port[0]
+ bus = ""
+ else:
+ num, bus = port
dev_config['port-%i' % int(num)] = str(bus)
except TypeError:
pass
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_console.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_console.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_console.c
@@ -38,6 +38,8 @@
#include "qemu-char.h"
#include "xen_backend.h"
+static int log_guest = 0;
+
struct buffer {
uint8_t *data;
size_t consumed;
@@ -54,8 +56,24 @@ struct XenConsole {
void *sring;
CharDriverState *chr;
int backlog;
+ int log_fd;
};
+static int write_all(int fd, const char* buf, size_t len)
+{
+ while (len) {
+ ssize_t ret = write(fd, buf, len);
+ if (ret == -1 && errno == EINTR)
+ continue;
+ if (ret < 0)
+ return -1;
+ len -= ret;
+ buf += ret;
+ }
+
+ return 0;
+}
+
static void buffer_append(struct XenConsole *con)
{
struct buffer *buffer = &con->buffer;
@@ -83,6 +101,15 @@ static void buffer_append(struct XenCons
intf->out_cons = cons;
xen_be_send_notify(&con->xendev);
+ if (con->log_fd != -1) {
+ int logret;
+ logret = write_all(con->log_fd, buffer->data + buffer->size - size, size);
+ if (logret < 0) {
+ xen_be_printf(&con->xendev, 1, "Write to log failed on domain %d: %d (%s)\n",
+ con->xendev.dom, errno, strerror(errno));
+ }
+ }
+
if (buffer->max_capacity &&
buffer->size > buffer->max_capacity) {
/* Discard the middle of the data. */
@@ -176,6 +203,37 @@ static void xencons_send(struct XenConso
}
}
+static int create_domain_log(struct XenConsole *con)
+{
+ char *logfile;
+ char *path, *domname;
+ int fd;
+ const char *logdir = "/var/log/xen/console";
+
+ path = xs_get_domain_path(xenstore, con->xendev.dom);
+ domname = xenstore_read_str(path, "name");
+ free(path);
+ if (!domname)
+ return -1;
+
+ if (mkdir(logdir, 0755) && errno != EEXIST)
+ {
+ xen_be_printf(&con->xendev, 1, "Directory %s does not exist and fail to create it!", logdir);
+ return -1;
+ }
+
+ if (asprintf(&logfile, "%s/guest-%s.log", logdir, domname) < 0)
+ return -1;
+ qemu_free(domname);
+
+ fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ free(logfile);
+ if (fd == -1)
+ xen_be_printf(&con->xendev, 1, "Failed to open log %s: %d (%s)", logfile, errno, strerror(errno));
+
+ return fd;
+}
+
/* -------------------------------------------------------------------- */
static int con_init(struct XenDevice *xendev)
@@ -183,6 +241,7 @@ static int con_init(struct XenDevice *xe
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
char *type, *dom, label[32];
const char *output;
+ char *logenv = NULL;
/* setup */
dom = xs_get_domain_path(xenstore, con->xendev.dom);
@@ -209,6 +268,10 @@ static int con_init(struct XenDevice *xe
con->chr = qemu_chr_open(label, output, NULL);
xenstore_store_pv_console_info(con->xendev.dev, con->chr, output);
+ logenv = getenv("XENCONSOLED_TRACE");
+ if (logenv != NULL && strlen(logenv) == strlen("guest") && !strcmp(logenv, "guest")) {
+ log_guest = 1;
+ }
return 0;
}
@@ -246,6 +309,9 @@ static int con_initialise(struct XenDevi
con->xendev.remote_port,
con->xendev.local_port,
con->buffer.max_capacity);
+ con->log_fd = -1;
+ if (log_guest)
+ con->log_fd = create_domain_log(con);
return 0;
}
@@ -266,6 +332,12 @@ static void con_disconnect(struct XenDev
xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1);
con->sring = NULL;
}
+
+ if (con->log_fd != -1) {
+ close(con->log_fd);
+ con->log_fd = -1;
+ }
+
}
static void con_event(struct XenDevice *xendev)
Index: xen-4.3.0-testing/tools/python/xen/xm/xenapi_create.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xm/xenapi_create.py
+++ xen-4.3.0-testing/tools/python/xen/xm/xenapi_create.py
@@ -740,7 +740,7 @@ class sxp2xml:
if get_child_by_name(config, "maxmem"):
memory.attributes["static_max"] = \
- str(int(get_child_by_name(config, "maxmem")*1024*1024))
+ str(int(get_child_by_name(config, "maxmem"))*1024*1024)
vm.appendChild(memory)
@@ -1046,7 +1046,12 @@ class sxp2xml:
'acpi',
'apic',
'boot',
+ 'actmem',
+ 'xenpaging_file',
+ 'xenpaging_extra',
'device_model',
+ 'smbios_firmware',
+ 'acpi_firmware',
'loader',
'fda',
'fdb',
@@ -1074,7 +1079,9 @@ class sxp2xml:
'xen_platform_pci',
'tsc_mode'
'description',
- 'nomigrate'
+ 'nomigrate',
+ 'watchdog',
+ 'watchdog_action'
]
platform_configs = []
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_machine_fv.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_machine_fv.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_machine_fv.c
@@ -270,6 +270,7 @@ void qemu_invalidate_entry(uint8_t *buff
#endif /* defined(MAPCACHE) */
+extern void init_blktap(void);
static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size,
const char *boot_device,
@@ -295,6 +296,11 @@ static void xen_init_fv(ram_addr_t ram_s
}
#endif
+#ifndef CONFIG_STUBDOM
+ /* Initialize tapdisk client */
+ init_blktap();
+#endif
+
#ifdef CONFIG_STUBDOM /* the hvmop is not supported on older hypervisors */
xc_set_hvm_param(xc_handle, domid, HVM_PARAM_DM_DOMAIN, DOMID_SELF);
#endif
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.c
@@ -46,7 +46,7 @@
#define BLKTAP_CTRL_DIR "/var/run/tap"
/* If enabled, print debug messages to stderr */
-#if 1
+#if 0
#define DPRINTF(_f, _a...) fprintf(stderr, __FILE__ ":%d: " _f, __LINE__, ##_a)
#else
#define DPRINTF(_f, _a...) ((void)0)
@@ -65,6 +65,7 @@ int read_fd;
int write_fd;
static pid_t process;
+int connected_disks = 0;
fd_list_entry_t *fd_start = NULL;
static void handle_blktap_iomsg(void* private);
@@ -218,11 +219,13 @@ static int map_new_dev(struct td_state *
return -1;
}
-static int open_disk(struct td_state *s, char *path, int readonly)
+static int open_disk(struct td_state *s, char *path, int driver, int readonly)
{
BlockDriverState* bs;
+ BlockDriver* drv;
char* devname;
static int devnumber = 0;
+ int flags = readonly ? BDRV_O_RDONLY : BDRV_O_RDWR;
int i;
DPRINTF("Opening %s as blktap%d\n", path, devnumber);
@@ -230,7 +233,25 @@ static int open_disk(struct td_state *s,
bs = bdrv_new(devname);
free(devname);
- if (bdrv_open(bs, path, 0) != 0) {
+ /* Search for disk driver */
+ for (i = 0; blktap_drivers[i].idnum >= 0; i++) {
+ if (blktap_drivers[i].idnum == driver)
+ break;
+ }
+
+ if (blktap_drivers[i].idnum < 0) {
+ fprintf(stderr, "Could not find image format id %d\n", driver);
+ return -ENOMEM;
+ }
+
+ drv = blktap_drivers[i].drv;
+ DPRINTF("%s driver specified\n", drv ? drv->format_name : "No");
+
+ /* Open the image
+ * Use BDRV_O_CACHE_WB for write-through caching,
+ * no flags for write-back caching
+ */
+ if (bdrv_open2(bs, path, flags|BDRV_O_CACHE_WB, drv) != 0) {
fprintf(stderr, "Could not open image file %s\n", path);
return -ENOMEM;
}
@@ -240,6 +261,12 @@ static int open_disk(struct td_state *s,
s->size = bs->total_sectors;
s->sector_size = 512;
+ if (s->size == 0) {
+ fprintf(stderr, "Error: Disk image %s is too small\n",
+ path);
+ return -ENOMEM;
+ }
+
s->info = ((s->flags & TD_RDONLY) ? VDISK_READONLY : 0);
#ifndef QEMU_TOOL
@@ -337,6 +364,15 @@ static void qemu_send_responses(void* op
}
/**
+ * Callback function for AIO flush
+ */
+static void qemu_flush_response(void* opaque, int ret) {
+ if (ret != 0) {
+ DPRINTF("aio_flush: ret = %d (%s)\n", ret, strerror(-ret));
+ }
+}
+
+/**
* Callback function for the IO message pipe. Reads requests from the ring
* and processes them (call qemu read/write functions).
*
@@ -355,6 +391,7 @@ static void handle_blktap_iomsg(void* pr
blkif_t *blkif = s->blkif;
tapdev_info_t *info = s->ring_info;
int page_size = getpagesize();
+ int sync;
struct aiocb_info *aiocb_info;
@@ -387,7 +424,7 @@ static void handle_blktap_iomsg(void* pr
/* Don't allow writes on readonly devices */
if ((s->flags & TD_RDONLY) &&
- (req->operation == BLKIF_OP_WRITE)) {
+ (req->operation != BLKIF_OP_READ)) {
blkif->pending_list[idx].status = BLKIF_RSP_ERROR;
goto send_response;
}
@@ -408,7 +445,7 @@ static void handle_blktap_iomsg(void* pr
DPRINTF("Sector request failed:\n");
DPRINTF("%s request, idx [%d,%d] size [%llu], "
"sector [%llu,%llu]\n",
- (req->operation == BLKIF_OP_WRITE ?
+ (req->operation != BLKIF_OP_READ ?
"WRITE" : "READ"),
idx,i,
(long long unsigned)
@@ -421,8 +458,14 @@ static void handle_blktap_iomsg(void* pr
blkif->pending_list[idx].secs_pending += nsects;
- switch (req->operation)
+ sync = 0;
+ switch (req->operation)
{
+ case BLKIF_OP_WRITE_BARRIER:
+ sync = 1;
+ bdrv_aio_flush(s->bs, qemu_flush_response, NULL);
+ /* fall through */
+
case BLKIF_OP_WRITE:
aiocb_info = malloc(sizeof(*aiocb_info));
@@ -442,6 +485,10 @@ static void handle_blktap_iomsg(void* pr
DPRINTF("ERROR: bdrv_write() == NULL\n");
goto send_response;
}
+
+ if (sync)
+ bdrv_aio_flush(s->bs, qemu_flush_response, NULL);
+
break;
case BLKIF_OP_READ:
@@ -519,9 +566,10 @@ static void handle_blktap_ctrlmsg(void*
/* Allocate the disk structs */
s = state_init();
+ connected_disks++;
/*Open file*/
- if (s == NULL || open_disk(s, path, msg->readonly)) {
+ if (s == NULL || open_disk(s, path, msg->drivertype, msg->readonly)) {
msglen = sizeof(msg_hdr_t);
msg->type = CTLMSG_IMG_FAIL;
msg->len = msglen;
@@ -569,7 +617,8 @@ static void handle_blktap_ctrlmsg(void*
case CTLMSG_CLOSE:
s = get_state(msg->cookie);
if (s) unmap_disk(s);
- break;
+ connected_disks--;
+ break;
case CTLMSG_PID:
memset(buf, 0x00, MSG_SIZE);
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.h
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.h
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_blktap.h
@@ -52,4 +52,18 @@ typedef struct fd_list_entry {
int init_blktap(void);
+typedef struct disk_info {
+ int idnum;
+ struct BlockDriver *drv;
+} disk_info_t;
+
+static disk_info_t blktap_drivers[] = {
+ { DISK_TYPE_AIO, &bdrv_raw },
+ { DISK_TYPE_SYNC, &bdrv_raw },
+ { DISK_TYPE_VMDK, &bdrv_vmdk },
+ { DISK_TYPE_QCOW, &bdrv_qcow },
+ { DISK_TYPE_QCOW2, &bdrv_qcow2 },
+ { -1, NULL }
+};
+
#endif /*XEN_BLKTAP_H_*/
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/configure
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/configure
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/configure
@@ -1511,7 +1511,7 @@ bsd)
;;
esac
-tools=
+tools="tapdisk-ioemu"
if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
tools="qemu-img\$(EXESUF) $tools"
if [ "$linux" = "yes" ] ; then
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-tool.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/qemu-tool.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-tool.c
@@ -68,7 +68,7 @@ void qemu_bh_delete(QEMUBH *bh)
qemu_free(bh);
}
-int qemu_set_fd_handler2(int fd,
+int __attribute__((weak)) qemu_set_fd_handler2(int fd,
IOCanRWHandler *fd_read_poll,
IOHandler *fd_read,
IOHandler *fd_write,
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/tapdisk-ioemu.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/tapdisk-ioemu.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/tapdisk-ioemu.c
@@ -12,34 +12,13 @@
extern void qemu_aio_init(void);
extern void qemu_aio_poll(void);
-extern void bdrv_init(void);
-
-extern void *qemu_mallocz(size_t size);
-extern void qemu_free(void *ptr);
extern void *fd_start;
+extern int connected_disks;
int domid = 0;
FILE* logfile;
-void term_printf(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
-void term_print_filename(const char *filename)
-{
- term_printf(filename);
-}
-
-
-typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
-typedef int IOCanRWHandler(void *opaque);
-typedef void IOHandler(void *opaque);
-
typedef struct IOHandlerRecord {
int fd;
IOCanRWHandler *fd_read_poll;
@@ -98,25 +77,29 @@ int main(void)
int max_fd;
fd_set rfds;
struct timeval tv;
- void *old_fd_start = NULL;
+ int old_connected_disks = 0;
+
+ /* Daemonize */
+ if (fork() != 0)
+ exit(0);
- logfile = stderr;
-
bdrv_init();
- qemu_aio_init();
init_blktap();
- /* Daemonize */
- if (fork() != 0)
- exit(0);
-
+ logfile = fopen("/var/log/xen/tapdisk-ioemu.log", "a");
+ if (logfile) {
+ setbuf(logfile, NULL);
+ fclose(stderr);
+ stderr = logfile;
+ } else {
+ logfile = stderr;
+ }
+
/*
* Main loop: Pass events to the corrsponding handlers and check for
* completed aio operations.
*/
while (1) {
- qemu_aio_poll();
-
max_fd = -1;
FD_ZERO(&rfds);
for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next)
@@ -146,11 +129,17 @@ int main(void)
pioh = &ioh->next;
}
+ if (old_connected_disks != connected_disks)
+ fprintf(stderr, "connected disks: %d => %d\n",
+ old_connected_disks, connected_disks);
+
/* Exit when the last image has been closed */
- if (old_fd_start != NULL && fd_start == NULL)
+ if (old_connected_disks != 0 && connected_disks == 0) {
+ fprintf(stderr, "Last image is closed, exiting.\n");
exit(0);
+ }
- old_fd_start = fd_start;
+ old_connected_disks = connected_disks;
}
return 0;
}
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/block.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block.c
@@ -350,7 +350,7 @@ int bdrv_file_open(BlockDriverState **pb
int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
{
- return bdrv_open2(bs, filename, flags, NULL);
+ return bdrv_open2(bs, filename, flags|BDRV_O_RDWR, NULL);
}
int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
@@ -419,12 +419,13 @@ int bdrv_open2(BlockDriverState *bs, con
}
bs->drv = drv;
bs->opaque = qemu_mallocz(drv->instance_size);
- /* Note: for compatibility, we open disk image files as RDWR, and
- RDONLY as fallback */
if (!(flags & BDRV_O_FILE))
- open_flags = (flags & BDRV_O_ACCESS) | (flags & BDRV_O_CACHE_MASK);
+ open_flags = flags;
else
open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
+ if (!(open_flags & BDRV_O_RDWR))
+ bs->read_only = 1;
+
ret = drv->bdrv_open(bs, filename, open_flags);
if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
@@ -595,6 +596,16 @@ int bdrv_read(BlockDriverState *bs, int6
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
+
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+ memcpy(buf, bs->boot_sector_data, 512);
+ sector_num++;
+ nb_sectors--;
+ buf += 512;
+ if (nb_sectors == 0)
+ return 0;
+ }
+
if (drv->bdrv_pread) {
int ret, len;
len = nb_sectors * 512;
@@ -630,6 +641,10 @@ int bdrv_write(BlockDriverState *bs, int
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+ memcpy(bs->boot_sector_data, buf, 512);
+ }
+
if (drv->bdrv_pwrite) {
int ret, len, count = 0;
len = nb_sectors * 512;
@@ -933,6 +948,16 @@ void bdrv_guess_geometry(BlockDriverStat
}
}
+/* force a given boot sector. */
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
+{
+ bs->boot_sector_enabled = 1;
+ if (size > 512)
+ size = 512;
+ memcpy(bs->boot_sector_data, data, size);
+ memset(bs->boot_sector_data + size, 0, 512 - size);
+}
+
void bdrv_set_geometry_hint(BlockDriverState *bs,
int cyls, int heads, int secs)
{
@@ -1463,6 +1488,14 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDri
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
+ /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+ memcpy(buf, bs->boot_sector_data, 512);
+ sector_num++;
+ nb_sectors--;
+ buf += 512;
+ }
+
ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
if (ret) {
@@ -1488,6 +1521,10 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDr
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+ memcpy(bs->boot_sector_data, buf, 512);
+ }
+
ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
if (ret) {
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/usb-msd.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/usb-msd.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/usb-msd.c
@@ -551,7 +551,7 @@ USBDevice *usb_msd_init(const char *file
s = qemu_mallocz(sizeof(MSDState));
bdrv = bdrv_new("usb");
- if (bdrv_open2(bdrv, filename, 0, drv) < 0)
+ if (bdrv_open2(bdrv, filename, BDRV_O_RDWR, drv) < 0)
goto fail;
s->bs = bdrv;
*pbs = bdrv;
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-img.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/qemu-img.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-img.c
@@ -32,7 +32,7 @@
#endif
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
-#define BRDV_O_FLAGS BDRV_O_CACHE_WB
+#define BDRV_O_FLAGS BDRV_O_CACHE_WB
static void QEMU_NORETURN error(const char *fmt, ...)
{
@@ -185,7 +185,7 @@ static int read_password(char *buf, int
#endif
static BlockDriverState *bdrv_new_open(const char *filename,
- const char *fmt)
+ const char *fmt, int flags)
{
BlockDriverState *bs;
BlockDriver *drv;
@@ -201,7 +201,7 @@ static BlockDriverState *bdrv_new_open(c
} else {
drv = &bdrv_raw;
}
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
+ if (bdrv_open2(bs, filename, flags, drv) < 0) {
error("Could not open '%s'", filename);
}
if (bdrv_is_encrypted(bs)) {
@@ -253,7 +253,7 @@ static int img_create(int argc, char **a
size = 0;
if (base_filename) {
BlockDriverState *bs;
- bs = bdrv_new_open(base_filename, NULL);
+ bs = bdrv_new_open(base_filename, NULL, BDRV_O_RDWR);
bdrv_get_geometry(bs, &size);
size *= 512;
bdrv_delete(bs);
@@ -332,7 +332,7 @@ static int img_commit(int argc, char **a
} else {
drv = NULL;
}
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
+ if (bdrv_open2(bs, filename, BDRV_O_RDWR, drv) < 0) {
error("Could not open '%s'", filename);
}
ret = bdrv_commit(bs);
@@ -455,7 +455,8 @@ static int img_convert(int argc, char **
total_sectors = 0;
for (bs_i = 0; bs_i < bs_n; bs_i++) {
- bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
+ bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt,
+ BDRV_O_CACHE_WB|BDRV_O_RDONLY);
if (!bs[bs_i])
error("Could not open '%s'", argv[optind + bs_i]);
bdrv_get_geometry(bs[bs_i], &bs_sectors);
@@ -483,7 +484,7 @@ static int img_convert(int argc, char **
}
}
- out_bs = bdrv_new_open(out_filename, out_fmt);
+ out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_CACHE_WB|BDRV_O_RDWR);
bs_i = 0;
bs_offset = 0;
@@ -706,7 +707,7 @@ static int img_info(int argc, char **arg
} else {
drv = NULL;
}
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
+ if (bdrv_open2(bs, filename, BDRV_O_FLAGS|BDRV_O_RDWR, drv) < 0) {
error("Could not open '%s'", filename);
}
bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
@@ -810,7 +811,7 @@ static void img_snapshot(int argc, char
if (!bs)
error("Not enough memory");
- if (bdrv_open2(bs, filename, 0, NULL) < 0) {
+ if (bdrv_open2(bs, filename, BDRV_O_RDWR, NULL) < 0) {
error("Could not open '%s'", filename);
}
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block-qcow2.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/block-qcow2.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block-qcow2.c
@@ -916,7 +916,7 @@ static int alloc_cluster_link_l2(BlockDr
goto err;
for (i = 0; i < j; i++)
- free_any_clusters(bs, old_cluster[i], 1);
+ free_any_clusters(bs, be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1);
ret = 0;
err:
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_platform.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/xen_platform.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/xen_platform.c
@@ -30,6 +30,8 @@
#include "qemu-xen.h"
#include "net.h"
#include "xen_platform.h"
+#include "sysemu.h"
+#include <xc_private.h>
#include <assert.h>
#include <xenguest.h>
@@ -335,11 +337,66 @@ static void xen_platform_ioport_writeb(v
}
}
+static uint32_t ioport_base;
+
+static void platform_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ DECLARE_DOMCTL;
+ int rc;
+
+ if (val == 0)
+ qemu_invalidate_map_cache();
+
+ switch (addr - ioport_base) {
+ case 0:
+ fprintf(logfile, "Init hypercall page %x, addr %x.\n", val, addr);
+ domctl.domain = (domid_t)domid;
+ domctl.u.hypercall_init.gmfn = val;
+ domctl.cmd = XEN_DOMCTL_hypercall_init;
+ rc = xc_domctl(xc_handle, &domctl);
+ fprintf(logfile, "result -> %d.\n", rc);
+ break;
+ case 4:
+ fprintf(logfile, "Disconnect IDE hard disk...\n");
+ ide_unplug_harddisks();
+ fprintf(logfile, "Disconnect SCSI hard disk...\n");
+ pci_unplug_scsi();
+ fprintf(logfile, "Disconnect netifs...\n");
+ pci_unplug_netifs();
+ fprintf(logfile, "Shutdown taps...\n");
+ net_tap_shutdown_all();
+ fprintf(logfile, "Done.\n");
+ break;
+ case 8:
+ if (val ==1 ) {
+ fprintf(logfile, "Disconnect IDE hard disk...\n");
+ ide_unplug_harddisks();
+ fprintf(logfile, "Done.\n");
+ } else if (val == 2) {
+ fprintf(logfile, "Disconnect netifs...\n");
+ pci_unplug_netifs();
+ fprintf(logfile, "Shutdown taps...\n");
+ net_tap_shutdown_all();
+ fprintf(logfile, "Done.\n");
+ }
+ break;
+ default:
+ fprintf(logfile, "Write to bad port %x (base %x) on evtchn device.\n",
+ addr, ioport_base);
+ break;
+ }
+}
+
static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type)
{
+ ioport_base = addr;
+
+ register_ioport_write(addr, 16, 4, platform_ioport_write, NULL);
+/*
PCIXenPlatformState *d = (PCIXenPlatformState *)pci_dev;
register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
+*/
}
static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/ide.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/ide.c
@@ -935,8 +935,9 @@ static inline void ide_dma_submit_check(
static inline void ide_set_irq(IDEState *s)
{
- BMDMAState *bm = s->bmdma;
- if (!s->bs) return; /* ouch! (see ide_flush_cb) */
+ BMDMAState *bm;
+ if (!s || !s->bs) return; /* ouch! (see ide_flush_cb) */
+ bm = s->bmdma;
if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
if (bm) {
bm->status |= BM_STATUS_INT;
@@ -1224,14 +1225,14 @@ static void ide_read_dma_cb(void *opaque
int n;
int64_t sector_num;
+ if (!s || !s->bs) return; /* ouch! (see ide_flush_cb) */
+
if (ret < 0) {
dma_buf_commit(s, 1);
ide_dma_error(s);
return;
}
- if (!s->bs) return; /* ouch! (see ide_flush_cb) */
-
n = s->io_buffer_size >> 9;
sector_num = ide_get_sector(s);
if (n > 0) {
@@ -1335,6 +1336,8 @@ static void ide_write_flush_cb(void *opa
BMDMAState *bm = opaque;
IDEState *s = bm->ide_if;
+ if (!s) return; /* yikes */
+
if (ret != 0) {
ide_dma_error(s);
return;
@@ -1366,13 +1369,13 @@ static void ide_write_dma_cb(void *opaqu
int n;
int64_t sector_num;
+ if (!s || !s->bs) return; /* ouch! (see ide_flush_cb) */
+
if (ret < 0) {
if (ide_handle_write_error(s, -ret, BM_STATUS_DMA_RETRY))
return;
}
- if (!s->bs) return; /* ouch! (see ide_flush_cb) */
-
n = s->io_buffer_size >> 9;
sector_num = ide_get_sector(s);
if (n > 0) {
@@ -1429,7 +1432,7 @@ static void ide_flush_cb(void *opaque, i
{
IDEState *s = opaque;
- if (!s->bs) return; /* ouch! (see below) */
+ if (!s || !s->bs) return; /* ouch! (see below) */
if (ret) {
/* We are completely doomed. The IDE spec does not permit us
@@ -1686,7 +1689,7 @@ static void ide_atapi_cmd_read_dma_cb(vo
IDEState *s = bm->ide_if;
int data_offset, n;
- if (!s->bs) return; /* ouch! (see ide_flush_cb) */
+ if (!s || !s->bs) return; /* ouch! (see ide_flush_cb) */
if (ret < 0) {
ide_atapi_io_error(s, ret);
@@ -2365,7 +2368,7 @@ static void cdrom_change_cb(void *opaque
IDEState *s = opaque;
uint64_t nb_sectors;
- if (!s->bs) return; /* ouch! (see ide_flush_cb) */
+ if (!s || !s->bs) return; /* ouch! (see ide_flush_cb) */
bdrv_get_geometry(s->bs, &nb_sectors);
s->nb_sectors = nb_sectors;
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/vl.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/vl.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/vl.c
@@ -30,6 +30,7 @@
#include "hw/isa.h"
#include "hw/baum.h"
#include "hw/bt.h"
+#include "hw/watchdog.h"
#include "net.h"
#include "console.h"
#include "sysemu.h"
@@ -200,7 +201,7 @@ DriveInfo drives_table[MAX_DRIVES+1];
int nb_drives;
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
int vga_ram_size;
-static DisplayState *display_state;
+DisplayState *display_state;
int nographic;
static int curses;
static int sdl;
@@ -2627,6 +2628,8 @@ int drive_init(struct drive_opt *arg, in
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
nb_drives++;
+ bdrv_flags = BDRV_O_RDWR;
+
switch(type) {
case IF_IDE:
case IF_XEN:
@@ -2640,6 +2643,7 @@ int drive_init(struct drive_opt *arg, in
break;
case MEDIA_CDROM:
bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
+ bdrv_flags &= ~BDRV_O_RDWR;
break;
}
break;
@@ -2660,7 +2664,6 @@ int drive_init(struct drive_opt *arg, in
}
if (!file[0])
return -2;
- bdrv_flags = 0;
if (snapshot) {
bdrv_flags |= BDRV_O_SNAPSHOT;
cache = 2; /* always use write-back with snapshot */
@@ -4175,6 +4178,10 @@ static void help(int exitcode)
"-startdate select initial date of the clock\n"
"-icount [N|auto]\n"
" enable virtual instruction counter with 2^N clock ticks per instruction\n"
+ "-watchdog i6300esb|ib700\n"
+ " enable virtual hardware watchdog [default=none]\n"
+ "-watchdog-action reset|shutdown|poweroff|pause|debug|none\n"
+ " action when watchdog fires [default=reset]\n"
"-echr chr set terminal escape character instead of ctrl-a\n"
"-virtioconsole c\n"
" set virtio console\n"
@@ -4322,6 +4329,8 @@ enum {
QEMU_OPTION_localtime,
QEMU_OPTION_startdate,
QEMU_OPTION_icount,
+ QEMU_OPTION_watchdog,
+ QEMU_OPTION_watchdog_action,
QEMU_OPTION_echr,
QEMU_OPTION_virtiocon,
QEMU_OPTION_show_cursor,
@@ -4448,6 +4457,8 @@ static const QEMUOption qemu_options[] =
{ "localtime", 0, QEMU_OPTION_localtime },
{ "startdate", HAS_ARG, QEMU_OPTION_startdate },
{ "icount", HAS_ARG, QEMU_OPTION_icount },
+ { "watchdog", HAS_ARG, QEMU_OPTION_watchdog },
+ { "watchdog-action", HAS_ARG, QEMU_OPTION_watchdog_action },
{ "echr", HAS_ARG, QEMU_OPTION_echr },
{ "virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon },
{ "show-cursor", 0, QEMU_OPTION_show_cursor },
@@ -4949,6 +4960,8 @@ int main(int argc, char **argv, char **e
tb_size = 0;
autostart= 1;
+ register_watchdogs();
+
optind = 1;
for(;;) {
if (optind >= argc)
@@ -5323,6 +5336,17 @@ int main(int argc, char **argv, char **e
serial_devices[serial_device_index] = optarg;
serial_device_index++;
break;
+ case QEMU_OPTION_watchdog:
+ i = select_watchdog(optarg);
+ if (i > 0)
+ exit (i == 1 ? 1 : 0);
+ break;
+ case QEMU_OPTION_watchdog_action:
+ if (select_watchdog_action(optarg) == -1) {
+ fprintf(stderr, "Unknown -watchdog-action parameter\n");
+ exit(1);
+ }
+ break;
case QEMU_OPTION_virtiocon:
if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
fprintf(stderr, "qemu: too many virtio consoles\n");
@@ -5838,9 +5862,9 @@ int main(int argc, char **argv, char **e
if ((msg = xenbus_read(XBT_NIL, "domid", &domid_s)))
fprintf(stderr,"Can not read our own domid: %s\n", msg);
else
- xenstore_parse_domain_config(atoi(domid_s));
+ xenstore_parse_domain_config(atoi(domid_s), machine);
#else
- xenstore_parse_domain_config(domid);
+ xenstore_parse_domain_config(domid, machine);
#endif /* CONFIG_STUBDOM */
}
Index: xen-4.3.0-testing/tools/python/xen/xend/XendConstants.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendConstants.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendConstants.py
@@ -94,7 +94,7 @@ DOM_STATES_OLD = [
SHUTDOWN_TIMEOUT = (60.0 * 5)
"""Minimum time between domain restarts in seconds."""
-MINIMUM_RESTART_TIME = 60
+MINIMUM_RESTART_TIME = 10
RESTART_IN_PROGRESS = 'xend/restart_in_progress'
DUMPCORE_IN_PROGRESS = 'xend/dumpcore_in_progress'
Index: xen-4.3.0-testing/tools/python/xen/xend/XendLogging.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendLogging.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendLogging.py
@@ -76,7 +76,7 @@ if 'TRACE' not in logging.__dict__:
log = logging.getLogger("xend")
-MAX_BYTES = 1 << 20 # 1MB
+MAX_BYTES = 0
BACKUP_COUNT = 5
STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
Index: xen-4.3.0-testing/tools/python/xen/xend/server/XMLRPCServer.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/XMLRPCServer.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/XMLRPCServer.py
@@ -95,7 +95,7 @@ methods = ['device_create', 'device_conf
'destroyDevice','getDeviceSxprs',
'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
'send_sysrq', 'getVCPUInfo', 'waitForDevices',
- 'getRestartCount', 'getBlockDeviceClass']
+ 'getRestartCount', 'getBlockDeviceClass', 'chgvncpasswd']
exclude = ['domain_create', 'domain_restore']
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block_int.h
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/block_int.h
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block_int.h
@@ -122,6 +122,9 @@ struct BlockDriverState {
BlockDriver *drv; /* NULL means no media */
void *opaque;
+ int boot_sector_enabled;
+ uint8_t boot_sector_data[512];
+
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block.h
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/block.h
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/block.h
@@ -82,6 +82,7 @@ int64_t bdrv_getlength(BlockDriverState
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
int bdrv_commit(BlockDriverState *bs);
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
/* async block I/O */
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/watchdog.c
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/watchdog.c
@@ -0,0 +1,146 @@
+/*
+ * Virtual hardware watchdog.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * By Richard W.M. Jones (rjones@redhat.com).
+ */
+
+#include "qemu-common.h"
+#include "sys-queue.h"
+#include "sysemu.h"
+#include "hw/watchdog.h"
+
+/* Possible values for action parameter. */
+#define WDT_RESET 1 /* Hard reset. */
+#define WDT_SHUTDOWN 2 /* Shutdown. */
+#define WDT_POWEROFF 3 /* Quit. */
+#define WDT_PAUSE 4 /* Pause. */
+#define WDT_DEBUG 5 /* Prints a message and continues running. */
+#define WDT_NONE 6 /* Do nothing. */
+
+static WatchdogTimerModel *watchdog;
+static int watchdog_action = WDT_RESET;
+static LIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
+
+void watchdog_add_model(WatchdogTimerModel *model)
+{
+ LIST_INSERT_HEAD(&watchdog_list, model, entry);
+}
+
+/* Returns:
+ * 0 = continue
+ * 1 = exit program with error
+ * 2 = exit program without error
+ */
+int select_watchdog(const char *p)
+{
+ WatchdogTimerModel *model;
+
+ if (watchdog) {
+ fprintf(stderr,
+ "qemu: only one watchdog option may be given\n");
+ return 1;
+ }
+
+ /* -watchdog ? lists available devices and exits cleanly. */
+ if (strcmp(p, "?") == 0) {
+ LIST_FOREACH(model, &watchdog_list, entry) {
+ fprintf(stderr, "\t%s\t%s\n",
+ model->wdt_name, model->wdt_description);
+ }
+ return 2;
+ }
+
+ LIST_FOREACH(model, &watchdog_list, entry) {
+ if (strcasecmp(model->wdt_name, p) == 0) {
+ watchdog = model;
+ return 0;
+ }
+ }
+
+ fprintf(stderr, "Unknown -watchdog device. Supported devices are:\n");
+ LIST_FOREACH(model, &watchdog_list, entry) {
+ fprintf(stderr, "\t%s\t%s\n",
+ model->wdt_name, model->wdt_description);
+ }
+ return 1;
+}
+
+int select_watchdog_action(const char *p)
+{
+ if (strcasecmp(p, "reset") == 0)
+ watchdog_action = WDT_RESET;
+ else if (strcasecmp(p, "shutdown") == 0)
+ watchdog_action = WDT_SHUTDOWN;
+ else if (strcasecmp(p, "poweroff") == 0)
+ watchdog_action = WDT_POWEROFF;
+ else if (strcasecmp(p, "pause") == 0)
+ watchdog_action = WDT_PAUSE;
+ else if (strcasecmp(p, "debug") == 0)
+ watchdog_action = WDT_DEBUG;
+ else if (strcasecmp(p, "none") == 0)
+ watchdog_action = WDT_NONE;
+ else
+ return -1;
+
+ return 0;
+}
+
+/* This actually performs the "action" once a watchdog has expired,
+ * ie. reboot, shutdown, exit, etc.
+ */
+void watchdog_perform_action(void)
+{
+ switch(watchdog_action) {
+ case WDT_RESET: /* same as 'system_reset' in monitor */
+ qemu_system_reset_request();
+ break;
+
+ case WDT_SHUTDOWN: /* same as 'system_powerdown' in monitor */
+ qemu_system_powerdown_request();
+ break;
+
+ case WDT_POWEROFF: /* same as 'quit' command in monitor */
+ exit(0);
+ break;
+
+ case WDT_PAUSE: /* same as 'stop' command in monitor */
+ vm_stop(0);
+ break;
+
+ case WDT_DEBUG:
+ fprintf(stderr, "watchdog: timer fired\n");
+ break;
+
+ case WDT_NONE:
+ break;
+ }
+}
+
+void watchdog_pc_init(PCIBus *pci_bus)
+{
+ if (watchdog)
+ watchdog->wdt_pc_init(pci_bus);
+}
+
+void register_watchdogs(void)
+{
+ wdt_ib700_init();
+ wdt_i6300esb_init();
+}
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/watchdog.h
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/watchdog.h
@@ -0,0 +1,54 @@
+/*
+ * Virtual hardware watchdog.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * By Richard W.M. Jones (rjones@redhat.com).
+ */
+
+#ifndef QEMU_WATCHDOG_H
+#define QEMU_WATCHDOG_H
+
+extern void wdt_i6300esb_init(void);
+extern void wdt_ib700_init(void);
+
+
+struct WatchdogTimerModel {
+ LIST_ENTRY(WatchdogTimerModel) entry;
+
+ /* Short name of the device - used to select it on the command line. */
+ const char *wdt_name;
+ /* Longer description (eg. manufacturer and full model number). */
+ const char *wdt_description;
+
+ /* This callback should create/register the device. It is called
+ * indirectly from hw/pc.c when the virtual PC is being set up.
+ */
+ void (*wdt_pc_init)(PCIBus *pci_bus);
+};
+typedef struct WatchdogTimerModel WatchdogTimerModel;
+
+/* in hw/watchdog.c */
+extern int select_watchdog(const char *p);
+extern int select_watchdog_action(const char *action);
+extern void watchdog_add_model(WatchdogTimerModel *model);
+extern void watchdog_perform_action(void);
+extern void watchdog_pc_init(PCIBus *pci_bus);
+extern void register_watchdogs(void);
+
+#endif /* QEMU_WATCHDOG_H */
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/wdt_i6300esb.c
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/wdt_i6300esb.c
@@ -0,0 +1,470 @@
+/*
+ * Virtual hardware watchdog.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * By Richard W.M. Jones (rjones@redhat.com).
+ */
+
+#include <inttypes.h>
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "watchdog.h"
+#include "hw.h"
+#include "isa.h"
+#include "pc.h"
+#include "pci.h"
+
+/*#define I6300ESB_DEBUG 1*/
+
+#ifdef I6300ESB_DEBUG
+#define i6300esb_debug(fs,...) \
+ fprintf(stderr,"i6300esb: %s: "fs,__func__,##__VA_ARGS__)
+#else
+#define i6300esb_debug(fs,...)
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_ESB_9
+#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab
+#endif
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG 0x60 /* Config register */
+#define ESB_LOCK_REG 0x68 /* WDT lock register */
+
+/* Memory mapped registers (offset from base address) */
+#define ESB_TIMER1_REG 0x00 /* Timer1 value after each reset */
+#define ESB_TIMER2_REG 0x04 /* Timer2 value after each reset */
+#define ESB_GINTSR_REG 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG 0x0c /* Reload register */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */
+#define ESB_WDT_ENABLE (0x01 << 1) /* Enable WDT */
+#define ESB_WDT_LOCK (0x01 << 0) /* Lock (nowayout) */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */
+#define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */
+#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */
+
+/* Magic constants */
+#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
+#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */
+
+/* Device state. */
+struct I6300State {
+ PCIDevice dev; /* PCI device state, must be first field. */
+
+ int reboot_enabled; /* "Reboot" on timer expiry. The real action
+ * performed depends on the -watchdog-action
+ * param passed on QEMU command line.
+ */
+ int clock_scale; /* Clock scale. */
+#define CLOCK_SCALE_1KHZ 0
+#define CLOCK_SCALE_1MHZ 1
+
+ int int_type; /* Interrupt type generated. */
+#define INT_TYPE_IRQ 0 /* APIC 1, INT 10 */
+#define INT_TYPE_SMI 2
+#define INT_TYPE_DISABLED 3
+
+ int free_run; /* If true, reload timer on expiry. */
+ int locked; /* If true, enabled field cannot be changed. */
+ int enabled; /* If true, watchdog is enabled. */
+
+ QEMUTimer *timer; /* The actual watchdog timer. */
+
+ uint32_t timer1_preload; /* Values preloaded into timer1, timer2. */
+ uint32_t timer2_preload;
+ int stage; /* Stage (1 or 2). */
+
+ int unlock_state; /* Guest writes 0x80, 0x86 to unlock the
+ * registers, and we transition through
+ * states 0 -> 1 -> 2 when this happens.
+ */
+
+ int previous_reboot_flag; /* If the watchdog caused the previous
+ * reboot, this flag will be set.
+ */
+};
+
+typedef struct I6300State I6300State;
+
+/* This function is called when the watchdog has either been enabled
+ * (hence it starts counting down) or has been keep-alived.
+ */
+static void i6300esb_restart_timer(I6300State *d, int stage)
+{
+ int64_t timeout;
+
+ if (!d->enabled)
+ return;
+
+ d->stage = stage;
+
+ if (d->stage <= 1)
+ timeout = d->timer1_preload;
+ else
+ timeout = d->timer2_preload;
+
+ if (d->clock_scale == CLOCK_SCALE_1KHZ)
+ timeout <<= 15;
+ else
+ timeout <<= 5;
+
+ /* Get the timeout in units of ticks_per_sec. */
+ timeout = ticks_per_sec * timeout / 33000000;
+
+ i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);
+
+ qemu_mod_timer(d->timer, qemu_get_clock(vm_clock) + timeout);
+}
+
+/* This is called when the guest disables the watchdog. */
+static void i6300esb_disable_timer(I6300State *d)
+{
+ i6300esb_debug("timer disabled\n");
+
+ qemu_del_timer(d->timer);
+}
+
+static void i6300esb_reset(I6300State *d)
+{
+ /* XXX We should probably reset other parts of the state here,
+ * but we should also reset our state on general machine reset
+ * too. For now just disable the timer so it doesn't fire
+ * again after the reboot.
+ */
+ i6300esb_disable_timer(d);
+}
+
+/* This function is called when the watchdog expires. Note that
+ * the hardware has two timers, and so expiry happens in two stages.
+ * If d->stage == 1 then we perform the first stage action (usually,
+ * sending an interrupt) and then restart the timer again for the
+ * second stage. If the second stage expires then the watchdog
+ * really has run out.
+ */
+static void i6300esb_timer_expired(void *vp)
+{
+ I6300State *d = (I6300State *) vp;
+
+ i6300esb_debug("stage %d\n", d->stage);
+
+ if (d->stage == 1) {
+ /* What to do at the end of stage 1? */
+ switch (d->int_type) {
+ case INT_TYPE_IRQ:
+ fprintf(stderr, "i6300esb_timer_expired: I would send APIC 1 INT 10 here if I knew how (XXX)\n");
+ break;
+ case INT_TYPE_SMI:
+ fprintf(stderr, "i6300esb_timer_expired: I would send SMI here if I knew how (XXX)\n");
+ break;
+ }
+
+ /* Start the second stage. */
+ i6300esb_restart_timer(d, 2);
+ } else {
+ /* Second stage expired, reboot for real. */
+ if (d->reboot_enabled) {
+ d->previous_reboot_flag = 1;
+ watchdog_perform_action(); /* This reboots, exits, etc */
+ i6300esb_reset(d);
+ }
+
+ /* In "free running mode" we start stage 1 again. */
+ if (d->free_run)
+ i6300esb_restart_timer(d, 1);
+ }
+}
+
+static void i6300esb_config_write(PCIDevice *dev, uint32_t addr,
+ uint32_t data, int len)
+{
+ I6300State *d = (I6300State *) dev;
+ int old;
+
+ i6300esb_debug("addr = %x, data = %x, len = %d\n", addr, data, len);
+
+ if (addr == ESB_CONFIG_REG && len == 2) {
+ d->reboot_enabled = (data & ESB_WDT_REBOOT) == 0;
+ d->clock_scale =
+ (data & ESB_WDT_FREQ) != 0 ? CLOCK_SCALE_1MHZ : CLOCK_SCALE_1KHZ;
+ d->int_type = (data & ESB_WDT_INTTYPE);
+ } else if (addr == ESB_LOCK_REG && len == 1) {
+ if (!d->locked) {
+ d->locked = (data & ESB_WDT_LOCK) != 0;
+ d->free_run = (data & ESB_WDT_FUNC) != 0;
+ old = d->enabled;
+ d->enabled = (data & ESB_WDT_ENABLE) != 0;
+ if (!old && d->enabled) /* Enabled transitioned from 0 -> 1 */
+ i6300esb_restart_timer(d, 1);
+ else if (!d->enabled)
+ i6300esb_disable_timer(d);
+ }
+ } else {
+ pci_default_write_config(dev, addr, data, len);
+ }
+}
+
+static uint32_t i6300esb_config_read(PCIDevice *dev, uint32_t addr, int len)
+{
+ I6300State *d = (I6300State *) dev;
+ uint32_t data;
+
+ i6300esb_debug ("addr = %x, len = %d\n", addr, len);
+
+ if (addr == ESB_CONFIG_REG && len == 2) {
+ data =
+ (d->reboot_enabled ? 0 : ESB_WDT_REBOOT) |
+ (d->clock_scale == CLOCK_SCALE_1MHZ ? ESB_WDT_FREQ : 0) |
+ d->int_type;
+ return data;
+ } else if (addr == ESB_LOCK_REG && len == 1) {
+ data =
+ (d->free_run ? ESB_WDT_FUNC : 0) |
+ (d->locked ? ESB_WDT_LOCK : 0) |
+ (d->enabled ? ESB_WDT_ENABLE : 0);
+ return data;
+ } else {
+ return pci_default_read_config(dev, addr, len);
+ }
+}
+
+static uint32_t i6300esb_mem_readb(void *vp, target_phys_addr_t addr)
+{
+ i6300esb_debug ("addr = %x\n", (int) addr);
+
+ return 0;
+}
+
+static uint32_t i6300esb_mem_readw(void *vp, target_phys_addr_t addr)
+{
+ uint32_t data = 0;
+ I6300State *d = (I6300State *) vp;
+
+ i6300esb_debug("addr = %x\n", (int) addr);
+
+ if (addr == 0xc) {
+ /* The previous reboot flag is really bit 9, but there is
+ * a bug in the Linux driver where it thinks it's bit 12.
+ * Set both.
+ */
+ data = d->previous_reboot_flag ? 0x1200 : 0;
+ }
+
+ return data;
+}
+
+static uint32_t i6300esb_mem_readl(void *vp, target_phys_addr_t addr)
+{
+ i6300esb_debug("addr = %x\n", (int) addr);
+
+ return 0;
+}
+
+static void i6300esb_mem_writeb(void *vp, target_phys_addr_t addr, uint32_t val)
+{
+ I6300State *d = (I6300State *) vp;
+
+ i6300esb_debug("addr = %x, val = %x\n", (int) addr, val);
+
+ if (addr == 0xc && val == 0x80)
+ d->unlock_state = 1;
+ else if (addr == 0xc && val == 0x86 && d->unlock_state == 1)
+ d->unlock_state = 2;
+}
+
+static void i6300esb_mem_writew(void *vp, target_phys_addr_t addr, uint32_t val)
+{
+ I6300State *d = (I6300State *) vp;
+
+ i6300esb_debug("addr = %x, val = %x\n", (int) addr, val);
+
+ if (addr == 0xc && val == 0x80)
+ d->unlock_state = 1;
+ else if (addr == 0xc && val == 0x86 && d->unlock_state == 1)
+ d->unlock_state = 2;
+ else {
+ if (d->unlock_state == 2) {
+ if (addr == 0xc) {
+ if ((val & 0x100) != 0)
+ /* This is the "ping" from the userspace watchdog in
+ * the guest ...
+ */
+ i6300esb_restart_timer(d, 1);
+
+ /* Setting bit 9 resets the previous reboot flag.
+ * There's a bug in the Linux driver where it sets
+ * bit 12 instead.
+ */
+ if ((val & 0x200) != 0 || (val & 0x1000) != 0) {
+ d->previous_reboot_flag = 0;
+ }
+ }
+
+ d->unlock_state = 0;
+ }
+ }
+}
+
+static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
+{
+ I6300State *d = (I6300State *) vp;
+
+ i6300esb_debug ("addr = %x, val = %x\n", (int) addr, val);
+
+ if (addr == 0xc && val == 0x80)
+ d->unlock_state = 1;
+ else if (addr == 0xc && val == 0x86 && d->unlock_state == 1)
+ d->unlock_state = 2;
+ else {
+ if (d->unlock_state == 2) {
+ if (addr == 0)
+ d->timer1_preload = val & 0xfffff;
+ else if (addr == 4)
+ d->timer2_preload = val & 0xfffff;
+
+ d->unlock_state = 0;
+ }
+ }
+}
+
+static void i6300esb_map(PCIDevice *dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ static CPUReadMemoryFunc *mem_read[3] = {
+ i6300esb_mem_readb,
+ i6300esb_mem_readw,
+ i6300esb_mem_readl,
+ };
+ static CPUWriteMemoryFunc *mem_write[3] = {
+ i6300esb_mem_writeb,
+ i6300esb_mem_writew,
+ i6300esb_mem_writel,
+ };
+ I6300State *d = (I6300State *) dev;
+ int io_mem;
+
+ i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
+
+ io_mem = cpu_register_io_memory (0, mem_read, mem_write, d);
+ cpu_register_physical_memory (addr, 0x10, io_mem);
+ /* qemu_register_coalesced_mmio (addr, 0x10); ? */
+}
+
+static void i6300esb_save(QEMUFile *f, void *vp)
+{
+ I6300State *d = (I6300State *) vp;
+
+ pci_device_save(&d->dev, f);
+ qemu_put_be32(f, d->reboot_enabled);
+ qemu_put_be32(f, d->clock_scale);
+ qemu_put_be32(f, d->int_type);
+ qemu_put_be32(f, d->free_run);
+ qemu_put_be32(f, d->locked);
+ qemu_put_be32(f, d->enabled);
+ qemu_put_timer(f, d->timer);
+ qemu_put_be32(f, d->timer1_preload);
+ qemu_put_be32(f, d->timer2_preload);
+ qemu_put_be32(f, d->stage);
+ qemu_put_be32(f, d->unlock_state);
+ qemu_put_be32(f, d->previous_reboot_flag);
+}
+
+static int i6300esb_load(QEMUFile *f, void *vp, int version)
+{
+ I6300State *d = (I6300State *) vp;
+
+ if (version != sizeof (I6300State))
+ return -EINVAL;
+
+ pci_device_load(&d->dev, f);
+ d->reboot_enabled = qemu_get_be32(f);
+ d->clock_scale = qemu_get_be32(f);
+ d->int_type = qemu_get_be32(f);
+ d->free_run = qemu_get_be32(f);
+ d->locked = qemu_get_be32(f);
+ d->enabled = qemu_get_be32(f);
+ qemu_get_timer(f, d->timer);
+ d->timer1_preload = qemu_get_be32(f);
+ d->timer2_preload = qemu_get_be32(f);
+ d->stage = qemu_get_be32(f);
+ d->unlock_state = qemu_get_be32(f);
+ d->previous_reboot_flag = qemu_get_be32(f);
+
+ return 0;
+}
+
+/* Create and initialize a virtual Intel 6300ESB during PC creation. */
+static void i6300esb_pc_init(PCIBus *pci_bus)
+{
+ I6300State *d;
+ uint8_t *pci_conf;
+
+ if (!pci_bus) {
+ fprintf(stderr, "wdt_i6300esb: no PCI bus in this machine\n");
+ return;
+ }
+
+ d = (I6300State *)
+ pci_register_device (pci_bus, "i6300esb_wdt", sizeof (I6300State),
+ -1,
+ i6300esb_config_read, i6300esb_config_write);
+
+ d->reboot_enabled = 1;
+ d->clock_scale = CLOCK_SCALE_1KHZ;
+ d->int_type = INT_TYPE_IRQ;
+ d->free_run = 0;
+ d->locked = 0;
+ d->enabled = 0;
+ d->timer = qemu_new_timer(vm_clock, i6300esb_timer_expired, d);
+ d->timer1_preload = 0xfffff;
+ d->timer2_preload = 0xfffff;
+ d->stage = 1;
+ d->unlock_state = 0;
+ d->previous_reboot_flag = 0;
+
+ pci_conf = d->dev.config;
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9);
+ pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER);
+ pci_conf[0x0e] = 0x00;
+
+ pci_register_io_region(&d->dev, 0, 0x10,
+ PCI_ADDRESS_SPACE_MEM, i6300esb_map);
+
+ register_savevm("i6300esb_wdt", -1, sizeof(I6300State),
+ i6300esb_save, i6300esb_load, d);
+}
+
+static WatchdogTimerModel model = {
+ .wdt_name = "i6300esb",
+ .wdt_description = "Intel 6300ESB",
+ .wdt_pc_init = i6300esb_pc_init,
+};
+
+void wdt_i6300esb_init(void)
+{
+ watchdog_add_model(&model);
+}
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/wdt_ib700.c
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/wdt_ib700.c
@@ -0,0 +1,112 @@
+/*
+ * Virtual hardware watchdog.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * By Richard W.M. Jones (rjones@redhat.com).
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "watchdog.h"
+#include "hw.h"
+#include "isa.h"
+#include "pc.h"
+
+/*#define IB700_DEBUG 1*/
+
+#ifdef IB700_DEBUG
+#define ib700_debug(fs,...) \
+ fprintf(stderr,"ib700: %s: "fs,__func__,##__VA_ARGS__)
+#else
+#define ib700_debug(fs,...)
+#endif
+
+/* This is the timer. We use a global here because the watchdog
+ * code ensures there is only one watchdog (it is located at a fixed,
+ * unchangable IO port, so there could only ever be one anyway).
+ */
+static QEMUTimer *timer = NULL;
+
+/* A write to this register enables the timer. */
+static void ib700_write_enable_reg(void *vp, uint32_t addr, uint32_t data)
+{
+ static int time_map[] = {
+ 30, 28, 26, 24, 22, 20, 18, 16,
+ 14, 12, 10, 8, 6, 4, 2, 0
+ };
+ int64 timeout;
+
+ ib700_debug("addr = %x, data = %x\n", addr, data);
+
+ timeout = (int64_t) time_map[data & 0xF] * ticks_per_sec;
+ qemu_mod_timer(timer, qemu_get_clock (vm_clock) + timeout);
+}
+
+/* A write (of any value) to this register disables the timer. */
+static void ib700_write_disable_reg(void *vp, uint32_t addr, uint32_t data)
+{
+ ib700_debug("addr = %x, data = %x\n", addr, data);
+
+ qemu_del_timer(timer);
+}
+
+/* This is called when the watchdog expires. */
+static void ib700_timer_expired(void *vp)
+{
+ ib700_debug("watchdog expired\n");
+
+ watchdog_perform_action();
+ qemu_del_timer(timer);
+}
+
+static void ib700_save(QEMUFile *f, void *vp)
+{
+ qemu_put_timer(f, timer);
+}
+
+static int ib700_load(QEMUFile *f, void *vp, int version)
+{
+ if (version != 0)
+ return -EINVAL;
+
+ qemu_get_timer(f, timer);
+
+ return 0;
+}
+
+/* Create and initialize a virtual IB700 during PC creation. */
+static void ib700_pc_init(PCIBus *unused)
+{
+ timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL);
+ register_savevm("ib700_wdt", -1, 0, ib700_save, ib700_load, NULL);
+
+ register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, NULL);
+ register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, NULL);
+}
+
+static WatchdogTimerModel model = {
+ .wdt_name = "ib700",
+ .wdt_description = "iBASE 700",
+ .wdt_pc_init = ib700_pc_init,
+};
+
+void wdt_ib700_init(void)
+{
+ watchdog_add_model(&model);
+}
Index: xen-4.3.0-testing/tools/libxl/libxl_dm.c
===================================================================
--- xen-4.3.0-testing.orig/tools/libxl/libxl_dm.c
+++ xen-4.3.0-testing/tools/libxl/libxl_dm.c
@@ -220,6 +220,12 @@ static char ** libxl__build_device_model
}
}
}
+ if (b_info->u.hvm.watchdog || b_info->u.hvm.watchdog_action) {
+ flexarray_append(dm_args, "-watchdog");
+ if (b_info->u.hvm.watchdog_action) {
+ flexarray_vappend(dm_args, "-watchdog-action", b_info->u.hvm.watchdog_action, NULL);
+ }
+ }
if (b_info->u.hvm.soundhw) {
flexarray_vappend(dm_args, "-soundhw", b_info->u.hvm.soundhw, NULL);
}
@@ -507,6 +513,12 @@ static char ** libxl__build_device_model
}
}
}
+ if (b_info->u.hvm.watchdog || b_info->u.hvm.watchdog_action) {
+ flexarray_append(dm_args, "-watchdog");
+ if (b_info->u.hvm.watchdog_action) {
+ flexarray_vappend(dm_args, "-watchdog-action", b_info->u.hvm.watchdog_action, NULL);
+ }
+ }
if (b_info->u.hvm.soundhw) {
flexarray_vappend(dm_args, "-soundhw", b_info->u.hvm.soundhw, NULL);
}
Index: xen-4.3.0-testing/tools/libxl/libxl_types.idl
===================================================================
--- xen-4.3.0-testing.orig/tools/libxl/libxl_types.idl
+++ xen-4.3.0-testing/tools/libxl/libxl_types.idl
@@ -332,6 +332,8 @@ libxl_domain_build_info = Struct("domain
("soundhw", string),
("xen_platform_pci", libxl_defbool),
("usbdevice_list", libxl_string_list),
+ ("watchdog", string),
+ ("watchdog_action", string),
])),
("pv", Struct(None, [("kernel", string),
("slack_memkb", MemKB),
Index: xen-4.3.0-testing/tools/libxl/xl_cmdimpl.c
===================================================================
--- xen-4.3.0-testing.orig/tools/libxl/xl_cmdimpl.c
+++ xen-4.3.0-testing/tools/libxl/xl_cmdimpl.c
@@ -1516,6 +1516,8 @@ skip_vfb:
xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
xlu_cfg_get_defbool(config, "xen_platform_pci",
&b_info->u.hvm.xen_platform_pci, 0);
+ xlu_cfg_replace_string (config, "watchdog", &b_info->u.hvm.watchdog, 0);
+ xlu_cfg_replace_string (config, "watchdog_action", &b_info->u.hvm.watchdog_action, 0);
if(b_info->u.hvm.vnc.listen
&& b_info->u.hvm.vnc.display
Index: xen-4.3.0-testing/tools/python/xen/xm/cpupool.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xm/cpupool.py
+++ xen-4.3.0-testing/tools/python/xen/xm/cpupool.py
@@ -157,9 +157,17 @@ def make_cpus_config(cfg_cpus):
# ["0,2","1,3"] -> [[0,2],[1,3]]
# ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]]
try:
- for c in cfg_cpus:
- cpus = cnv(c)
- cpus_list.append(cpus)
+ cpus_str = ""
+ list_len = len(cfg_cpus)
+ n = 0
+ while n < list_len:
+ if type(cfg_cpus[n]) != str:
+ raise SyntaxError('cpus = %s' % cfg_cpus)
+ cpus_str += cfg_cpus[n]
+ n += 1
+ if n < list_len:
+ cpus_str += ', '
+ cpus_list = cnv(cpus_str)
except ValueError, e:
raise err('cpus = %s: %s' % (cfg_cpus, e))
else:
Index: xen-4.3.0-testing/tools/python/xen/xend/server/netif.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/netif.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/netif.py
@@ -23,6 +23,7 @@
import os
import random
import re
+import commands
from xen.xend import XendOptions, sxp
from xen.xend.server.DevController import DevController
@@ -101,6 +102,14 @@ class NetifController(DevController):
def __init__(self, vm):
DevController.__init__(self, vm)
+ def createDevice(self, config):
+ bridge = config.get('bridge')
+ if bridge is not None:
+ bridge_result = commands.getstatusoutput("/sbin/ifconfig %s" % bridge)
+ if bridge_result[0] != 0:
+ raise VmError('Network bridge does not exist: %s' % bridge)
+ DevController.createDevice(self, config)
+
def getDeviceDetails(self, config):
"""@see DevController.getDeviceDetails"""
Index: xen-4.3.0-testing/tools/python/xen/util/pci.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/util/pci.py
+++ xen-4.3.0-testing/tools/python/xen/util/pci.py
@@ -20,6 +20,8 @@ from xen.xend import sxp
from xen.xend.XendConstants import AUTO_PHP_SLOT
from xen.xend.XendSXPDev import dev_dict_to_sxp
from xen.xend.XendLogging import log
+from xen.xend.xenstore.xstransact import xstransact
+from xen.xend.XendError import XendError
# for 2.3 compatibility
try:
@@ -27,9 +29,11 @@ try:
except NameError:
from sets import Set as set
+XS_PCIBACK_PATH = '/xm/pciback'
PROC_PCI_PATH = '/proc/bus/pci/devices'
PROC_PCI_NUM_RESOURCES = 7
+SYSFS_PCI_DRVS_PATH = 'bus/pci/drivers'
SYSFS_PCI_DEVS_PATH = '/bus/pci/devices'
SYSFS_PCI_DEV_RESOURCE_PATH = '/resource'
SYSFS_PCI_DEV_CONFIG_PATH = '/config'
@@ -161,7 +165,7 @@ def PCI_BDF(domain, bus, slot, func):
def check_pci_opts(opts):
def f((k, v)):
- if k not in ['msitranslate', 'power_mgmt'] or \
+ if k not in ['msitranslate', 'power_mgmt', 'managed'] or \
not v.lower() in ['0', '1', 'yes', 'no']:
raise PciDeviceParseError('Invalid pci option %s=%s: ' % (k, v))
@@ -427,6 +431,9 @@ def __pci_dict_to_fmt_str(fmt, dev):
def pci_dict_to_bdf_str(dev):
return __pci_dict_to_fmt_str('%04x:%02x:%02x.%01x', dev)
+def pci_dict_to_xs_bdf_str(dev):
+ return __pci_dict_to_fmt_str('%04x-%02x-%02x-%01x', dev)
+
def pci_dict_to_xc_str(dev):
return __pci_dict_to_fmt_str('0x%x, 0x%x, 0x%x, 0x%x', dev)
@@ -560,6 +567,115 @@ def find_all_assignable_devices():
dev_list = dev_list + [dev]
return dev_list
+def pci_assignable_add(dev):
+ '''detach pci device from driver that we need to unbind from and rebind
+ to pciback driver, then it can be assigned to guest.
+ '''
+ sysfs_mnt = find_sysfs_mnt()
+ pcidev_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH
+ pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
+
+ # See if the device exists
+ pci_bdf = pci_dict_to_bdf_str(dev)
+ path = pcidev_path + '/' + pci_bdf
+ if not os.path.exists(path):
+ log.debug("Pci device %s doesn't exist" % pci_bdf)
+ return -1
+
+ # Check to see if it's already assigned to pciback
+ path = pciback_path + '/' + pci_bdf
+ if os.path.exists(path):
+ log.debug("Pci device %s is already assigned to pciback" % pci_bdf)
+ return 0
+
+ # Check to see if there's already a driver that we need to unbind from
+ path = pcidev_path + '/' + pci_bdf + '/driver'
+ drv_path = None
+ if os.path.exists(path):
+ drv_path = os.path.realpath(path).replace(" ", "\ ")
+ cmd = 'echo %s > %s/unbind' % (pci_bdf, drv_path)
+ if os.system(cmd):
+ log.debug("Couldn't unbind device")
+ return -1;
+
+ # Store driver_path for rebinding to dom0
+ if drv_path is not None:
+ xs_pci_bdf = pci_dict_to_xs_bdf_str(dev)
+ path = XS_PCIBACK_PATH + '/' + xs_pci_bdf
+ xstransact.Mkdir(path)
+ xstransact.Write(path, 'driver_path', drv_path)
+ else:
+ log.debug("Not bound to a driver, will not be rebound")
+
+ # Bind to pciback
+ try:
+ # Scan through /sys/.../pciback/slots looking for pcidev's BDF
+ slots = os.popen('cat %s/slots' % pciback_path).read()
+ if re.search(pci_bdf, slots) is None:
+ # write bdf to new_slot
+ cmd = 'echo %s > %s/new_slot' % (pci_bdf, pciback_path)
+ if os.system(cmd):
+ raise XendError("Couldn't add device to pciback new_slot")
+
+ # Bind to pciback
+ cmd = 'echo %s > %s/bind' % (pci_bdf, pciback_path)
+ if os.system(cmd):
+ raise XendError("Couldn't bind device to pciback")
+ except XendError:
+ # rebind to original driver
+ if drv_path is not None:
+ log.debug("Rebind to original driver")
+ cmd = 'echo %s > %s/bind' % (pci_bdf, drv_path)
+ if os.system(cmd):
+ log.debug("Failed to rebind")
+ return -1
+
+ return 0
+
+def pci_assignable_remove(dev):
+ '''unbind pci device from pciback, and rebind to host pci driver where it
+ was detached from in pci-assignable-add.
+ '''
+ sysfs_mnt = find_sysfs_mnt()
+ pcidrv_path = sysfs_mnt + SYSFS_PCI_DRVS_PATH
+ pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
+ pci_bdf = pci_dict_to_bdf_str(dev)
+
+ # Unbind from pciback
+ path = pciback_path + '/' + pci_bdf
+ if os.path.exists(path):
+ # unbind
+ cmd = 'echo %s > %s/unbind' % (pci_bdf, pciback_path)
+ if os.system(cmd):
+ log.debug("Couldn't unbind device to pciback")
+ return -1
+
+ # remove slots if necessary
+ slots = os.popen('cat %s/slots' % pciback_path).read()
+ if re.search(pci_bdf, slots):
+ # write bdf to remove_slot
+ cmd = 'echo %s > %s/remove_slot' % (pci_bdf, pciback_path)
+ if os.system(cmd):
+ log.debug("Couldn't remove pciback slot")
+ return -1
+ else:
+ log.debug("Not bound to pciback")
+
+ # Rebind if necessary
+ xs_pci_bdf = pci_dict_to_xs_bdf_str(dev)
+ path = XS_PCIBACK_PATH + '/' + xs_pci_bdf
+ drv_path = xstransact.Read(path, 'driver_path')
+ if drv_path:
+ cmd = 'echo %s > %s/bind' % (pci_bdf, drv_path)
+ if os.system(cmd):
+ log.debug("Couldn't rebind to driver %s" % drv_path)
+ return -1
+ xstransact.Remove(path)
+ else:
+ log.debug("Counldn't find path for original driver. Not rebinding")
+
+ return 0
+
def transform_list(target, src):
''' src: its element is pci string (Format: xxxx:xx:xx.x).
target: its element is pci string, or a list of pci string.
Index: xen-4.3.0-testing/tools/python/xen/xend/server/pciif.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/pciif.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/pciif.py
@@ -86,6 +86,48 @@ def get_all_assigned_pci_devices(domid =
pci_str_list = pci_str_list + get_assigned_pci_devices(int(d))
return pci_str_list
+def reattach_host_pci_devices(devconfig):
+ pci_dev_list = devconfig.get('devs', [])
+ for pci_dev in pci_dev_list:
+ managed = 0
+ pci_opts_config = pci_dev.get('opts', [])
+ for opt in pci_opts_config:
+ if opt[0] == 'managed':
+ managed = opt[1]
+ if managed:
+ if pci_assignable_remove(pci_dev) != 0:
+ raise VmError('pci_assignable_remove failed')
+
+def detach_host_pci_devices(devconfig):
+ pci_dev_list = devconfig.get('devs', [])
+ reattach = 0
+ for pci_dev in pci_dev_list:
+ managed = 0
+ pci_opts_config = pci_dev.get('opts', [])
+ for opt in pci_opts_config:
+ if opt[0] == 'managed':
+ managed = opt[1]
+ if managed:
+ if pci_assignable_add(pci_dev) != 0:
+ log.debug('pci_assignable_add failed')
+ reattach = 1
+ break
+
+ if reattach:
+ reattach_host_pci_devices(devconfig)
+ raise VmError('detach_host_pci_devices failed')
+
+def prepare_host_pci_devices(devconfig):
+ # Test whether the device used by other domain
+ pci_dev_list = devconfig.get('devs', [])
+ for pci_dev in pci_dev_list:
+ pci_name = pci_dict_to_bdf_str(pci_dev)
+ if pci_name in get_all_assigned_pci_devices():
+ raise VmError("failed to assign device %s that has"
+ " already been assigned to other domain." % pci_name)
+ # Detach 'managed' devices
+ detach_host_pci_devices(devconfig)
+
class PciController(DevController):
def __init__(self, vm):
Index: xen-4.3.0-testing/tools/python/xen/lowlevel/xc/xc.c
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/lowlevel/xc/xc.c
+++ xen-4.3.0-testing/tools/python/xen/lowlevel/xc/xc.c
@@ -954,18 +954,23 @@ static PyObject *pyxc_hvm_build(XcObject
struct hvm_info_table *va_hvm;
uint8_t *va_map, sum;
#endif
- int i;
- char *image;
+ int i, datalen;
+ char *image, *smbios_str, *acpi_str;
int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1;
+ PyObject *acpi_firmware = NULL;
+ PyObject *smbios_firmware = NULL;
PyObject *vcpu_avail_handle = NULL;
uint8_t vcpu_avail[(HVM_MAX_VCPUS + 7)/8];
+ struct xc_hvm_build_args hvm_args = {};
static char *kwd_list[] = { "domid",
"memsize", "image", "target", "vcpus",
- "vcpu_avail", "acpi", "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiOii", kwd_list,
+ "vcpu_avail", "acpi", "apic",
+ "smbios_firmware", "acpi_firmware", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiOiiOO", kwd_list,
&dom, &memsize, &image, &target, &vcpus,
- &vcpu_avail_handle, &acpi, &apic) )
+ &vcpu_avail_handle, &acpi,
+ &apic, &smbios_firmware, &acpi_firmware) )
return NULL;
memset(vcpu_avail, 0, sizeof(vcpu_avail));
@@ -996,8 +1001,38 @@ static PyObject *pyxc_hvm_build(XcObject
if ( target == -1 )
target = memsize;
- if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize,
- target, image) != 0 )
+ memset(&hvm_args, 0, sizeof(struct xc_hvm_build_args));
+ hvm_args.mem_size = (uint64_t)memsize << 20;
+ hvm_args.mem_target = (uint64_t)target << 20;
+ hvm_args.image_file_name = image;
+
+ if ( PyString_Check(smbios_firmware ) )
+ {
+ smbios_str = PyString_AsString(smbios_firmware);
+ if ( smbios_str )
+ {
+ datalen = *(int *)smbios_str;
+ if ( datalen ) {
+ hvm_args.smbios_module.data = &((uint8_t *)smbios_str)[4];
+ hvm_args.smbios_module.length = (uint32_t)datalen;
+ }
+ }
+ }
+
+ if ( PyString_Check(acpi_firmware ) )
+ {
+ acpi_str = PyString_AsString(acpi_firmware);
+ if (acpi_str)
+ {
+ datalen = *(int *)acpi_str;
+ if ( datalen ) {
+ hvm_args.acpi_module.data = &((uint8_t *)acpi_str)[4];
+ hvm_args.acpi_module.length = (uint32_t)datalen;
+ }
+ }
+ }
+
+ if ( xc_hvm_build(self->xc_handle, dom, &hvm_args) != 0 )
return pyxc_error_to_exception(self->xc_handle);
#if !defined(__ia64__)
Index: xen-4.3.0-testing/tools/python/README.sxpcfg
===================================================================
--- xen-4.3.0-testing.orig/tools/python/README.sxpcfg
+++ xen-4.3.0-testing/tools/python/README.sxpcfg
@@ -51,6 +51,11 @@ image
- vncunused
(HVM)
- device_model
+ - actmem
+ - xenpaging_file
+ - xenpaging_extra
+ - smbios_firmware
+ - acpi_firmware
- display
- xauthority
- vncconsole
Index: xen-4.3.0-testing/tools/python/README.XendConfig
===================================================================
--- xen-4.3.0-testing.orig/tools/python/README.XendConfig
+++ xen-4.3.0-testing/tools/python/README.XendConfig
@@ -118,6 +118,11 @@ otherConfig
image.vncdisplay
image.vncunused
image.hvm.device_model
+ image.hvm.actmem
+ image.hvm.xenpaging_file
+ image.hvm.xenpaging_extra
+ image.hvm.smbios_firmware
+ image.hvm.apci_firmware
image.hvm.display
image.hvm.xauthority
image.hvm.vncconsole
Index: xen-4.3.0-testing/tools/hotplug/Linux/domain-lock
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/hotplug/Linux/domain-lock
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+basedir=$(dirname "$0")
+
+usage() {
+ echo "usage: domain-lock [-l|-u] -n <vm name> -i <vm uuid> -p <physical host> path"
+ echo "usage: domain-lock [-s] -i <vm uuid> path"
+ echo ""
+ echo "-l lock"
+ echo "-u unlock"
+ echo "-s status (default)"
+ echo "-n Virtual Machine name"
+ echo "-i Virtual Machine Id or UUID"
+ echo "-p Virtual Machine Server (physical host) name"
+ echo "path A per-VM, unique location where external lock will be managed"
+ exit 1
+}
+
+remove_lock(){
+ local path=$1/lock
+ local name=$2
+
+ pid=`ps -efwww | grep vm-monitor | grep $name | awk '{print $2}'`
+ if [ -n "$pid" ]; then
+ kill $pid
+ rm -f $path
+ fi
+}
+
+get_status(){
+ local path=$1/lock
+ [ -f $path ] || exit 1
+
+ rc=`flock -xn $path /bin/true`
+ cat $path
+ exit $rc
+}
+
+mode="status"
+
+while getopts ":lusn:i:p:" opt; do
+ case $opt in
+ l )
+ mode="lock"
+ ;;
+ u )
+ mode="unlock"
+ ;;
+ s )
+ mode="status"
+ ;;
+ p )
+ vm_host=$OPTARG
+ ;;
+ n )
+ vm_name=$OPTARG
+ ;;
+ i )
+ vm_uuid=$OPTARG
+ ;;
+ \? )
+ usage
+ ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+vm_path=$1
+
+case $mode in
+ lock )
+ [ -z "$vm_path" ] || [ -z "$vm_name" ] || [ -z "$vm_uuid" ] || [ -z "$vm_host" ] && usage
+ $basedir/set-lock $vm_path $vm_name $vm_uuid $vm_host
+ ;;
+ unlock )
+ [ -z "$vm_path" ] || [ -z "$vm_name" ] || [ -z "$vm_uuid" ] || [ -z "$vm_host" ] && usage
+ remove_lock $vm_path $vm_name $vm_uuid $vm_host
+ ;;
+ status )
+ [ -z "$vm_path" ] && usage
+ get_status $vm_path
+ ;;
+esac
Index: xen-4.3.0-testing/tools/hotplug/Linux/vm-monitor
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/hotplug/Linux/vm-monitor
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+basedir=$(dirname "$0")
+HA_TICK=2
+
+monitor() {
+ local path=$1
+ local name=$2
+ local uuid=$3
+ local host=$4
+ local count=0
+ path=$path/lock
+
+ while :
+ do
+ echo "name=$name uuid=$uuid host=$host count=$count" > $path
+ count=$(($count+1))
+ sleep $HA_TICK
+ done&
+}
+
+create_lock() {
+ local path=$1/lock
+ local rc=0
+
+ [ -f $path ] || touch $path
+ flock -x -w $HA_TICK $path $basedir/vm-monitor $*
+ rc=$?
+ if [ $rc -eq 1 ]; then
+ echo `cat $path`
+ exit 1
+ else
+ exit $rc
+ fi
+}
+
+if [ $0 = "$basedir/set-lock" ]; then
+ create_lock $*
+elif [ $0 = "$basedir/vm-monitor" ]; then
+ monitor $*
+fi
Index: xen-4.3.0-testing/tools/python/xen/xend/XendOptions.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/XendOptions.py
+++ xen-4.3.0-testing/tools/python/xen/xend/XendOptions.py
@@ -154,6 +154,20 @@ class XendOptions:
use loose check automatically if necessary."""
pci_dev_assign_strict_check_default = True
+ """Default for the flag indicating whether xend should create
+ a lock file for domains when they are started."""
+ xend_domain_lock = 'no'
+
+ """Default domain lock storage path."""
+ xend_domain_lock_path_default = '/var/lib/xen/images/vm_locks'
+
+ """Default script to acquire/release domain lock"""
+ xend_domain_lock_utility = auxbin.scripts_dir() + "/domain-lock"
+
+ """Default block device for lock service"""
+ xend_domain_lock_device = ""
+
+
def __init__(self):
self.configure()
@@ -401,6 +415,26 @@ class XendOptions:
else:
return None
+ def get_xend_domain_lock(self):
+ """Get the flag indicating whether xend should create a lock file
+ for domains when they are started."""
+ return self.get_config_bool("xend-domain-lock", self.xend_domain_lock)
+
+ def get_xend_domain_lock_path(self):
+ """ Get the path for domain lock storage
+ """
+ return self.get_config_string("xend-domain-lock-path", self.xend_domain_lock_path_default)
+
+ def get_xend_domain_lock_utility(self):
+ s = self.get_config_string('xend-domain-lock-utility')
+
+ if s:
+ return os.path.join(auxbin.scripts_dir(), s)
+ else:
+ return self.xend_domain_lock_utility
+
+ def get_xend_domain_lock_device(self):
+ return self.get_config_string('xend-domain-lock-device', self.xend_domain_lock_device)
def get_vnc_tls(self):
return self.get_config_string('vnc-tls', self.xend_vnc_tls)
Index: xen-4.3.0-testing/tools/hotplug/Linux/domain-lock-sfex
===================================================================
--- /dev/null
+++ xen-4.3.0-testing/tools/hotplug/Linux/domain-lock-sfex
@@ -0,0 +1,166 @@
+#!/bin/bash
+
+# pre-condition
+# 1. device is ready: logical volume activated if used
+# 2. device already initialized
+# 3. index is assigned correctly
+
+#error code:
+# 0: success
+# 1: error
+
+if [ `uname -m` = "x86_64" ]; then
+ SFEX_DAEMON=/usr/lib64/heartbeat/sfex_daemon
+else
+ SFEX_DAEMON=/usr/lib/heartbeat/sfex_daemon
+fi
+SFEX_INIT=/usr/sbin/sfex_init
+COLLISION_TIMEOUT=1
+LOCK_TIMEOUT=3
+MONITOR_INTERVAL=2
+LOCAL_LOCK_FILE=/var/lock/sfex
+
+usage() {
+ echo "usage: domain-lock-sfex [-l|-u|-s] -i <vm uuid> -x <sfex device>"
+ echo ""
+ echo "-l lock"
+ echo "-u unlock"
+ echo "-s status (default)"
+ echo "-i Virtual Machine Id or UUID"
+ echo "-x SFEX device which used for sfex lock"
+ exit 1
+}
+
+get_lock_host() {
+ local rscname=$1
+ local device=$2
+ r=`$SFEX_DAEMON -s -u $rscname $device`
+ echo $r
+}
+
+get_status() {
+ local rscname=$1
+ if /usr/bin/pgrep -f "$SFEX_DAEMON .* ${rscname} " > /dev/null 2>&1; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+acquire_lock() {
+ local rscname=$1
+ local device=$2
+ get_status $rscname
+ ## We assume xend will take care to avoid starting same VM twice on the same machine.
+ if [ $? -eq 0 ]; then
+ return 0
+ fi
+ $SFEX_DAEMON -c $COLLISION_TIMEOUT -t $LOCK_TIMEOUT -m $MONITOR_INTERVAL -u $rscname $device
+ rc=$?
+ if [ $rc -ne 0 ]; then
+ return $rc
+ fi
+ sleep 4
+ get_status $rscname
+ if [ $? -eq 0 ]; then
+ return 0
+ fi
+ return 1
+}
+
+# release has to success
+release_lock(){
+ local rscname=$1
+
+ ## If the lock is already released
+ get_status $rscname
+ if [ $? -ne 0 ]; then
+ return 0
+ fi
+
+ pid=`/usr/bin/pgrep -f "$SFEX_DAEMON .* ${rscname} "`
+ /bin/kill $pid
+
+ count=0
+ while [ $count -lt 10 ]
+ do
+ get_status $rscname
+ if [ $? -eq 1 ]; then
+ return 0
+ fi
+ count=`expr $count + 1`
+ sleep 1
+ done
+
+ /bin/kill -9 $pid
+ while :
+ do
+ get_status $rscname
+ if [ $? -eq 1 ]; then
+ break;
+ fi
+ sleep 1
+ done
+
+ return 0
+}
+
+mode="status"
+
+while getopts ":lusn:i:p:x:" opt; do
+case $opt in
+l )
+mode="lock"
+;;
+u )
+mode="unlock"
+;;
+s )
+mode="status"
+;;
+n )
+vm_name=$OPTARG
+;;
+i )
+vm_uuid=$OPTARG
+;;
+p )
+vm_host=$OPTARG
+;;
+x )
+vm_sfex_device=$OPTARG
+;;
+\? )
+usage
+;;
+esac
+done
+
+shift $(($OPTIND - 1))
+[ -z $vm_uuid ] && usage
+[ -z $vm_sfex_device ] && usage
+
+case $mode in
+lock )
+ (
+ flock -x 200
+ acquire_lock $vm_uuid $vm_sfex_device
+ rc=$?
+ flock -u 200
+ exit $rc
+ ) 200>$LOCAL_LOCK_FILE-$vm_uuid
+;;
+unlock )
+ (
+ flock -x 200
+ release_lock $vm_uuid
+ rc=$?
+ flock -u 200
+ exit $rc
+ ) 200>$LOCAL_LOCK_FILE-$vm_uuid
+;;
+status )
+ get_lock_host $vm_uuid $vm_sfex_device
+;;
+esac
+
Index: xen-4.3.0-testing/tools/python/xen/xend/server/BlktapController.py
===================================================================
--- xen-4.3.0-testing.orig/tools/python/xen/xend/server/BlktapController.py
+++ xen-4.3.0-testing/tools/python/xen/xend/server/BlktapController.py
@@ -15,6 +15,7 @@ blktap1_disk_types = [
'ram',
'qcow',
'qcow2',
+ 'cdrom',
'ioemu',
]
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-xen.h
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/qemu-xen.h
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/qemu-xen.h
@@ -1,6 +1,8 @@
#ifndef QEMU_XEN_H
#define QEMU_XEN_H
+#include "hw/boards.h"
+
/* vl.c */
extern int restore;
extern int vga_ram_size;
@@ -47,6 +49,7 @@ void unset_vram_mapping(void *opaque);
#endif
void pci_unplug_netifs(void);
+void pci_unplug_scsi(void);
void destroy_hvm_domain(void);
void unregister_iomem(target_phys_addr_t start);
@@ -64,7 +67,7 @@ void handle_buffered_pio(void);
/* xenstore.c */
void xenstore_init(void);
uint32_t xenstore_read_target(void);
-void xenstore_parse_domain_config(int domid);
+void xenstore_parse_domain_config(int domid, QEMUMachine *machine);
int xenstore_parse_disable_pf_config(void);
int xenstore_fd(void);
void xenstore_process_event(void *opaque);
Index: xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/pci.c
===================================================================
--- xen-4.3.0-testing.orig/tools/qemu-xen-traditional-dir-remote/hw/pci.c
+++ xen-4.3.0-testing/tools/qemu-xen-traditional-dir-remote/hw/pci.c
@@ -871,6 +871,50 @@ void pci_unplug_netifs(void)
}
}
+void pci_unplug_scsi(void)
+{
+ PCIBus *bus;
+ PCIDevice *dev;
+ PCIIORegion *region;
+ int x;
+ int i;
+
+ /* We only support one PCI bus */
+ for (bus = first_bus; bus; bus = NULL) {
+ for (x = 0; x < 256; x++) {
+ dev = bus->devices[x];
+ if (dev &&
+ dev->config[0xa] == 0 &&
+ dev->config[0xb] == 1
+#ifdef CONFIG_PASSTHROUGH
+ && test_pci_devfn(x) != 1
+#endif
+ ) {
+ /* Found a scsi disk. Remove it from the bus. Note that
+ we don't free it here, since there could still be
+ references to it floating around. There are only
+ ever one or two structures leaked, and it's not
+ worth finding them all. */
+ bus->devices[x] = NULL;
+ for (i = 0; i < PCI_NUM_REGIONS; i++) {
+ region = &dev->io_regions[i];
+ if (region->addr == (uint32_t)-1 ||
+ region->size == 0)
+ continue;
+ fprintf(logfile, "region type %d at [%x,%x).\n",
+ region->type, region->addr,
+ region->addr+region->size);
+ if (region->type == PCI_ADDRESS_SPACE_IO) {
+ isa_unassign_ioport(region->addr, region->size);
+ } else if (region->type == PCI_ADDRESS_SPACE_MEM) {
+ unregister_iomem(region->addr);
+ }
+ }
+ }
+ }
+ }
+}
+
typedef struct {
PCIDevice dev;
PCIBus *bus;
Index: xen-4.3.0-testing/tools/examples/xmexample.hvm
===================================================================
--- xen-4.3.0-testing.orig/tools/examples/xmexample.hvm
+++ xen-4.3.0-testing/tools/examples/xmexample.hvm
@@ -142,6 +142,15 @@ disk = [ 'file:/var/lib/xen/images/disk.
# Device Model to be used
device_model = 'qemu-dm'
+# the amount of memory in MiB for the guest
+#actmem=42
+
+# Optional: guest page file
+#xenpaging_file="/var/lib/xen/xenpaging/<domain_name>.<domaind_id>.paging"
+
+# Optional: extra cmdline options for xenpaging
+#xenpaging_extra=[ 'string', 'string' ]
+
#-----------------------------------------------------------------------------
# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d)
# default: hard disk, cd-rom, floppy