diff options
author | Alex Williamson <alex.williamson@hp.com> | 2007-09-27 12:22:16 -0600 |
---|---|---|
committer | Alex Williamson <alex.williamson@hp.com> | 2007-09-27 12:22:16 -0600 |
commit | 265e5c6b08e411d36c173f1c08b3ffe8b747f7eb (patch) | |
tree | 990c4f947485ebd192af3bc03b4e47e6678efee5 /tools | |
parent | 1169dee6d4e25e1eceff1257562ab33e21032950 (diff) | |
parent | 9f5581fda701ef44f339bda7462907de5e85ede8 (diff) | |
download | xen-265e5c6b08e411d36c173f1c08b3ffe8b747f7eb.tar.gz xen-265e5c6b08e411d36c173f1c08b3ffe8b747f7eb.tar.bz2 xen-265e5c6b08e411d36c173f1c08b3ffe8b747f7eb.zip |
merge with xen-unstable.hg (staging)
Diffstat (limited to 'tools')
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, ¬ify); +} + +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, " |