aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2007-09-27 12:22:16 -0600
committerAlex Williamson <alex.williamson@hp.com>2007-09-27 12:22:16 -0600
commit265e5c6b08e411d36c173f1c08b3ffe8b747f7eb (patch)
tree990c4f947485ebd192af3bc03b4e47e6678efee5 /tools
parent1169dee6d4e25e1eceff1257562ab33e21032950 (diff)
parent9f5581fda701ef44f339bda7462907de5e85ede8 (diff)
downloadxen-265e5c6b08e411d36c173f1c08b3ffe8b747f7eb.tar.gz
xen-265e5c6b08e411d36c173f1c08b3ffe8b747f7eb.tar.bz2
xen-265e5c6b08e411d36c173f1c08b3ffe8b747f7eb.zip
merge with xen-unstable.hg (staging)
Diffstat (limited to 'tools')
-rwxr-xr-xtools/check/check_crypto_lib8
-rwxr-xr-xtools/check/check_zlib_lib8
-rw-r--r--tools/console/client/main.c6
-rw-r--r--tools/console/daemon/utils.c1
-rw-r--r--tools/examples/blktap2
-rwxr-xr-xtools/examples/network-bridge1
-rwxr-xr-xtools/firmware/hvmloader/mkhex2
-rw-r--r--tools/firmware/rombios/32bit/Makefile2
-rw-r--r--tools/firmware/rombios/32bit/mkhex2
-rw-r--r--tools/firmware/rombios/32bit/tcgbios/tcgbios.c43
-rw-r--r--tools/firmware/vmxassist/vm86.c5
-rw-r--r--tools/include/NetBSD/evtchn.h89
-rw-r--r--tools/include/NetBSD/privcmd.h105
-rw-r--r--tools/ioemu/Makefile.target10
-rw-r--r--tools/ioemu/audio/audio.c4
-rw-r--r--tools/ioemu/audio/mixeng.c4
-rw-r--r--tools/ioemu/audio/ossaudio.c7
-rw-r--r--tools/ioemu/block-raw.c35
-rw-r--r--tools/ioemu/block-vvfat.c2
-rw-r--r--tools/ioemu/bswap.h7
-rw-r--r--tools/ioemu/cutils.c6
-rw-r--r--tools/ioemu/hw/fdc.c9
-rw-r--r--tools/ioemu/hw/ne2000.c8
-rw-r--r--tools/ioemu/hw/pass-through.c454
-rw-r--r--tools/ioemu/hw/pass-through.h89
-rw-r--r--tools/ioemu/hw/pc.c27
-rw-r--r--tools/ioemu/hw/sb16.c6
-rw-r--r--tools/ioemu/monitor.c38
-rw-r--r--tools/ioemu/osdep.h4
-rw-r--r--tools/ioemu/target-i386-dm/exec-dm.c4
-rw-r--r--tools/ioemu/usb-linux.c2
-rw-r--r--tools/ioemu/vl.c96
-rw-r--r--tools/ioemu/vl.h6
-rw-r--r--tools/ioemu/vnc.c3
-rw-r--r--tools/libaio/src/compat-0_1.c2
-rw-r--r--tools/libfsimage/ext2fs/fsys_ext2fs.c6
-rw-r--r--tools/libfsimage/fat/fsys_fat.c12
-rw-r--r--tools/libfsimage/iso9660/fsys_iso9660.c2
-rw-r--r--tools/libfsimage/reiserfs/fsys_reiserfs.c6
-rw-r--r--tools/libfsimage/ufs/fsys_ufs.c4
-rw-r--r--tools/libxc/Makefile1
-rw-r--r--tools/libxc/xc_core.c3
-rw-r--r--tools/libxc/xc_core_x86.c3
-rw-r--r--tools/libxc/xc_dom_boot.c5
-rw-r--r--tools/libxc/xc_dom_core.c4
-rw-r--r--tools/libxc/xc_domain.c108
-rw-r--r--tools/libxc/xc_domain_restore.c216
-rw-r--r--tools/libxc/xc_domain_save.c224
-rw-r--r--tools/libxc/xc_netbsd.c271
-rw-r--r--tools/libxc/xc_private.c95
-rw-r--r--tools/libxc/xc_resume.c13
-rw-r--r--tools/libxc/xenctrl.h39
-rw-r--r--tools/libxc/xg_private.h27
-rw-r--r--tools/libxc/xg_save_restore.h83
-rw-r--r--tools/libxen/include/xen/api/xen_all.h1
-rw-r--r--tools/pygrub/src/GrubConf.py28
-rw-r--r--tools/pygrub/src/LiloConf.py18
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c1
-rw-r--r--tools/python/xen/lowlevel/xs/xs.c1
-rw-r--r--tools/python/xen/util/bootloader.py156
-rw-r--r--tools/python/xen/util/xsm/acm/acm.py28
-rw-r--r--tools/python/xen/util/xsm/dummy/dummy.py4
-rw-r--r--tools/python/xen/util/xsm/flask/flask.py4
-rw-r--r--tools/python/xen/xend/XendConfig.py23
-rw-r--r--tools/python/xen/xend/XendDomain.py15
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py58
-rw-r--r--tools/python/xen/xend/balloon.py16
-rw-r--r--tools/python/xen/xend/image.py2
-rw-r--r--tools/python/xen/xend/server/netif.py8
-rw-r--r--tools/python/xen/xm/create.py2
-rw-r--r--tools/python/xen/xm/main.py8
-rw-r--r--tools/python/xen/xm/xenapi_create.py9
-rw-r--r--tools/vtpm/tpm_emulator.patch32
-rw-r--r--tools/vtpm_manager/tcs/tcs.c2
-rw-r--r--tools/xenmon/xenbaked.c603
-rw-r--r--tools/xenstat/libxenstat/Makefile1
-rw-r--r--tools/xenstat/libxenstat/src/xenstat_netbsd.c97
-rw-r--r--tools/xenstat/xentop/xentop.c9
-rw-r--r--tools/xenstore/Makefile1
-rw-r--r--tools/xenstore/xenstored_netbsd.c73
-rw-r--r--tools/xentrace/xentrace.c136
-rw-r--r--tools/xm-test/lib/XmTestLib/acm.py2
82 files changed, 2778 insertions, 779 deletions
diff --git a/tools/check/check_crypto_lib b/tools/check/check_crypto_lib
index 8002f1d109..4717cca7f9 100755
--- a/tools/check/check_crypto_lib
+++ b/tools/check/check_crypto_lib
@@ -3,6 +3,14 @@
RC=0
+case $(uname -s) in
+FreeBSD|NetBSD|OpenBSD)
+ exit 0
+ ;;
+*)
+ ;;
+esac
+
PATH=/sbin:$PATH
set -e
ldconfig -p 2>&1 | grep -q libcrypto.so || RC=1
diff --git a/tools/check/check_zlib_lib b/tools/check/check_zlib_lib
index 4e7282f618..a4231d606a 100755
--- a/tools/check/check_zlib_lib
+++ b/tools/check/check_zlib_lib
@@ -3,6 +3,14 @@
RC=0
+case $(uname -s) in
+FreeBSD|NetBSD|OpenBSD)
+ exit 0
+ ;;
+*)
+ ;;
+esac
+
PATH=/sbin:$PATH
set -e
diff --git a/tools/console/client/main.c b/tools/console/client/main.c
index b7a45212a0..509e44bf91 100644
--- a/tools/console/client/main.c
+++ b/tools/console/client/main.c
@@ -34,7 +34,7 @@
#include <sys/select.h>
#include <err.h>
#include <errno.h>
-#include <pty.h>
+#include <string.h>
#include "xs.h"
@@ -113,9 +113,8 @@ static void init_term(int fd, struct termios *old)
{
struct termios new_term;
- if (tcgetattr(fd, old) == -1) {
+ if (tcgetattr(fd, old) == -1)
return;
- }
new_term = *old;
cfmakeraw(&new_term);
@@ -289,6 +288,7 @@ int main(int argc, char **argv)
err(errno, "Could not read tty from store");
}
+ init_term(spty, &attr);
init_term(STDIN_FILENO, &attr);
console_loop(spty, xs, path);
restore_term(STDIN_FILENO, &attr);
diff --git a/tools/console/daemon/utils.c b/tools/console/daemon/utils.c
index 6697e13527..657bfa0cde 100644
--- a/tools/console/daemon/utils.c
+++ b/tools/console/daemon/utils.c
@@ -32,6 +32,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
+#include <signal.h>
#include "xenctrl.h"
#include "utils.h"
diff --git a/tools/examples/blktap b/tools/examples/blktap
index b3a0b63544..bd914d5858 100644
--- a/tools/examples/blktap
+++ b/tools/examples/blktap
@@ -73,7 +73,7 @@ fi
if [ -L "$p" ]; then
file=$(readlink -f "$p") || ebusy "$p link does not exist."
else
- [ -f "$p" ] || { ebusy "$p file does not exist." }
+ [ -f "$p" ] || { ebusy "$p file does not exist."; }
file="$p"
fi
diff --git a/tools/examples/network-bridge b/tools/examples/network-bridge
index b0b318b7fd..5440f51c1e 100755
--- a/tools/examples/network-bridge
+++ b/tools/examples/network-bridge
@@ -58,6 +58,7 @@ evalVariables "$@"
netdev=${netdev:-$(ip route list | awk '/^default / { print $NF }' |
sed 's/.* dev //')}
+netdev=${netdev:-eth0}
bridge=${bridge:-${netdev}}
antispoof=${antispoof:-no}
diff --git a/tools/firmware/hvmloader/mkhex b/tools/firmware/hvmloader/mkhex
index 7389d70483..4517e36c53 100755
--- a/tools/firmware/hvmloader/mkhex
+++ b/tools/firmware/hvmloader/mkhex
@@ -21,6 +21,6 @@
#
echo "unsigned $1[] = {"
-od -v -t x $2 | sed 's/^[0-9]* /0x/' | sed 's/ /, 0x/g' | sed 's/$/,/'
+od -v -t x $2 | sed 's/^[0-9]* */0x/' | sed 's/ */, 0x/g' | sed 's/$/,/' | sed 's/0x,//' | sed 's/^[0-9]*,//'
echo "};"
diff --git a/tools/firmware/rombios/32bit/Makefile b/tools/firmware/rombios/32bit/Makefile
index 1cd7100ae9..0a17154a43 100644
--- a/tools/firmware/rombios/32bit/Makefile
+++ b/tools/firmware/rombios/32bit/Makefile
@@ -39,4 +39,4 @@ $(TARGET): subdirs 32bitbios.o util.o
nm -u 32bitbios_all.o; \
exit 11; \
} || :
- bash mkhex highbios_array 32bitbios_all.o > $@
+ sh mkhex highbios_array 32bitbios_all.o > $@
diff --git a/tools/firmware/rombios/32bit/mkhex b/tools/firmware/rombios/32bit/mkhex
index 7389d70483..4517e36c53 100644
--- a/tools/firmware/rombios/32bit/mkhex
+++ b/tools/firmware/rombios/32bit/mkhex
@@ -21,6 +21,6 @@
#
echo "unsigned $1[] = {"
-od -v -t x $2 | sed 's/^[0-9]* /0x/' | sed 's/ /, 0x/g' | sed 's/$/,/'
+od -v -t x $2 | sed 's/^[0-9]* */0x/' | sed 's/ */, 0x/g' | sed 's/$/,/' | sed 's/0x,//' | sed 's/^[0-9]*,//'
echo "};"
diff --git a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c
index e4483982c4..c9b10f8327 100644
--- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c
@@ -260,31 +260,44 @@ uint8_t acpi_validate_entry(struct acpi_header *hdr)
}
+/*
+ * Search for the RSDP ACPI table in the memory starting at addr and
+ * ending at addr + len - 1.
+ */
+static struct acpi_20_rsdp *find_rsdp(const void *start, unsigned int len)
+{
+ char *rsdp = (char *)start;
+ char *end = rsdp + len;
+ /* scan memory in steps of 16 bytes */
+ while (rsdp < end) {
+ /* check for expected string */
+ if (!strncmp( rsdp, "RSD PTR ", 8))
+ return (struct acpi_20_rsdp *)rsdp;
+ rsdp += 0x10;
+ }
+ return 0;
+}
+
void tcpa_acpi_init(void)
{
struct acpi_20_rsdt *rsdt;
- uint32_t length;
struct acpi_20_tcpa *tcpa = (void *)0;
- uint16_t found = 0;
- uint16_t rsdp_off;
+ struct acpi_20_rsdp *rsdp;
+ uint32_t length;
uint16_t off;
- struct acpi_20_rsdp *rsdp = (void *)0;
+ int found = 0;
+ uint16_t ebda_seg;
if (MA_IsTPMPresent() == 0) {
return;
}
- /* scan memory in steps of 16 bytes in the ACPI_SEGMENT segment */
- found = 0;
- for (rsdp_off = 0; rsdp_off < 0xfff0; rsdp_off += 0x10) {
- char *_rsdp = (char *)(ACPI_SEGMENT << 4);
- /* check for expected string */
- if (!strncmp( &_rsdp[rsdp_off], "RSD PTR ", 8)) {
- found = 1;
- rsdp = (struct acpi_20_rsdp *)&_rsdp[rsdp_off];
- break;
- }
- }
+ /* RSDP in EBDA? */
+ ebda_seg = *(uint16_t *)ADDR_FROM_SEG_OFF(0x40, 0xe);
+ rsdp = find_rsdp((void *)(ebda_seg << 16), 1024);
+
+ if (!rsdp)
+ rsdp = find_rsdp((void *)(ACPI_SEGMENT << 4), 0x20000);
if (rsdp) {
uint32_t ctr = 0;
diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c
index 0ac9ed51df..772af1bf8c 100644
--- a/tools/firmware/vmxassist/vm86.c
+++ b/tools/firmware/vmxassist/vm86.c
@@ -1622,6 +1622,11 @@ opcode(struct regs *regs)
TRACE((regs, regs->eip - eip, "lock"));
continue;
+ case 0xF4: /* hlt */
+ TRACE((regs, regs->eip - eip, "hlt"));
+ /* Do something power-saving here! */
+ return OPC_EMULATED;
+
case 0xF6: /* addr32 testb $imm, r/m8 */
if (!(prefix & ADDR32))
goto invalid;
diff --git a/tools/include/NetBSD/evtchn.h b/tools/include/NetBSD/evtchn.h
new file mode 100644
index 0000000000..dc30e815dc
--- /dev/null
+++ b/tools/include/NetBSD/evtchn.h
@@ -0,0 +1,89 @@
+/* $NetBSD: evtchn.h,v 1.1.1.1 2007/06/14 19:39:45 bouyer Exp $ */
+/******************************************************************************
+ * evtchn.h
+ *
+ * Interface to /dev/xen/evtchn.
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __NetBSD_EVTCHN_H__
+#define __NetBSD_EVTCHN_H__
+
+/*
+ * Bind a fresh port to VIRQ @virq.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_VIRQ \
+ _IOWR('E', 4, struct ioctl_evtchn_bind_virq)
+struct ioctl_evtchn_bind_virq {
+ unsigned int virq;
+ unsigned int port;
+};
+
+/*
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
+ _IOWR('E', 5, struct ioctl_evtchn_bind_interdomain)
+struct ioctl_evtchn_bind_interdomain {
+ unsigned int remote_domain, remote_port;
+ unsigned int port;
+};
+
+/*
+ * Allocate a fresh port for binding to @remote_domain.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
+ _IOWR('E', 6, struct ioctl_evtchn_bind_unbound_port)
+struct ioctl_evtchn_bind_unbound_port {
+ unsigned int remote_domain;
+ unsigned int port;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_UNBIND \
+ _IOW('E', 7, struct ioctl_evtchn_unbind)
+struct ioctl_evtchn_unbind {
+ unsigned int port;
+};
+
+/*
+ * Send event to previously allocated @port.
+ */
+#define IOCTL_EVTCHN_NOTIFY \
+ _IOW('E', 8, struct ioctl_evtchn_notify)
+struct ioctl_evtchn_notify {
+ unsigned int port;
+};
+
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET \
+ _IO('E', 9)
+
+#endif /* __NetBSD_EVTCHN_H__ */
diff --git a/tools/include/NetBSD/privcmd.h b/tools/include/NetBSD/privcmd.h
new file mode 100644
index 0000000000..d670b41475
--- /dev/null
+++ b/tools/include/NetBSD/privcmd.h
@@ -0,0 +1,105 @@
+/* NetBSD: xenio.h,v 1.3 2005/05/24 12:07:12 yamt Exp $ */
+
+/******************************************************************************
+ * privcmd.h
+ *
+ * Copyright (c) 2003-2004, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __NetBSD_PRIVCMD_H__
+#define __NetBSD_PRIVCMD_H__
+
+/* Interface to /proc/xen/privcmd */
+
+typedef struct privcmd_hypercall
+{
+ unsigned long op;
+ unsigned long arg[5];
+} privcmd_hypercall_t;
+
+typedef struct privcmd_mmap_entry {
+ unsigned long va;
+ unsigned long mfn;
+ unsigned long npages;
+} privcmd_mmap_entry_t;
+
+typedef struct privcmd_mmap {
+ int num;
+ domid_t dom; /* target domain */
+ privcmd_mmap_entry_t *entry;
+} privcmd_mmap_t;
+
+typedef struct privcmd_mmapbatch {
+ int num; /* number of pages to populate */
+ domid_t dom; /* target domain */
+ unsigned long addr; /* virtual address */
+ unsigned long *arr; /* array of mfns - top nibble set on err */
+} privcmd_mmapbatch_t;
+
+typedef struct privcmd_blkmsg
+{
+ unsigned long op;
+ void *buf;
+ int buf_size;
+} privcmd_blkmsg_t;
+
+/*
+ * @cmd: IOCTL_PRIVCMD_HYPERCALL
+ * @arg: &privcmd_hypercall_t
+ * Return: Value returned from execution of the specified hypercall.
+ */
+#define IOCTL_PRIVCMD_HYPERCALL \
+ _IOWR('P', 0, privcmd_hypercall_t)
+
+#if defined(_KERNEL)
+/* compat */
+#define IOCTL_PRIVCMD_INITDOMAIN_EVTCHN_OLD \
+ _IO('P', 1)
+#endif /* defined(_KERNEL) */
+
+#define IOCTL_PRIVCMD_MMAP \
+ _IOW('P', 2, privcmd_mmap_t)
+#define IOCTL_PRIVCMD_MMAPBATCH \
+ _IOW('P', 3, privcmd_mmapbatch_t)
+#define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN \
+ _IOR('P', 4, unsigned long)
+
+/*
+ * @cmd: IOCTL_PRIVCMD_INITDOMAIN_EVTCHN
+ * @arg: n/a
+ * Return: Port associated with domain-controller end of control event channel
+ * for the initial domain.
+ */
+#define IOCTL_PRIVCMD_INITDOMAIN_EVTCHN \
+ _IOR('P', 5, int)
+
+/* Interface to /dev/xenevt */
+/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
+#define EVTCHN_RESET _IO('E', 1)
+/* EVTCHN_BIND: Bind to the specified event-channel port. */
+#define EVTCHN_BIND _IOW('E', 2, unsigned long)
+/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
+#define EVTCHN_UNBIND _IOW('E', 3, unsigned long)
+
+#endif /* __NetBSD_PRIVCMD_H__ */
diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target
index 33773a4929..5f1af2fabd 100644
--- a/tools/ioemu/Makefile.target
+++ b/tools/ioemu/Makefile.target
@@ -348,6 +348,16 @@ ifdef CONFIG_WIN32
VL_OBJS+=tap-win32.o
endif
+ifeq (,$(wildcard /usr/include/pci))
+$(warning *** pciutils-devl package not found - missing /usr/include/pci)
+$(warning *** PCI passthrough capability has been disabled)
+else
+LIBS+=-lpci
+VL_OBJS+= pass-through.o
+CFLAGS += -DCONFIG_PASSTHROUGH
+$(info *** PCI passthrough capability has been enabled ***)
+endif
+
SOUND_HW = sb16.o es1370.o
AUDIODRV = audio.o noaudio.o wavaudio.o
ifdef CONFIG_SDL
diff --git a/tools/ioemu/audio/audio.c b/tools/ioemu/audio/audio.c
index 556e6fdbcb..65e1de8118 100644
--- a/tools/ioemu/audio/audio.c
+++ b/tools/ioemu/audio/audio.c
@@ -207,7 +207,7 @@ static char *audio_alloc_prefix (const char *s)
strcat (r, s);
for (i = 0; i < len; ++i) {
- u[i] = toupper (u[i]);
+ u[i] = toupper ((uint8_t)u[i]);
}
}
return r;
@@ -446,7 +446,7 @@ static void audio_process_options (const char *prefix,
/* copy while upper-casing, including trailing zero */
for (i = 0; i <= preflen; ++i) {
- optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);
+ optname[i + sizeof (qemu_prefix) - 1] = toupper ((uint8_t)prefix[i]);
}
strcat (optname, "_");
strcat (optname, opt->name);
diff --git a/tools/ioemu/audio/mixeng.c b/tools/ioemu/audio/mixeng.c
index 6308d41004..74f79958a3 100644
--- a/tools/ioemu/audio/mixeng.c
+++ b/tools/ioemu/audio/mixeng.c
@@ -102,6 +102,7 @@
#undef SHIFT
t_sample *mixeng_conv[2][2][2][2] = {
+#ifndef _BSD
{
{
{
@@ -146,9 +147,11 @@ t_sample *mixeng_conv[2][2][2][2] = {
}
}
}
+#endif /* !_BSD */
};
f_sample *mixeng_clip[2][2][2][2] = {
+#ifndef _BSD
{
{
{
@@ -193,6 +196,7 @@ f_sample *mixeng_clip[2][2][2][2] = {
}
}
}
+#endif /* !_BSD */
};
/*
diff --git a/tools/ioemu/audio/ossaudio.c b/tools/ioemu/audio/ossaudio.c
index 125e4c8ff7..bf5932e114 100644
--- a/tools/ioemu/audio/ossaudio.c
+++ b/tools/ioemu/audio/ossaudio.c
@@ -21,10 +21,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
+#if defined(__OpenBSD__)
+#include <soundcard.h>
+#else
#include <sys/soundcard.h>
+#endif
#include "vl.h"
#define AUDIO_CAP "oss"
@@ -231,7 +236,7 @@ static int oss_open (int in, struct oss_params *req,
goto err;
}
- if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
+ if (ioctl (fd, SNDCTL_DSP_NONBLOCK, NULL)) {
oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
goto err;
}
diff --git a/tools/ioemu/block-raw.c b/tools/ioemu/block-raw.c
index f2ce456fc4..68e8a370ca 100644
--- a/tools/ioemu/block-raw.c
+++ b/tools/ioemu/block-raw.c
@@ -53,9 +53,14 @@
#include <linux/cdrom.h>
#include <linux/fd.h>
#endif
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
#include <sys/disk.h>
#endif
+#if defined(__OpenBSD__)
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/dkio.h>
+#endif
//#define DEBUG_FLOPPY
@@ -150,7 +155,7 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
++(s->lseek_err_cnt);
if(s->lseek_err_cnt <= 10) {
- DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %ld, %p, %d) [%ld] lseek failed : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] lseek failed : %d = %s\n",
s->fd,
bs->filename,
offset,
@@ -166,7 +171,7 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
if (ret == count)
goto label__raw_read__success;
- DEBUG_BLOCK_PRINT("raw_read(%d:%s, %ld, %p, %d) [%ld] read failed %d : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_read(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] read failed %d : %d = %s\n",
s->fd,
bs->filename,
offset,
@@ -185,7 +190,7 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
if (ret == count)
goto label__raw_read__success;
- DEBUG_BLOCK_PRINT("raw_read(%d:%s, %ld, %p, %d) [%ld] retry read failed %d : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_read(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] retry read failed %d : %d = %s\n",
s->fd,
bs->filename,
offset,
@@ -215,7 +220,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
++(s->lseek_err_cnt);
if(s->lseek_err_cnt) {
- DEBUG_BLOCK_PRINT("raw_write(%d:%s, %ld, %p, %d) [%ld] lseek failed : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_write(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] lseek failed : %d = %s\n",
s->fd,
bs->filename,
offset,
@@ -231,7 +236,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
if (ret == count)
goto label__raw_write__success;
- DEBUG_BLOCK_PRINT("raw_write(%d:%s, %ld, %p, %d) [%ld] write failed %d : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_write(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] write failed %d : %d = %s\n",
s->fd,
bs->filename,
offset,
@@ -496,6 +501,23 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
return 0;
}
+#ifdef __OpenBSD__
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+ int fd = ((BDRVRawState*)bs->opaque)->fd;
+ struct stat st;
+ if(fstat(fd, &st))
+ return -1;
+ if(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)){
+ struct disklabel dl;
+ if(ioctl(fd, DIOCGDINFO, &dl))
+ return -1;
+ return (uint64_t)dl.d_secsize *
+ dl.d_partitions[DISKPART(st.st_rdev)].p_size;
+ }else
+ return st.st_size;
+}
+#else /* !__OpenBSD__ */
static int64_t raw_getlength(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
@@ -542,6 +564,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
}
return size;
}
+#endif
static int raw_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
diff --git a/tools/ioemu/block-vvfat.c b/tools/ioemu/block-vvfat.c
index 48a52e3116..faa53a5ac2 100644
--- a/tools/ioemu/block-vvfat.c
+++ b/tools/ioemu/block-vvfat.c
@@ -1017,7 +1017,7 @@ DLOG(if (stderr == NULL) {
i = strrchr(dirname, ':') - dirname;
assert(i >= 3);
- if (dirname[i-2] == ':' && isalpha(dirname[i-1]))
+ if (dirname[i-2] == ':' && isalpha((uint8_t)dirname[i-1]))
/* workaround for DOS drive names */
dirname += i-1;
else
diff --git a/tools/ioemu/bswap.h b/tools/ioemu/bswap.h
index 37fb04ed97..f0d77f591c 100644
--- a/tools/ioemu/bswap.h
+++ b/tools/ioemu/bswap.h
@@ -5,6 +5,11 @@
#include <inttypes.h>
+#ifdef _BSD
+#include <sys/endian.h>
+#include <sys/types.h>
+#else
+
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#else
@@ -73,6 +78,8 @@ static inline void bswap64s(uint64_t *s)
*s = bswap64(*s);
}
+#endif /* _BSD */
+
#if defined(WORDS_BIGENDIAN)
#define be_bswap(v, size) (v)
#define le_bswap(v, size) bswap ## size(v)
diff --git a/tools/ioemu/cutils.c b/tools/ioemu/cutils.c
index 352c47e211..dc51e67235 100644
--- a/tools/ioemu/cutils.c
+++ b/tools/ioemu/cutils.c
@@ -23,7 +23,7 @@
*/
#include "vl.h"
-void pstrcpy(char *buf, int buf_size, const char *str)
+void pstrcpy(char *buf, size_t buf_size, const char *str)
{
int c;
char *q = buf;
@@ -41,7 +41,7 @@ void pstrcpy(char *buf, int buf_size, const char *str)
}
/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
+char *pstrcat(char *buf, size_t buf_size, const char *s)
{
int len;
len = strlen(buf);
@@ -72,7 +72,7 @@ int stristart(const char *str, const char *val, const char **ptr)
p = str;
q = val;
while (*q != '\0') {
- if (toupper(*p) != toupper(*q))
+ if (toupper((uint8_t)*p) != toupper((uint8_t)*q))
return 0;
p++;
q++;
diff --git a/tools/ioemu/hw/fdc.c b/tools/ioemu/hw/fdc.c
index 0012834f44..dc2ea6ebff 100644
--- a/tools/ioemu/hw/fdc.c
+++ b/tools/ioemu/hw/fdc.c
@@ -1100,8 +1100,13 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
len = fdctrl->data_len - fdctrl->data_pos;
if (len > FD_SECTOR_LEN)
len = FD_SECTOR_LEN;
- bdrv_read(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, len);
+ if (cur_drv->bs) {
+ bdrv_read(cur_drv->bs, fd_sector(cur_drv),
+ fdctrl->fifo, len);
+ } else {
+ FLOPPY_ERROR("can't read data from drive\n");
+ return 0;
+ }
}
}
retval = fdctrl->fifo[pos];
diff --git a/tools/ioemu/hw/ne2000.c b/tools/ioemu/hw/ne2000.c
index 92720e0811..82168c020d 100644
--- a/tools/ioemu/hw/ne2000.c
+++ b/tools/ioemu/hw/ne2000.c
@@ -252,7 +252,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
{
NE2000State *s = opaque;
uint8_t *p;
- int total_len, next, avail, len, index, mcast_idx;
+ unsigned int total_len, next, avail, len, index, mcast_idx;
uint8_t buf1[60];
static const uint8_t broadcast_macaddr[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -327,7 +327,11 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
/* write packet data */
while (size > 0) {
- avail = s->stop - index;
+ /* taviso: this can wrap, so check its okay. */
+ if (index <= s->stop)
+ avail = s->stop - index;
+ else
+ avail = 0;
len = size;
if (len > avail)
len = avail;
diff --git a/tools/ioemu/hw/pass-through.c b/tools/ioemu/hw/pass-through.c
new file mode 100644
index 0000000000..fcf3617cfa
--- /dev/null
+++ b/tools/ioemu/hw/pass-through.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2007, Neocleus Corporation.
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Alex Novik <alex@neocleus.com>
+ * Allen Kay <allen.m.kay@intel.com>
+ * Guy Zana <guy@neocleus.com>
+ *
+ * This file implements direct PCI assignment to a HVM guest
+ *
+ */
+#include "vl.h"
+#include "pass-through.h"
+#include "pci/header.h"
+#include "pci/pci.h"
+
+extern FILE *logfile;
+char *token;
+
+int pci_devs(const char *direct_pci)
+{
+ int count = 0;
+ const char *c;
+
+ /* skip first "[" character */
+ c = direct_pci + 1;
+ while ((c = strchr(c, '[')) != NULL) {
+ c++;
+ count++;
+ }
+ return (count);
+}
+
+int next_token(char *direct_pci)
+{
+ if (token == NULL)
+ token = strtok(direct_pci, ",");
+ else
+ token = strtok(NULL, ",");
+ token = strchr(token, 'x');
+ token = token + 1;
+ return ((int) strtol(token, NULL, 16));
+}
+
+void next_bdf(char *direct_pci, int *seg,
+ int *bus, int *dev, int *func)
+{
+ *seg = next_token(direct_pci);
+ *bus = next_token(direct_pci);
+ *dev = next_token(direct_pci);
+ *func = next_token(direct_pci);
+}
+
+uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
+{
+ int id;
+ int max_cap = 48;
+ int pos = PCI_CAPABILITY_LIST;
+ int status;
+
+ status = pci_read_byte(pci_dev, PCI_STATUS);
+ if ( (status & PCI_STATUS_CAP_LIST) == 0 )
+ return 0;
+
+ while ( max_cap-- )
+ {
+ pos = pci_read_byte(pci_dev, pos);
+ if ( pos < 0x40 )
+ break;
+
+ pos &= ~3;
+ id = pci_read_byte(pci_dev, pos + PCI_CAP_LIST_ID);
+
+ if ( id == 0xff )
+ break;
+ if ( id == cap )
+ return pos;
+
+ pos += PCI_CAP_LIST_NEXT;
+ }
+ return 0;
+}
+
+void pdev_flr(struct pci_dev *pci_dev)
+{
+ int pos;
+ int dev_cap;
+ int dev_status;
+
+ pos = find_cap_offset(pci_dev, PCI_CAP_ID_EXP);
+ if ( pos )
+ {
+ dev_cap = pci_read_long(pci_dev, pos + PCI_EXP_DEVCAP);
+ if ( dev_cap & PCI_EXP_DEVCAP_FLR )
+ {
+ pci_write_word(pci_dev, pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR);
+ do {
+ dev_status = pci_read_long(pci_dev, pos + PCI_EXP_DEVSTA);
+ } while (dev_status & PCI_EXP_DEVSTA_TRPND);
+ }
+ }
+}
+
+/* Being called each time a mmio region has been updated */
+void pt_iomem_map(PCIDevice *d, int i, uint32_t e_phys, uint32_t e_size,
+ int type)
+{
+ struct pt_dev *assigned_device = (struct pt_dev *)d;
+ uint32_t old_ebase = assigned_device->bases[i].e_physbase;
+ int first_map = ( assigned_device->bases[i].e_size == 0 );
+ int ret = 0;
+
+ assigned_device->bases[i].e_physbase = e_phys;
+ assigned_device->bases[i].e_size= e_size;
+
+ PT_LOG("e_phys=%08x maddr=%08x type=%d len=%08x index=%d\n",
+ e_phys, assigned_device->bases[i].access.maddr, type, e_size, i);
+
+ if ( e_size == 0 )
+ return;
+
+ if ( !first_map )
+ {
+ /* Remove old mapping */
+ ret = xc_domain_memory_mapping(xc_handle, domid, old_ebase >> 12,
+ assigned_device->bases[i].access.maddr >> 12,
+ (e_size+0xFFF) >> 12,
+ DPCI_REMOVE_MAPPING);
+ if ( ret != 0 )
+ {
+ PT_LOG("Error: remove old mapping failed!\n");
+ return;
+ }
+ }
+
+ /* Create new mapping */
+ ret = xc_domain_memory_mapping(xc_handle, domid,
+ assigned_device->bases[i].e_physbase >> 12,
+ assigned_device->bases[i].access.maddr >> 12,
+ (e_size+0xFFF) >> 12,
+ DPCI_ADD_MAPPING);
+ if ( ret != 0 )
+ PT_LOG("Error: create new mapping failed!\n");
+
+}
+
+/* Being called each time a pio region has been updated */
+void pt_ioport_map(PCIDevice *d, int i,
+ uint32_t e_phys, uint32_t e_size, int type)
+{
+ struct pt_dev *assigned_device = (struct pt_dev *)d;
+ uint32_t old_ebase = assigned_device->bases[i].e_physbase;
+ int first_map = ( assigned_device->bases[i].e_size == 0 );
+ int ret = 0;
+
+ assigned_device->bases[i].e_physbase = e_phys;
+ assigned_device->bases[i].e_size= e_size;
+
+ PT_LOG("e_phys=%04x pio_base=%04x len=%04x index=%d\n",
+ (uint16_t)e_phys, (uint16_t)assigned_device->bases[i].access.pio_base,
+ (uint16_t)e_size, i);
+
+ if ( e_size == 0 )
+ return;
+
+ if ( !first_map )
+ {
+ /* Remove old mapping */
+ ret = xc_domain_ioport_mapping(xc_handle, domid, old_ebase,
+ assigned_device->bases[i].access.pio_base, e_size,
+ DPCI_REMOVE_MAPPING);
+ if ( ret != 0 )
+ {
+ PT_LOG("Error: remove old mapping failed!\n");
+ return;
+ }
+ }
+
+ /* Create new mapping */
+ ret = xc_domain_ioport_mapping(xc_handle, domid, e_phys,
+ assigned_device->bases[i].access.pio_base, e_size,
+ DPCI_ADD_MAPPING);
+ if ( ret != 0 )
+ PT_LOG("Error: create new mapping failed!\n");
+
+}
+
+static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val,
+ int len)
+{
+ struct pt_dev *assigned_device = (struct pt_dev *)d;
+ struct pci_dev *pci_dev = assigned_device->pci_dev;
+
+#ifdef PT_DEBUG_PCI_CONFIG_ACCESS
+ PT_LOG("(%x.%x): address=%04x val=0x%08x len=%d\n",
+ (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len);
+#endif
+
+ /* Pre-write hooking */
+ switch ( address ) {
+ case 0x0C ... 0x3F:
+ pci_default_write_config(d, address, val, len);
+ return;
+ }
+
+ /* PCI config pass-through */
+ if (address == 0x4) {
+ switch (len){
+ case 1:
+ pci_write_byte(pci_dev, address, val);
+ break;
+ case 2:
+ pci_write_word(pci_dev, address, val);
+ break;
+ case 4:
+ pci_write_long(pci_dev, address, val);
+ break;
+ }
+ }
+
+ if (address == 0x4) {
+ /* Post-write hooking */
+ pci_default_write_config(d, address, val, len);
+ }
+}
+
+static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t address, int len)
+{
+ struct pt_dev *assigned_device = (struct pt_dev *)d;
+ struct pci_dev *pci_dev = assigned_device->pci_dev;
+ uint32_t val = 0xFF;
+
+ /* Pre-hooking */
+ switch ( address ) {
+ case 0x0C ... 0x3F:
+ val = pci_default_read_config(d, address, len);
+ goto exit;
+ }
+
+ switch ( len ) {
+ case 1:
+ val = pci_read_byte(pci_dev, address);
+ break;
+ case 2:
+ val = pci_read_word(pci_dev, address);
+ break;
+ case 4:
+ val = pci_read_long(pci_dev, address);
+ break;
+ }
+
+exit:
+
+#ifdef PT_DEBUG_PCI_CONFIG_ACCESS
+ PT_LOG("(%x.%x): address=%04x val=0x%08x len=%d\n",
+ (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len);
+#endif
+
+ return val;
+}
+
+static int pt_register_regions(struct pt_dev *assigned_device)
+{
+ int i = 0;
+ uint32_t bar_data = 0;
+ struct pci_dev *pci_dev = assigned_device->pci_dev;
+ PCIDevice *d = &assigned_device->dev;
+
+ /* Register PIO/MMIO BARs */
+ for ( i=0; i < PCI_BAR_ENTRIES; i++ )
+ {
+ if ( pci_dev->base_addr[i] )
+ {
+ assigned_device->bases[i].e_physbase = pci_dev->base_addr[i];
+ assigned_device->bases[i].access.u = pci_dev->base_addr[i];
+
+ /* Register current region */
+ bar_data = *((uint32_t*)(d->config + PCI_BASE_ADDRESS_0) + i);
+ if ( bar_data & PCI_ADDRESS_SPACE_IO )
+ pci_register_io_region((PCIDevice *)assigned_device, i,
+ (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_IO,
+ pt_ioport_map);
+ else if ( bar_data & PCI_ADDRESS_SPACE_MEM_PREFETCH )
+ pci_register_io_region((PCIDevice *)assigned_device, i,
+ (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM_PREFETCH,
+ pt_iomem_map);
+ else
+ pci_register_io_region((PCIDevice *)assigned_device, i,
+ (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM,
+ pt_iomem_map);
+
+ PT_LOG("IO region registered (size=0x%08x base_addr=0x%08x)\n",
+ (uint32_t)(pci_dev->size[i]),
+ (uint32_t)(pci_dev->base_addr[i]));
+ }
+ }
+
+ /* Register expansion ROM address */
+ if ( pci_dev->rom_base_addr && pci_dev->rom_size )
+ {
+ assigned_device->bases[PCI_ROM_SLOT].e_physbase =
+ pci_dev->rom_base_addr;
+ assigned_device->bases[PCI_ROM_SLOT].access.maddr =
+ pci_dev->rom_base_addr;
+ pci_register_io_region((PCIDevice *)assigned_device, PCI_ROM_SLOT,
+ pci_dev->rom_size, PCI_ADDRESS_SPACE_MEM_PREFETCH,
+ pt_iomem_map);
+
+ PT_LOG("Expansion ROM registered (size=0x%08x base_addr=0x%08x)\n",
+ (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr));
+ }
+
+ return 0;
+}
+
+struct pt_dev * register_real_device(PCIBus *e_bus,
+ const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
+ uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access)
+{
+ int rc, i;
+ struct pt_dev *assigned_device = NULL;
+ struct pci_dev *pci_dev;
+ struct pci_config_cf8 machine_bdf;
+ uint8_t e_device, e_intx;
+
+ PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
+ r_bus, r_dev, r_func);
+
+ /* Find real device structure */
+ for (pci_dev = pci_access->devices; pci_dev != NULL;
+ pci_dev = pci_dev->next)
+ {
+ if ((r_bus == pci_dev->bus) && (r_dev == pci_dev->dev)
+ && (r_func == pci_dev->func))
+ break;
+ }
+ if ( pci_dev == NULL )
+ {
+ PT_LOG("Error: couldn't locate device in libpci structures\n");
+ return NULL;
+ }
+
+ /* Register device */
+ assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name,
+ sizeof(struct pt_dev), e_devfn,
+ pt_pci_read_config, pt_pci_write_config);
+ if ( assigned_device == NULL )
+ {
+ PT_LOG("Error: couldn't register real device\n");
+ return NULL;
+ }
+
+ assigned_device->pci_dev = pci_dev;
+
+ /* Issue PCIe FLR */
+ pdev_flr(pci_dev);
+
+ /* Tell XEN vmm to change iommu settings */
+ machine_bdf.reg = 0;
+ machine_bdf.bus = r_bus;
+ machine_bdf.dev = r_dev;
+ machine_bdf.func = r_func;
+ rc = xc_assign_device(xc_handle, domid, machine_bdf.value);
+ if ( rc < 0 )
+ PT_LOG("Error: xc_domain_assign_device error %d\n", rc);
+
+ /* Initialize virtualized PCI configuration (Extended 256 Bytes) */
+ for ( i = 0; i < PCI_CONFIG_SIZE; i++ )
+ assigned_device->dev.config[i] = pci_read_byte(pci_dev, i);
+
+ /* Handle real device's MMIO/PIO BARs */
+ pt_register_regions(assigned_device);
+
+ /* Bind interrupt */
+ e_device = (assigned_device->dev.devfn >> 3) & 0x1f;
+ e_intx = assigned_device->dev.config[0x3d]-1;
+
+ if ( PT_MACHINE_IRQ_AUTO == machine_irq )
+ machine_irq = pci_dev->irq;
+
+ /* bind machine_irq to device */
+ if ( 0 != machine_irq )
+ {
+ rc = xc_domain_bind_pt_pci_irq(xc_handle, domid, machine_irq, 0,
+ e_device, e_intx);
+ if ( rc < 0 )
+ {
+ /* TBD: unregister device in case of an error */
+ PT_LOG("Error: Binding of interrupt failed! rc=%d\n", rc);
+ }
+ }
+ else {
+ /* Disable PCI intx assertion (turn on bit10 of devctl) */
+ assigned_device->dev.config[0x05] |= 0x04;
+ pci_write_word(pci_dev, 0x04,
+ *(uint16_t *)(&assigned_device->dev.config[0x04]));
+ }
+
+ PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n",
+ r_bus, r_dev, r_func);
+
+ return assigned_device;
+}
+
+int pt_init(PCIBus *e_bus, char *direct_pci)
+{
+ int i;
+ int seg, b, d, f;
+ struct pt_dev *pt_dev;
+ struct pci_access *pci_access;
+ int dev_count = pci_devs(direct_pci);
+
+ /* Initialize libpci */
+ pci_access = pci_alloc();
+ if ( pci_access == NULL )
+ {
+ PT_LOG("pci_access is NULL\n");
+ return -1;
+ }
+ pci_init(pci_access);
+ pci_scan_bus(pci_access);
+
+ /* Assign given devices to guest */
+ for ( i = 0; i < dev_count; i++ )
+ {
+ /* Get next device bdf (bus, device, function) */
+ next_bdf(direct_pci, &seg, &b, &d, &f);
+
+ /* Register real device with the emulated bus */
+ pt_dev = register_real_device(e_bus, "DIRECT PCI", PT_VIRT_DEVFN_AUTO,
+ b, d, f, PT_MACHINE_IRQ_AUTO, pci_access);
+ if ( pt_dev == NULL )
+ {
+ PT_LOG("Error: Registration failed (%02x:%02x.%x)\n", b, d, f);
+ return -1;
+ }
+ }
+
+ /* Success */
+ return 0;
+}
diff --git a/tools/ioemu/hw/pass-through.h b/tools/ioemu/hw/pass-through.h
new file mode 100644
index 0000000000..42f7b52d74
--- /dev/null
+++ b/tools/ioemu/hw/pass-through.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007, Neocleus Corporation.
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PASSTHROUGH_H__
+#define __PASSTHROUGH_H__
+
+#include "vl.h"
+#include "pci/header.h"
+#include "pci/pci.h"
+
+/* Log acesss */
+#define PT_LOGGING_ENABLED
+
+#ifdef PT_LOGGING_ENABLED
+#define PT_LOG(_f, _a...) fprintf(logfile, "%s: " _f, __func__, ##_a)
+#else
+#define PT_LOG(_f, _a...)
+#endif
+
+/* Some compilation flags */
+// #define PT_DEBUG_PCI_CONFIG_ACCESS
+
+#define PT_MACHINE_IRQ_AUTO (0xFFFFFFFF)
+#define PT_VIRT_DEVFN_AUTO (-1)
+
+/* Misc PCI constants that should be moved to a separate library :) */
+#define PCI_CONFIG_SIZE (256)
+#define PCI_EXP_DEVCAP_FLR (1 << 28)
+#define PCI_EXP_DEVCTL_FLR (0x1b)
+#define PCI_BAR_ENTRIES (6)
+
+struct pt_region {
+ /* Virtual phys base & size */
+ uint32_t e_physbase;
+ uint32_t e_size;
+ /* Index of region in qemu */
+ uint32_t memory_index;
+ /* Translation of the emulated address */
+ union {
+ uint32_t maddr;
+ uint32_t pio_base;
+ uint32_t u;
+ } access;
+};
+
+/*
+ This structure holds the context of the mapping functions
+ and data that is relevant for qemu device management.
+*/
+struct pt_dev {
+ PCIDevice dev;
+ struct pci_dev *pci_dev; /* libpci struct */
+ struct pt_region bases[PCI_NUM_REGIONS]; /* Access regions */
+};
+
+/* Used for formatting PCI BDF into cf8 format */
+struct pci_config_cf8 {
+ union {
+ unsigned int value;
+ struct {
+ unsigned int reserved1:2;
+ unsigned int reg:6;
+ unsigned int func:3;
+ unsigned int dev:5;
+ unsigned int bus:8;
+ unsigned int reserved2:7;
+ unsigned int enable:1;
+ };
+ };
+};
+
+int pt_init(PCIBus * e_bus, char * direct_pci);
+
+#endif /* __PASSTHROUGH_H__ */
+
diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c
index 1c33cdc8da..8c17c25477 100644
--- a/tools/ioemu/hw/pc.c
+++ b/tools/ioemu/hw/pc.c
@@ -465,7 +465,7 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename,
- int pci_enabled)
+ int pci_enabled, const char *direct_pci)
{
#ifndef NOBIOS
char buf[1024];
@@ -480,6 +480,7 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
int piix3_devfn = -1;
CPUState *env;
NICInfo *nd;
+ int rc;
linux_boot = (kernel_filename != NULL);
@@ -665,6 +666,19 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
}
}
+#ifdef CONFIG_PASSTHROUGH
+ /* Pass-through Initialization */
+ if ( pci_enabled && direct_pci )
+ {
+ rc = pt_init(pci_bus, direct_pci);
+ if ( rc < 0 )
+ {
+ fprintf(logfile, "Error: Initialization failed for pass-through devices\n");
+ exit(1);
+ }
+ }
+#endif
+
rtc_state = rtc_init(0x70, 8);
register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
@@ -801,12 +815,14 @@ static void pc_init_pci(uint64_t ram_size, int vga_ram_size, char *boot_device,
int snapshot,
const char *kernel_filename,
const char *kernel_cmdline,
- const char *initrd_filename)
+ const char *initrd_filename,
+ const char *direct_pci)
{
pc_init1(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline,
- initrd_filename, 1);
+ initrd_filename, 1,
+ direct_pci);
}
static void pc_init_isa(uint64_t ram_size, int vga_ram_size, char *boot_device,
@@ -814,12 +830,13 @@ static void pc_init_isa(uint64_t ram_size, int vga_ram_size, char *boot_device,
int snapshot,
const char *kernel_filename,
const char *kernel_cmdline,
- const char *initrd_filename)
+ const char *initrd_filename,
+ const char *unused)
{
pc_init1(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline,
- initrd_filename, 0);
+ initrd_filename, 0, NULL);
}
QEMUMachine pc_machine = {
diff --git a/tools/ioemu/hw/sb16.c b/tools/ioemu/hw/sb16.c
index 04325ac031..387330f414 100644
--- a/tools/ioemu/hw/sb16.c
+++ b/tools/ioemu/hw/sb16.c
@@ -1235,8 +1235,10 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
s->block_size);
#endif
- while (s->left_till_irq <= 0) {
- s->left_till_irq = s->block_size + s->left_till_irq;
+ if (s->block_size) {
+ while (s->left_till_irq <= 0) {
+ s->left_till_irq = s->block_size + s->left_till_irq;
+ }
}
return dma_pos;
diff --git a/tools/ioemu/monitor.c b/tools/ioemu/monitor.c
index f3bfe0fbf1..5f0a69af27 100644
--- a/tools/ioemu/monitor.c
+++ b/tools/ioemu/monitor.c
@@ -1698,7 +1698,7 @@ static void next(void)
{
if (pch != '\0') {
pch++;
- while (isspace(*pch))
+ while (isspace((uint8_t)*pch))
pch++;
}
}
@@ -1756,7 +1756,7 @@ static target_long expr_unary(void)
*q++ = *pch;
pch++;
}
- while (isspace(*pch))
+ while (isspace((uint8_t)*pch))
pch++;
*q = 0;
ret = get_monitor_def(&n, buf);
@@ -1780,7 +1780,7 @@ static target_long expr_unary(void)
expr_error("invalid char in expression");
}
pch = p;
- while (isspace(*pch))
+ while (isspace((uint8_t)*pch))
pch++;
break;
}
@@ -1874,7 +1874,7 @@ static int get_expr(target_long *pval, const char **pp)
*pp = pch;
return -1;
}
- while (isspace(*pch))
+ while (isspace((uint8_t)*pch))
pch++;
*pval = expr_sum();
*pp = pch;
@@ -1890,7 +1890,7 @@ static int get_str(char *buf, int buf_size, const char **pp)
q = buf;
p = *pp;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*p == '\0') {
fail:
@@ -1935,7 +1935,7 @@ static int get_str(char *buf, int buf_size, const char **pp)
}
p++;
} else {
- while (*p != '\0' && !isspace(*p)) {
+ while (*p != '\0' && !isspace((uint8_t)*p)) {
if ((q - buf) < buf_size - 1) {
*q++ = *p;
}
@@ -1975,12 +1975,12 @@ static void monitor_handle_command(const char *cmdline)
/* extract the command name */
p = cmdline;
q = cmdname;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*p == '\0')
return;
pstart = p;
- while (*p != '\0' && *p != '/' && !isspace(*p))
+ while (*p != '\0' && *p != '/' && !isspace((uint8_t)*p))
p++;
len = p - pstart;
if (len > sizeof(cmdname) - 1)
@@ -2016,7 +2016,7 @@ static void monitor_handle_command(const char *cmdline)
int ret;
char *str;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*typestr == '?') {
typestr++;
@@ -2058,15 +2058,15 @@ static void monitor_handle_command(const char *cmdline)
{
int count, format, size;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*p == '/') {
/* format found */
p++;
count = 1;
- if (isdigit(*p)) {
+ if (isdigit((uint8_t)*p)) {
count = 0;
- while (isdigit(*p)) {
+ while (isdigit((uint8_t)*p)) {
count = count * 10 + (*p - '0');
p++;
}
@@ -2105,7 +2105,7 @@ static void monitor_handle_command(const char *cmdline)
}
}
next:
- if (*p != '\0' && !isspace(*p)) {
+ if (*p != '\0' && !isspace((uint8_t)*p)) {
term_printf("invalid char in format: '%c'\n", *p);
goto fail;
}
@@ -2138,7 +2138,7 @@ static void monitor_handle_command(const char *cmdline)
case 'l':
{
target_long val;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*typestr == '?' || *typestr == '.') {
if (*typestr == '?') {
@@ -2149,7 +2149,7 @@ static void monitor_handle_command(const char *cmdline)
} else {
if (*p == '.') {
p++;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
has_arg = 1;
} else {
@@ -2195,7 +2195,7 @@ static void monitor_handle_command(const char *cmdline)
c = *typestr++;
if (c == '\0')
goto bad_type;
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
has_option = 0;
if (*p == '-') {
@@ -2225,7 +2225,7 @@ static void monitor_handle_command(const char *cmdline)
}
}
/* check that all arguments were parsed */
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*p != '\0') {
term_printf("%s: extraneous characters at the end of line\n",
@@ -2364,7 +2364,7 @@ static void parse_cmdline(const char *cmdline,
p = cmdline;
nb_args = 0;
for(;;) {
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
if (*p == '\0')
break;
@@ -2398,7 +2398,7 @@ void readline_find_completion(const char *cmdline)
/* if the line ends with a space, it means we want to complete the
next arg */
len = strlen(cmdline);
- if (len > 0 && isspace(cmdline[len - 1])) {
+ if (len > 0 && isspace((uint8_t)cmdline[len - 1])) {
if (nb_args >= MAX_ARGS)
return;
args[nb_args++] = qemu_strdup("");
diff --git a/tools/ioemu/osdep.h b/tools/ioemu/osdep.h
index 325baf14eb..bd6ffc1713 100644
--- a/tools/ioemu/osdep.h
+++ b/tools/ioemu/osdep.h
@@ -2,6 +2,10 @@
#define QEMU_OSDEP_H
#include <stdarg.h>
+#ifdef __OpenBSD__
+#include <sys/types.h>
+#include <sys/signal.h>
+#endif
#define qemu_printf printf
diff --git a/tools/ioemu/target-i386-dm/exec-dm.c b/tools/ioemu/target-i386-dm/exec-dm.c
index b67c55414d..f7525b1f20 100644
--- a/tools/ioemu/target-i386-dm/exec-dm.c
+++ b/tools/ioemu/target-i386-dm/exec-dm.c
@@ -168,8 +168,8 @@ void cpu_set_log_filename(const char *filename)
#else
setvbuf(logfile, NULL, _IOLBF, 0);
#endif
- stdout = logfile;
- stderr = logfile;
+ dup2(fileno(logfile), 1);
+ dup2(fileno(logfile), 2);
}
/* mask must never be zero, except for A20 change call */
diff --git a/tools/ioemu/usb-linux.c b/tools/ioemu/usb-linux.c
index d0a75d8cdc..b757066ae6 100644
--- a/tools/ioemu/usb-linux.c
+++ b/tools/ioemu/usb-linux.c
@@ -268,7 +268,7 @@ static int get_tag_value(char *buf, int buf_size,
if (!p)
return -1;
p += strlen(tag);
- while (isspace(*p))
+ while (isspace((uint8_t)*p))
p++;
q = buf;
while (*p != '\0' && !strchr(stopchars, *p)) {
diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c
index 6c300fa3d3..369769090a 100644
--- a/tools/ioemu/vl.c
+++ b/tools/ioemu/vl.c
@@ -24,6 +24,7 @@
#include "vl.h"
#include <unistd.h>
+#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
@@ -38,22 +39,29 @@
#include <sys/poll.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
+#include <sys/resource.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <net/if.h>
+#if defined(__NetBSD__)
+#include <net/if_tap.h>
+#endif
+#if defined(__linux__) || defined(__Linux__)
+#include <linux/if_tun.h>
+#endif
#include <arpa/inet.h>
#include <dirent.h>
#include <netdb.h>
#ifdef _BSD
#include <sys/stat.h>
-#ifndef __APPLE__
+#ifndef _BSD
#include <libutil.h>
+#else
+#include <util.h>
#endif
#else
#ifndef __sun__
-#include <linux/if.h>
-#include <linux/if_tun.h>
#include <pty.h>
-#include <malloc.h>
#include <linux/rtc.h>
#include <linux/ppdev.h>
#endif
@@ -65,7 +73,6 @@
#endif
#ifdef _WIN32
-#include <malloc.h>
#include <sys/timeb.h>
#include <windows.h>
#define getopt_long_only getopt_long
@@ -91,7 +98,11 @@
#include <xen/hvm/params.h>
#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
+#ifdef _BSD
+#define DEFAULT_BRIDGE "bridge0"
+#else
#define DEFAULT_BRIDGE "xenbr0"
+#endif
#ifdef __sun__
#define SMBD_COMMAND "/usr/sfw/sbin/smbd"
#else
@@ -1794,7 +1805,7 @@ static int store_dev_info(char *devName, int domid,
return 0;
}
-#if defined(__linux__)
+#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
static CharDriverState *qemu_chr_open_pty(void)
{
struct termios tty;
@@ -1949,6 +1960,7 @@ static CharDriverState *qemu_chr_open_tty(const char *filename)
return chr;
}
+#if defined(__linux__)
static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
{
int fd = (int)chr->opaque;
@@ -2013,13 +2025,14 @@ static CharDriverState *qemu_chr_open_pp(const char *filename)
return chr;
}
+#endif /* __linux__ */
#else
static CharDriverState *qemu_chr_open_pty(void)
{
return NULL;
}
-#endif
+#endif /* __linux__ || __NetBSD__ || __OpenBSD__ */
#endif /* !defined(_WIN32) */
@@ -2958,7 +2971,7 @@ static int parse_macaddr(uint8_t *macaddr, const char *p)
return 0;
}
-static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
+static int get_str_sep(char *buf, size_t buf_size, const char **pp, int sep)
{
const char *p, *p1;
int len;
@@ -3031,7 +3044,7 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
if (buf[0] == '\0') {
saddr->sin_addr.s_addr = 0;
} else {
- if (isdigit(buf[0])) {
+ if (isdigit((uint8_t)buf[0])) {
if (!inet_aton(buf, &saddr->sin_addr))
return -1;
} else {
@@ -3373,18 +3386,30 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
static int tap_open(char *ifname, int ifname_size)
{
int fd;
+#ifndef TAPGIFNAME
char *dev;
struct stat s;
+#endif
+ struct ifreq ifr;
fd = open("/dev/tap", O_RDWR);
if (fd < 0) {
- fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n");
+ fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation %s\n", strerror(errno));
return -1;
}
+#ifdef TAPGIFNAME
+ if (ioctl (fd, TAPGIFNAME, (void*)&ifr) < 0) {
+ fprintf(stderr, "warning: could not open get tap name: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ pstrcpy(ifname, ifname_size, ifr.ifr_name);
+#else
fstat(fd, &s);
dev = devname(s.st_rdev, S_IFCHR);
pstrcpy(ifname, ifname_size, dev);
+#endif
fcntl(fd, F_SETFL, O_NONBLOCK);
return fd;
@@ -3435,6 +3460,8 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
char **parg;
char ifname[128];
+ memset(ifname, 0, sizeof(ifname));
+
if (ifname1 != NULL)
pstrcpy(ifname, sizeof(ifname), ifname1);
else
@@ -3611,7 +3638,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
val = 1;
ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (const char *)&val, sizeof(val));
+ (const char *)&val, sizeof(char));
if (ret < 0) {
perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
goto fail;
@@ -3893,7 +3920,7 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
}
-static int get_param_value(char *buf, int buf_size,
+static int get_param_value(char *buf, size_t buf_size,
const char *tag, const char *str)
{
const char *p;
@@ -4019,6 +4046,10 @@ static int net_client_init(const char *str)
char setup_script[1024];
char bridge[16];
int fd;
+
+ memset(ifname, 0, sizeof(ifname));
+ memset(setup_script, 0, sizeof(setup_script));
+
if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
fd = strtol(buf, NULL, 0);
ret = -1;
@@ -6513,6 +6544,7 @@ enum {
QEMU_OPTION_acpi,
QEMU_OPTION_vncviewer,
QEMU_OPTION_vncunused,
+ QEMU_OPTION_pci,
};
typedef struct QEMUOption {
@@ -6610,6 +6642,7 @@ const QEMUOption qemu_options[] = {
{ "d", HAS_ARG, QEMU_OPTION_d },
{ "vcpus", 1, QEMU_OPTION_vcpus },
{ "acpi", 0, QEMU_OPTION_acpi },
+ { "pci", HAS_ARG, QEMU_OPTION_pci},
{ NULL },
};
@@ -6912,7 +6945,6 @@ static int qemu_map_cache_init(void)
nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
(1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
(MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
- fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx\n", nr_buckets);
/*
* Use mmap() directly: lets us allocate a big hash table with no up-front
@@ -6921,8 +6953,9 @@ static int qemu_map_cache_init(void)
*/
size = nr_buckets * sizeof(struct map_cache);
size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n", nr_buckets, size);
mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
- MAP_SHARED|MAP_ANONYMOUS, 0, 0);
+ MAP_SHARED|MAP_ANON, -1, 0);
if (mapcache_entry == MAP_FAILED) {
errno = ENOMEM;
return -1;
@@ -7059,15 +7092,40 @@ int main(int argc, char **argv)
unsigned long ioreq_pfn;
extern void *shared_page;
extern void *buffered_io_page;
+ struct rlimit rl;
#ifdef __ia64__
unsigned long nr_pages;
xen_pfn_t *page_array;
extern void *buffered_pio_page;
#endif
sigset_t set;
-
char qemu_dm_logfilename[128];
-
+ const char *direct_pci = NULL;
+
+ /* Maximise rlimits. Needed where default constraints are tight (*BSD). */
+ if (getrlimit(RLIMIT_STACK, &rl) != 0) {
+ perror("getrlimit(RLIMIT_STACK)");
+ exit(1);
+ }
+ rl.rlim_cur = rl.rlim_max;
+ if (setrlimit(RLIMIT_STACK, &rl) != 0)
+ perror("setrlimit(RLIMIT_STACK)");
+ if (getrlimit(RLIMIT_DATA, &rl) != 0) {
+ perror("getrlimit(RLIMIT_DATA)");
+ exit(1);
+ }
+ rl.rlim_cur = rl.rlim_max;
+ if (setrlimit(RLIMIT_DATA, &rl) != 0)
+ perror("setrlimit(RLIMIT_DATA)");
+ rl.rlim_cur = RLIM_INFINITY;
+ rl.rlim_max = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_RSS, &rl) != 0)
+ perror("setrlimit(RLIMIT_RSS)");
+ rl.rlim_cur = RLIM_INFINITY;
+ rl.rlim_max = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0)
+ perror("setrlimit(RLIMIT_MEMLOCK)");
+
/* Ensure that SIGUSR2 is blocked by default when a new thread is created,
then only the threads that use the signal unblock it -- this fixes a
race condition in Qcow support where the AIO signal is misdelivered. */
@@ -7560,6 +7618,9 @@ int main(int argc, char **argv)
case QEMU_OPTION_vncunused:
vncunused++;
break;
+ case QEMU_OPTION_pci:
+ direct_pci = optarg;
+ break;
}
}
}
@@ -7926,7 +7987,8 @@ int main(int argc, char **argv)
machine->init(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline, initrd_filename);
+ kernel_filename, kernel_cmdline, initrd_filename,
+ direct_pci);
free(boot_device);
/* init USB devices */
diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h
index dda595b480..b087e20c00 100644
--- a/tools/ioemu/vl.h
+++ b/tools/ioemu/vl.h
@@ -103,8 +103,8 @@ static inline char *realpath(const char *path, char *resolved_path)
#endif
/* cutils.c */
-void pstrcpy(char *buf, int buf_size, const char *str);
-char *pstrcat(char *buf, int buf_size, const char *s);
+void pstrcpy(char *buf, size_t buf_size, const char *str);
+char *pstrcat(char *buf, size_t buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int stristart(const char *str, const char *val, const char **ptr);
@@ -717,7 +717,7 @@ typedef void QEMUMachineInitFunc(uint64_t ram_size, int vga_ram_size,
char *boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename);
+ const char *initrd_filename, const char *direct_pci);
typedef struct QEMUMachine {
const char *name;
diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c
index 0473042820..ca697e64d2 100644
--- a/tools/ioemu/vnc.c
+++ b/tools/ioemu/vnc.c
@@ -24,6 +24,9 @@
* THE SOFTWARE.
*/
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include "vl.h"
#include "qemu_socket.h"
#include <assert.h>
diff --git a/tools/libaio/src/compat-0_1.c b/tools/libaio/src/compat-0_1.c
index 136396f996..53d520b9f9 100644
--- a/tools/libaio/src/compat-0_1.c
+++ b/tools/libaio/src/compat-0_1.c
@@ -19,7 +19,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
-#include <asm/errno.h>
+#include <sys/time.h>
#include "libaio.h"
#include "vsys_def.h"
diff --git a/tools/libfsimage/ext2fs/fsys_ext2fs.c b/tools/libfsimage/ext2fs/fsys_ext2fs.c
index 7a25c55022..366c4aa76d 100644
--- a/tools/libfsimage/ext2fs/fsys_ext2fs.c
+++ b/tools/libfsimage/ext2fs/fsys_ext2fs.c
@@ -594,7 +594,7 @@ ext2fs_dir (fsi_file_t *ffi, char *dirname)
/* Find out how long our remaining name is. */
len = 0;
- while (dirname[len] && !isspace (dirname[len]))
+ while (dirname[len] && !isspace ((uint8_t)dirname[len]))
len++;
/* Get the symlink size. */
@@ -651,7 +651,7 @@ ext2fs_dir (fsi_file_t *ffi, char *dirname)
}
/* if end of filename, INODE points to the file's inode */
- if (!*dirname || isspace (*dirname))
+ if (!*dirname || isspace ((uint8_t)*dirname))
{
if (!S_ISREG (INODE->i_mode))
{
@@ -678,7 +678,7 @@ ext2fs_dir (fsi_file_t *ffi, char *dirname)
}
/* skip to next slash or end of filename (space) */
- for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
+ for (rest = dirname; (ch = *rest) && !isspace ((uint8_t)ch) && ch != '/';
rest++);
/* look through this directory and find the next filename component */
diff --git a/tools/libfsimage/fat/fsys_fat.c b/tools/libfsimage/fat/fsys_fat.c
index a0afb87f49..819465a16b 100644
--- a/tools/libfsimage/fat/fsys_fat.c
+++ b/tools/libfsimage/fat/fsys_fat.c
@@ -301,7 +301,7 @@ fat_dir (fsi_file_t *ffi, char *dirname)
/* if we have a real file (and we're not just printing possibilities),
then this is where we want to exit */
- if (!*dirname || isspace (*dirname))
+ if (!*dirname || isspace ((uint8_t)*dirname))
{
if (attrib & FAT_ATTRIB_DIR)
{
@@ -325,7 +325,7 @@ fat_dir (fsi_file_t *ffi, char *dirname)
/* Directories don't have a file size */
filemax = INT_MAX;
- for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ for (rest = dirname; (ch = *rest) && !isspace ((uint8_t)ch) && ch != '/'; rest++);
*rest = 0;
@@ -426,13 +426,13 @@ fat_dir (fsi_file_t *ffi, char *dirname)
{
int i, j, c;
- for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i]))
- && !isspace (c); i++);
+ for (i = 0; i < 8 && (c = filename[i] = tolower ((uint8_t)dir_buf[i]))
+ && !isspace ((uint8_t)c); i++);
filename[i++] = '.';
- for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j]))
- && !isspace (c); j++);
+ for (j = 0; j < 3 && (c = filename[i + j] = tolower ((uint8_t)dir_buf[8 + j]))
+ && !isspace ((uint8_t)c); j++);
if (j == 0)
i--;
diff --git a/tools/libfsimage/iso9660/fsys_iso9660.c b/tools/libfsimage/iso9660/fsys_iso9660.c
index 31a317a637..20254ba4f5 100644
--- a/tools/libfsimage/iso9660/fsys_iso9660.c
+++ b/tools/libfsimage/iso9660/fsys_iso9660.c
@@ -164,7 +164,7 @@ iso9660_dir (fsi_file_t *ffi, char *dirname)
/* pathlen = strcspn(dirname, "/\n\t "); */
for (pathlen = 0 ;
dirname[pathlen]
- && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ;
+ && !isspace((uint8_t)dirname[pathlen]) && dirname[pathlen] != '/' ;
pathlen++)
;
diff --git a/tools/libfsimage/reiserfs/fsys_reiserfs.c b/tools/libfsimage/reiserfs/fsys_reiserfs.c
index 6bf6067ded..9ec173bf6d 100644
--- a/tools/libfsimage/reiserfs/fsys_reiserfs.c
+++ b/tools/libfsimage/reiserfs/fsys_reiserfs.c
@@ -1029,7 +1029,7 @@ reiserfs_dir (fsi_file_t *ffi, char *dirname)
/* Find out how long our remaining name is. */
len = 0;
- while (dirname[len] && !isspace (dirname[len]))
+ while (dirname[len] && !isspace ((uint8_t)dirname[len]))
len++;
if (filemax + len > sizeof (linkbuf) - 1)
@@ -1078,7 +1078,7 @@ reiserfs_dir (fsi_file_t *ffi, char *dirname)
/* if we have a real file (and we're not just printing possibilities),
then this is where we want to exit */
- if (! *dirname || isspace (*dirname))
+ if (! *dirname || isspace ((uint8_t)*dirname))
{
if (! S_ISREG (mode))
{
@@ -1109,7 +1109,7 @@ reiserfs_dir (fsi_file_t *ffi, char *dirname)
errnum = ERR_BAD_FILETYPE;
return 0;
}
- for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
+ for (rest = dirname; (ch = *rest) && ! isspace ((uint8_t)ch) && ch != '/'; rest++);
*rest = 0;
# ifndef STAGE1_5
diff --git a/tools/libfsimage/ufs/fsys_ufs.c b/tools/libfsimage/ufs/fsys_ufs.c
index d187dbf414..a92a6e5307 100644
--- a/tools/libfsimage/ufs/fsys_ufs.c
+++ b/tools/libfsimage/ufs/fsys_ufs.c
@@ -72,13 +72,13 @@ ufs_dir(fsi_file_t *ffi, char *dirname)
while (*dirname == '/')
dirname++;
- while (inode && *dirname && !isspace(*dirname)) {
+ while (inode && *dirname && !isspace((uint8_t)*dirname)) {
if (!openi(ffi, inode))
return 0;
/* parse for next path component */
fname = dirname;
- while (*dirname && !isspace(*dirname) && *dirname != '/')
+ while (*dirname && !isspace((uint8_t)*dirname) && *dirname != '/')
dirname++;
ch = *dirname;
*dirname = 0; /* ensure null termination */
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 102653ff95..7a273c70f8 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -23,6 +23,7 @@ CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c
+CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
GUEST_SRCS-y :=
GUEST_SRCS-y += xg_private.c
diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c
index b404730800..defe8ca5dd 100644
--- a/tools/libxc/xc_core.c
+++ b/tools/libxc/xc_core.c
@@ -58,6 +58,9 @@
/* number of pages to write at a time */
#define DUMP_INCREMENT (4 * 1024)
+/* Don't yet support cross-address-size core dump */
+#define guest_width (sizeof (unsigned long))
+
/* string table */
struct xc_core_strtab {
char *strings;
diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c
index 4aa825b87d..fa92934ea6 100644
--- a/tools/libxc/xc_core_x86.c
+++ b/tools/libxc/xc_core_x86.c
@@ -21,6 +21,9 @@
#include "xg_private.h"
#include "xc_core.h"
+/* Don't yet support cross-address-size core dump */
+#define guest_width (sizeof (unsigned long))
+
static int nr_gpfns(int xc_handle, domid_t domid)
{
return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid) + 1;
diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c
index a9d6b5a9a5..e26941f737 100644
--- a/tools/libxc/xc_dom_boot.c
+++ b/tools/libxc/xc_dom_boot.c
@@ -152,6 +152,7 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
privcmd_mmap_entry_t *entries;
void *ptr;
int i, rc;
+ int err;
entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t));
if ( entries == NULL )
@@ -166,9 +167,11 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
MAP_SHARED, dom->guest_xc, 0);
if ( ptr == MAP_FAILED )
{
+ err = errno;
xc_dom_panic(XC_INTERNAL_ERROR,
"%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
- " [mmap]\n", __FUNCTION__, pfn, count);
+ " [mmap, errno=%i (%s)]\n", __FUNCTION__, pfn, count,
+ err, strerror(err));
return NULL;
}
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
index c338498f08..0375e41208 100644
--- a/tools/libxc/xc_dom_core.c
+++ b/tools/libxc/xc_dom_core.c
@@ -122,7 +122,7 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
memset(block, 0, sizeof(*block));
block->mmap_len = size;
block->mmap_ptr = mmap(NULL, block->mmap_len,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
-1, 0);
if ( block->mmap_ptr == MAP_FAILED )
{
@@ -354,7 +354,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
{
mode = "anonymous memory";
phys->ptr = mmap(NULL, phys->count << page_shift,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
-1, 0);
if ( phys->ptr == MAP_FAILED )
{
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index fdb87f0bd1..3c3bb351f6 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -734,6 +734,114 @@ int xc_domain_setdebugging(int xc_handle,
return do_domctl(xc_handle, &domctl);
}
+int xc_assign_device(
+ int xc_handle,
+ uint32_t domid,
+ uint32_t machine_bdf)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_assign_device;
+ domctl.domain = domid;
+ domctl.u.assign_device.machine_bdf = machine_bdf;
+
+ return do_domctl(xc_handle, &domctl);
+}
+
+/* Pass-through: binds machine irq to guests irq */
+int xc_domain_bind_pt_irq(
+ int xc_handle,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t irq_type,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx,
+ uint8_t isa_irq)
+{
+ int rc;
+ xen_domctl_bind_pt_irq_t * bind;
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_bind_pt_irq;
+ domctl.domain = (domid_t)domid;
+
+ bind = &(domctl.u.bind_pt_irq);
+ bind->hvm_domid = domid;
+ bind->irq_type = irq_type;
+ bind->machine_irq = machine_irq;
+ bind->u.pci.bus = bus;
+ bind->u.pci.device = device;
+ bind->u.pci.intx = intx;
+ bind->u.isa.isa_irq = isa_irq;
+
+ rc = do_domctl(xc_handle, &domctl);
+ return rc;
+}
+
+int xc_domain_bind_pt_pci_irq(
+ int xc_handle,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx)
+{
+
+ return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
+ PT_IRQ_TYPE_PCI, bus, device, intx, 0));
+}
+
+int xc_domain_bind_pt_isa_irq(
+ int xc_handle,
+ uint32_t domid,
+ uint8_t machine_irq)
+{
+
+ return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
+ PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
+}
+
+int xc_domain_memory_mapping(
+ int xc_handle,
+ uint32_t domid,
+ unsigned long first_gfn,
+ unsigned long first_mfn,
+ unsigned long nr_mfns,
+ uint32_t add_mapping)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_memory_mapping;
+ domctl.domain = domid;
+ domctl.u.memory_mapping.first_gfn = first_gfn;
+ domctl.u.memory_mapping.first_mfn = first_mfn;
+ domctl.u.memory_mapping.nr_mfns = nr_mfns;
+ domctl.u.memory_mapping.add_mapping = add_mapping;
+
+ return do_domctl(xc_handle, &domctl);
+}
+
+int xc_domain_ioport_mapping(
+ int xc_handle,
+ uint32_t domid,
+ uint32_t first_gport,
+ uint32_t first_mport,
+ uint32_t nr_ports,
+ uint32_t add_mapping)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_ioport_mapping;
+ domctl.domain = domid;
+ domctl.u.ioport_mapping.first_gport = first_gport;
+ domctl.u.ioport_mapping.first_mport = first_mport;
+ domctl.u.ioport_mapping.nr_ports = nr_ports;
+ domctl.u.ioport_mapping.add_mapping = add_mapping;
+
+ return do_domctl(xc_handle, &domctl);
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 3a26669aa7..fd1f1e5ca8 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -56,6 +56,10 @@ static xen_pfn_t *p2m = NULL;
/* A table of P2M mappings in the current region */
static xen_pfn_t *p2m_batch = NULL;
+/* Address size of the guest, in bytes */
+unsigned int guest_width;
+
+
static ssize_t
read_exact(int fd, void *buf, size_t count)
{
@@ -168,22 +172,17 @@ static int uncanonicalize_pagetable(int xc_handle, uint32_t dom,
static xen_pfn_t *load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
{
xen_pfn_t *p2m_frame_list;
- vcpu_guest_context_t ctxt;
+ vcpu_guest_context_either_t ctxt;
+ xen_pfn_t p2m_fl_zero;
- if ( (p2m_frame_list = malloc(P2M_FL_SIZE)) == NULL )
- {
- ERROR("Couldn't allocate p2m_frame_list array");
- return NULL;
- }
-
/* Read first entry of P2M list, or extended-info signature (~0UL). */
- if ( !read_exact(io_fd, p2m_frame_list, sizeof(long)) )
+ if ( !read_exact(io_fd, &p2m_fl_zero, sizeof(long)) )
{
ERROR("read extended-info signature failed");
return NULL;
}
- if ( p2m_frame_list[0] == ~0UL )
+ if ( p2m_fl_zero == ~0UL )
{
uint32_t tot_bytes;
@@ -211,25 +210,42 @@ static xen_pfn_t *load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
/* VCPU context structure? */
if ( !strncmp(chunk_sig, "vcpu", 4) )
{
- if ( !read_exact(io_fd, &ctxt, sizeof(ctxt)) )
+ /* Pick a guest word-size and PT depth from the ctxt size */
+ if ( chunk_bytes == sizeof (ctxt.x32) )
+ {
+ guest_width = 4;
+ if ( pt_levels > 2 )
+ pt_levels = 3;
+ }
+ else if ( chunk_bytes == sizeof (ctxt.x64) )
+ {
+ guest_width = 8;
+ pt_levels = 4;
+ }
+ else
+ {
+ ERROR("bad extended-info context size %d", chunk_bytes);
+ return NULL;
+ }
+
+ if ( !read_exact(io_fd, &ctxt, chunk_bytes) )
{
ERROR("read extended-info vcpu context failed");
return NULL;
}
- tot_bytes -= sizeof(struct vcpu_guest_context);
- chunk_bytes -= sizeof(struct vcpu_guest_context);
-
- if ( ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3) )
+ tot_bytes -= chunk_bytes;
+ chunk_bytes = 0;
+
+ if ( GET_FIELD(&ctxt, vm_assist)
+ & (1UL << VMASST_TYPE_pae_extended_cr3) )
*pae_extended_cr3 = 1;
}
/* Any remaining bytes of this chunk: read and discard. */
while ( chunk_bytes )
{
- unsigned long sz = chunk_bytes;
- if ( sz > P2M_FL_SIZE )
- sz = P2M_FL_SIZE;
- if ( !read_exact(io_fd, p2m_frame_list, sz) )
+ unsigned long sz = MIN(chunk_bytes, sizeof(xen_pfn_t));
+ if ( !read_exact(io_fd, &p2m_fl_zero, sz) )
{
ERROR("read-and-discard extended-info chunk bytes failed");
return NULL;
@@ -240,15 +256,25 @@ static xen_pfn_t *load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
}
/* Now read the real first entry of P2M list. */
- if ( !read_exact(io_fd, p2m_frame_list, sizeof(long)) )
+ if ( !read_exact(io_fd, &p2m_fl_zero, sizeof(xen_pfn_t)) )
{
ERROR("read first entry of p2m_frame_list failed");
return NULL;
}
}
- /* First entry is already read into the p2m array. */
- if ( !read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long)) )
+ /* Now that we know the guest's word-size, can safely allocate
+ * the p2m frame list */
+ if ( (p2m_frame_list = malloc(P2M_FL_SIZE)) == NULL )
+ {
+ ERROR("Couldn't allocate p2m_frame_list array");
+ return NULL;
+ }
+
+ /* First entry has already been read. */
+ p2m_frame_list[0] = p2m_fl_zero;
+ if ( !read_exact(io_fd, &p2m_frame_list[1],
+ (P2M_FL_ENTRIES - 1) * sizeof(xen_pfn_t)) )
{
ERROR("read p2m_frame_list failed");
return NULL;
@@ -272,11 +298,11 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
- shared_info_t *old_shared_info = (shared_info_t *)shared_info_page;
- shared_info_t *new_shared_info;
+ shared_info_either_t *old_shared_info = (shared_info_either_t *)shared_info_page;
+ shared_info_either_t *new_shared_info;
/* A copy of the CPU context of the guest. */
- vcpu_guest_context_t ctxt;
+ vcpu_guest_context_either_t ctxt;
/* A table containing the type of each PFN (/not/ MFN!). */
unsigned long *pfn_type = NULL;
@@ -291,7 +317,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
xen_pfn_t *p2m_frame_list = NULL;
/* A temporary mapping of the guest's start_info page. */
- start_info_t *start_info;
+ start_info_either_t *start_info;
/* Our mapping of the current region (batch) */
char *region_base;
@@ -324,32 +350,19 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
}
DPRINTF("xc_domain_restore start: p2m_size = %lx\n", p2m_size);
- if ( !hvm )
- {
- /*
- * XXX For now, 32bit dom0's can only save/restore 32bit domUs
- * on 64bit hypervisors.
- */
- memset(&domctl, 0, sizeof(domctl));
- domctl.domain = dom;
- domctl.cmd = XEN_DOMCTL_set_address_size;
- domctl.u.address_size.size = sizeof(unsigned long) * 8;
- rc = do_domctl(xc_handle, &domctl);
- if ( rc != 0 )
- {
- ERROR("Unable to set guest address size.");
- goto out;
- }
- rc = 1;
- }
-
if ( !get_platform_info(xc_handle, dom,
- &max_mfn, &hvirt_start, &pt_levels) )
+ &max_mfn, &hvirt_start, &pt_levels, &guest_width) )
{
ERROR("Unable to get platform info.");
return 1;
}
-
+
+ /* The *current* word size of the guest isn't very interesting; for now
+ * assume the guest will be the same as we are. We'll fix that later
+ * if we discover otherwise. */
+ guest_width = sizeof(unsigned long);
+ pt_levels = (guest_width == 8) ? 4 : (pt_levels == 2) ? 2 : 3;
+
if ( lock_pages(&ctxt, sizeof(ctxt)) )
{
/* needed for build domctl, but might as well do early */
@@ -357,16 +370,29 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
return 1;
}
- /* Load the p2m frame list, plus potential extended info chunk */
if ( !hvm )
{
+ /* Load the p2m frame list, plus potential extended info chunk */
p2m_frame_list = load_p2m_frame_list(io_fd, &pae_extended_cr3);
if ( !p2m_frame_list )
goto out;
+
+ /* Now that we know the word size, tell Xen about it */
+ memset(&domctl, 0, sizeof(domctl));
+ domctl.domain = dom;
+ domctl.cmd = XEN_DOMCTL_set_address_size;
+ domctl.u.address_size.size = guest_width * 8;
+ rc = do_domctl(xc_handle, &domctl);
+ if ( rc != 0 )
+ {
+ ERROR("Unable to set guest address size.");
+ goto out;
+ }
+ rc = 1;
}
/* We want zeroed memory so use calloc rather than malloc. */
- p2m = calloc(p2m_size, sizeof(xen_pfn_t));
+ p2m = calloc(p2m_size, MAX(guest_width, sizeof (xen_pfn_t)));
pfn_type = calloc(p2m_size, sizeof(unsigned long));
region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
p2m_batch = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
@@ -963,14 +989,16 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
if ( !(vcpumap & (1ULL << i)) )
continue;
- if ( !read_exact(io_fd, &ctxt, sizeof(ctxt)) )
+ if ( !read_exact(io_fd, &ctxt, ((guest_width == 8)
+ ? sizeof(ctxt.x64)
+ : sizeof(ctxt.x32))) )
{
ERROR("Error when reading ctxt %d", i);
goto out;
}
if ( !new_ctxt_format )
- ctxt.flags |= VGCF_online;
+ SET_FIELD(&ctxt, flags, GET_FIELD(&ctxt, flags) | VGCF_online);
if ( i == 0 )
{
@@ -978,48 +1006,49 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
* Uncanonicalise the suspend-record frame number and poke
* resume record.
*/
- pfn = ctxt.user_regs.edx;
+ pfn = GET_FIELD(&ctxt, user_regs.edx);
if ( (pfn >= p2m_size) ||
(pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
ERROR("Suspend record frame number is bad");
goto out;
}
- ctxt.user_regs.edx = mfn = p2m[pfn];
+ mfn = p2m[pfn];
+ SET_FIELD(&ctxt, user_regs.edx, mfn);
start_info = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
- start_info->nr_pages = p2m_size;
- start_info->shared_info = shared_info_frame << PAGE_SHIFT;
- start_info->flags = 0;
- *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn];
- start_info->store_evtchn = store_evtchn;
- start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
- start_info->console.domU.evtchn = console_evtchn;
- *console_mfn = start_info->console.domU.mfn;
+ SET_FIELD(start_info, nr_pages, p2m_size);
+ SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
+ SET_FIELD(start_info, flags, 0);
+ *store_mfn = p2m[GET_FIELD(start_info, store_mfn)];
+ SET_FIELD(start_info, store_mfn, *store_mfn);
+ SET_FIELD(start_info, store_evtchn, store_evtchn);
+ *console_mfn = p2m[GET_FIELD(start_info, console.domU.mfn)];
+ SET_FIELD(start_info, console.domU.mfn, *console_mfn);
+ SET_FIELD(start_info, console.domU.evtchn, console_evtchn);
munmap(start_info, PAGE_SIZE);
}
-
/* Uncanonicalise each GDT frame number. */
- if ( ctxt.gdt_ents > 8192 )
+ if ( GET_FIELD(&ctxt, gdt_ents) > 8192 )
{
ERROR("GDT entry count out of range");
goto out;
}
- for ( j = 0; (512*j) < ctxt.gdt_ents; j++ )
+ for ( j = 0; (512*j) < GET_FIELD(&ctxt, gdt_ents); j++ )
{
- pfn = ctxt.gdt_frames[j];
+ pfn = GET_FIELD(&ctxt, gdt_frames[j]);
if ( (pfn >= p2m_size) ||
(pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
- ERROR("GDT frame number is bad");
+ ERROR("GDT frame number %i (0x%lx) is bad",
+ j, (unsigned long)pfn);
goto out;
}
- ctxt.gdt_frames[j] = p2m[pfn];
+ SET_FIELD(&ctxt, gdt_frames[j], p2m[pfn]);
}
-
/* Uncanonicalise the page table base pointer. */
- pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
+ pfn = xen_cr3_to_pfn(GET_FIELD(&ctxt, ctrlreg[3]));
if ( pfn >= p2m_size )
{
@@ -1036,21 +1065,18 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
(unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
-
- ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
+ SET_FIELD(&ctxt, ctrlreg[3], xen_pfn_to_cr3(p2m[pfn]));
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
- if ( (pt_levels == 4) && ctxt.ctrlreg[1] )
+ if ( (pt_levels == 4) && (ctxt.x64.ctrlreg[1] & 1) )
{
- pfn = xen_cr3_to_pfn(ctxt.ctrlreg[1]);
-
+ pfn = xen_cr3_to_pfn(ctxt.x64.ctrlreg[1] & ~1);
if ( pfn >= p2m_size )
{
- ERROR("User PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
- pfn, p2m_size, pfn_type[pfn]);
+ ERROR("User PT base is bad: pfn=%lu p2m_size=%lu",
+ pfn, p2m_size);
goto out;
}
-
if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) )
{
@@ -1059,14 +1085,12 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
(unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
-
- ctxt.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
+ ctxt.x64.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
}
-
domctl.cmd = XEN_DOMCTL_setvcpucontext;
domctl.domain = (domid_t)dom;
domctl.u.vcpucontext.vcpu = i;
- set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
+ set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt.c);
rc = xc_domctl(xc_handle, &domctl);
if ( rc != 0 )
{
@@ -1087,22 +1111,16 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
xc_handle, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
/* restore saved vcpu_info and arch specific info */
- memcpy(&new_shared_info->vcpu_info,
- &old_shared_info->vcpu_info,
- sizeof(new_shared_info->vcpu_info));
- memcpy(&new_shared_info->arch,
- &old_shared_info->arch,
- sizeof(new_shared_info->arch));
+ MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
+ MEMCPY_FIELD(new_shared_info, old_shared_info, arch);
/* clear any pending events and the selector */
- memset(&(new_shared_info->evtchn_pending[0]), 0,
- sizeof (new_shared_info->evtchn_pending));
+ MEMSET_ARRAY_FIELD(new_shared_info, evtchn_pending, 0);
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
- new_shared_info->vcpu_info[i].evtchn_pending_sel = 0;
+ SET_FIELD(new_shared_info, vcpu_info[i].evtchn_pending_sel, 0);
/* mask event channels */
- memset(&(new_shared_info->evtchn_mask[0]), 0xff,
- sizeof (new_shared_info->evtchn_mask));
+ MEMSET_ARRAY_FIELD(new_shared_info, evtchn_mask, 0xff);
/* leave wallclock time. set by hypervisor */
munmap(new_shared_info, PAGE_SIZE);
@@ -1113,10 +1131,9 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
pfn = p2m_frame_list[i];
if ( (pfn >= p2m_size) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
- ERROR("PFN-to-MFN frame number is bad");
+ ERROR("PFN-to-MFN frame number %i (%#lx) is bad", i, pfn);
goto out;
}
-
p2m_frame_list[i] = p2m[pfn];
}
@@ -1128,8 +1145,17 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
goto out;
}
- memcpy(live_p2m, p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
- munmap(live_p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
+ /* If the domain we're restoring has a different word size to ours,
+ * we need to repack the p2m appropriately */
+ if ( guest_width > sizeof (xen_pfn_t) )
+ for ( i = p2m_size - 1; i >= 0; i-- )
+ ((uint64_t *)p2m)[i] = p2m[i];
+ else if ( guest_width > sizeof (xen_pfn_t) )
+ for ( i = 0; i < p2m_size; i++ )
+ ((uint32_t *)p2m)[i] = p2m[i];
+
+ memcpy(live_p2m, p2m, ROUNDUP(p2m_size * guest_width, PAGE_SHIFT));
+ munmap(live_p2m, ROUNDUP(p2m_size * guest_width, PAGE_SHIFT));
DPRINTF("Domain ready to be built.\n");
rc = 0;
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index abd3cedf32..8bd1248ebc 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -54,9 +54,17 @@ static xen_pfn_t *live_p2m = NULL;
static xen_pfn_t *live_m2p = NULL;
static unsigned long m2p_mfn0;
+/* Address size of the guest */
+unsigned int guest_width;
+
/* grep fodder: machine_to_phys */
-#define mfn_to_pfn(_mfn) live_m2p[(_mfn)]
+#define mfn_to_pfn(_mfn) (live_m2p[(_mfn)])
+
+#define pfn_to_mfn(_pfn) \
+ ((xen_pfn_t) ((guest_width==8) \
+ ? (((uint64_t *)live_p2m)[(_pfn)]) \
+ : (((uint32_t *)live_p2m)[(_pfn)])))
/*
* Returns TRUE if the given machine frame number has a unique mapping
@@ -65,19 +73,7 @@ static unsigned long m2p_mfn0;
#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
(((_mfn) < (max_mfn)) && \
((mfn_to_pfn(_mfn) < (p2m_size)) && \
- (live_p2m[mfn_to_pfn(_mfn)] == (_mfn))))
-
-/* Returns TRUE if MFN is successfully converted to a PFN. */
-#define translate_mfn_to_pfn(_pmfn) \
-({ \
- unsigned long mfn = *(_pmfn); \
- int _res = 1; \
- if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \
- _res = 0; \
- else \
- *(_pmfn) = mfn_to_pfn(mfn); \
- _res; \
-})
+ (pfn_to_mfn(mfn_to_pfn(_mfn)) == (_mfn))))
/*
** During (live) save/migrate, we maintain a number of bitmaps to track
@@ -451,22 +447,25 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
** it to update the MFN to a reasonable value.
*/
static void *map_frame_list_list(int xc_handle, uint32_t dom,
- shared_info_t *shinfo)
+ shared_info_either_t *shinfo)
{
int count = 100;
void *p;
+ uint64_t fll = GET_FIELD(shinfo, arch.pfn_to_mfn_frame_list_list);
- while ( count-- && (shinfo->arch.pfn_to_mfn_frame_list_list == 0) )
+ while ( count-- && (fll == 0) )
+ {
usleep(10000);
+ fll = GET_FIELD(shinfo, arch.pfn_to_mfn_frame_list_list);
+ }
- if ( shinfo->arch.pfn_to_mfn_frame_list_list == 0 )
+ if ( fll == 0 )
{
ERROR("Timed out waiting for frame list updated.");
return NULL;
}
- p = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ,
- shinfo->arch.pfn_to_mfn_frame_list_list);
+ p = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, fll);
if ( p == NULL )
ERROR("Couldn't map p2m_frame_list_list (errno %d)", errno);
@@ -659,15 +658,16 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
int io_fd,
uint32_t dom,
unsigned long p2m_size,
- shared_info_t *live_shinfo)
+ shared_info_either_t *live_shinfo)
{
- vcpu_guest_context_t ctxt;
+ vcpu_guest_context_either_t ctxt;
/* Double and single indirect references to the live P2M table */
- xen_pfn_t *live_p2m_frame_list_list = NULL;
- xen_pfn_t *live_p2m_frame_list = NULL;
+ void *live_p2m_frame_list_list = NULL;
+ void *live_p2m_frame_list = NULL;
- /* A copy of the pfn-to-mfn table frame list. */
+ /* Copies of the above. */
+ xen_pfn_t *p2m_frame_list_list = NULL;
xen_pfn_t *p2m_frame_list = NULL;
/* The mapping of the live p2m table itself */
@@ -680,9 +680,28 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
if ( !live_p2m_frame_list_list )
goto out;
+ /* Get a local copy of the live_P2M_frame_list_list */
+ if ( !(p2m_frame_list_list = malloc(PAGE_SIZE)) )
+ {
+ ERROR("Couldn't allocate p2m_frame_list_list array");
+ goto out;
+ }
+ memcpy(p2m_frame_list_list, live_p2m_frame_list_list, PAGE_SIZE);
+
+ /* Canonicalize guest's unsigned long vs ours */
+ if ( guest_width > sizeof(unsigned long) )
+ for ( i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++ )
+ if ( i < PAGE_SIZE/guest_width )
+ p2m_frame_list_list[i] = ((uint64_t *)p2m_frame_list_list)[i];
+ else
+ p2m_frame_list_list[i] = 0;
+ else if ( guest_width < sizeof(unsigned long) )
+ for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i++ )
+ p2m_frame_list_list[i] = ((uint32_t *)p2m_frame_list_list)[i];
+
live_p2m_frame_list =
xc_map_foreign_batch(xc_handle, dom, PROT_READ,
- live_p2m_frame_list_list,
+ p2m_frame_list_list,
P2M_FLL_ENTRIES);
if ( !live_p2m_frame_list )
{
@@ -690,6 +709,22 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
goto out;
}
+ /* Get a local copy of the live_P2M_frame_list */
+ if ( !(p2m_frame_list = malloc(P2M_FL_SIZE)) )
+ {
+ ERROR("Couldn't allocate p2m_frame_list array");
+ goto out;
+ }
+ memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE);
+
+ /* Canonicalize guest's unsigned long vs ours */
+ if ( guest_width > sizeof(unsigned long) )
+ for ( i = 0; i < P2M_FL_ENTRIES; i++ )
+ p2m_frame_list[i] = ((uint64_t *)p2m_frame_list)[i];
+ else if ( guest_width < sizeof(unsigned long) )
+ for ( i = P2M_FL_ENTRIES - 1; i >= 0; i++ )
+ p2m_frame_list[i] = ((uint32_t *)p2m_frame_list)[i];
+
/* Map all the frames of the pfn->mfn table. For migrate to succeed,
the guest must not change which frames are used for this purpose.
@@ -697,7 +732,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
from a safety POV anyhow. */
p2m = xc_map_foreign_batch(xc_handle, dom, PROT_READ,
- live_p2m_frame_list,
+ p2m_frame_list,
P2M_FL_ENTRIES);
if ( !p2m )
{
@@ -706,27 +741,30 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
}
live_p2m = p2m; /* So that translation macros will work */
- /* Get a local copy of the live_P2M_frame_list */
- if ( !(p2m_frame_list = malloc(P2M_FL_SIZE)) )
- {
- ERROR("Couldn't allocate p2m_frame_list array");
- goto out;
- }
- memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE);
-
/* Canonicalise the pfn-to-mfn table frame-number list. */
- for ( i = 0; i < p2m_size; i += fpp )
+ for ( i = 0; i < p2m_size; i += FPP )
{
- if ( !translate_mfn_to_pfn(&p2m_frame_list[i/fpp]) )
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(p2m_frame_list[i/FPP]) )
{
ERROR("Frame# in pfn-to-mfn frame list is not in pseudophys");
- ERROR("entry %d: p2m_frame_list[%ld] is 0x%"PRIx64, i, i/fpp,
- (uint64_t)p2m_frame_list[i/fpp]);
+ ERROR("entry %d: p2m_frame_list[%ld] is 0x%"PRIx64", max 0x%lx",
+ i, i/FPP, (uint64_t)p2m_frame_list[i/FPP], max_mfn);
+ if ( p2m_frame_list[i/FPP] < max_mfn )
+ {
+ ERROR("m2p[0x%"PRIx64"] = 0x%"PRIx64,
+ (uint64_t)p2m_frame_list[i/FPP],
+ (uint64_t)live_m2p[p2m_frame_list[i/FPP]]);
+ ERROR("p2m[0x%"PRIx64"] = 0x%"PRIx64,
+ (uint64_t)live_m2p[p2m_frame_list[i/FPP]],
+ (uint64_t)p2m[live_m2p[p2m_frame_list[i/FPP]]]);
+
+ }
goto out;
}
+ p2m_frame_list[i/FPP] = mfn_to_pfn(p2m_frame_list[i/FPP]);
}
- if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
+ if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt.c) )
{
ERROR("Could not get vcpu context");
goto out;
@@ -737,25 +775,26 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
* a PAE guest understands extended CR3 (PDPTs above 4GB). Turns off
* slow paths in the restore code.
*/
- if ( (pt_levels == 3) &&
- (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) )
{
unsigned long signature = ~0UL;
- uint32_t tot_sz = sizeof(struct vcpu_guest_context) + 8;
- uint32_t chunk_sz = sizeof(struct vcpu_guest_context);
+ uint32_t chunk_sz = ((guest_width==8)
+ ? sizeof(ctxt.x64)
+ : sizeof(ctxt.x32));
+ uint32_t tot_sz = chunk_sz + 8;
char chunk_sig[] = "vcpu";
if ( !write_exact(io_fd, &signature, sizeof(signature)) ||
!write_exact(io_fd, &tot_sz, sizeof(tot_sz)) ||
!write_exact(io_fd, &chunk_sig, 4) ||
!write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) ||
- !write_exact(io_fd, &ctxt, sizeof(ctxt)) )
+ !write_exact(io_fd, &ctxt, chunk_sz) )
{
ERROR("write: extended info");
goto out;
}
}
- if ( !write_exact(io_fd, p2m_frame_list, P2M_FL_SIZE) )
+ if ( !write_exact(io_fd, p2m_frame_list,
+ P2M_FL_ENTRIES * sizeof(xen_pfn_t)) )
{
ERROR("write: p2m_frame_list");
goto out;
@@ -774,6 +813,9 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
if ( live_p2m_frame_list )
munmap(live_p2m_frame_list, P2M_FLL_ENTRIES * PAGE_SIZE);
+ if ( p2m_frame_list_list )
+ free(p2m_frame_list_list);
+
if ( p2m_frame_list )
free(p2m_frame_list);
@@ -789,7 +831,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
{
xc_dominfo_t info;
- int rc = 1, i, j, last_iter, iter = 0;
+ int rc = 1, frc, i, j, last_iter, iter = 0;
int live = (flags & XCFLAGS_LIVE);
int debug = (flags & XCFLAGS_DEBUG);
int race = 0, sent_last_iter, skip_this_iter;
@@ -798,7 +840,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
unsigned long shared_info_frame;
/* A copy of the CPU context of the guest. */
- vcpu_guest_context_t ctxt;
+ vcpu_guest_context_either_t ctxt;
/* A table containing the type of each PFN (/not/ MFN!). */
unsigned long *pfn_type = NULL;
@@ -808,7 +850,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
char page[PAGE_SIZE];
/* Live mapping of shared info structure */
- shared_info_t *live_shinfo = NULL;
+ shared_info_either_t *live_shinfo = NULL;
/* base of the region in which domain memory is mapped */
unsigned char *region_base = NULL;
@@ -836,6 +878,8 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* HVM: magic frames for ioreqs and xenstore comms. */
uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */
+ unsigned long mfn;
+
/* If no explicit control parameters given, use defaults */
max_iters = max_iters ? : DEF_MAX_ITERS;
max_factor = max_factor ? : DEF_MAX_FACTOR;
@@ -843,7 +887,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
initialize_mbit_rate();
if ( !get_platform_info(xc_handle, dom,
- &max_mfn, &hvirt_start, &pt_levels) )
+ &max_mfn, &hvirt_start, &pt_levels, &guest_width) )
{
ERROR("Unable to get platform info.");
return 1;
@@ -882,13 +926,18 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
{
/* log-dirty already enabled? There's no test op,
so attempt to disable then reenable it */
- if ( !(xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_OFF,
- NULL, 0, NULL, 0, NULL) >= 0 &&
- xc_shadow_control(xc_handle, dom,
- XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
- NULL, 0, NULL, 0, NULL) >= 0) )
+ frc = xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_OFF,
+ NULL, 0, NULL, 0, NULL);
+ if ( frc >= 0 )
+ {
+ frc = xc_shadow_control(xc_handle, dom,
+ XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
+ NULL, 0, NULL, 0, NULL);
+ }
+
+ if ( frc < 0 )
{
- ERROR("Couldn't enable shadow mode");
+ ERROR("Couldn't enable shadow mode (rc %d) (errno %d)", frc, errno );
goto out;
}
}
@@ -1001,7 +1050,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if ( !hvm )
{
int err = 0;
- unsigned long mfn;
/* Map the P2M table, and write the list of P2M frames */
live_p2m = map_and_save_p2m_table(xc_handle, io_fd, dom,
@@ -1018,7 +1066,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
for ( i = 0; i < p2m_size; i++ )
{
- mfn = live_p2m[i];
+ mfn = pfn_to_mfn(i);
if( (mfn != INVALID_P2M_ENTRY) && (mfn_to_pfn(mfn) != i) )
{
DPRINTF("i=0x%x mfn=%lx live_m2p=%lx\n", i,
@@ -1078,11 +1126,16 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
int n = permute(N, p2m_size, order_nr);
if ( debug )
- DPRINTF("%d pfn= %08lx mfn= %08lx %d [mfn]= %08lx\n",
- iter, (unsigned long)n, hvm ? 0 : live_p2m[n],
- test_bit(n, to_send),
- hvm ? 0 : mfn_to_pfn(live_p2m[n]&0xFFFFF));
-
+ {
+ DPRINTF("%d pfn= %08lx mfn= %08lx %d",
+ iter, (unsigned long)n,
+ hvm ? 0 : pfn_to_mfn(n),
+ test_bit(n, to_send));
+ if ( !hvm && is_mapped(pfn_to_mfn(n)) )
+ DPRINTF(" [mfn]= %08lx",
+ mfn_to_pfn(pfn_to_mfn(n)&0xFFFFF));
+ DPRINTF("\n");
+ }
if ( !last_iter &&
test_bit(n, to_send) &&
test_bit(n, to_skip) )
@@ -1113,7 +1166,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if ( hvm )
pfn_type[batch] = n;
else
- pfn_type[batch] = live_p2m[n];
+ pfn_type[batch] = pfn_to_mfn(n);
if ( !is_mapped(pfn_type[batch]) )
{
@@ -1446,7 +1499,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
for ( i = 0, j = 0; i < p2m_size; i++ )
{
- if ( !is_mapped(live_p2m[i]) )
+ if ( !is_mapped(pfn_to_mfn(i)) )
j++;
}
@@ -1458,7 +1511,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
for ( i = 0, j = 0; i < p2m_size; )
{
- if ( !is_mapped(live_p2m[i]) )
+ if ( !is_mapped(pfn_to_mfn(i)) )
pfntab[j++] = i;
i++;
@@ -1475,63 +1528,75 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
}
- if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
+ if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt.c) )
{
ERROR("Could not get vcpu context");
goto out;
}
/* Canonicalise the suspend-record frame number. */
- if ( !translate_mfn_to_pfn(&ctxt.user_regs.edx) )
+ mfn = GET_FIELD(&ctxt, user_regs.edx);
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
ERROR("Suspend record is not in range of pseudophys map");
goto out;
}
+ SET_FIELD(&ctxt, user_regs.edx, mfn_to_pfn(mfn));
for ( i = 0; i <= info.max_vcpu_id; i++ )
{
if ( !(vcpumap & (1ULL << i)) )
continue;
- if ( (i != 0) && xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) )
+ if ( (i != 0) && xc_vcpu_getcontext(xc_handle, dom, i, &ctxt.c) )
{
ERROR("No context for VCPU%d", i);
goto out;
}
/* Canonicalise each GDT frame number. */
- for ( j = 0; (512*j) < ctxt.gdt_ents; j++ )
+ for ( j = 0; (512*j) < GET_FIELD(&ctxt, gdt_ents); j++ )
{
- if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[j]) )
+ mfn = GET_FIELD(&ctxt, gdt_frames[j]);
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
ERROR("GDT frame is not in range of pseudophys map");
goto out;
}
+ SET_FIELD(&ctxt, gdt_frames[j], mfn_to_pfn(mfn));
}
/* Canonicalise the page table base pointer. */
- if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) )
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(
+ GET_FIELD(&ctxt, ctrlreg[3]))) )
{
ERROR("PT base is not in range of pseudophys map");
goto out;
}
- ctxt.ctrlreg[3] =
- xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3])));
+ SET_FIELD(&ctxt, ctrlreg[3],
+ xen_pfn_to_cr3(
+ mfn_to_pfn(
+ xen_cr3_to_pfn(
+ GET_FIELD(&ctxt, ctrlreg[3])))));
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
- if ( (pt_levels == 4) && ctxt.ctrlreg[1] )
+ if ( (pt_levels == 4) && ctxt.x64.ctrlreg[1] )
{
- if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[1])) )
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(
+ xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])) )
{
ERROR("PT base is not in range of pseudophys map");
goto out;
}
/* Least-significant bit means 'valid PFN'. */
- ctxt.ctrlreg[1] = 1 |
- xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[1])));
+ ctxt.x64.ctrlreg[1] = 1 |
+ xen_pfn_to_cr3(
+ mfn_to_pfn(xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])));
}
- if ( !write_exact(io_fd, &ctxt, sizeof(ctxt)) )
+ if ( !write_exact(io_fd, &ctxt, ((guest_width==8)
+ ? sizeof(ctxt.x64)
+ : sizeof(ctxt.x32))) )
{
ERROR("Error when writing to state file (1) (errno %d)", errno);
goto out;
@@ -1542,7 +1607,8 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
* Reset the MFN to be a known-invalid value. See map_frame_list_list().
*/
memcpy(page, live_shinfo, PAGE_SIZE);
- ((shared_info_t *)page)->arch.pfn_to_mfn_frame_list_list = 0;
+ SET_FIELD(((shared_info_either_t *)page),
+ arch.pfn_to_mfn_frame_list_list, 0);
if ( !write_exact(io_fd, page, PAGE_SIZE) )
{
ERROR("Error when writing to state file (1) (errno %d)", errno);
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
new file mode 100644
index 0000000000..606a98f050
--- /dev/null
+++ b/tools/libxc/xc_netbsd.c
@@ -0,0 +1,271 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#include "xc_private.h"
+
+#include <xen/memory.h>
+#include <xen/sys/evtchn.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int xc_interface_open(void)
+{
+ int flags, saved_errno;
+ int fd = open("/kern/xen/privcmd", O_RDWR);
+
+ if ( fd == -1 )
+ {
+ PERROR("Could not obtain handle on privileged command interface");
+ return -1;
+ }
+
+ /* Although we return the file handle as the 'xc handle' the API
+ does not specify / guarentee that this integer is in fact
+ a file handle. Thus we must take responsiblity to ensure
+ it doesn't propagate (ie leak) outside the process */
+ if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+ {
+ PERROR("Could not get file handle flags");
+ goto error;
+ }
+ flags |= FD_CLOEXEC;
+ if ( fcntl(fd, F_SETFD, flags) < 0 )
+ {
+ PERROR("Could not set file handle flags");
+ goto error;
+ }
+
+ return fd;
+
+ error:
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+}
+
+int xc_interface_close(int xc_handle)
+{
+ return close(xc_handle);
+}
+
+void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
+ xen_pfn_t *arr, int num)
+{
+ privcmd_mmapbatch_t ioctlx;
+ void *addr;
+ addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0);
+ if ( addr == MAP_FAILED )
+ return NULL;
+
+ ioctlx.num=num;
+ ioctlx.dom=dom;
+ ioctlx.addr=(unsigned long)addr;
+ ioctlx.arr=arr;
+ if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
+ {
+ int saved_errno = errno;
+ perror("XXXXXXXX");
+ (void)munmap(addr, num*PAGE_SIZE);
+ errno = saved_errno;
+ return NULL;
+ }
+ return addr;
+
+}
+
+void *xc_map_foreign_range(int xc_handle, uint32_t dom,
+ int size, int prot,
+ unsigned long mfn)
+{
+ privcmd_mmap_t ioctlx;
+ privcmd_mmap_entry_t entry;
+ void *addr;
+ addr = mmap(NULL, size, prot, MAP_ANON | MAP_SHARED, -1, 0);
+ if ( addr == MAP_FAILED )
+ return NULL;
+
+ ioctlx.num=1;
+ ioctlx.dom=dom;
+ ioctlx.entry=&entry;
+ entry.va=(unsigned long) addr;
+ entry.mfn=mfn;
+ entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
+ if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx) < 0 )
+ {
+ int saved_errno = errno;
+ (void)munmap(addr, size);
+ errno = saved_errno;
+ return NULL;
+ }
+ return addr;
+}
+
+int xc_map_foreign_ranges(int xc_handle, uint32_t dom,
+ privcmd_mmap_entry_t *entries, int nr)
+{
+ privcmd_mmap_t ioctlx;
+ int err;
+
+ ioctlx.num = nr;
+ ioctlx.dom = dom;
+ ioctlx.entry = entries;
+
+ err = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx);
+ if (err == 0)
+ return 0;
+ else
+ return -errno;
+}
+
+static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data)
+{
+ int err = ioctl(xc_handle, cmd, data);
+ if (err == 0)
+ return 0;
+ else
+ return -errno;
+}
+
+int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
+{
+ return do_privcmd(xc_handle,
+ IOCTL_PRIVCMD_HYPERCALL,
+ (unsigned long)hypercall);
+}
+
+#define EVTCHN_DEV_NAME "/dev/xenevt"
+
+int xc_evtchn_open(void)
+{
+ return open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+}
+
+int xc_evtchn_close(int xce_handle)
+{
+ return close(xce_handle);
+}
+
+int xc_evtchn_fd(int xce_handle)
+{
+ return xce_handle;
+}
+
+int xc_evtchn_notify(int xce_handle, evtchn_port_t port)
+{
+ struct ioctl_evtchn_notify notify;
+
+ notify.port = port;
+
+ return ioctl(xce_handle, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
+evtchn_port_or_error_t
+xc_evtchn_bind_interdomain(int xce_handle, int domid,
+ evtchn_port_t remote_port)
+{
+ struct ioctl_evtchn_bind_interdomain bind;
+ int ret;
+
+ bind.remote_domain = domid;
+ bind.remote_port = remote_port;
+
+ ret = ioctl(xce_handle, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+ if (ret == 0)
+ return bind.port;
+ else
+ return -1;
+}
+
+int xc_evtchn_unbind(int xce_handle, evtchn_port_t port)
+{
+ struct ioctl_evtchn_unbind unbind;
+
+ unbind.port = port;
+
+ return ioctl(xce_handle, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+evtchn_port_or_error_t
+xc_evtchn_bind_virq(int xce_handle, unsigned int virq)
+{
+ struct ioctl_evtchn_bind_virq bind;
+ int err;
+
+ bind.virq = virq;
+
+ err = ioctl(xce_handle, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+ if (err)
+ return -1;
+ else
+ return bind.port;
+}
+
+static int dorw(int fd, char *data, size_t size, int do_write)
+{
+ size_t offset = 0;
+ ssize_t len;
+
+ while ( offset < size )
+ {
+ if (do_write)
+ len = write(fd, data + offset, size - offset);
+ else
+ len = read(fd, data + offset, size - offset);
+
+ if ( len == -1 )
+ {
+ if ( errno == EINTR )
+ continue;
+ return -1;
+ }
+
+ offset += len;
+ }
+
+ return 0;
+}
+
+evtchn_port_or_error_t
+xc_evtchn_pending(int xce_handle)
+{
+ evtchn_port_t port;
+
+ if ( dorw(xce_handle, (char *)&port, sizeof(port), 0) == -1 )
+ return -1;
+
+ return port;
+}
+
+int xc_evtchn_unmask(int xce_handle, evtchn_port_t port)
+{
+ return dorw(xce_handle, (char *)&port, sizeof(port), 1);
+}
+
+/* Optionally flush file to disk and discard page cache */
+void discard_file_cache(int fd, int flush)
+{
+
+ if ( flush && (fsync(fd) < 0) )
+ {
+ /*PERROR("Failed to flush file: %s", strerror(errno));*/
+ }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index cfb129ef9e..18a18f4c65 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -10,7 +10,12 @@
#include <stdarg.h>
#include <pthread.h>
-static __thread xc_error last_error = { XC_ERROR_NONE, ""};
+static pthread_key_t last_error_pkey;
+static pthread_once_t last_error_pkey_once = PTHREAD_ONCE_INIT;
+
+static pthread_key_t errbuf_pkey;
+static pthread_once_t errbuf_pkey_once = PTHREAD_ONCE_INIT;
+
#if DEBUG
static xc_error_handler error_handler = xc_default_error_handler;
#else
@@ -23,15 +28,45 @@ void xc_default_error_handler(const xc_error *err)
fprintf(stderr, "ERROR %s: %s\n", desc, err->message);
}
+static void
+_xc_clean_last_error(void *m)
+{
+ free(m);
+ pthread_setspecific(last_error_pkey, NULL);
+}
+
+static void
+_xc_init_last_error(void)
+{
+ pthread_key_create(&last_error_pkey, _xc_clean_last_error);
+}
+
+static xc_error *
+_xc_get_last_error(void)
+{
+ xc_error *last_error;
+
+ pthread_once(&last_error_pkey_once, _xc_init_last_error);
+
+ last_error = pthread_getspecific(last_error_pkey);
+ if (last_error == NULL) {
+ last_error = malloc(sizeof(xc_error));
+ pthread_setspecific(last_error_pkey, last_error);
+ }
+
+ return last_error;
+}
+
const xc_error *xc_get_last_error(void)
{
- return &last_error;
+ return _xc_get_last_error();
}
void xc_clear_last_error(void)
{
- last_error.code = XC_ERROR_NONE;
- last_error.message[0] = '\0';
+ xc_error *last_error = _xc_get_last_error();
+ last_error->code = XC_ERROR_NONE;
+ last_error->message[0] = '\0';
}
const char *xc_error_code_to_desc(int code)
@@ -61,12 +96,12 @@ xc_error_handler xc_set_error_handler(xc_error_handler handler)
return old;
}
-
static void _xc_set_error(int code, const char *msg)
{
- last_error.code = code;
- strncpy(last_error.message, msg, XC_MAX_ERROR_MSG_LEN - 1);
- last_error.message[XC_MAX_ERROR_MSG_LEN-1] = '\0';
+ xc_error *last_error = _xc_get_last_error();
+ last_error->code = code;
+ strncpy(last_error->message, msg, XC_MAX_ERROR_MSG_LEN - 1);
+ last_error->message[XC_MAX_ERROR_MSG_LEN-1] = '\0';
}
void xc_set_error(int code, const char *fmt, ...)
@@ -84,23 +119,29 @@ void xc_set_error(int code, const char *fmt, ...)
errno = saved_errno;
- if ( error_handler != NULL )
- error_handler(&last_error);
+ if ( error_handler != NULL ) {
+ xc_error *last_error = _xc_get_last_error();
+ error_handler(last_error);
+ }
}
int lock_pages(void *addr, size_t len)
{
int e = 0;
#ifndef __sun__
- e = mlock(addr, len);
+ void *laddr = (void *)((unsigned long)addr & PAGE_MASK);
+ size_t llen = (len + PAGE_SIZE - 1) & PAGE_MASK;
+ e = mlock(laddr, llen);
#endif
- return (e);
+ return e;
}
void unlock_pages(void *addr, size_t len)
{
#ifndef __sun__
- safe_munlock(addr, len);
+ void *laddr = (void *)((unsigned long)addr & PAGE_MASK);
+ size_t llen = (len + PAGE_SIZE - 1) & PAGE_MASK;
+ safe_munlock(laddr, llen);
#endif
}
@@ -466,20 +507,42 @@ unsigned long xc_make_page_below_4G(
return new_mfn;
}
+static void
+_xc_clean_errbuf(void * m)
+{
+ free(m);
+ pthread_setspecific(errbuf_pkey, NULL);
+}
+
+static void
+_xc_init_errbuf(void)
+{
+ pthread_key_create(&errbuf_pkey, _xc_clean_errbuf);
+}
+
char *safe_strerror(int errcode)
{
- static __thread char errbuf[32];
+#define XS_BUFSIZE 32
+ char *errbuf;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char *strerror_str;
+ pthread_once(&errbuf_pkey_once, _xc_init_errbuf);
+
+ errbuf = pthread_getspecific(errbuf_pkey);
+ if (errbuf == NULL) {
+ errbuf = malloc(XS_BUFSIZE);
+ pthread_setspecific(errbuf_pkey, errbuf);
+ }
+
/*
* Thread-unsafe strerror() is protected by a local mutex. We copy
* the string to a thread-private buffer before releasing the mutex.
*/
pthread_mutex_lock(&mutex);
strerror_str = strerror(errcode);
- strncpy(errbuf, strerror_str, sizeof(errbuf));
- errbuf[sizeof(errbuf)-1] = '\0';
+ strncpy(errbuf, strerror_str, XS_BUFSIZE);
+ errbuf[XS_BUFSIZE-1] = '\0';
pthread_mutex_unlock(&mutex);
return errbuf;
diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c
index df48fa3dff..3ce213e1f7 100644
--- a/tools/libxc/xc_resume.c
+++ b/tools/libxc/xc_resume.c
@@ -8,13 +8,8 @@
#include <xen/foreign/x86_64.h>
#include <xen/hvm/params.h>
-/* Need to provide the right flavour of vcpu context for Xen */
-typedef union
-{
- vcpu_guest_context_x86_64_t c64;
- vcpu_guest_context_x86_32_t c32;
- vcpu_guest_context_t c;
-} vcpu_guest_context_either_t;
+/* Don't yet support cross-address-size uncooperative resume */
+#define guest_width (sizeof (unsigned long))
static int modify_returncode(int xc_handle, uint32_t domid)
{
@@ -50,9 +45,9 @@ static int modify_returncode(int xc_handle, uint32_t domid)
if ( !info.hvm )
ctxt.c.user_regs.eax = 1;
else if ( strstr(caps, "x86_64") )
- ctxt.c64.user_regs.eax = 1;
+ ctxt.x64.user_regs.eax = 1;
else
- ctxt.c32.user_regs.eax = 1;
+ ctxt.x32.user_regs.eax = 1;
if ( (rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt.c)) != 0 )
return rc;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 8566b518f0..6b056b9e9d 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -897,4 +897,43 @@ int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom);
/* IA64 specific, nvram init */
int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom);
+/* HVM guest pass-through */
+int xc_assign_device(int xc_handle,
+ uint32_t domid,
+ uint32_t machine_bdf);
+
+int xc_domain_memory_mapping(int xc_handle,
+ uint32_t domid,
+ unsigned long first_gfn,
+ unsigned long first_mfn,
+ unsigned long nr_mfns,
+ uint32_t add_mapping);
+
+int xc_domain_ioport_mapping(int xc_handle,
+ uint32_t domid,
+ uint32_t first_gport,
+ uint32_t first_mport,
+ uint32_t nr_ports,
+ uint32_t add_mapping);
+
+int xc_domain_bind_pt_irq(int xc_handle,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t irq_type,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx,
+ uint8_t isa_irq);
+
+int xc_domain_bind_pt_pci_irq(int xc_handle,
+ uint32_t domid,
+ uint8_t machine_irq,
+ uint8_t bus,
+ uint8_t device,
+ uint8_t intx);
+
+int xc_domain_bind_pt_isa_irq(int xc_handle,
+ uint32_t domid,
+ uint8_t machine_irq);
+
#endif /* XENCTRL_H */
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index 5de7083112..679c31896c 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -15,7 +15,6 @@
#include "xenguest.h"
#include "xc_private.h"
-#include <xen/sys/privcmd.h>
#include <xen/memory.h>
#include <xen/elfnote.h>
@@ -134,13 +133,6 @@ typedef l4_pgentry_64_t l4_pgentry_t;
#define PAGE_SHIFT_X86 12
#define PAGE_SIZE_X86 (1UL << PAGE_SHIFT_X86)
#define PAGE_MASK_X86 (~(PAGE_SIZE_X86-1))
-#if defined(__i386__)
-#define MADDR_BITS_X86 44
-#elif defined(__x86_64__)
-#define MADDR_BITS_X86 52
-#endif
-#define MFN_MASK_X86 ((1ULL << (MADDR_BITS_X86 - PAGE_SHIFT_X86)) - 1)
-#define MADDR_MASK_X86 (MFN_MASK_X86 << PAGE_SHIFT_X86)
#define PAGE_SHIFT_IA64 14
#define PAGE_SIZE_IA64 (1UL << PAGE_SHIFT_IA64)
@@ -148,19 +140,28 @@ typedef l4_pgentry_64_t l4_pgentry_t;
#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
+
+/* XXX SMH: following skanky macros rely on variable p2m_size being set */
+/* XXX TJD: also, "guest_width" should be the guest's sizeof(unsigned long) */
+
/* Number of xen_pfn_t in a page */
-#define fpp (PAGE_SIZE/sizeof(xen_pfn_t))
-/* XXX SMH: following 3 skanky macros rely on variable p2m_size being set */
+#define FPP (PAGE_SIZE/(guest_width))
/* Number of entries in the pfn_to_mfn_frame_list_list */
-#define P2M_FLL_ENTRIES (((p2m_size)+(fpp*fpp)-1)/(fpp*fpp))
+#define P2M_FLL_ENTRIES (((p2m_size)+(FPP*FPP)-1)/(FPP*FPP))
/* Number of entries in the pfn_to_mfn_frame_list */
-#define P2M_FL_ENTRIES (((p2m_size)+fpp-1)/fpp)
+#define P2M_FL_ENTRIES (((p2m_size)+FPP-1)/FPP)
/* Size in bytes of the pfn_to_mfn_frame_list */
-#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*sizeof(unsigned long))
+#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*(guest_width))
+
+/* Masks for PTE<->PFN conversions */
+#define MADDR_BITS_X86 ((guest_width == 8) ? 52 : 44)
+#define MFN_MASK_X86 ((1ULL << (MADDR_BITS_X86 - PAGE_SHIFT_X86)) - 1)
+#define MADDR_MASK_X86 (MFN_MASK_X86 << PAGE_SHIFT_X86)
+
#define PAEKERN_no 0
#define PAEKERN_yes 1
diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h
index 8579ca8a5e..b0379a4550 100644
--- a/tools/libxc/xg_save_restore.h
+++ b/tools/libxc/xg_save_restore.h
@@ -6,6 +6,9 @@
#include "xc_private.h"
+#include <xen/foreign/x86_32.h>
+#include <xen/foreign/x86_64.h>
+
/*
** We process save/restore/migrate in batches of pages; the below
** determines how many pages we (at maximum) deal with in each batch.
@@ -32,15 +35,19 @@
** be a property of the domain, but for the moment we just read it
** from the hypervisor.
**
+** - The width of a guest word (unsigned long), in bytes.
+**
** Returns 1 on success, 0 on failure.
*/
static inline int get_platform_info(int xc_handle, uint32_t dom,
/* OUT */ unsigned long *max_mfn,
/* OUT */ unsigned long *hvirt_start,
- /* OUT */ unsigned int *pt_levels)
+ /* OUT */ unsigned int *pt_levels,
+ /* OUT */ unsigned int *guest_width)
{
xen_capabilities_info_t xen_caps = "";
xen_platform_parameters_t xen_params;
+ DECLARE_DOMCTL;
if (xc_version(xc_handle, XENVER_platform_parameters, &xen_params) != 0)
return 0;
@@ -52,17 +59,18 @@ static inline int get_platform_info(int xc_handle, uint32_t dom,
*hvirt_start = xen_params.virt_start;
- /*
- * XXX For now, 32bit dom0's can only save/restore 32bit domUs
- * on 64bit hypervisors, so no need to check which type of domain
- * we're dealing with.
- */
+ memset(&domctl, 0, sizeof(domctl));
+ domctl.domain = dom;
+ domctl.cmd = XEN_DOMCTL_get_address_size;
+
+ if ( do_domctl(xc_handle, &domctl) != 0 )
+ return 0;
+
+ *guest_width = domctl.u.address_size.size / 8;
+
if (strstr(xen_caps, "xen-3.0-x86_64"))
-#if defined(__i386__)
- *pt_levels = 3;
-#else
- *pt_levels = 4;
-#endif
+ /* Depends on whether it's a compat 32-on-64 guest */
+ *pt_levels = ( (*guest_width == 8) ? 4 : 3 );
else if (strstr(xen_caps, "xen-3.0-x86_32p"))
*pt_levels = 3;
else if (strstr(xen_caps, "xen-3.0-x86_32"))
@@ -95,3 +103,56 @@ static inline int get_platform_info(int xc_handle, uint32_t dom,
/* Returns TRUE if the PFN is currently mapped */
#define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL))
+
+
+/* 32-on-64 support: saving 32bit guests from 64bit tools and vice versa */
+typedef union
+{
+ vcpu_guest_context_x86_64_t x64;
+ vcpu_guest_context_x86_32_t x32;
+ vcpu_guest_context_t c;
+} vcpu_guest_context_either_t;
+
+typedef union
+{
+ shared_info_x86_64_t x64;
+ shared_info_x86_32_t x32;
+ shared_info_t s;
+} shared_info_either_t;
+
+typedef union
+{
+ start_info_x86_64_t x64;
+ start_info_x86_32_t x32;
+ start_info_t s;
+} start_info_either_t;
+
+#define GET_FIELD(_p, _f) ((guest_width==8) ? ((_p)->x64._f) : ((_p)->x32._f))
+
+#define SET_FIELD(_p, _f, _v) do { \
+ if (guest_width == 8) \
+ (_p)->x64._f = (_v); \
+ else \
+ (_p)->x32._f = (_v); \
+} while (0)
+
+#define MEMCPY_FIELD(_d, _s, _f) do { \
+ if (guest_width == 8) \
+ memcpy(&(_d)->x64._f, &(_s)->x64._f,sizeof((_d)->x64._f)); \
+ else \
+ memcpy(&(_d)->x32._f, &(_s)->x32._f,sizeof((_d)->x32._f)); \
+} while (0)
+
+#define MEMSET_ARRAY_FIELD(_p, _f, _v) do { \
+ if (guest_width == 8) \
+ memset(&(_p)->x64._f[0], (_v), sizeof((_p)->x64._f)); \
+ else \
+ memset(&(_p)->x32._f[0], (_v), sizeof((_p)->x32._f)); \
+} while (0)
+
+#ifndef MAX
+#define MAX(_a, _b) ((_a) >= (_b) ? (_a) : (_b))
+#endif
+#ifndef MIN
+#define MIN(_a, _b) ((_a) <= (_b) ? (_a) : (_b))
+#endif
diff --git a/tools/libxen/include/xen/api/xen_all.h b/tools/libxen/include/xen/api/xen_all.h
index 8f0c1b83bc..4d08226668 100644
--- a/tools/libxen/include/xen/api/xen_all.h
+++ b/tools/libxen/include/xen/api/xen_all.h
@@ -36,4 +36,5 @@
#include <xen/api/xen_vm_metrics.h>
#include <xen/api/xen_vm_power_state.h>
#include <xen/api/xen_vtpm.h>
+#include <xen/api/xen_xspolicy.h>
#endif
diff --git a/tools/pygrub/src/GrubConf.py b/tools/pygrub/src/GrubConf.py
index d4c3c79ccf..2192be6522 100644
--- a/tools/pygrub/src/GrubConf.py
+++ b/tools/pygrub/src/GrubConf.py
@@ -101,7 +101,7 @@ class GrubImage(object):
if self.commands.has_key(com):
if self.commands[com] is not None:
- exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
+ setattr(self, self.commands[com], arg.strip())
else:
logging.info("Ignored image directive %s" %(com,))
else:
@@ -142,11 +142,11 @@ class GrubImage(object):
initrd = property(get_initrd, set_initrd)
# set up command handlers
- commands = { "title": "self.title",
- "root": "self.root",
- "rootnoverify": "self.root",
- "kernel": "self.kernel",
- "initrd": "self.initrd",
+ commands = { "title": "title",
+ "root": "root",
+ "rootnoverify": "root",
+ "kernel": "kernel",
+ "initrd": "initrd",
"chainloader": None,
"module": None}
@@ -195,7 +195,7 @@ class GrubConfigFile(object):
(com, arg) = grub_exact_split(l, 2)
if self.commands.has_key(com):
if self.commands[com] is not None:
- exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
+ setattr(self, self.commands[com], arg.strip())
else:
logging.info("Ignored directive %s" %(com,))
else:
@@ -208,7 +208,7 @@ class GrubConfigFile(object):
(com, arg) = grub_exact_split(line, 2)
if self.commands.has_key(com):
if self.commands[com] is not None:
- exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
+ setattr(self, self.commands[com], arg.strip())
else:
logging.info("Ignored directive %s" %(com,))
else:
@@ -236,12 +236,12 @@ class GrubConfigFile(object):
splash = property(get_splash, set_splash)
# set up command handlers
- commands = { "default": "self.default",
- "timeout": "self.timeout",
- "fallback": "self.fallback",
- "hiddenmenu": "self.hiddenmenu",
- "splashimage": "self.splash",
- "password": "self.password" }
+ commands = { "default": "default",
+ "timeout": "timeout",
+ "fallback": "fallback",
+ "hiddenmenu": "hiddenmenu",
+ "splashimage": "splash",
+ "password": "password" }
for c in ("bootp", "color", "device", "dhcp", "hide", "ifconfig",
"pager", "partnew", "parttype", "rarp", "serial",
"setkey", "terminal", "terminfo", "tftpserver", "unhide"):
diff --git a/tools/pygrub/src/LiloConf.py b/tools/pygrub/src/LiloConf.py
index 2dde05825a..deb94998b9 100644
--- a/tools/pygrub/src/LiloConf.py
+++ b/tools/pygrub/src/LiloConf.py
@@ -31,7 +31,7 @@ class LiloImage(object):
if self.commands.has_key(com):
if self.commands[com] is not None:
- exec("%s = r\'%s\'" %(self.commands[com], re.sub('^"(.+)"$', r"\1", arg.strip())))
+ setattr(self, self.commands[com], re.sub('^"(.+)"$', r"\1", arg.strip()))
else:
logging.info("Ignored image directive %s" %(com,))
else:
@@ -74,13 +74,13 @@ class LiloImage(object):
readonly = property(get_readonly, set_readonly)
# set up command handlers
- commands = { "label": "self.title",
- "root": "self.root",
- "rootnoverify": "self.root",
- "image": "self.kernel",
- "initrd": "self.initrd",
- "append": "self.args",
- "read-only": "self.readonly",
+ commands = { "label": "title",
+ "root": "root",
+ "rootnoverify": "root",
+ "image": "kernel",
+ "initrd": "initrd",
+ "append": "args",
+ "read-only": "readonly",
"chainloader": None,
"module": None}
@@ -129,7 +129,7 @@ class LiloConfigFile(object):
(com, arg) = GrubConf.grub_exact_split(l, 2)
if self.commands.has_key(com):
if self.commands[com] is not None:
- exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
+ setattr(self, self.commands[com], arg.strip())
else:
logging.info("Ignored directive %s" %(com,))
else:
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 93402b1e5b..d91b795636 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -346,6 +346,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
Py_DECREF(list);
if ( pyhandle != NULL ) { Py_DECREF(pyhandle); }
if ( info_dict != NULL ) { Py_DECREF(info_dict); }
+ free(info);
return NULL;
}
for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c
index 45cbf773d9..b2c4b090e4 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -365,6 +365,7 @@ static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args)
goto exit;
}
+ free(xsperms);
Py_INCREF(Py_None);
return Py_None;
diff --git a/tools/python/xen/util/bootloader.py b/tools/python/xen/util/bootloader.py
index 8660bd8956..9be6708b65 100644
--- a/tools/python/xen/util/bootloader.py
+++ b/tools/python/xen/util/bootloader.py
@@ -21,7 +21,10 @@ import os, stat
import tempfile
import shutil
import threading
+
from xen.xend.XendLogging import log
+from xen.util import mkdir
+import xen.util.xsm.xsm as security
__bootloader = None
@@ -70,8 +73,9 @@ def set_boot_policy(title_idx, filename):
def loads_default_policy(filename):
""" Determine whether the given policy is loaded by the default boot title """
- polfile = get_default_policy()
- if polfile != None:
+ policy = get_default_policy()
+ if policy:
+ polfile = policy + ".bin"
if polfile == filename or \
"/"+polfile == filename:
return True
@@ -220,28 +224,6 @@ class Grub(Bootloader):
return boot_file
- def __get_titles(self):
- """ Get the names of all boot titles in the grub config file
- @rtype: list
- @return: list of names of available boot titles
- """
- titles = []
- try:
- boot_file = self.__get_bootfile()
- except:
- return []
- try:
- self.__bootfile_lock.acquire()
- grub_fd = open(boot_file)
- for line in grub_fd:
- if self.title_re.match(line):
- line = line.rstrip().lstrip()
- titles.append(line.lstrip('title').lstrip())
- finally:
- self.__bootfile_lock.release()
- return titles
-
-
def get_default_title(self):
""" Get the index (starting with 0) of the default boot title
This number is read from the grub configuration file.
@@ -261,8 +243,8 @@ class Grub(Bootloader):
for line in grub_fd:
line = line.rstrip()
if def_re.match(line):
- line = line.rstrip()
- line = line.lstrip("default=")
+ #remove 'default='
+ line = line.lstrip()[8:]
default = int(line)
break
finally:
@@ -295,11 +277,13 @@ class Grub(Bootloader):
if self.policy_re.match(line):
start = line.find("module")
pol = line[start+6:]
- pol = pol.lstrip().rstrip()
+ pol = pol.strip()
if pol[0] == '/':
pol = pol[1:]
if pol[0:5] == "boot/":
pol = pol[5:]
+ if pol.endswith(".bin"):
+ pol = pol[:-4]
policies[idx] = pol
finally:
self.__bootfile_lock.release()
@@ -399,7 +383,7 @@ class Grub(Bootloader):
if self.policy_re.match(line):
start = line.find("module")
pol = line[start+6:len(line)]
- pol = pol.lstrip().rstrip()
+ pol = pol.strip()
if pol in namelist:
omit_line = True
found = True
@@ -499,7 +483,7 @@ class Grub(Bootloader):
within_title = 0
ctr = ctr + 1
if within_title and self.kernel_re.match(line):
- line = line.rstrip().lstrip()
+ line = line.strip()
items = line.split(" ")
i = 0
while i < len(items):
@@ -513,9 +497,123 @@ class Grub(Bootloader):
self.__bootfile_lock.release()
return None # Not found
+class LatePolicyLoader(Bootloader):
+ """ A fake bootloader file that holds the policy to load automatically
+ once xend has started up and the Domain-0 label to set. """
+ def __init__(self):
+ self.__bootfile_lock = threading.RLock()
+ self.PATH = security.security_dir_prefix
+ self.FILENAME = self.PATH + "/xen_boot_policy"
+ self.DEFAULT_TITLE = "ANY"
+ self.POLICY_ATTR = "POLICY"
+ Bootloader.__init__(self)
+
+ def probe(self):
+ _dir=os.path.dirname(self.FILENAME)
+ mkdir.parents(_dir, stat.S_IRWXU)
+ return True
+
+ def get_default_title(self):
+ return self.DEFAULT_TITLE
+
+ def get_boot_policies(self):
+ policies = {}
+ try:
+ self.__bootfile_lock.acquire()
+
+ res = self.__loadcontent()
+
+ pol = res.get( self.POLICY_ATTR )
+ if pol:
+ policies.update({ self.DEFAULT_TITLE : pol })
+
+ finally:
+ self.__bootfile_lock.release()
+
+ return policies
+
+ def add_boot_policy(self, index, binpolname):
+ try:
+ self.__bootfile_lock.acquire()
+
+ res = self.__loadcontent()
+ if binpolname.endswith(".bin"):
+ binpolname = binpolname[0:-4]
+ res[ self.POLICY_ATTR ] = binpolname
+ self.__writecontent(res)
+ finally:
+ self.__bootfile_lock.release()
+
+ return True
+
+ def rm_policy_from_boottitle(self, index, unamelist):
+ try:
+ self.__bootfile_lock.acquire()
+
+ res = self.__loadcontent()
+ if self.POLICY_ATTR in res:
+ del(res[self.POLICY_ATTR])
+ self.__writecontent(res)
+ finally:
+ self.__bootfile_lock.release()
+
+ return True
+
+ def set_kernel_attval(self, index, att, val):
+ try:
+ self.__bootfile_lock.acquire()
+
+ res = self.__loadcontent()
+ res[att] = val
+ self.__writecontent(res)
+ finally:
+ self.__bootfile_lock.release()
+
+ return True
+
+ def get_kernel_val(self, index, att):
+ try:
+ self.__bootfile_lock.acquire()
+
+ res = self.__loadcontent()
+ return res.get(att)
+ finally:
+ self.__bootfile_lock.release()
+
+ def __loadcontent(self):
+ res={}
+ try:
+ file = open(self.FILENAME)
+ for line in file:
+ tmp = line.split("=",1)
+ if len(tmp) == 2:
+ res[tmp[0]] = tmp[1].strip()
+ file.close()
+ except:
+ pass
+
+ return res
+
+ def __writecontent(self, items):
+ rc = True
+ try:
+ file = open(self.FILENAME,"w")
+ if file:
+ for key, value in items.items():
+ file.write("%s=%s\n" % (str(key),str(value)))
+ file.close()
+ except:
+ rc = False
+
+ return rc
+
__bootloader = Bootloader()
grub = Grub()
if grub.probe() == True:
__bootloader = grub
+else:
+ late = LatePolicyLoader()
+ if late.probe() == True:
+ __bootloader = late
diff --git a/tools/python/xen/util/xsm/acm/acm.py b/tools/python/xen/util/xsm/acm/acm.py
index b2dff14edd..52f6ad6333 100644
--- a/tools/python/xen/util/xsm/acm/acm.py
+++ b/tools/python/xen/util/xsm/acm/acm.py
@@ -33,7 +33,8 @@ from xen.util import dictio, xsconstants
from xen.xend.XendConstants import *
#global directories and tools for security management
-policy_dir_prefix = "/etc/xen/acm-security/policies"
+security_dir_prefix = "/etc/xen/acm-security"
+policy_dir_prefix = security_dir_prefix + "/policies"
res_label_filename = policy_dir_prefix + "/resource_labels"
boot_filename = "/boot/grub/menu.lst"
altboot_filename = "/boot/grub/grub.conf"
@@ -1308,12 +1309,33 @@ def parse_security_label(security_label):
return security_label
def set_security_label(policy, label):
- policytype = xsconstants.ACM_POLICY_ID
if label != "" and policy != "":
- return "%s:%s:%s" % (policytype, policy, label)
+ return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, policy, label)
else:
return ""
def ssidref2security_label(ssidref):
from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
return XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref)
+
+def get_security_label(self, xspol=None):
+ """
+ Get the security label of a domain
+ @param xspol The policy to use when converting the ssid into
+ a label; only to be passed during the updating
+ of the policy
+ """
+ domid = self.getDomid()
+
+ if not xspol:
+ from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+ xspol = XSPolicyAdminInstance().get_loaded_policy()
+
+ if domid == 0:
+ if xspol:
+ label = xspol.policy_get_domain_label_formatted(domid)
+ else:
+ label = ""
+ else:
+ label = self.info.get('security_label', '')
+ return label
diff --git a/tools/python/xen/util/xsm/dummy/dummy.py b/tools/python/xen/util/xsm/dummy/dummy.py
index 25e1ed989f..42a41b36c9 100644
--- a/tools/python/xen/util/xsm/dummy/dummy.py
+++ b/tools/python/xen/util/xsm/dummy/dummy.py
@@ -6,6 +6,7 @@ class XSMError(Exception):
def __str__(self):
return repr(self.value)
+security_dir_prefix = "";
policy_dir_prefix = "";
active_policy = "";
NULL_SSIDREF = 0;
@@ -51,3 +52,6 @@ def ssidref2security_label(ssidref):
def has_authorization(ssidref):
return True
+
+def get_security_label(self, xspol=None):
+ return ""
diff --git a/tools/python/xen/util/xsm/flask/flask.py b/tools/python/xen/util/xsm/flask/flask.py
index 1854cb46aa..a0f931b364 100644
--- a/tools/python/xen/util/xsm/flask/flask.py
+++ b/tools/python/xen/util/xsm/flask/flask.py
@@ -35,3 +35,7 @@ def set_security_label(policy, label):
def ssidref2security_label(ssidref):
return ssidref2label(ssidref)
+
+def get_security_label(self, xspol=None):
+ label = self.info.get('security_label', '')
+ return label
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index 7ec493a059..9a1e1da47b 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -127,7 +127,7 @@ XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display',
'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
'vncconsole', 'vncdisplay', 'vnclisten',
- 'vncpasswd', 'vncunused', 'xauthority']
+ 'vncpasswd', 'vncunused', 'xauthority', 'pci']
# Xen API console 'other_config' keys.
XENAPI_CONSOLE_OTHER_CFG = ['vncunused', 'vncdisplay', 'vnclisten',
@@ -168,6 +168,7 @@ XENAPI_CFG_TYPES = {
'tools_version': dict,
'other_config': dict,
'security_label': str,
+ 'pci': str,
}
# List of legacy configuration keys that have no equivalent in the
@@ -177,8 +178,6 @@ LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [
# roundtripped (dynamic, unmodified)
'shadow_memory',
'vcpu_avail',
- 'cpu_weight',
- 'cpu_cap',
'features',
# read/write
'on_xend_start',
@@ -202,8 +201,6 @@ LEGACY_CFG_TYPES = {
'shadow_memory': int,
'maxmem': int,
'start_time': float,
- 'cpu_cap': int,
- 'cpu_weight': int,
'cpu_time': float,
'features': str,
'localtime': int,
@@ -329,8 +326,6 @@ class XendConfig(dict):
'on_xend_start': 'ignore',
'on_xend_stop': 'ignore',
'cpus': [],
- 'cpu_weight': 256,
- 'cpu_cap': 0,
'VCPUs_max': 1,
'VCPUs_live': 1,
'VCPUs_at_startup': 1,
@@ -495,6 +490,14 @@ class XendConfig(dict):
if sxp.child_value(sxp_cfg, "maxmem") != None:
cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
+ # Convert scheduling parameters to vcpus_params
+ if 'vcpus_params' not in cfg:
+ cfg['vcpus_params'] = {}
+ cfg["vcpus_params"]["weight"] = \
+ int(sxp.child_value(sxp_cfg, "cpu_weight", 256))
+ cfg["vcpus_params"]["cap"] = \
+ int(sxp.child_value(sxp_cfg, "cpu_cap", 0))
+
# Only extract options we know about.
extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
@@ -811,8 +814,6 @@ class XendConfig(dict):
_set_cfg_if_exists('on_xend_stop')
_set_cfg_if_exists('on_xend_start')
_set_cfg_if_exists('vcpu_avail')
- _set_cfg_if_exists('cpu_weight')
- _set_cfg_if_exists('cpu_cap')
# Parse and store runtime configuration
_set_cfg_if_exists('start_time')
@@ -864,6 +865,10 @@ class XendConfig(dict):
self[key] = type_conv(val)
else:
self[key] = val
+
+ self['vcpus_params']['weight'] = \
+ int(self['vcpus_params'].get('weight', 256))
+ self['vcpus_params']['cap'] = int(self['vcpus_params'].get('cap', 0))
def to_sxp(self, domain = None, ignore_devices = False, ignore = [],
legacy_only = True):
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index 6ceea45e08..5e09126bb2 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -1176,12 +1176,16 @@ class XendDomain:
log.exception("domain_unpause")
raise XendError(str(ex))
- def domain_pause(self, domid):
+ def domain_pause(self, domid, state=False):
"""Pause domain execution.
@param domid: Domain ID or Name
@type domid: int or string.
- @rtype: None
+ @keyword state: If True, will return the domain state before pause
+ @type state: bool
+ @rtype: int if state is True
+ @return: Domain state (DOM_STATE_*)
+ @rtype: None if state is False
@raise XendError: Failed to pause
@raise XendInvalidDomain: Domain is not valid
"""
@@ -1191,13 +1195,16 @@ class XendDomain:
raise XendInvalidDomain(str(domid))
if dominfo.getDomid() == DOM0_ID:
raise XendError("Cannot pause privileged domain %s" % domid)
- if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
+ ds = dominfo._stateGet()
+ if ds not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
raise VMBadState("Domain '%s' is not started" % domid,
POWER_STATE_NAMES[DOM_STATE_RUNNING],
- POWER_STATE_NAMES[dominfo._stateGet()])
+ POWER_STATE_NAMES[ds])
log.info("Domain %s (%d) paused.", dominfo.getName(),
int(dominfo.getDomid()))
dominfo.pause()
+ if state:
+ return ds
except XendInvalidDomain:
log.exception("domain_pause")
raise
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 65e38f82d5..6de4b2ff54 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -174,7 +174,8 @@ def recreate(info, priv):
except XendError:
pass # our best shot at 'goto' in python :)
- vm = XendDomainInfo(xeninfo, domid, dompath, augment = True, priv = priv)
+ vm = XendDomainInfo(xeninfo, domid, dompath, augment = True, priv = priv,
+ vmpath = vmpath)
if needs_reinitialising:
vm._recreateDom()
@@ -321,7 +322,7 @@ class XendDomainInfo:
"""
def __init__(self, info, domid = None, dompath = None, augment = False,
- priv = False, resume = False):
+ priv = False, resume = False, vmpath = None):
"""Constructor for a domain
@param info: parsed configuration
@@ -348,7 +349,22 @@ class XendDomainInfo:
#if not self._infoIsSet('uuid'):
# self.info['uuid'] = uuid.toString(uuid.create())
- self.vmpath = XS_VMROOT + self.info['uuid']
+ # Find a unique /vm/<uuid>/<integer> path if not specified.
+ # This avoids conflict between pre-/post-migrate domains when doing
+ # localhost relocation.
+ self.vmpath = vmpath
+ i = 0
+ while self.vmpath == None:
+ self.vmpath = XS_VMROOT + self.info['uuid']
+ if i != 0:
+ self.vmpath = self.vmpath + '-' + str(i)
+ try:
+ if self._readVm("uuid"):
+ self.vmpath = None
+ i = i + 1
+ except:
+ pass
+
self.dompath = dompath
self.image = None
@@ -1101,16 +1117,16 @@ class XendDomainInfo:
return str(self._resume)
def getCap(self):
- return self.info.get('cpu_cap', 0)
+ return self.info['vcpus_params']['cap']
def setCap(self, cpu_cap):
- self.info['cpu_cap'] = cpu_cap
+ self.info['vcpus_params']['cap'] = cpu_cap
def getWeight(self):
- return self.info.get('cpu_weight', 256)
+ return self.info['vcpus_params']['weight']
def setWeight(self, cpu_weight):
- self.info['cpu_weight'] = cpu_weight
+ self.info['vcpus_params']['weight'] = cpu_weight
def setResume(self, state):
self._resume = state
@@ -1582,7 +1598,7 @@ class XendDomainInfo:
def _initDomain(self):
log.debug('XendDomainInfo.initDomain: %s %s',
self.domid,
- self.info['cpu_weight'])
+ self.info['vcpus_params']['weight'])
self._configureBootloader()
@@ -1592,7 +1608,8 @@ class XendDomainInfo:
if self.info['platform'].get('localtime', 0):
xc.domain_set_time_offset(self.domid)
- xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
+ xc.domain_setcpuweight(self.domid, \
+ self.info['vcpus_params']['weight'])
# repin domain vcpus if a restricted cpus list is provided
# this is done prior to memory allocation to aide in memory
@@ -2167,7 +2184,7 @@ class XendDomainInfo:
raise VmError('Invalid VM Name')
dom = XendDomain.instance().domain_lookup_nr(name)
- if dom and dom.domid != self.domid:
+ if dom and dom.info['uuid'] != self.info['uuid']:
raise VmError("VM name '%s' already exists%s" %
(name,
dom.domid is not None and
@@ -2275,25 +2292,8 @@ class XendDomainInfo:
def get_security_label(self, xspol=None):
- """
- Get the security label of a domain
- @param xspol The policy to use when converting the ssid into
- a label; only to be passed during the updating
- of the policy
- """
- domid = self.getDomid()
-
- if not xspol:
- from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
- xspol = XSPolicyAdminInstance().get_loaded_policy()
-
- if domid == 0:
- if xspol:
- label = xspol.policy_get_domain_label_formatted(domid)
- else:
- label = ""
- else:
- label = self.info.get('security_label', '')
+ import xen.util.xsm.xsm as security
+ label = security.get_security_label(self, xspol)
return label
def set_security_label(self, seclab, old_seclab, xspol=None,
diff --git a/tools/python/xen/xend/balloon.py b/tools/python/xen/xend/balloon.py
index 69d91e2859..168070ea13 100644
--- a/tools/python/xen/xend/balloon.py
+++ b/tools/python/xen/xend/balloon.py
@@ -100,12 +100,28 @@ def free(need_mem):
try:
dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
+ dom0_alloc = get_dom0_current_alloc()
retries = 0
sleep_time = SLEEP_TIME_GROWTH
+ new_alloc = 0
last_new_alloc = None
last_free = None
rlimit = RETRY_LIMIT
+
+ # If unreasonable memory size is required, we give up waiting
+ # for ballooning or scrubbing, as if had retried.
+ physinfo = xc.physinfo()
+ free_mem = physinfo['free_memory']
+ scrub_mem = physinfo['scrub_memory']
+ total_mem = physinfo['total_memory']
+ if dom0_min_mem > 0:
+ max_free_mem = total_mem - dom0_min_mem
+ else:
+ max_free_mem = total_mem - dom0_alloc
+ if need_mem >= max_free_mem:
+ retries = rlimit
+
while retries < rlimit:
physinfo = xc.physinfo()
free_mem = physinfo['free_memory']
diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
index bd5e6b2cf4..95366820b0 100644
--- a/tools/python/xen/xend/image.py
+++ b/tools/python/xen/xend/image.py
@@ -309,7 +309,7 @@ class HVMImageHandler(ImageHandler):
def parseDeviceModelArgs(self, vmConfig):
dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
'localtime', 'serial', 'stdvga', 'isa',
- 'acpi', 'usb', 'usbdevice', 'keymap' ]
+ 'acpi', 'usb', 'usbdevice', 'keymap', 'pci' ]
ret = ['-vcpus', str(self.vm.getVCpuCount())]
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
index fbf059b9fb..250fa848a0 100644
--- a/tools/python/xen/xend/server/netif.py
+++ b/tools/python/xen/xend/server/netif.py
@@ -115,17 +115,15 @@ class NetifController(DevController):
accel = config.get('accel')
sec_lab = config.get('security_label')
- if not typ:
- typ = xoptions.netback_type
-
if not mac:
raise VmError("MAC address not specified or generated.")
devid = self.allocateDeviceID()
back = { 'script' : script,
- 'mac' : mac,
- 'type' : typ }
+ 'mac' : mac }
+ if typ:
+ back['type'] = typ
if ipaddr:
back['ip'] = ipaddr
if bridge:
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index a6d24b8b69..bcfd0c73ec 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -721,7 +721,7 @@ def configure_hvm(config_image, vals):
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
- 'acpi', 'apic', 'usb', 'usbdevice', 'keymap' ]
+ 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
config_image.append([a, vals.__dict__[a]])
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
index 8473f8bf5b..25f7c4e1da 100644
--- a/tools/python/xen/xm/main.py
+++ b/tools/python/xen/xm/main.py
@@ -931,11 +931,11 @@ def xm_brief_list(doms):
print format % d
def xm_label_list(doms):
- print '%-40s %3s %5s %5s %10s %9s %-10s' % \
+ print '%-40s %5s %5s %5s %10s %9s %-10s' % \
('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
output = []
- format = '%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
+ format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
'%(cpu_time)8.1f %(seclabel)10s'
import xen.util.xsm.xsm as security
@@ -1287,13 +1287,13 @@ def xm_dump_core(args):
filename = None
if not live:
- server.xend.domain.pause(dom)
+ ds = server.xend.domain.pause(dom, True)
try:
print "Dumping core of domain: %s ..." % str(dom)
server.xend.domain.dump(dom, filename, live, crash)
finally:
- if not live:
+ if not live and ds == DOM_STATE_RUNNING:
server.xend.domain.unpause(dom)
if crash:
diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py
index 70c91140b7..ac4408f4fe 100644
--- a/tools/python/xen/xm/xenapi_create.py
+++ b/tools/python/xen/xm/xenapi_create.py
@@ -26,6 +26,7 @@ from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
XEN_API_ON_CRASH_BEHAVIOUR
from xen.xm.opts import OptionError
from xen.util import xsconstants
+import xen.util.xsm.xsm as security
import sys
import os
@@ -569,7 +570,7 @@ class sxp2xml:
if sec_data:
try :
vm.attributes['security_label'] = \
- "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, sec_data[0][1][1],sec_data[0][2][1])
+ security.set_security_label(sec_data[0][1][1],sec_data[0][2][1])
except Exception, e:
raise "Invalid security data format: %s" % str(sec_data)
@@ -753,11 +754,7 @@ class sxp2xml:
policy = get_child_by_name(vif_sxp, "policy")
label = get_child_by_name(vif_sxp, "label")
- if label and policy:
- vif.attributes["security_label"] \
- = "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, policy, label)
- else:
- vif.attributes["security_label"] = ""
+ vif.attributes["security_label"] = security.set_security_label(policy, label)
if get_child_by_name(vif_sxp, "bridge") is not None:
vif.attributes["network"] \
diff --git a/tools/vtpm/tpm_emulator.patch b/tools/vtpm/tpm_emulator.patch
index c03810446a..8cd439f725 100644
--- a/tools/vtpm/tpm_emulator.patch
+++ b/tools/vtpm/tpm_emulator.patch
@@ -547,10 +547,31 @@ diff -uprN orig/tpm_emulator-0.4/README tpm_emulator/README
Installation
--------------------------------------------------------------------------
The compilation and installation process uses the build environment for
+diff -uprN orig/tpm_emulator-0.4/tpm/tpm_cmd_handler.c tpm_emulator/tpm/tpm_cmd_handler.c
+--- orig/tpm_emulator-0.4/tpm/tpm_cmd_handler.c 2006-06-23 19:37:07.000000000 +0900
++++ tpm_emulator/tpm/tpm_cmd_handler.c 2007-09-12 20:23:00.000000000 +0900
+@@ -565,7 +565,7 @@ static TPM_RESULT execute_TPM_Seal(TPM_R
+ if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)
+ || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &encAuth)
+ || tpm_unmarshal_UINT32(&ptr, &len, &pcrInfoSize)
+- || tpm_unmarshal_TPM_PCR_INFO(&ptr, &len, &pcrInfo)
++ || (pcrInfoSize >0 && tpm_unmarshal_TPM_PCR_INFO(&ptr, &len, &pcrInfo))
+ || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)
+ || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)
+ || len != 0) return TPM_BAD_PARAMETER;
+@@ -798,7 +798,7 @@ static TPM_RESULT execute_TPM_Sealx(TPM_
+ if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)
+ || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &encAuth)
+ || tpm_unmarshal_UINT32(&ptr, &len, &pcrInfoSize)
+- || tpm_unmarshal_TPM_PCR_INFO(&ptr, &len, &pcrInfo)
++ || (pcrInfoSize > 0 && tpm_unmarshal_TPM_PCR_INFO(&ptr, &len, &pcrInfo))
+ || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)
+ || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)
+ || len != 0) return TPM_BAD_PARAMETER;
diff -uprN orig/tpm_emulator-0.4/tpm/tpm_credentials.c tpm_emulator/tpm/tpm_credentials.c
---- orig/tpm_emulator-0.4/tpm/tpm_credentials.c 2006-06-23 03:37:07.000000000 -0700
-+++ tpm_emulator/tpm/tpm_credentials.c 2006-07-24 14:35:35.000000000 -0700
-@@ -47,16 +47,16 @@ int tpm_compute_pubkey_checksum(TPM_NONC
+--- orig/tpm_emulator-0.4/tpm/tpm_credentials.c 2006-06-23 19:37:07.000000000 +0900
++++ tpm_emulator/tpm/tpm_credentials.c 2007-09-12 20:23:30.000000000 +0900
+@@ -47,20 +47,20 @@ int tpm_compute_pubkey_checksum(TPM_NONC
TPM_RESULT tpm_get_pubek(TPM_PUBKEY *pubEndorsementKey)
{
@@ -572,6 +593,11 @@ diff -uprN orig/tpm_emulator-0.4/tpm/tpm_credentials.c tpm_emulator/tpm/tpm_cred
pubEndorsementKey->algorithmParms.algorithmID = TPM_ALG_RSA;
pubEndorsementKey->algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
pubEndorsementKey->algorithmParms.sigScheme = TPM_SS_NONE;
+- pubEndorsementKey->algorithmParms.parms.rsa.keyLength = key_length;
++ pubEndorsementKey->algorithmParms.parms.rsa.keyLength = key_length << 3;
+ pubEndorsementKey->algorithmParms.parms.rsa.numPrimes = 2;
+ pubEndorsementKey->algorithmParms.parms.rsa.exponentSize = 0;
+ pubEndorsementKey->algorithmParms.parms.rsa.exponent = NULL;
@@ -175,6 +175,7 @@ TPM_RESULT TPM_OwnerReadInternalPub(TPM_
{
TPM_RESULT res;
diff --git a/tools/vtpm_manager/tcs/tcs.c b/tools/vtpm_manager/tcs/tcs.c
index a711d1b57f..7c1378cdff 100644
--- a/tools/vtpm_manager/tcs/tcs.c
+++ b/tools/vtpm_manager/tcs/tcs.c
@@ -775,7 +775,7 @@ TPM_RESULT TCSP_UnBind(TCS_CONTEXT_HANDLE hContext, // in
TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
// check input params
- if (inData == NULL || privAuth == NULL || outDataSize == NULL || *outData == NULL)
+ if (inData == NULL || privAuth == NULL || outDataSize == NULL || outData == NULL)
return TPM_BAD_PARAMETER;
// Convert Byte Input parameter in the input byte stream InBuf
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 1587016335..27125a3142 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -12,7 +12,8 @@
* Authors: Diwaker Gupta, diwaker.gupta@hp.com
* Rob Gardner, rob.gardner@hp.com
* Lucy Cherkasova, lucy.cherkasova.hp.com
- * Much code based on xentrace, authored by Mark Williamson, mark.a.williamson@intel.com
+ * Much code based on xentrace, authored by Mark Williamson,
+ * mark.a.williamson@intel.com
* Date: November, 2005
*
* This program is free software; you can redistribute it and/or modify
@@ -107,31 +108,31 @@ int NCPU = 0;
void init_current(int ncpu)
{
- running = calloc(ncpu, sizeof(int));
- NCPU = ncpu;
- printf("Initialized with %d %s\n", ncpu, (ncpu == 1) ? "cpu" : "cpu's");
+ running = calloc(ncpu, sizeof(int));
+ NCPU = ncpu;
+ printf("Initialized with %d %s\n", ncpu, (ncpu == 1) ? "cpu" : "cpu's");
}
int is_current(int domain, int cpu)
{
- // int i;
+ // int i;
- // for (i=0; i<NCPU; i++)
+ // for (i=0; i<NCPU; i++)
if (running[cpu] == domain)
- return 1;
- return 0;
+ return 1;
+ return 0;
}
// return the domain that's currently running on the given cpu
int current(int cpu)
{
- return running[cpu];
+ return running[cpu];
}
void set_current(int cpu, int domain)
{
- running[cpu] = domain;
+ running[cpu] = domain;
}
@@ -145,7 +146,7 @@ void close_handler(int signal)
void dump_record(int cpu, struct t_rec *x)
{
printf("record: cpu=%x, tsc=%lx, event=%x, d1=%lx\n",
- cpu, x->cycles, x->event, x->data[0]);
+ cpu, x->cycles, x->event, x->data[0]);
}
#endif
@@ -198,15 +199,15 @@ void check_gotten_sum(void)
int i;
for (i=0; i<NCPU; i++) {
- new_qos = cpu_qos_data[i];
- ns = billion;
- sum = total_ns_gotten(&ns);
-
- printf("[cpu%d] ns_gotten over all domains = %lldns, over %lldns\n",
- i, sum, ns);
- percent = (double) sum;
- percent = (100.0*percent) / (double)ns;
- printf(" ==> ns_gotten = %7.3f%%\n", percent);
+ new_qos = cpu_qos_data[i];
+ ns = billion;
+ sum = total_ns_gotten(&ns);
+
+ printf("[cpu%d] ns_gotten over all domains = %lldns, over %lldns\n",
+ i, sum, ns);
+ percent = (double) sum;
+ percent = (100.0*percent) / (double)ns;
+ printf(" ==> ns_gotten = %7.3f%%\n", percent);
}
#endif
}
@@ -229,7 +230,7 @@ void dump_stats(void)
}
printf("processed %d total records in %d seconds (%ld per second)\n",
- rec_count, (int)run_time, rec_count/run_time);
+ rec_count, (int)run_time, rec_count/run_time);
printf("woke up %d times in %d seconds (%ld per second)\n", wakeups,
(int) run_time, wakeups/run_time);
@@ -261,56 +262,56 @@ int xce_handle = -1;
/* Stolen from xenstore code */
int eventchn_init(void)
{
- int rc;
+ int rc;
- // to revert to old way:
- if (0)
- return -1;
+ // to revert to old way:
+ if (0)
+ return -1;
- xce_handle = xc_evtchn_open();
+ xce_handle = xc_evtchn_open();
- if (xce_handle < 0)
- perror("Failed to open evtchn device");
+ if (xce_handle < 0)
+ perror("Failed to open evtchn device");
- if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_TBUF)) == -1)
- perror("Failed to bind to domain exception virq port");
- virq_port = rc;
+ if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_TBUF)) == -1)
+ perror("Failed to bind to domain exception virq port");
+ virq_port = rc;
- return xce_handle;
+ return xce_handle;
}
void wait_for_event(void)
{
- int ret;
- fd_set inset;
- evtchn_port_t port;
- struct timeval tv;
- int evtchn_fd;
+ int ret;
+ fd_set inset;
+ evtchn_port_t port;
+ struct timeval tv;
+ int evtchn_fd;
- if (xce_handle < 0) {
- nanosleep(&opts.poll_sleep, NULL);
- return;
- }
-
- evtchn_fd = xc_evtchn_fd(xce_handle);
-
- FD_ZERO(&inset);
- FD_SET(evtchn_fd, &inset);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- // tv = millis_to_timespec(&opts.poll_sleep);
- ret = select(evtchn_fd+1, &inset, NULL, NULL, &tv);
+ if (xce_handle < 0) {
+ nanosleep(&opts.poll_sleep, NULL);
+ return;
+ }
+
+ evtchn_fd = xc_evtchn_fd(xce_handle);
+
+ FD_ZERO(&inset);
+ FD_SET(evtchn_fd, &inset);
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ // tv = millis_to_timespec(&opts.poll_sleep);
+ ret = select(evtchn_fd+1, &inset, NULL, NULL, &tv);
- if ( (ret == 1) && FD_ISSET(evtchn_fd, &inset)) {
- if ((port = xc_evtchn_pending(xce_handle)) == -1)
- perror("Failed to read from event fd");
+ if ( (ret == 1) && FD_ISSET(evtchn_fd, &inset)) {
+ if ((port = xc_evtchn_pending(xce_handle)) == -1)
+ perror("Failed to read from event fd");
- // if (port == virq_port)
- // printf("got the event I was looking for\r\n");
+ // if (port == virq_port)
+ // printf("got the event I was looking for\r\n");
- if (xc_evtchn_unmask(xce_handle, port) == -1)
- perror("Failed to write to event fd");
- }
+ if (xc_evtchn_unmask(xce_handle, port) == -1)
+ perror("Failed to write to event fd");
+ }
}
static void get_tbufs(unsigned long *mfn, unsigned long *size)
@@ -336,9 +337,9 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size)
void disable_tracing(void)
{
- int xc_handle = xc_interface_open();
- xc_tbuf_disable(xc_handle);
- xc_interface_close(xc_handle);
+ int xc_handle = xc_interface_open();
+ xc_tbuf_disable(xc_handle);
+ xc_interface_close(xc_handle);
}
/**
@@ -387,7 +388,7 @@ struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
* mapped region containing all trace buffers.
*/
struct t_buf **init_bufs_ptrs(void *bufs_mapped, unsigned int num,
- unsigned long size)
+ unsigned long size)
{
int i;
struct t_buf **user_ptrs;
@@ -472,7 +473,7 @@ unsigned int get_num_cpus(void)
int monitor_tbufs(void)
{
int i;
- extern void process_record(int, struct t_rec *);
+ extern int process_record(int, struct t_rec *);
extern void alloc_qos_data(int ncpu);
void *tbufs_mapped; /* pointer to where the tbufs are mapped */
@@ -483,7 +484,7 @@ int monitor_tbufs(void)
unsigned int num; /* number of trace buffers / logical CPUS */
unsigned long size; /* size of a single trace buffer */
- int size_in_recs;
+ unsigned long data_size, rec_size;
/* get number of logical CPUs (and therefore number of trace buffers) */
num = get_num_cpus();
@@ -496,34 +497,32 @@ int monitor_tbufs(void)
/* setup access to trace buffers */
get_tbufs(&tbufs_mfn, &size);
- // printf("from dom0op: %ld, t_buf: %d, t_rec: %d\n",
- // size, sizeof(struct t_buf), sizeof(struct t_rec));
-
tbufs_mapped = map_tbufs(tbufs_mfn, num, size);
- size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec);
- // fprintf(stderr, "size_in_recs = %d\n", size_in_recs);
+ data_size = size - sizeof(struct t_buf);
/* build arrays of convenience ptrs */
meta = init_bufs_ptrs (tbufs_mapped, num, size);
data = init_rec_ptrs(meta, num);
- // Set up event channel for select()
- if (eventchn_init() < 0) {
- fprintf(stderr, "Failed to initialize event channel; Using POLL method\r\n");
- }
+ if ( eventchn_init() < 0 )
+ fprintf(stderr, "Failed to initialize event channel; "
+ "Using POLL method\r\n");
/* now, scan buffers for events */
while ( !interrupted )
{
- for ( i = 0; ( i < num ) && !interrupted; i++ )
+ for ( i = 0; (i < num) && !interrupted; i++ )
+ {
while ( meta[i]->cons != meta[i]->prod )
{
rmb(); /* read prod, then read item. */
- process_record(i, data[i] + meta[i]->cons % size_in_recs);
+ rec_size = process_record(
+ i, data[i] + meta[i]->cons % data_size);
mb(); /* read item, then update cons. */
- meta[i]->cons++;
+ meta[i]->cons += rec_size;
}
+ }
wait_for_event();
wakeups++;
@@ -550,44 +549,44 @@ error_t cmd_parser(int key, char *arg, struct argp_state *state)
switch ( key )
{
- case 't': /* set new records threshold for logging */
- {
- char *inval;
- setup->new_data_thresh = strtol(arg, &inval, 0);
- if ( inval == arg )
- argp_usage(state);
- }
- break;
+ case 't': /* set new records threshold for logging */
+ {
+ char *inval;
+ setup->new_data_thresh = strtol(arg, &inval, 0);
+ if ( inval == arg )
+ argp_usage(state);
+ }
+ break;
- case 's': /* set sleep time (given in milliseconds) */
- {
- char *inval;
- setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0));
- if ( inval == arg )
- argp_usage(state);
- }
- break;
+ case 's': /* set sleep time (given in milliseconds) */
+ {
+ char *inval;
+ setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0));
+ if ( inval == arg )
+ argp_usage(state);
+ }
+ break;
- case 'm': /* set ms_per_sample */
- {
- char *inval;
- setup->ms_per_sample = strtol(arg, &inval, 0);
- if ( inval == arg )
- argp_usage(state);
- }
- break;
+ case 'm': /* set ms_per_sample */
+ {
+ char *inval;
+ setup->ms_per_sample = strtol(arg, &inval, 0);
+ if ( inval == arg )
+ argp_usage(state);
+ }
+ break;
- case ARGP_KEY_ARG:
- {
- if ( state->arg_num == 0 )
- setup->outfile = arg;
- else
- argp_usage(state);
- }
- break;
+ case ARGP_KEY_ARG:
+ {
+ if ( state->arg_num == 0 )
+ setup->outfile = arg;
+ else
+ argp_usage(state);
+ }
+ break;
- default:
- return ARGP_ERR_UNKNOWN;
+ default:
+ return ARGP_ERR_UNKNOWN;
}
return 0;
@@ -614,27 +613,27 @@ void alloc_qos_data(int ncpu)
for (n=0; n<ncpu; n++) {
- for (i=0; i<sizeof(_new_qos_data); i=i+pgsize)
- if ((write(qos_fd, dummy, pgsize)) != pgsize) {
- PERROR(SHARED_MEM_FILE);
- exit(2);
- }
-
- new_qos = (_new_qos_data *) mmap(0, sizeof(_new_qos_data), PROT_READ|PROT_WRITE,
- MAP_SHARED, qos_fd, off);
- off += i;
- if (new_qos == NULL) {
- PERROR("mmap");
- exit(3);
- }
- // printf("new_qos = %p\n", new_qos);
- memset(new_qos, 0, sizeof(_new_qos_data));
- new_qos->next_datapoint = 0;
- advance_next_datapoint(0);
- new_qos->structlen = i;
- new_qos->ncpu = ncpu;
- // printf("structlen = 0x%x\n", i);
- cpu_qos_data[n] = new_qos;
+ for (i=0; i<sizeof(_new_qos_data); i=i+pgsize)
+ if ((write(qos_fd, dummy, pgsize)) != pgsize) {
+ PERROR(SHARED_MEM_FILE);
+ exit(2);
+ }
+
+ new_qos = (_new_qos_data *) mmap(0, sizeof(_new_qos_data), PROT_READ|PROT_WRITE,
+ MAP_SHARED, qos_fd, off);
+ off += i;
+ if (new_qos == NULL) {
+ PERROR("mmap");
+ exit(3);
+ }
+ // printf("new_qos = %p\n", new_qos);
+ memset(new_qos, 0, sizeof(_new_qos_data));
+ new_qos->next_datapoint = 0;
+ advance_next_datapoint(0);
+ new_qos->structlen = i;
+ new_qos->ncpu = ncpu;
+ // printf("structlen = 0x%x\n", i);
+ cpu_qos_data[n] = new_qos;
}
free(dummy);
new_qos = NULL;
@@ -647,19 +646,19 @@ void alloc_qos_data(int ncpu)
const struct argp_option cmd_opts[] =
{
{ .name = "log-thresh", .key='t', .arg="l",
- .doc =
- "Set number, l, of new records required to trigger a write to output "
- "(default " xstr(NEW_DATA_THRESH) ")." },
+ .doc =
+ "Set number, l, of new records required to trigger a write to output "
+ "(default " xstr(NEW_DATA_THRESH) ")." },
{ .name = "poll-sleep", .key='s', .arg="p",
- .doc =
- "Set sleep time, p, in milliseconds between polling the trace buffer "
- "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." },
+ .doc =
+ "Set sleep time, p, in milliseconds between polling the trace buffer "
+ "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." },
{ .name = "ms_per_sample", .key='m', .arg="MS",
- .doc =
- "Specify the number of milliseconds per sample "
- " (default " xstr(MS_PER_SAMPLE) ")." },
+ .doc =
+ "Specify the number of milliseconds per sample "
+ " (default " xstr(MS_PER_SAMPLE) ")." },
{0}
};
@@ -670,10 +669,10 @@ const struct argp parser_def =
.parser = cmd_parser,
// .args_doc = "[output file]",
.doc =
- "Tool to capture and partially process Xen trace buffer data"
- "\v"
- "This tool is used to capture trace buffer data from Xen. The data is "
- "saved in a shared memory structure to be further processed by xenmon."
+ "Tool to capture and partially process Xen trace buffer data"
+ "\v"
+ "This tool is used to capture trace buffer data from Xen. The data is "
+ "saved in a shared memory structure to be further processed by xenmon."
};
@@ -716,101 +715,101 @@ int main(int argc, char **argv)
void qos_init_domain(int domid, int idx)
{
- int i;
-
- memset(&new_qos->domain_info[idx], 0, sizeof(_domain_info));
- new_qos->domain_info[idx].last_update_time = global_now;
- // runnable_start_time[idx] = 0;
- new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
- new_qos->domain_info[idx].in_use = 1;
- new_qos->domain_info[idx].blocked_start_time = 0;
- new_qos->domain_info[idx].id = domid;
- if (domid == IDLE_DOMAIN_ID)
- sprintf(new_qos->domain_info[idx].name, "Idle Task%d", global_cpu);
- else
- sprintf(new_qos->domain_info[idx].name, "Domain#%d", domid);
+ int i;
+
+ memset(&new_qos->domain_info[idx], 0, sizeof(_domain_info));
+ new_qos->domain_info[idx].last_update_time = global_now;
+ // runnable_start_time[idx] = 0;
+ new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
+ new_qos->domain_info[idx].in_use = 1;
+ new_qos->domain_info[idx].blocked_start_time = 0;
+ new_qos->domain_info[idx].id = domid;
+ if (domid == IDLE_DOMAIN_ID)
+ sprintf(new_qos->domain_info[idx].name, "Idle Task%d", global_cpu);
+ else
+ sprintf(new_qos->domain_info[idx].name, "Domain#%d", domid);
- for (i=0; i<NSAMPLES; i++) {
- new_qos->qdata[i].ns_gotten[idx] = 0;
- new_qos->qdata[i].ns_allocated[idx] = 0;
- new_qos->qdata[i].ns_waiting[idx] = 0;
- new_qos->qdata[i].ns_blocked[idx] = 0;
- new_qos->qdata[i].switchin_count[idx] = 0;
- new_qos->qdata[i].io_count[idx] = 0;
- }
+ for (i=0; i<NSAMPLES; i++) {
+ new_qos->qdata[i].ns_gotten[idx] = 0;
+ new_qos->qdata[i].ns_allocated[idx] = 0;
+ new_qos->qdata[i].ns_waiting[idx] = 0;
+ new_qos->qdata[i].ns_blocked[idx] = 0;
+ new_qos->qdata[i].switchin_count[idx] = 0;
+ new_qos->qdata[i].io_count[idx] = 0;
+ }
}
void global_init_domain(int domid, int idx)
{
- int cpu;
- _new_qos_data *saved_qos;
+ int cpu;
+ _new_qos_data *saved_qos;
- saved_qos = new_qos;
+ saved_qos = new_qos;
- for (cpu=0; cpu<NCPU; cpu++) {
- new_qos = cpu_qos_data[cpu];
- qos_init_domain(domid, idx);
- }
- new_qos = saved_qos;
+ for (cpu=0; cpu<NCPU; cpu++) {
+ new_qos = cpu_qos_data[cpu];
+ qos_init_domain(domid, idx);
+ }
+ new_qos = saved_qos;
}
// give index of this domain in the qos data array
int indexof(int domid)
{
- int idx;
- xc_dominfo_t dominfo[NDOMAINS];
- int xc_handle, ndomains;
- extern void qos_kill_thread(int domid);
+ int idx;
+ xc_dominfo_t dominfo[NDOMAINS];
+ int xc_handle, ndomains;
+ extern void qos_kill_thread(int domid);
- if (domid < 0) { // shouldn't happen
- printf("bad domain id: %d\r\n", domid);
- return 0;
- }
+ if (domid < 0) { // shouldn't happen
+ printf("bad domain id: %d\r\n", domid);
+ return 0;
+ }
- for (idx=0; idx<NDOMAINS; idx++)
- if ( (new_qos->domain_info[idx].id == domid) && new_qos->domain_info[idx].in_use)
- return idx;
+ for (idx=0; idx<NDOMAINS; idx++)
+ if ( (new_qos->domain_info[idx].id == domid) && new_qos->domain_info[idx].in_use)
+ return idx;
- // not found, make a new entry
- for (idx=0; idx<NDOMAINS; idx++)
- if (new_qos->domain_info[idx].in_use == 0) {
- global_init_domain(domid, idx);
- return idx;
- }
+ // not found, make a new entry
+ for (idx=0; idx<NDOMAINS; idx++)
+ if (new_qos->domain_info[idx].in_use == 0) {
+ global_init_domain(domid, idx);
+ return idx;
+ }
+
+ // call domaininfo hypercall to try and garbage collect unused entries
+ xc_handle = xc_interface_open();
+ ndomains = xc_domain_getinfo(xc_handle, 0, NDOMAINS, dominfo);
+ xc_interface_close(xc_handle);
- // call domaininfo hypercall to try and garbage collect unused entries
- xc_handle = xc_interface_open();
- ndomains = xc_domain_getinfo(xc_handle, 0, NDOMAINS, dominfo);
- xc_interface_close(xc_handle);
-
- // for each domain in our data, look for it in the system dominfo structure
- // and purge the domain's data from our state if it does not exist in the
- // dominfo structure
- for (idx=0; idx<NDOMAINS; idx++) {
- int domid = new_qos->domain_info[idx].id;
- int jdx;
+ // for each domain in our data, look for it in the system dominfo structure
+ // and purge the domain's data from our state if it does not exist in the
+ // dominfo structure
+ for (idx=0; idx<NDOMAINS; idx++) {
+ int domid = new_qos->domain_info[idx].id;
+ int jdx;
- for (jdx=0; jdx<ndomains; jdx++) {
- if (dominfo[jdx].domid == domid)
- break;
+ for (jdx=0; jdx<ndomains; jdx++) {
+ if (dominfo[jdx].domid == domid)
+ break;
+ }
+ if (jdx == ndomains) // we didn't find domid in the dominfo struct
+ if (domid != IDLE_DOMAIN_ID) // exception for idle domain, which is not
+ // contained in dominfo
+ qos_kill_thread(domid); // purge our stale data
}
- if (jdx == ndomains) // we didn't find domid in the dominfo struct
- if (domid != IDLE_DOMAIN_ID) // exception for idle domain, which is not
- // contained in dominfo
- qos_kill_thread(domid); // purge our stale data
- }
- // look again for a free slot
- for (idx=0; idx<NDOMAINS; idx++)
- if (new_qos->domain_info[idx].in_use == 0) {
- global_init_domain(domid, idx);
- return idx;
- }
+ // look again for a free slot
+ for (idx=0; idx<NDOMAINS; idx++)
+ if (new_qos->domain_info[idx].in_use == 0) {
+ global_init_domain(domid, idx);
+ return idx;
+ }
- // still no space found, so bail
- fprintf(stderr, "out of space in domain table, increase NDOMAINS\r\n");
- exit(2);
+ // still no space found, so bail
+ fprintf(stderr, "out of space in domain table, increase NDOMAINS\r\n");
+ exit(2);
}
int domain_runnable(int domid)
@@ -879,25 +878,25 @@ void qos_update_thread(int cpu, int domid, uint64_t now)
time_since_update = now - last_update_time;
if (time_since_update < 0) {
- // what happened here? either a timestamp wraparound, or more likely,
- // a slight inconsistency among timestamps from various cpu's
- if (-time_since_update < billion) {
- // fairly small difference, let's just adjust 'now' to be a little
- // beyond last_update_time
- time_since_update = -time_since_update;
- }
- else if ( ((~0ULL - last_update_time) < billion) && (now < billion) ) {
- // difference is huge, must be a wraparound
- // last_update time should be "near" ~0ULL,
- // and now should be "near" 0
- time_since_update = now + (~0ULL - last_update_time);
- printf("time wraparound\n");
- }
- else {
- // none of the above, may be an out of order record
- // no good solution, just ignore and update again later
- return;
- }
+ // what happened here? either a timestamp wraparound, or more likely,
+ // a slight inconsistency among timestamps from various cpu's
+ if (-time_since_update < billion) {
+ // fairly small difference, let's just adjust 'now' to be a little
+ // beyond last_update_time
+ time_since_update = -time_since_update;
+ }
+ else if ( ((~0ULL - last_update_time) < billion) && (now < billion) ) {
+ // difference is huge, must be a wraparound
+ // last_update time should be "near" ~0ULL,
+ // and now should be "near" 0
+ time_since_update = now + (~0ULL - last_update_time);
+ printf("time wraparound\n");
+ }
+ else {
+ // none of the above, may be an out of order record
+ // no good solution, just ignore and update again later
+ return;
+ }
}
new_qos->domain_info[id].last_update_time = now;
@@ -985,7 +984,7 @@ void qos_switch_in(int cpu, int domid, uint64_t now, unsigned long ns_alloc, uns
// count up page flips for dom0 execution
if (domid == 0)
- dom0_flips = 0;
+ dom0_flips = 0;
}
// called when the current thread is taken off the cpu
@@ -1011,8 +1010,8 @@ void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
#if 0
new_qos->qdata[n].ns_gotten[idx] += gotten;
if (gotten > new_qos->qdata[n].ns_passed)
- printf("inconsistency #257, diff = %lld\n",
- gotten - new_qos->qdata[n].ns_passed );
+ printf("inconsistency #257, diff = %lld\n",
+ gotten - new_qos->qdata[n].ns_passed );
#endif
new_qos->domain_info[idx].ns_oncpu_since_boot += gotten;
new_qos->domain_info[idx].runnable_start_time = now;
@@ -1021,8 +1020,8 @@ void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
// process dom0 page flips
if (domid == 0)
- if (dom0_flips == 0)
- new_qos->qdata[n].flip_free_periods++;
+ if (dom0_flips == 0)
+ new_qos->qdata[n].flip_free_periods++;
}
// called when domain is put to sleep, may also be called
@@ -1047,11 +1046,11 @@ void qos_state_sleeping(int cpu, int domid, uint64_t now)
// domain died, presume it's dead on all cpu's, not just mostly dead
void qos_kill_thread(int domid)
{
- int cpu;
+ int cpu;
- for (cpu=0; cpu<NCPU; cpu++) {
- cpu_qos_data[cpu]->domain_info[indexof(domid)].in_use = 0;
- }
+ for (cpu=0; cpu<NCPU; cpu++) {
+ cpu_qos_data[cpu]->domain_info[indexof(domid)].in_use = 0;
+ }
}
@@ -1060,7 +1059,7 @@ void qos_kill_thread(int domid)
// when thread is already runnable
void qos_state_runnable(int cpu, int domid, uint64_t now)
{
- int idx;
+ int idx;
qos_update_thread_stats(cpu, domid, now);
@@ -1080,79 +1079,85 @@ void qos_state_runnable(int cpu, int domid, uint64_t now)
void qos_count_packets(domid_t domid, uint64_t now)
{
- int i, idx = indexof(domid);
- _new_qos_data *cpu_data;
+ int i, idx = indexof(domid);
+ _new_qos_data *cpu_data;
- for (i=0; i<NCPU; i++) {
- cpu_data = cpu_qos_data[i];
- if (cpu_data->domain_info[idx].in_use) {
- cpu_data->qdata[cpu_data->next_datapoint].io_count[idx]++;
+ for (i=0; i<NCPU; i++) {
+ cpu_data = cpu_qos_data[i];
+ if (cpu_data->domain_info[idx].in_use) {
+ cpu_data->qdata[cpu_data->next_datapoint].io_count[idx]++;
+ }
}
- }
- new_qos->qdata[new_qos->next_datapoint].io_count[0]++;
- dom0_flips++;
+ new_qos->qdata[new_qos->next_datapoint].io_count[0]++;
+ dom0_flips++;
}
-void process_record(int cpu, struct t_rec *r)
+int process_record(int cpu, struct t_rec *r)
{
- uint64_t now;
+ uint64_t now = 0;
+ uint32_t *extra_u32 = r->u.nocycles.extra_u32;
- new_qos = cpu_qos_data[cpu];
+ new_qos = cpu_qos_data[cpu];
- rec_count++;
+ rec_count++;
- now = ((double)r->cycles) / (opts.cpu_freq / 1000.0);
+ if ( r->cycles_included )
+ {
+ now = ((uint64_t)r->u.cycles.cycles_hi << 32) | r->u.cycles.cycles_lo;
+ now = ((double)now) / (opts.cpu_freq / 1000.0);
+ extra_u32 = r->u.cycles.extra_u32;
+ }
- global_now = now;
- global_cpu = cpu;
+ global_now = now;
+ global_cpu = cpu;
- log_event(r->event);
+ log_event(r->event);
- switch (r->event) {
+ switch (r->event) {
- case TRC_SCHED_SWITCH_INFPREV:
- // domain data[0] just switched out and received data[1] ns of cpu time
- qos_switch_out(cpu, r->data[0], now, r->data[1]);
- // printf("ns_gotten %ld\n", r->data[1]);
- break;
+ case TRC_SCHED_SWITCH_INFPREV:
+ // domain data[0] just switched out and received data[1] ns of cpu time
+ qos_switch_out(cpu, extra_u32[0], now, extra_u32[1]);
+ // printf("ns_gotten %ld\n", extra_u32[1]);
+ break;
- case TRC_SCHED_SWITCH_INFNEXT:
- // domain data[0] just switched in and
- // waited data[1] ns, and was allocated data[2] ns of cpu time
- qos_switch_in(cpu, r->data[0], now, r->data[2], r->data[1]);
- break;
+ case TRC_SCHED_SWITCH_INFNEXT:
+ // domain data[0] just switched in and
+ // waited data[1] ns, and was allocated data[2] ns of cpu time
+ qos_switch_in(cpu, extra_u32[0], now, extra_u32[2], extra_u32[1]);
+ break;
- case TRC_SCHED_DOM_ADD:
- (void) indexof(r->data[0]);
- break;
+ case TRC_SCHED_DOM_ADD:
+ (void) indexof(extra_u32[0]);
+ break;
- case TRC_SCHED_DOM_REM:
- qos_kill_thread(r->data[0]);
- break;
+ case TRC_SCHED_DOM_REM:
+ qos_kill_thread(extra_u32[0]);
+ break;
- case TRC_SCHED_SLEEP:
- qos_state_sleeping(cpu, r->data[0], now);
- break;
+ case TRC_SCHED_SLEEP:
+ qos_state_sleeping(cpu, extra_u32[0], now);
+ break;
- case TRC_SCHED_WAKE:
- qos_state_runnable(cpu, r->data[0], now);
- break;
+ case TRC_SCHED_WAKE:
+ qos_state_runnable(cpu, extra_u32[0], now);
+ break;
- case TRC_SCHED_BLOCK:
- qos_state_sleeping(cpu, r->data[0], now);
- break;
+ case TRC_SCHED_BLOCK:
+ qos_state_sleeping(cpu, extra_u32[0], now);
+ break;
- case TRC_MEM_PAGE_GRANT_TRANSFER:
- qos_count_packets(r->data[0], now);
- break;
+ case TRC_MEM_PAGE_GRANT_TRANSFER:
+ qos_count_packets(extra_u32[0], now);
+ break;
- default:
- break;
- }
- new_qos = NULL;
-}
-
+ default:
+ break;
+ }
+ new_qos = NULL;
+ return 4 + (r->cycles_included ? 8 : 0) + (r->extra_u32 * 4);
+}
diff --git a/tools/xenstat/libxenstat/Makefile b/tools/xenstat/libxenstat/Makefile
index ed359a6ded..69cbf2fca7 100644
--- a/tools/xenstat/libxenstat/Makefile
+++ b/tools/xenstat/libxenstat/Makefile
@@ -31,6 +31,7 @@ SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
OBJECTS-y=src/xenstat.o
OBJECTS-$(CONFIG_Linux) += src/xenstat_linux.o
OBJECTS-$(CONFIG_SunOS) += src/xenstat_solaris.o
+OBJECTS-$(CONFIG_NetBSD) += src/xenstat_netbsd.o
SONAME_FLAGS=-Wl,$(SONAME_LDFLAG) -Wl,libxenstat.so.$(MAJOR)
WARN_FLAGS=-Wall -Werror
diff --git a/tools/xenstat/libxenstat/src/xenstat_netbsd.c b/tools/xenstat/libxenstat/src/xenstat_netbsd.c
new file mode 100644
index 0000000000..6e9d6aee10
--- /dev/null
+++ b/tools/xenstat/libxenstat/src/xenstat_netbsd.c
@@ -0,0 +1,97 @@
+/* libxenstat: statistics-collection library for Xen
+ * Copyright (C) International Business Machines Corp., 2005
+ * Authors: Josh Triplett <josht@us.ibm.com>
+ * Judy Fischbach <jfisch@us.ibm.com>
+ * David Hendricks <dhendrix@us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xenstat_priv.h"
+
+#define SYSFS_VBD_PATH "/sys/devices/xen-backend/"
+
+struct priv_data {
+ FILE *procnetdev;
+ DIR *sysfsvbd;
+};
+
+static struct priv_data *
+get_priv_data(xenstat_handle *handle)
+{
+ if (handle->priv != NULL)
+ return handle->priv;
+
+ handle->priv = malloc(sizeof(struct priv_data));
+ if (handle->priv == NULL)
+ return (NULL);
+
+ ((struct priv_data *)handle->priv)->procnetdev = NULL;
+ ((struct priv_data *)handle->priv)->sysfsvbd = NULL;
+
+ return handle->priv;
+}
+
+/* Expected format of /proc/net/dev */
+static const char PROCNETDEV_HEADER[] =
+ "Inter-| Receive |"
+ " Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|"
+ "bytes packets errs drop fifo colls carrier compressed\n";
+
+/* Collect information about networks */
+int xenstat_collect_networks(xenstat_node * node)
+{
+ /* XXX fixme: implement code to get stats from libkvm ! */
+ return 1;
+}
+
+/* Free network information in handle */
+void xenstat_uninit_networks(xenstat_handle * handle)
+{
+ struct priv_data *priv = get_priv_data(handle);
+ if (priv != NULL && priv->procnetdev != NULL)
+ fclose(priv->procnetdev);
+}
+
+static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap)
+{
+ /* XXX implement */
+ return 0;
+}
+
+/* Collect information about VBDs */
+int xenstat_collect_vbds(xenstat_node * node)
+{
+ return 1;
+}
+
+/* Free VBD information in handle */
+void xenstat_uninit_vbds(xenstat_handle * handle)
+{
+ struct priv_data *priv = get_priv_data(handle);
+ if (priv != NULL && priv->sysfsvbd != NULL)
+ closedir(priv->sysfsvbd);
+}
diff --git a/tools/xenstat/xentop/xentop.c b/tools/xenstat/xentop/xentop.c
index 92d4eb217a..755e322f56 100644
--- a/tools/xenstat/xentop/xentop.c
+++ b/tools/xenstat/xentop/xentop.c
@@ -28,7 +28,9 @@
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
+#if defined(__linux__)
#include <linux/kdev_t.h>
+#endif
#include <xenstat.h>
@@ -938,11 +940,12 @@ void do_vbd(xenstat_domain *domain)
vbd = xenstat_domain_vbd(domain,i);
-#ifdef __sun__
+#if !defined(__linux__)
details[0] = '\0';
#else
- snprintf(details, 20, "[%2x:%2x] ", MAJOR(xenstat_vbd_dev(vbd)),
- MINOR(xenstat_vbd_dev(vbd)));
+ snprintf(details, 20, "[%2x:%2x] ",
+ MAJOR(xenstat_vbd_dev(vbd)),
+ MINOR(xenstat_vbd_dev(vbd)));
#endif
print("VBD %s %4d %s OO: %8llu RD: %8llu WR: %8llu\n",
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index a754fab85f..adbe605675 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -25,6 +25,7 @@ XENSTORED_OBJS = xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored
XENSTORED_OBJS_$(CONFIG_Linux) = xenstored_linux.o
XENSTORED_OBJS_$(CONFIG_SunOS) = xenstored_solaris.o
+XENSTORED_OBJS_$(CONFIG_NetBSD) = xenstored_netbsd.o
XENSTORED_OBJS += $(XENSTORED_OBJS_y)
diff --git a/tools/xenstore/xenstored_netbsd.c b/tools/xenstore/xenstored_netbsd.c
new file mode 100644
index 0000000000..1e94e41ff3
--- /dev/null
+++ b/tools/xenstore/xenstored_netbsd.c
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (C) 2005 Rusty Russell IBM Corporation
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include "xenstored_core.h"
+
+#define XENSTORED_PROC_KVA "/dev/xsd_kva"
+#define XENSTORED_PROC_PORT "/kern/xen/xsd_port"
+
+evtchn_port_t xenbus_evtchn(void)
+{
+ int fd;
+ int rc;
+ evtchn_port_t port;
+ char str[20];
+
+ fd = open(XENSTORED_PROC_PORT, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ rc = read(fd, str, sizeof(str));
+ if (rc == -1)
+ {
+ int err = errno;
+ close(fd);
+ errno = err;
+ return -1;
+ }
+
+ str[rc] = '\0';
+ port = strtoul(str, NULL, 0);
+
+ close(fd);
+ return port;
+}
+
+void *xenbus_map(void)
+{
+ int fd;
+ void *addr;
+
+ fd = open(XENSTORED_PROC_KVA, O_RDWR);
+ if (fd == -1)
+ return NULL;
+
+ addr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd, 0);
+
+ if (addr == MAP_FAILED)
+ addr = NULL;
+
+ close(fd);
+
+ return addr;
+}
+
+void xenbus_notify_running(void)
+{
+}
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index ad06778592..fdb5d5e57f 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -22,6 +22,7 @@
#include <signal.h>
#include <inttypes.h>
#include <string.h>
+#include <assert.h>
#include <xen/xen.h>
#include <xen/trace.h>
@@ -83,24 +84,62 @@ struct timespec millis_to_timespec(unsigned long millis)
}
/**
- * write_rec - output a trace record in binary format
+ * write_buffer - write a section of the trace buffer
* @cpu - source buffer CPU ID
- * @rec - trace record to output
+ * @start
+ * @size - size of write (may be less than total window size)
+ * @total_size - total size of the window (0 on 2nd write of wrapped windows)
* @out - output stream
*
- * Outputs the trace record to a filestream, prepending the CPU ID of the
- * source trace buffer.
+ * Outputs the trace buffer to a filestream, prepending the CPU and size
+ * of the buffer write.
*/
-void write_rec(unsigned int cpu, struct t_rec *rec, FILE *out)
+void write_buffer(unsigned int cpu, unsigned char *start, int size,
+ int total_size, int outfd)
{
size_t written = 0;
- written += fwrite(&cpu, sizeof(cpu), 1, out);
- written += fwrite(rec, sizeof(*rec), 1, out);
- if ( written != 2 )
+
+ /* Write a CPU_BUF record on each buffer "window" written. Wrapped
+ * windows may involve two writes, so only write the record on the
+ * first write. */
+ if ( total_size != 0 )
{
- PERROR("Failed to write trace record");
- exit(EXIT_FAILURE);
+ struct {
+ uint32_t header;
+ struct {
+ unsigned cpu;
+ unsigned byte_count;
+ } extra;
+ } rec;
+
+ rec.header = TRC_TRACE_CPU_CHANGE
+ | ((sizeof(rec.extra)/sizeof(uint32_t)) << TRACE_EXTRA_SHIFT);
+ rec.extra.cpu = cpu;
+ rec.extra.byte_count = total_size;
+
+ written = write(outfd, &rec, sizeof(rec));
+
+ if ( written != sizeof(rec) )
+ {
+ fprintf(stderr, "Cannot write cpu change (write returned %zd)\n",
+ written);
+ goto fail;
+ }
}
+
+ written = write(outfd, start, size);
+ if ( written != size )
+ {
+ fprintf(stderr, "Write failed! (size %d, returned %zd)\n",
+ size, written);
+ goto fail;
+ }
+
+ return;
+
+ fail:
+ PERROR("Failed to write trace data");
+ exit(EXIT_FAILURE);
}
static void get_tbufs(unsigned long *mfn, unsigned long *size)
@@ -233,12 +272,12 @@ struct t_buf **init_bufs_ptrs(void *bufs_mapped, unsigned int num,
* mapped in user space. Note that the trace buffer metadata contains machine
* pointers - the array returned allows more convenient access to them.
*/
-struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
+unsigned char **init_rec_ptrs(struct t_buf **meta, unsigned int num)
{
int i;
- struct t_rec **data;
+ unsigned char **data;
- data = calloc(num, sizeof(struct t_rec *));
+ data = calloc(num, sizeof(unsigned char *));
if ( data == NULL )
{
PERROR("Failed to allocate memory for data pointers\n");
@@ -246,7 +285,7 @@ struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
}
for ( i = 0; i < num; i++ )
- data[i] = (struct t_rec *)(meta[i] + 1);
+ data[i] = (unsigned char *)(meta[i] + 1);
return data;
}
@@ -281,19 +320,19 @@ unsigned int get_num_cpus(void)
* monitor_tbufs - monitor the contents of tbufs and output to a file
* @logfile: the FILE * representing the file to log to
*/
-int monitor_tbufs(FILE *logfile)
+int monitor_tbufs(int outfd)
{
int i;
void *tbufs_mapped; /* pointer to where the tbufs are mapped */
struct t_buf **meta; /* pointers to the trace buffer metadata */
- struct t_rec **data; /* pointers to the trace buffer data areas
+ unsigned char **data; /* pointers to the trace buffer data areas
* where they are mapped into user space. */
unsigned long tbufs_mfn; /* mfn of the tbufs */
unsigned int num; /* number of trace buffers / logical CPUS */
unsigned long size; /* size of a single trace buffer */
- int size_in_recs;
+ unsigned long data_size;
/* get number of logical CPUs (and therefore number of trace buffers) */
num = get_num_cpus();
@@ -302,7 +341,7 @@ int monitor_tbufs(FILE *logfile)
get_tbufs(&tbufs_mfn, &size);
tbufs_mapped = map_tbufs(tbufs_mfn, num, size);
- size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec);
+ data_size = size - sizeof(struct t_buf);
/* build arrays of convenience ptrs */
meta = init_bufs_ptrs(tbufs_mapped, num, size);
@@ -317,13 +356,48 @@ int monitor_tbufs(FILE *logfile)
{
for ( i = 0; (i < num) && !interrupted; i++ )
{
- while ( meta[i]->cons != meta[i]->prod )
+ unsigned long start_offset, end_offset, window_size, cons, prod;
+
+ /* Read window information only once. */
+ cons = meta[i]->cons;
+ prod = meta[i]->prod;
+ rmb(); /* read prod, then read item. */
+
+ if ( cons == prod )
+ continue;
+
+ assert(prod > cons);
+
+ window_size = prod - cons;
+ start_offset = cons % data_size;
+ end_offset = prod % data_size;
+
+ if ( end_offset > start_offset )
+ {
+ /* If window does not wrap, write in one big chunk */
+ write_buffer(i, data[i]+start_offset,
+ window_size,
+ window_size,
+ outfd);
+ }
+ else
{
- rmb(); /* read prod, then read item. */
- write_rec(i, data[i] + meta[i]->cons % size_in_recs, logfile);
- mb(); /* read item, then update cons. */
- meta[i]->cons++;
+ /* If wrapped, write in two chunks:
+ * - first, start to the end of the buffer
+ * - second, start of buffer to end of window
+ */
+ write_buffer(i, data[i] + start_offset,
+ data_size - start_offset,
+ window_size,
+ outfd);
+ write_buffer(i, data[i],
+ end_offset,
+ 0,
+ outfd);
}
+
+ mb(); /* read buffer, then update cons. */
+ meta[i]->cons = meta[i]->prod;
}
nanosleep(&opts.poll_sleep, NULL);
@@ -333,7 +407,7 @@ int monitor_tbufs(FILE *logfile)
free(meta);
free(data);
/* don't need to munmap - cleanup is automatic */
- fclose(logfile);
+ close(outfd);
return 0;
}
@@ -503,7 +577,6 @@ const char *argp_program_bug_address = "<mark.a.williamson@intel.com>";
int main(int argc, char **argv)
{
int outfd = 1, ret;
- FILE *logfile;
struct sigaction act;
opts.outfile = 0;
@@ -537,8 +610,6 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- logfile = fdopen(outfd, "w");
-
/* ensure that if we get a signal, we'll do cleanup, then exit */
act.sa_handler = close_handler;
act.sa_flags = 0;
@@ -547,7 +618,16 @@ int main(int argc, char **argv)
sigaction(SIGTERM, &act, NULL);
sigaction(SIGINT, &act, NULL);
- ret = monitor_tbufs(logfile);
+ ret = monitor_tbufs(outfd);
return ret;
}
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xm-test/lib/XmTestLib/acm.py b/tools/xm-test/lib/XmTestLib/acm.py
index 5456da6453..23564b5096 100644
--- a/tools/xm-test/lib/XmTestLib/acm.py
+++ b/tools/xm-test/lib/XmTestLib/acm.py
@@ -49,7 +49,7 @@ def ACMLoadPolicy_XenAPI(policy='xm-test'):
if polname != policy:
# Try it, maybe it's not activated
traceCommand("xm setpolicy %s %s" %
- (xsconstants.XS_POLICY_ACM, policy))
+ (xsconstants.ACM_POLICY_ID, policy))
polname = getSystemPolicyName()
if polname != policy:
FAIL("Need to have a system with no or policy '%s' active, "