diff options
-rw-r--r-- | Makefile.objs | 2 | ||||
-rw-r--r-- | audio/ossaudio.c | 30 | ||||
-rw-r--r-- | block.c | 41 | ||||
-rw-r--r-- | block.h | 3 | ||||
-rw-r--r-- | block/qcow.c | 9 | ||||
-rw-r--r-- | block/qcow2-refcount.c | 1 | ||||
-rw-r--r-- | block/qcow2.c | 110 | ||||
-rw-r--r-- | block_int.h | 3 | ||||
-rwxr-xr-x | configure | 49 | ||||
-rw-r--r-- | hw/eepro100.c | 15 | ||||
-rw-r--r-- | hw/iommu.c | 4 | ||||
-rw-r--r-- | hw/pci.h | 14 | ||||
-rw-r--r-- | hw/pcnet.c | 2 | ||||
-rw-r--r-- | hw/sun4m.c | 15 | ||||
-rw-r--r-- | hw/tcx.c | 2 | ||||
-rw-r--r-- | hw/vga.c | 1 | ||||
-rw-r--r-- | hw/virtio-blk.c | 5 | ||||
-rw-r--r-- | hw/virtio-net.c | 4 | ||||
-rw-r--r-- | hw/virtio-net.h | 1 | ||||
-rw-r--r-- | input.c | 238 | ||||
-rw-r--r-- | json-parser.c | 2 | ||||
-rw-r--r-- | osdep.c | 2 | ||||
-rw-r--r-- | qemu-img-cmds.hx | 6 | ||||
-rw-r--r-- | qemu-img.c | 227 | ||||
-rw-r--r-- | sparc-dis.c | 4 | ||||
-rw-r--r-- | target-i386/cpu.h | 3 | ||||
-rw-r--r-- | target-i386/helper.c | 35 | ||||
-rw-r--r-- | target-i386/kvm.c | 63 | ||||
-rw-r--r-- | target-i386/translate.c | 2 | ||||
-rw-r--r-- | target-sparc/helper.c | 5 | ||||
-rw-r--r-- | vl.c | 220 |
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); } @@ -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); } @@ -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); @@ -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; } @@ -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); @@ -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 @@ -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: @@ -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; } } @@ -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); } } |