aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs2
-rw-r--r--audio/ossaudio.c30
-rw-r--r--block.c41
-rw-r--r--block.h3
-rw-r--r--block/qcow.c9
-rw-r--r--block/qcow2-refcount.c1
-rw-r--r--block/qcow2.c110
-rw-r--r--block_int.h3
-rwxr-xr-xconfigure49
-rw-r--r--hw/eepro100.c15
-rw-r--r--hw/iommu.c4
-rw-r--r--hw/pci.h14
-rw-r--r--hw/pcnet.c2
-rw-r--r--hw/sun4m.c15
-rw-r--r--hw/tcx.c2
-rw-r--r--hw/vga.c1
-rw-r--r--hw/virtio-blk.c5
-rw-r--r--hw/virtio-net.c4
-rw-r--r--hw/virtio-net.h1
-rw-r--r--input.c238
-rw-r--r--json-parser.c2
-rw-r--r--osdep.c2
-rw-r--r--qemu-img-cmds.hx6
-rw-r--r--qemu-img.c227
-rw-r--r--sparc-dis.c4
-rw-r--r--target-i386/cpu.h3
-rw-r--r--target-i386/helper.c35
-rw-r--r--target-i386/kvm.c63
-rw-r--r--target-i386/translate.c2
-rw-r--r--target-sparc/helper.c5
-rw-r--r--vl.c220
31 files changed, 803 insertions, 315 deletions
diff --git a/Makefile.objs b/Makefile.objs
index ca5fa0e74..67971d9ea 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -48,7 +48,7 @@ common-obj-y += $(qobject-obj-y)
common-obj-y += readline.o console.o
common-obj-y += tcg-runtime.o host-utils.o
-common-obj-y += irq.o ioport.o
+common-obj-y += irq.o ioport.o input.o
common-obj-$(CONFIG_PTIMER) += ptimer.o
common-obj-$(CONFIG_MAX7310) += max7310.o
common-obj-$(CONFIG_WM8750) += wm8750.o
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index ebf8b2397..42bffaeaf 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -240,6 +240,31 @@ static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
}
#endif
+#ifdef USE_DSP_POLICY
+static int oss_get_version (int fd, int *version, const char *typ)
+{
+ if (ioctl (fd, OSS_GETVERSION, &version)) {
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ /*
+ * Looks like atm (20100109) FreeBSD knows OSS_GETVERSION
+ * since 7.x, but currently only on the mixer device (or in
+ * the Linuxolator), and in the native version that part of
+ * the code is in fact never reached so the ioctl fails anyway.
+ * Until this is fixed, just check the errno and if its what
+ * FreeBSD's sound drivers return atm assume they are new enough.
+ */
+ if (errno == EINVAL) {
+ *version = 0x040000;
+ return 0;
+ }
+#endif
+ oss_logerr2 (errno, typ, "Failed to get OSS version\n");
+ return -1;
+ }
+ return 0;
+}
+#endif
+
static int oss_open (int in, struct oss_params *req,
struct oss_params *obt, int *pfd)
{
@@ -289,10 +314,7 @@ static int oss_open (int in, struct oss_params *req,
if (conf.policy >= 0) {
int version;
- if (ioctl (fd, OSS_GETVERSION, &version)) {
- oss_logerr2 (errno, typ, "Failed to get OSS version\n");
- }
- else {
+ if (!oss_get_version (fd, &version, typ)) {
if (conf.debug) {
dolog ("OSS version = %#x\n", version);
}
diff --git a/block.c b/block.c
index 30ae2b1e5..115e5913e 100644
--- a/block.c
+++ b/block.c
@@ -477,7 +477,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
unlink(filename);
}
#endif
- if (bs->backing_file[0] != '\0') {
+ if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
/* if there is a backing file, use it */
BlockDriver *back_drv = NULL;
bs->backing_hd = bdrv_new("");
@@ -594,9 +594,35 @@ int bdrv_commit(BlockDriverState *bs)
if (drv->bdrv_make_empty)
return drv->bdrv_make_empty(bs);
+ /*
+ * Make sure all data we wrote to the backing device is actually
+ * stable on disk.
+ */
+ if (bs->backing_hd)
+ bdrv_flush(bs->backing_hd);
return 0;
}
+/*
+ * Return values:
+ * 0 - success
+ * -EINVAL - backing format specified, but no file
+ * -ENOSPC - can't update the backing file because no space is left in the
+ * image file header
+ * -ENOTSUP - format driver doesn't support changing the backing file
+ */
+int bdrv_change_backing_file(BlockDriverState *bs,
+ const char *backing_file, const char *backing_fmt)
+{
+ BlockDriver *drv = bs->drv;
+
+ if (drv->bdrv_change_backing_file != NULL) {
+ return drv->bdrv_change_backing_file(bs, backing_file, backing_fmt);
+ } else {
+ return -ENOTSUP;
+ }
+}
+
static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
size_t size)
{
@@ -1095,12 +1121,8 @@ const char *bdrv_get_device_name(BlockDriverState *bs)
void bdrv_flush(BlockDriverState *bs)
{
- if (!bs->drv)
- return;
- if (bs->drv->bdrv_flush)
+ if (bs->drv && bs->drv->bdrv_flush)
bs->drv->bdrv_flush(bs);
- if (bs->backing_hd)
- bdrv_flush(bs->backing_hd);
}
void bdrv_flush_all(void)
@@ -1352,7 +1374,7 @@ const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size)
{
- if (!bs->backing_hd) {
+ if (!bs->backing_file) {
pstrcpy(filename, filename_size, "");
} else {
pstrcpy(filename, filename_size, bs->backing_file);
@@ -1777,11 +1799,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
if (!drv)
return NULL;
-
- /*
- * Note that unlike bdrv_flush the driver is reponsible for flushing a
- * backing image if it exists.
- */
return drv->bdrv_aio_flush(bs, cb, opaque);
}
diff --git a/block.h b/block.h
index fa51ddf15..bee9ec566 100644
--- a/block.h
+++ b/block.h
@@ -39,6 +39,7 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */
+#define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
@@ -82,6 +83,8 @@ int64_t bdrv_getlength(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
int bdrv_commit(BlockDriverState *bs);
+int bdrv_change_backing_file(BlockDriverState *bs,
+ const char *backing_file, const char *backing_fmt);
void bdrv_register(BlockDriver *bdrv);
/* async block I/O */
diff --git a/block/qcow.c b/block/qcow.c
index 7fc85ae58..1e3e59b00 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -900,6 +900,14 @@ static void qcow_flush(BlockDriverState *bs)
bdrv_flush(s->hd);
}
+static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ BDRVQcowState *s = bs->opaque;
+
+ return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcowState *s = bs->opaque;
@@ -940,6 +948,7 @@ static BlockDriver bdrv_qcow = {
.bdrv_make_empty = qcow_make_empty,
.bdrv_aio_readv = qcow_aio_readv,
.bdrv_aio_writev = qcow_aio_writev,
+ .bdrv_aio_flush = qcow_aio_flush,
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_get_info = qcow_get_info,
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 54b19f86d..3a2d44a17 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -511,7 +511,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
l2_table = NULL;
l1_table = NULL;
l1_size2 = l1_size * sizeof(uint64_t);
- l1_allocated = 0;
if (l1_table_offset != s->l1_table_offset) {
if (l1_size2 != 0) {
l1_table = qemu_mallocz(align_offset(l1_size2, 512));
diff --git a/block/qcow2.c b/block/qcow2.c
index 984264b3e..6622ebadb 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -658,6 +658,105 @@ static void qcow_close(BlockDriverState *bs)
bdrv_delete(s->hd);
}
+/*
+ * Updates the variable length parts of the qcow2 header, i.e. the backing file
+ * name and all extensions. qcow2 was not designed to allow such changes, so if
+ * we run out of space (we can only use the first cluster) this function may
+ * fail.
+ *
+ * Returns 0 on success, -errno in error cases.
+ */
+static int qcow2_update_ext_header(BlockDriverState *bs,
+ const char *backing_file, const char *backing_fmt)
+{
+ size_t backing_file_len = 0;
+ size_t backing_fmt_len = 0;
+ BDRVQcowState *s = bs->opaque;
+ QCowExtension ext_backing_fmt = {0, 0};
+ int ret;
+
+ /* Backing file format doesn't make sense without a backing file */
+ if (backing_fmt && !backing_file) {
+ return -EINVAL;
+ }
+
+ /* Prepare the backing file format extension if needed */
+ if (backing_fmt) {
+ ext_backing_fmt.len = cpu_to_be32(strlen(backing_fmt));
+ ext_backing_fmt.magic = cpu_to_be32(QCOW_EXT_MAGIC_BACKING_FORMAT);
+ backing_fmt_len = ((sizeof(ext_backing_fmt)
+ + strlen(backing_fmt) + 7) & ~7);
+ }
+
+ /* Check if we can fit the new header into the first cluster */
+ if (backing_file) {
+ backing_file_len = strlen(backing_file);
+ }
+
+ size_t header_size = sizeof(QCowHeader) + backing_file_len
+ + backing_fmt_len;
+
+ if (header_size > s->cluster_size) {
+ return -ENOSPC;
+ }
+
+ /* Rewrite backing file name and qcow2 extensions */
+ size_t ext_size = header_size - sizeof(QCowHeader);
+ uint8_t buf[ext_size];
+ size_t offset = 0;
+ size_t backing_file_offset = 0;
+
+ if (backing_file) {
+ if (backing_fmt) {
+ int padding = backing_fmt_len -
+ (sizeof(ext_backing_fmt) + strlen(backing_fmt));
+
+ memcpy(buf + offset, &ext_backing_fmt, sizeof(ext_backing_fmt));
+ offset += sizeof(ext_backing_fmt);
+
+ memcpy(buf + offset, backing_fmt, strlen(backing_fmt));
+ offset += strlen(backing_fmt);
+
+ memset(buf + offset, 0, padding);
+ offset += padding;
+ }
+
+ memcpy(buf + offset, backing_file, backing_file_len);
+ backing_file_offset = sizeof(QCowHeader) + offset;
+ }
+
+ ret = bdrv_pwrite(s->hd, sizeof(QCowHeader), buf, ext_size);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ /* Update header fields */
+ uint64_t be_backing_file_offset = cpu_to_be64(backing_file_offset);
+ uint32_t be_backing_file_size = cpu_to_be32(backing_file_len);
+
+ ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, backing_file_offset),
+ &be_backing_file_offset, sizeof(uint64_t));
+ if (ret < 0) {
+ goto fail;
+ }
+
+ ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, backing_file_size),
+ &be_backing_file_size, sizeof(uint32_t));
+ if (ret < 0) {
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ return ret;
+}
+
+static int qcow2_change_backing_file(BlockDriverState *bs,
+ const char *backing_file, const char *backing_fmt)
+{
+ return qcow2_update_ext_header(bs, backing_file, backing_fmt);
+}
+
static int get_bits_from_size(size_t size)
{
int res = 0;
@@ -1012,6 +1111,14 @@ static void qcow_flush(BlockDriverState *bs)
bdrv_flush(s->hd);
}
+static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ BDRVQcowState *s = bs->opaque;
+
+ return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
static int64_t qcow_vm_state_offset(BDRVQcowState *s)
{
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
@@ -1126,6 +1233,7 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_aio_readv = qcow_aio_readv,
.bdrv_aio_writev = qcow_aio_writev,
+ .bdrv_aio_flush = qcow_aio_flush,
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_snapshot_create = qcow2_snapshot_create,
@@ -1137,6 +1245,8 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_save_vmstate = qcow_save_vmstate,
.bdrv_load_vmstate = qcow_load_vmstate,
+ .bdrv_change_backing_file = qcow2_change_backing_file,
+
.create_options = qcow_create_options,
.bdrv_check = qcow_check,
};
diff --git a/block_int.h b/block_int.h
index 9a3b2e09d..a0ebd90a0 100644
--- a/block_int.h
+++ b/block_int.h
@@ -98,6 +98,9 @@ struct BlockDriver {
int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size);
+ int (*bdrv_change_backing_file)(BlockDriverState *bs,
+ const char *backing_file, const char *backing_fmt);
+
/* removable device specific */
int (*bdrv_is_inserted)(BlockDriverState *bs);
int (*bdrv_media_changed)(BlockDriverState *bs);
diff --git a/configure b/configure
index bbcd85825..6a5781452 100755
--- a/configure
+++ b/configure
@@ -1006,6 +1006,15 @@ EOF
fi
##########################################
+# pkgconfig probe
+
+pkgconfig="${cross_prefix}pkg-config"
+if ! test -x "$(which $pkgconfig 2>/dev/null)"; then
+ # likely not cross compiling, or hope for the best
+ pkgconfig=pkg-config
+fi
+
+##########################################
# Sparse probe
if test "$sparse" != "no" ; then
if test -x "$(which cgcc 2>/dev/null)"; then
@@ -1021,18 +1030,24 @@ fi
##########################################
# SDL probe
-sdl_too_old=no
+if $pkgconfig sdl --modversion >/dev/null 2>&1; then
+ sdlconfig="$pkgconfig sdl"
+ _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
+else
+ sdlconfig='sdl-config'
+ _sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
+fi
+sdl_too_old=no
if test "$sdl" != "no" ; then
cat > $TMPC << EOF
#include <SDL.h>
#undef main /* We don't want SDL to override our main() */
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
EOF
- sdl_cflags=`sdl-config --cflags 2> /dev/null`
- sdl_libs=`sdl-config --libs 2> /dev/null`
+ sdl_cflags=`$sdlconfig --cflags 2> /dev/null`
+ sdl_libs=`$sdlconfig --libs 2> /dev/null`
if compile_prog "$sdl_cflags" "$sdl_libs" ; then
- _sdlversion=`sdl-config --version | sed 's/[^0-9]//g'`
if test "$_sdlversion" -lt 121 ; then
sdl_too_old=yes
else
@@ -1041,12 +1056,12 @@ EOF
fi
fi
- # static link with sdl ?
+ # static link with sdl ? (note: sdl.pc's --static --libs is broken)
if test "$sdl" = "yes" -a "$static" = "yes" ; then
sdl_libs=`sdl-config --static-libs 2>/dev/null`
- if test `sdl-config --static-libs 2>/dev/null | grep \\\-laa > /dev/null` ; then
+ if test $? = 0 && echo $sdl_libs | grep -- -laa > /dev/null; then
sdl_libs="$sdl_libs `aalib-config --static-libs >2 /dev/null`"
- sdl_cflags="$sd_cflags `aalib-config --cflags >2 /dev/null`"
+ sdl_cflags="$sdl_cflags `aalib-config --cflags >2 /dev/null`"
fi
if compile_prog "$sdl_cflags" "$sdl_libs" ; then
:
@@ -1088,8 +1103,8 @@ if test "$vnc_tls" != "no" ; then
#include <gnutls/gnutls.h>
int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; }
EOF
- vnc_tls_cflags=`pkg-config --cflags gnutls 2> /dev/null`
- vnc_tls_libs=`pkg-config --libs gnutls 2> /dev/null`
+ vnc_tls_cflags=`$pkgconfig --cflags gnutls 2> /dev/null`
+ vnc_tls_libs=`$pkgconfig --libs gnutls 2> /dev/null`
if compile_prog "$vnc_tls_cflags" "$vnc_tls_libs" ; then
vnc_tls=yes
libs_softmmu="$vnc_tls_libs $libs_softmmu"
@@ -1334,13 +1349,19 @@ fi
##########################################
# curl probe
+if $pkgconfig libcurl --modversion >/dev/null 2>&1; then
+ curlconfig="$pkgconfig libcurl"
+else
+ curlconfig=curl-config
+fi
+
if test "$curl" != "no" ; then
cat > $TMPC << EOF
#include <curl/curl.h>
int main(void) { return curl_easy_init(); }
EOF
- curl_cflags=`curl-config --cflags 2>/dev/null`
- curl_libs=`curl-config --libs 2>/dev/null`
+ curl_cflags=`$curlconfig --cflags 2>/dev/null`
+ curl_libs=`$curlconfig --libs 2>/dev/null`
if compile_prog "$curl_cflags" "$curl_libs" ; then
curl=yes
libs_tools="$curl_libs $libs_tools"
@@ -1361,7 +1382,7 @@ if test "$check_utests" != "no" ; then
#include <check.h>
int main(void) { suite_create("qemu test"); return 0; }
EOF
- check_libs=`pkg-config --libs check`
+ check_libs=`$pkgconfig --libs check`
if compile_prog "" $check_libs ; then
check_utests=yes
libs_tools="$check_libs $libs_tools"
@@ -1380,8 +1401,8 @@ if test "$bluez" != "no" ; then
#include <bluetooth/bluetooth.h>
int main(void) { return bt_error(0); }
EOF
- bluez_cflags=`pkg-config --cflags bluez 2> /dev/null`
- bluez_libs=`pkg-config --libs bluez 2> /dev/null`
+ bluez_cflags=`$pkgconfig --cflags bluez 2> /dev/null`
+ bluez_libs=`$pkgconfig --libs bluez 2> /dev/null`
if compile_prog "$bluez_cflags" "$bluez_libs" ; then
bluez=yes
libs_softmmu="$bluez_libs $libs_softmmu"
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 82e37665b..d0c45bfbb 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -40,7 +40,6 @@
#include <stddef.h> /* offsetof */
#include <stdbool.h>
#include "hw.h"
-#include "loader.h" /* rom_add_option */
#include "pci.h"
#include "net.h"
#include "eeprom93xx.h"
@@ -415,10 +414,8 @@ static void pci_reset(EEPRO100State * s)
/* TODO: this is the default, do not override. */
PCI_CONFIG_16(PCI_COMMAND, 0x0000);
/* PCI Status */
- /* TODO: this seems to make no sense. */
/* TODO: Value at RST# should be 0. */
- PCI_CONFIG_16(PCI_STATUS,
- PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_TARGET_ABORT);
+ PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK);
/* PCI Revision ID */
PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
/* TODO: this is the default, do not override. */
@@ -1865,15 +1862,6 @@ static int nic_init(PCIDevice *pci_dev, uint32_t device)
s->vmstate->name = s->nic->nc.model;
vmstate_register(-1, s->vmstate, s);
- if (!pci_dev->qdev.hotplugged) {
- static int loaded = 0;
- if (!loaded) {
- char fname[32];
- snprintf(fname, sizeof(fname), "pxe-%s.bin", s->nic->nc.model);
- rom_add_option(fname);
- loaded = 1;
- }
- }
return 0;
}
@@ -2033,6 +2021,7 @@ static PCIDeviceInfo eepro100_info[] = {
.qdev.size = sizeof(EEPRO100State),
.init = pci_i82559er_init,
.exit = pci_nic_uninit,
+ .romfile = "pxe-i82559er.bin",
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/iommu.c b/hw/iommu.c
index 4151022de..0cd2ed00e 100644
--- a/hw/iommu.c
+++ b/hw/iommu.c
@@ -272,13 +272,11 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
static target_phys_addr_t iommu_translate_pa(target_phys_addr_t addr,
uint32_t pte)
{
- uint32_t tmppte;
target_phys_addr_t pa;
- tmppte = pte;
pa = ((pte & IOPTE_PAGE) << 4) + (addr & ~IOMMU_PAGE_MASK);
DPRINTF("xlate dva " TARGET_FMT_plx " => pa " TARGET_FMT_plx
- " (iopte = %x)\n", addr, pa, tmppte);
+ " (iopte = %x)\n", addr, pa, pte);
return pa;
}
diff --git a/hw/pci.h b/hw/pci.h
index 7560df6c2..00c296d71 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -291,7 +291,7 @@ pci_set_byte(uint8_t *config, uint8_t val)
}
static inline uint8_t
-pci_get_byte(uint8_t *config)
+pci_get_byte(const uint8_t *config)
{
return *config;
}
@@ -303,9 +303,9 @@ pci_set_word(uint8_t *config, uint16_t val)
}
static inline uint16_t
-pci_get_word(uint8_t *config)
+pci_get_word(const uint8_t *config)
{
- return le16_to_cpupu((uint16_t *)config);
+ return le16_to_cpupu((const uint16_t *)config);
}
static inline void
@@ -315,9 +315,9 @@ pci_set_long(uint8_t *config, uint32_t val)
}
static inline uint32_t
-pci_get_long(uint8_t *config)
+pci_get_long(const uint8_t *config)
{
- return le32_to_cpupu((uint32_t *)config);
+ return le32_to_cpupu((const uint32_t *)config);
}
static inline void
@@ -327,9 +327,9 @@ pci_set_quad(uint8_t *config, uint64_t val)
}
static inline uint64_t
-pci_get_quad(uint8_t *config)
+pci_get_quad(const uint8_t *config)
{
- return le64_to_cpup((uint64_t *)config);
+ return le64_to_cpup((const uint64_t *)config);
}
static inline void
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 91d106d5b..44b5b3148 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1608,7 +1608,7 @@ static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
{
PCNetState *s = opaque;
- uint32_t val = s->prom[addr &= 15];
+ uint32_t val = s->prom[addr & 15];
#ifdef PCNET_DEBUG
printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
#endif
diff --git a/hw/sun4m.c b/hw/sun4m.c
index ad1efb1eb..85fd632ca 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -756,8 +756,8 @@ static void ram_register_devices(void)
device_init(ram_register_devices);
-static CPUState *cpu_devinit(const char *cpu_model, unsigned int id,
- uint64_t prom_addr, qemu_irq **cpu_irqs)
+static void cpu_devinit(const char *cpu_model, unsigned int id,
+ uint64_t prom_addr, qemu_irq **cpu_irqs)
{
CPUState *env;
@@ -776,8 +776,6 @@ static CPUState *cpu_devinit(const char *cpu_model, unsigned int id,
}
*cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
env->prom_addr = prom_addr;
-
- return env;
}
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
@@ -786,7 +784,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUState *envs[MAX_CPUS];
unsigned int i;
void *iommu, *espdma, *ledma, *nvram;
qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
@@ -803,7 +800,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
cpu_model = hwdef->default_cpu_model;
for(i = 0; i < smp_cpus; i++) {
- envs[i] = cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
+ cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
}
for (i = smp_cpus; i < MAX_CPUS; i++)
@@ -1408,7 +1405,6 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUState *envs[MAX_CPUS];
unsigned int i;
void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram;
qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS],
@@ -1423,7 +1419,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
cpu_model = hwdef->default_cpu_model;
for(i = 0; i < smp_cpus; i++) {
- envs[i] = cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
+ cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
}
for (i = smp_cpus; i < MAX_CPUS; i++)
@@ -1600,7 +1596,6 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size,
const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
- CPUState *env;
void *iommu, *espdma, *ledma, *nvram;
qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq;
qemu_irq esp_reset;
@@ -1615,7 +1610,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size,
if (!cpu_model)
cpu_model = hwdef->default_cpu_model;
- env = cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs);
+ cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs);
/* set up devices */
ram_init(0, RAM_size, hwdef->max_mem);
diff --git a/hw/tcx.c b/hw/tcx.c
index 7598e8c2f..beb30ac82 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -161,7 +161,7 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
p8++;
b = *p8++;
g = *p8++;
- r = *p8++;
+ r = *p8;
if (bgr)
dval = rgb_to_pixel32bgr(r, g, b);
else
diff --git a/hw/vga.c b/hw/vga.c
index 49c980999..668b7613f 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1305,7 +1305,6 @@ static void vga_draw_text(VGACommonState *s, int full_update)
line_offset = s->line_offset;
vga_get_text_resolution(s, &width, &height, &cw, &cheight);
- x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
if ((height * width) > CH_ATTR_SIZE) {
/* better than nothing: exit if transient size is too big */
return;
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index cb1ae1f95..865352a16 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -165,7 +165,7 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
struct sg_io_hdr hdr;
- int ret, size = 0;
+ int ret;
int status;
int i;
@@ -194,7 +194,6 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
* before the regular inhdr.
*/
req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
- size = sizeof(*req->in) + sizeof(*req->scsi);
memset(&hdr, 0, sizeof(struct sg_io_hdr));
hdr.interface_id = 'S';
@@ -226,7 +225,6 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
hdr.dxfer_len += req->elem.in_sg[i].iov_len;
hdr.dxferp = req->elem.in_sg;
- size += hdr.dxfer_len;
} else {
/*
* Some SCSI commands don't actually transfer any data.
@@ -236,7 +234,6 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
- size += hdr.mx_sb_len;
ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
if (ret) {
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index c2a389ffb..6e48997c0 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -151,6 +151,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
{
VirtIONet *n = to_virtio_net(vdev);
+ features |= (1 << VIRTIO_NET_F_MAC);
+
if (peer_has_vnet_hdr(n)) {
tap_using_vnet_hdr(n->nic->nc.peer, 1);
} else {
@@ -530,7 +532,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
int len, total;
struct iovec sg[VIRTQUEUE_MAX_SIZE];
- len = total = 0;
+ total = 0;
if ((i != 0 && !n->mergeable_rx_bufs) ||
virtqueue_pop(n->rx_vq, &elem) == 0) {
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 9130d75c9..e55119b61 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -157,7 +157,6 @@ struct virtio_net_ctrl_mac {
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
- DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
diff --git a/input.c b/input.c
new file mode 100644
index 000000000..955b9ab04
--- /dev/null
+++ b/input.c
@@ -0,0 +1,238 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (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.
+ */
+
+#include "sysemu.h"
+#include "net.h"
+#include "monitor.h"
+#include "console.h"
+#include "qjson.h"
+
+
+static QEMUPutKBDEvent *qemu_put_kbd_event;
+static void *qemu_put_kbd_event_opaque;
+static QEMUPutMouseEntry *qemu_put_mouse_event_head;
+static QEMUPutMouseEntry *qemu_put_mouse_event_current;
+
+void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
+{
+ qemu_put_kbd_event_opaque = opaque;
+ qemu_put_kbd_event = func;
+}
+
+QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
+ void *opaque, int absolute,
+ const char *name)
+{
+ QEMUPutMouseEntry *s, *cursor;
+
+ s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
+
+ s->qemu_put_mouse_event = func;
+ s->qemu_put_mouse_event_opaque = opaque;
+ s->qemu_put_mouse_event_absolute = absolute;
+ s->qemu_put_mouse_event_name = qemu_strdup(name);
+ s->next = NULL;
+
+ if (!qemu_put_mouse_event_head) {
+ qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
+ return s;
+ }
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor->next != NULL)
+ cursor = cursor->next;
+
+ cursor->next = s;
+ qemu_put_mouse_event_current = s;
+
+ return s;
+}
+
+void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
+{
+ QEMUPutMouseEntry *prev = NULL, *cursor;
+
+ if (!qemu_put_mouse_event_head || entry == NULL)
+ return;
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor != NULL && cursor != entry) {
+ prev = cursor;
+ cursor = cursor->next;
+ }
+
+ if (cursor == NULL) // does not exist or list empty
+ return;
+ else if (prev == NULL) { // entry is head
+ qemu_put_mouse_event_head = cursor->next;
+ if (qemu_put_mouse_event_current == entry)
+ qemu_put_mouse_event_current = cursor->next;
+ qemu_free(entry->qemu_put_mouse_event_name);
+ qemu_free(entry);
+ return;
+ }
+
+ prev->next = entry->next;
+
+ if (qemu_put_mouse_event_current == entry)
+ qemu_put_mouse_event_current = prev;
+
+ qemu_free(entry->qemu_put_mouse_event_name);
+ qemu_free(entry);
+}
+
+void kbd_put_keycode(int keycode)
+{
+ if (qemu_put_kbd_event) {
+ qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+ }
+}
+
+void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
+{
+ QEMUPutMouseEvent *mouse_event;
+ void *mouse_event_opaque;
+ int width;
+
+ if (!qemu_put_mouse_event_current) {
+ return;
+ }
+
+ mouse_event =
+ qemu_put_mouse_event_current->qemu_put_mouse_event;
+ mouse_event_opaque =
+ qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
+
+ if (mouse_event) {
+ if (graphic_rotate) {
+ if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute)
+ width = 0x7fff;
+ else
+ width = graphic_width - 1;
+ mouse_event(mouse_event_opaque,
+ width - dy, dx, dz, buttons_state);
+ } else
+ mouse_event(mouse_event_opaque,
+ dx, dy, dz, buttons_state);
+ }
+}
+
+int kbd_mouse_is_absolute(void)
+{
+ if (!qemu_put_mouse_event_current)
+ return 0;
+
+ return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
+}
+
+static void info_mice_iter(QObject *data, void *opaque)
+{
+ QDict *mouse;
+ Monitor *mon = opaque;
+
+ mouse = qobject_to_qdict(data);
+ monitor_printf(mon, "%c Mouse #%" PRId64 ": %s\n",
+ (qdict_get_bool(mouse, "current") ? '*' : ' '),
+ qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"));
+}
+
+void do_info_mice_print(Monitor *mon, const QObject *data)
+{
+ QList *mice_list;
+
+ mice_list = qobject_to_qlist(data);
+ if (qlist_empty(mice_list)) {
+ monitor_printf(mon, "No mouse devices connected\n");
+ return;
+ }
+
+ qlist_iter(mice_list, info_mice_iter, mon);
+}
+
+/**
+ * do_info_mice(): Show VM mice information
+ *
+ * Each mouse is represented by a QDict, the returned QObject is a QList of
+ * all mice.
+ *
+ * The mouse QDict contains the following:
+ *
+ * - "name": mouse's name
+ * - "index": mouse's index
+ * - "current": true if this mouse is receiving events, false otherwise
+ *
+ * Example:
+ *
+ * [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false },
+ * { "name": "QEMU PS/2 Mouse", "index": 1, "current": true } ]
+ */
+void do_info_mice(Monitor *mon, QObject **ret_data)
+{
+ QEMUPutMouseEntry *cursor;
+ QList *mice_list;
+ int index = 0;
+
+ mice_list = qlist_new();
+
+ if (!qemu_put_mouse_event_head) {
+ goto out;
+ }
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor != NULL) {
+ QObject *obj;
+ obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
+ cursor->qemu_put_mouse_event_name,
+ index, cursor == qemu_put_mouse_event_current);
+ qlist_append_obj(mice_list, obj);
+ index++;
+ cursor = cursor->next;
+ }
+
+out:
+ *ret_data = QOBJECT(mice_list);
+}
+
+void do_mouse_set(Monitor *mon, const QDict *qdict)
+{
+ QEMUPutMouseEntry *cursor;
+ int i = 0;
+ int index = qdict_get_int(qdict, "index");
+
+ if (!qemu_put_mouse_event_head) {
+ monitor_printf(mon, "No mouse devices connected\n");
+ return;
+ }
+
+ cursor = qemu_put_mouse_event_head;
+ while (cursor != NULL && index != i) {
+ i++;
+ cursor = cursor->next;
+ }
+
+ if (cursor != NULL)
+ qemu_put_mouse_event_current = cursor;
+ else
+ monitor_printf(mon, "Mouse at given index not found\n");
+}
diff --git a/json-parser.c b/json-parser.c
index 7624c0f9b..e04932f90 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -247,8 +247,6 @@ static QString *qstring_from_escaped_str(JSONParserContext *ctxt, QObject *token
}
}
- ptr++;
-
return str;
out:
diff --git a/osdep.c b/osdep.c
index bd2001bba..9d61da00c 100644
--- a/osdep.c
+++ b/osdep.c
@@ -301,7 +301,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
#ifdef CONFIG_ACCEPT4
ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
- if (ret != -1 || errno != EINVAL) {
+ if (ret != -1 || errno != ENOSYS) {
return ret;
}
#endif
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 641bd8775..f28ef3632 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -43,5 +43,11 @@ DEF("snapshot", img_snapshot,
"snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename")
STEXI
@item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
+ETEXI
+
+DEF("rebase", img_rebase,
+ "rebase [-u] -b backing_file [-F backing_fmt] filename")
+STEXI
+@item rebase [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
@end table
ETEXI
diff --git a/qemu-img.c b/qemu-img.c
index 1d97f2ebf..48b9315aa 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -81,6 +81,9 @@ static void help(void)
" name=value format. Use -o ? for an overview of the options supported by the\n"
" used format\n"
" '-c' indicates that target image must be compressed (qcow format only)\n"
+ " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
+ " match exactly. The image doesn't need a working backing file before\n"
+ " rebasing in this case (useful for renaming the backing file)\n"
" '-h' with or without a command shows this help and lists the supported formats\n"
"\n"
"Parameters to snapshot subcommand:\n"
@@ -527,6 +530,37 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
return v;
}
+/*
+ * Compares two buffers sector by sector. Returns 0 if the first sector of both
+ * buffers matches, non-zero otherwise.
+ *
+ * pnum is set to the number of sectors (including and immediately following
+ * the first one) that are known to have the same comparison result
+ */
+static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
+ int *pnum)
+{
+ int res, i;
+
+ if (n <= 0) {
+ *pnum = 0;
+ return 0;
+ }
+
+ res = !!memcmp(buf1, buf2, 512);
+ for(i = 1; i < n; i++) {
+ buf1 += 512;
+ buf2 += 512;
+
+ if (!!memcmp(buf1, buf2, 512) != res) {
+ break;
+ }
+ }
+
+ *pnum = i;
+ return res;
+}
+
#define IO_BUF_SIZE (2 * 1024 * 1024)
static int img_convert(int argc, char **argv)
@@ -884,7 +918,7 @@ static int img_info(int argc, char **argv)
} else {
drv = NULL;
}
- if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
+ if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_NO_BACKING, drv) < 0) {
error("Could not open '%s'", filename);
}
bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
@@ -1033,6 +1067,197 @@ static int img_snapshot(int argc, char **argv)
return 0;
}
+static int img_rebase(int argc, char **argv)
+{
+ BlockDriverState *bs, *bs_old_backing, *bs_new_backing;
+ BlockDriver *old_backing_drv, *new_backing_drv;
+ char *filename;
+ const char *out_basefmt, *out_baseimg;
+ int c, flags, ret;
+ int unsafe = 0;
+
+ /* Parse commandline parameters */
+ out_baseimg = NULL;
+ out_basefmt = NULL;
+
+ for(;;) {
+ c = getopt(argc, argv, "uhF:b:");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ return 0;
+ case 'F':
+ out_basefmt = optarg;
+ break;
+ case 'b':
+ out_baseimg = optarg;
+ break;
+ case 'u':
+ unsafe = 1;
+ break;
+ }
+ }
+
+ if ((optind >= argc) || !out_baseimg)
+ help();
+ filename = argv[optind++];
+
+ /*
+ * Open the images.
+ *
+ * Ignore the old backing file for unsafe rebase in case we want to correct
+ * the reference to a renamed or moved backing file.
+ */
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+
+ flags = BRDV_O_FLAGS | (unsafe ? BDRV_O_NO_BACKING : 0);
+ if (bdrv_open2(bs, filename, flags, NULL) < 0) {
+ error("Could not open '%s'", filename);
+ }
+
+ /* Find the right drivers for the backing files */
+ old_backing_drv = NULL;
+ new_backing_drv = NULL;
+
+ if (!unsafe && bs->backing_format[0] != '\0') {
+ old_backing_drv = bdrv_find_format(bs->backing_format);
+ if (old_backing_drv == NULL) {
+ error("Invalid format name: '%s'", bs->backing_format);
+ }
+ }
+
+ if (out_basefmt != NULL) {
+ new_backing_drv = bdrv_find_format(out_basefmt);
+ if (new_backing_drv == NULL) {
+ error("Invalid format name: '%s'", out_basefmt);
+ }
+ }
+
+ /* For safe rebasing we need to compare old and new backing file */
+ if (unsafe) {
+ /* Make the compiler happy */
+ bs_old_backing = NULL;
+ bs_new_backing = NULL;
+ } else {
+ char backing_name[1024];
+
+ bs_old_backing = bdrv_new("old_backing");
+ bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
+ if (bdrv_open2(bs_old_backing, backing_name, BRDV_O_FLAGS,
+ old_backing_drv))
+ {
+ error("Could not open old backing file '%s'", backing_name);
+ return -1;
+ }
+
+ bs_new_backing = bdrv_new("new_backing");
+ if (bdrv_open2(bs_new_backing, out_baseimg, BRDV_O_FLAGS,
+ new_backing_drv))
+ {
+ error("Could not open new backing file '%s'", backing_name);
+ return -1;
+ }
+ }
+
+ /*
+ * Check each unallocated cluster in the COW file. If it is unallocated,
+ * accesses go to the backing file. We must therefore compare this cluster
+ * in the old and new backing file, and if they differ we need to copy it
+ * from the old backing file into the COW file.
+ *
+ * If qemu-img crashes during this step, no harm is done. The content of
+ * the image is the same as the original one at any time.
+ */
+ if (!unsafe) {
+ uint64_t num_sectors;
+ uint64_t sector;
+ int n, n1;
+ uint8_t buf_old[IO_BUF_SIZE];
+ uint8_t buf_new[IO_BUF_SIZE];
+
+ bdrv_get_geometry(bs, &num_sectors);
+
+ for (sector = 0; sector < num_sectors; sector += n) {
+
+ /* How many sectors can we handle with the next read? */
+ if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
+ n = (IO_BUF_SIZE / 512);
+ } else {
+ n = num_sectors - sector;
+ }
+
+ /* If the cluster is allocated, we don't need to take action */
+ if (bdrv_is_allocated(bs, sector, n, &n1)) {
+ n = n1;
+ continue;
+ }
+
+ /* Read old and new backing file */
+ if (bdrv_read(bs_old_backing, sector, buf_old, n) < 0) {
+ error("error while reading from old backing file");
+ }
+ if (bdrv_read(bs_new_backing, sector, buf_new, n) < 0) {
+ error("error while reading from new backing file");
+ }
+
+ /* If they differ, we need to write to the COW file */
+ uint64_t written = 0;
+
+ while (written < n) {
+ int pnum;
+
+ if (compare_sectors(buf_old + written * 512,
+ buf_new + written * 512, n, &pnum))
+ {
+ ret = bdrv_write(bs, sector + written,
+ buf_old + written * 512, pnum);
+ if (ret < 0) {
+ error("Error while writing to COW image: %s",
+ strerror(-ret));
+ }
+ }
+
+ written += pnum;
+ }
+ }
+ }
+
+ /*
+ * Change the backing file. All clusters that are different from the old
+ * backing file are overwritten in the COW file now, so the visible content
+ * doesn't change when we switch the backing file.
+ */
+ ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
+ if (ret == -ENOSPC) {
+ error("Could not change the backing file to '%s': No space left in "
+ "the file header", out_baseimg);
+ } else if (ret < 0) {
+ error("Could not change the backing file to '%s': %s",
+ out_baseimg, strerror(-ret));
+ }
+
+ /*
+ * TODO At this point it is possible to check if any clusters that are
+ * allocated in the COW file are the same in the backing file. If so, they
+ * could be dropped from the COW file. Don't do this before switching the
+ * backing file, in case of a crash this would lead to corruption.
+ */
+
+ /* Cleanup */
+ if (!unsafe) {
+ bdrv_delete(bs_old_backing);
+ bdrv_delete(bs_new_backing);
+ }
+
+ bdrv_delete(bs);
+
+ return 0;
+}
+
static const img_cmd_t img_cmds[] = {
#define DEF(option, callback, arg_string) \
{ option, callback },
diff --git a/sparc-dis.c b/sparc-dis.c
index 53c8c9024..83a12ae99 100644
--- a/sparc-dis.c
+++ b/sparc-dis.c
@@ -2760,7 +2760,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
int found_plus = 0;
/* Nonzero means we have an annulled branch. */
- int is_annulled = 0;
+ /* int is_annulled = 0; */ /* see FIXME below */
/* Do we have an `add' or `or' instruction combining an
immediate with rs1? */
@@ -2796,7 +2796,7 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
{
case 'a':
(*info->fprintf_func) (stream, "a");
- is_annulled = 1;
+ /* is_annulled = 1; */ /* see FIXME below */
++s;
continue;
case 'N':
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 0df6f1d6c..7d0bbd012 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -717,7 +717,8 @@ typedef struct CPUX86State {
uint8_t nmi_pending;
uint8_t has_error_code;
uint32_t sipi_vector;
-
+ uint32_t cpuid_kvm_features;
+
/* in order to simplify APIC support, we leave this pointer to the
user */
struct APICState *apic_state;
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2d79e730a..f9d63f6ab 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -60,10 +60,18 @@ static const char *ext3_feature_name[] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
+static const char *kvm_feature_name[] = {
+ "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
uint32_t *ext_features,
uint32_t *ext2_features,
- uint32_t *ext3_features)
+ uint32_t *ext3_features,
+ uint32_t *kvm_features)
{
int i;
int found = 0;
@@ -88,6 +96,12 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
*ext3_features |= 1 << i;
found = 1;
}
+ for ( i = 0 ; i < 32 ; i++ )
+ if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
+ *kvm_features |= 1 << i;
+ found = 1;
+ }
+
if (!found) {
fprintf(stderr, "CPU feature %s not found\n", flagname);
}
@@ -100,7 +114,7 @@ typedef struct x86_def_t {
int family;
int model;
int stepping;
- uint32_t features, ext_features, ext2_features, ext3_features;
+ uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
uint32_t xlevel;
char model_id[48];
int vendor_override;
@@ -377,8 +391,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
char *s = strdup(cpu_model);
char *featurestr, *name = strtok(s, ",");
- uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
- uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
+ uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
+ uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0;
uint32_t numvalue;
def = NULL;
@@ -396,17 +410,20 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
memcpy(x86_cpu_def, def, sizeof(*def));
}
+ plus_kvm_features = ~0; /* not supported bits will be filtered out later */
+
add_flagname_to_bitmaps("hypervisor", &plus_features,
- &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
+ &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
+ &plus_kvm_features);
featurestr = strtok(NULL, ",");
while (featurestr) {
char *val;
if (featurestr[0] == '+') {
- add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
+ add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features);
} else if (featurestr[0] == '-') {
- add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
+ add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features);
} else if ((val = strchr(featurestr, '='))) {
*val = 0; val++;
if (!strcmp(featurestr, "family")) {
@@ -483,10 +500,12 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
x86_cpu_def->ext_features |= plus_ext_features;
x86_cpu_def->ext2_features |= plus_ext2_features;
x86_cpu_def->ext3_features |= plus_ext3_features;
+ x86_cpu_def->kvm_features |= plus_kvm_features;
x86_cpu_def->features &= ~minus_features;
x86_cpu_def->ext_features &= ~minus_ext_features;
x86_cpu_def->ext2_features &= ~minus_ext2_features;
x86_cpu_def->ext3_features &= ~minus_ext3_features;
+ x86_cpu_def->kvm_features &= ~minus_kvm_features;
free(s);
return 0;
@@ -531,7 +550,7 @@ static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_ext_features = def->ext_features;
env->cpuid_ext2_features = def->ext2_features;
env->cpuid_xlevel = def->xlevel;
- env->cpuid_ext3_features = def->ext3_features;
+ env->cpuid_kvm_features = def->kvm_features;
{
const char *model_id = def->model_id;
int c, len, i;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c338bf7cd..9af1e4851 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -26,6 +26,11 @@
#include "host-utils.h"
#ifdef KVM_UPSTREAM
+
+#ifdef CONFIG_KVM_PARA
+#include <linux/kvm_para.h>
+#endif
+//
//#define DEBUG_KVM
#ifdef DEBUG_KVM
@@ -135,6 +140,39 @@ static void kvm_trim_features(uint32_t *features, uint32_t supported)
}
}
+#ifdef CONFIG_KVM_PARA
+struct kvm_para_features {
+ int cap;
+ int feature;
+} para_features[] = {
+#ifdef KVM_CAP_CLOCKSOURCE
+ { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
+#endif
+#ifdef KVM_CAP_NOP_IO_DELAY
+ { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
+#endif
+#ifdef KVM_CAP_PV_MMU
+ { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
+#endif
+#ifdef KVM_CAP_CR3_CACHE
+ { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE },
+#endif
+ { -1, -1 }
+};
+
+static int get_para_features(CPUState *env)
+{
+ int i, features = 0;
+
+ for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
+ if (kvm_check_extension(env->kvm_state, para_features[i].cap))
+ features |= (1 << para_features[i].feature);
+ }
+
+ return features;
+}
+#endif
+
int kvm_arch_init_vcpu(CPUState *env)
{
struct {
@@ -143,6 +181,10 @@ int kvm_arch_init_vcpu(CPUState *env)
} __attribute__((packed)) cpuid_data;
uint32_t limit, i, j, cpuid_i;
uint32_t unused;
+ struct kvm_cpuid_entry2 *c;
+#ifdef KVM_CPUID_SIGNATURE
+ uint32_t signature[3];
+#endif
env->mp_state = KVM_MP_STATE_RUNNABLE;
@@ -161,10 +203,27 @@ int kvm_arch_init_vcpu(CPUState *env)
cpuid_i = 0;
+#ifdef CONFIG_KVM_PARA
+ /* Paravirtualization CPUIDs */
+ memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+ c = &cpuid_data.entries[cpuid_i++];
+ memset(c, 0, sizeof(*c));
+ c->function = KVM_CPUID_SIGNATURE;
+ c->eax = 0;
+ c->ebx = signature[0];
+ c->ecx = signature[1];
+ c->edx = signature[2];
+
+ c = &cpuid_data.entries[cpuid_i++];
+ memset(c, 0, sizeof(*c));
+ c->function = KVM_CPUID_FEATURES;
+ c->eax = env->cpuid_kvm_features & get_para_features(env);
+#endif
+
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
for (i = 0; i <= limit; i++) {
- struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++];
+ c = &cpuid_data.entries[cpuid_i++];
switch (i) {
case 2: {
@@ -214,7 +273,7 @@ int kvm_arch_init_vcpu(CPUState *env)
cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused);
for (i = 0x80000000; i <= limit; i++) {
- struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++];
+ c = &cpuid_data.entries[cpuid_i++];
c->function = i;
c->flags = 0;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 511a4eae9..807811205 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2207,8 +2207,6 @@ static void gen_add_A0_ds_seg(DisasContext *s)
if (s->override >= 0) {
override = s->override;
must_add_seg = 1;
- } else {
- override = R_DS;
}
if (must_add_seg) {
#ifdef TARGET_X86_64
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index e80147488..f456f20f4 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -107,12 +107,10 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
int access_perms = 0;
target_phys_addr_t pde_ptr;
uint32_t pde;
- target_ulong virt_addr;
int error_code = 0, is_dirty, is_user;
unsigned long page_offset;
is_user = mmu_idx == MMU_USER_IDX;
- virt_addr = address & TARGET_PAGE_MASK;
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
// Boot mode: instruction fetches are taken from PROM
@@ -174,18 +172,15 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
case 3: /* Reserved */
return (3 << 8) | (4 << 2);
case 2: /* L3 PTE */
- virt_addr = address & TARGET_PAGE_MASK;
page_offset = (address & TARGET_PAGE_MASK) &
(TARGET_PAGE_SIZE - 1);
}
break;
case 2: /* L2 PTE */
- virt_addr = address & ~0x3ffff;
page_offset = address & 0x3ffff;
}
break;
case 2: /* L1 PTE */
- virt_addr = address & ~0xffffff;
page_offset = address & 0xffffff;
}
}
diff --git a/vl.c b/vl.c
index 794669a74..d72326fd9 100644
--- a/vl.c
+++ b/vl.c
@@ -389,216 +389,9 @@ ram_addr_t qemu_balloon_status(void)
return 0;
}
-/***********************************************************/
-/* keyboard/mouse */
-
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
-static QEMUPutMouseEntry *qemu_put_mouse_event_head;
-static QEMUPutMouseEntry *qemu_put_mouse_event_current;
-
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
-{
- qemu_put_kbd_event_opaque = opaque;
- qemu_put_kbd_event = func;
-}
-
-QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
- void *opaque, int absolute,
- const char *name)
-{
- QEMUPutMouseEntry *s, *cursor;
-
- s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
-
- s->qemu_put_mouse_event = func;
- s->qemu_put_mouse_event_opaque = opaque;
- s->qemu_put_mouse_event_absolute = absolute;
- s->qemu_put_mouse_event_name = qemu_strdup(name);
- s->next = NULL;
-
- if (!qemu_put_mouse_event_head) {
- qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
- return s;
- }
-
- cursor = qemu_put_mouse_event_head;
- while (cursor->next != NULL)
- cursor = cursor->next;
-
- cursor->next = s;
- qemu_put_mouse_event_current = s;
-
- return s;
-}
-
-void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
-{
- QEMUPutMouseEntry *prev = NULL, *cursor;
-
- if (!qemu_put_mouse_event_head || entry == NULL)
- return;
-
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL && cursor != entry) {
- prev = cursor;
- cursor = cursor->next;
- }
-
- if (cursor == NULL) // does not exist or list empty
- return;
- else if (prev == NULL) { // entry is head
- qemu_put_mouse_event_head = cursor->next;
- if (qemu_put_mouse_event_current == entry)
- qemu_put_mouse_event_current = cursor->next;
- qemu_free(entry->qemu_put_mouse_event_name);
- qemu_free(entry);
- return;
- }
-
- prev->next = entry->next;
-
- if (qemu_put_mouse_event_current == entry)
- qemu_put_mouse_event_current = prev;
-
- qemu_free(entry->qemu_put_mouse_event_name);
- qemu_free(entry);
-}
-
-void kbd_put_keycode(int keycode)
-{
- if (qemu_put_kbd_event) {
- qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
- }
-}
-
-void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
-{
- QEMUPutMouseEvent *mouse_event;
- void *mouse_event_opaque;
- int width;
-
- if (!qemu_put_mouse_event_current) {
- return;
- }
-
- mouse_event =
- qemu_put_mouse_event_current->qemu_put_mouse_event;
- mouse_event_opaque =
- qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
-
- if (mouse_event) {
- if (graphic_rotate) {
- if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute)
- width = 0x7fff;
- else
- width = graphic_width - 1;
- mouse_event(mouse_event_opaque,
- width - dy, dx, dz, buttons_state);
- } else
- mouse_event(mouse_event_opaque,
- dx, dy, dz, buttons_state);
- }
-}
-
-int kbd_mouse_is_absolute(void)
-{
- if (!qemu_put_mouse_event_current)
- return 0;
-
- return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
-}
-
-static void info_mice_iter(QObject *data, void *opaque)
-{
- QDict *mouse;
- Monitor *mon = opaque;
-
- mouse = qobject_to_qdict(data);
- monitor_printf(mon, "%c Mouse #%" PRId64 ": %s\n",
- (qdict_get_bool(mouse, "current") ? '*' : ' '),
- qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"));
-}
-
-void do_info_mice_print(Monitor *mon, const QObject *data)
-{
- QList *mice_list;
-
- mice_list = qobject_to_qlist(data);
- if (qlist_empty(mice_list)) {
- monitor_printf(mon, "No mouse devices connected\n");
- return;
- }
-
- qlist_iter(mice_list, info_mice_iter, mon);
-}
-
-/**
- * do_info_mice(): Show VM mice information
- *
- * Each mouse is represented by a QDict, the returned QObject is a QList of
- * all mice.
- *
- * The mouse QDict contains the following:
- *
- * - "name": mouse's name
- * - "index": mouse's index
- * - "current": true if this mouse is receiving events, false otherwise
- *
- * Example:
- *
- * [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false },
- * { "name": "QEMU PS/2 Mouse", "index": 1, "current": true } ]
- */
-void do_info_mice(Monitor *mon, QObject **ret_data)
-{
- QEMUPutMouseEntry *cursor;
- QList *mice_list;
- int index = 0;
-
- mice_list = qlist_new();
- if (!qemu_put_mouse_event_head) {
- goto out;
- }
-
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL) {
- QObject *obj;
- obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
- cursor->qemu_put_mouse_event_name,
- index, cursor == qemu_put_mouse_event_current);
- qlist_append_obj(mice_list, obj);
- index++;
- cursor = cursor->next;
- }
-
-out:
- *ret_data = QOBJECT(mice_list);
-}
-
-void do_mouse_set(Monitor *mon, const QDict *qdict)
-{
- QEMUPutMouseEntry *cursor;
- int i = 0;
- int index = qdict_get_int(qdict, "index");
-
- if (!qemu_put_mouse_event_head) {
- monitor_printf(mon, "No mouse devices connected\n");
- return;
- }
-
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL && index != i) {
- i++;
- cursor = cursor->next;
- }
-
- if (cursor != NULL)
- qemu_put_mouse_event_current = cursor;
- else
- monitor_printf(mon, "Mouse at given index not found\n");
-}
+/***********************************************************/
+/* real time host monotonic timer */
/* compute with 96 bit intermediate result: (a*b)/c */
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
@@ -624,9 +417,6 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
return res.ll;
}
-/***********************************************************/
-/* real time host monotonic timer */
-
static int64_t get_clock_realtime(void)
{
struct timeval tv;
@@ -2637,17 +2427,13 @@ static void smp_parse(const char *optarg)
threads = threads > 0 ? threads : 1;
if (smp == 0) {
smp = cores * threads * sockets;
- } else {
- sockets = smp / (cores * threads);
}
} else {
if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = smp / (sockets * threads);
} else {
- if (sockets == 0) {
- sockets = smp / (cores * threads);
- } else {
+ if (sockets) {
threads = smp / (cores * sockets);
}
}