diff options
author | 2010-05-09 14:05:19 +0300 | |
---|---|---|
committer | 2010-05-09 14:05:19 +0300 | |
commit | 4b1b0617b6f454b368a7f04786c0bc842253f849 (patch) | |
tree | 46842c3026a59c6431e9c236734666b5d7286836 | |
parent | pci passthrough: zap option rom scanning. (diff) | |
parent | Update for 0.12.4 release (diff) | |
download | qemu-kvm-4b1b0617b6f454b368a7f04786c0bc842253f849.tar.gz qemu-kvm-4b1b0617b6f454b368a7f04786c0bc842253f849.tar.bz2 qemu-kvm-4b1b0617b6f454b368a7f04786c0bc842253f849.zip |
Merge commit 'v0.12.4' into stable-0.12qemu-kvm-0.12.4
* commit 'v0.12.4': (49 commits)
Update for 0.12.4 release
Workaround for broken OSS_GETVERSION on FreeBSD, part two
oss: fix fragment setting
oss: issue OSS_GETVERSION ioctl only when needed
oss: refactor code around policy setting
oss: workaround for cases when OSS_GETVERSION is not defined
block: Free iovec arrays allocated by multiwrite_merge()
lsi: fix segfault in lsi_command_complete
lsi: pass lsi_request to lsi_reselect
lsi: move dma_len+dma_buf into lsi_request
lsi: move current_dev into lsi_request
lsi: have lsi_request for the whole life time of the request.
lsi: use QTAILQ for lsi_queue
tcp/mips: Change TCG_AREG0 (fp -> s0)
sh_pci: fix memory and I/O access
Fix incoming migration with iothread
Fix SIGFPE for vnc display of width/height = 1
net: remove broken net_set_boot_mask() boot device validation
qcow2: Remove request from in-flight list after error
qcow2: Don't ignore immediate read/write failures
...
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | Changelog | 50 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | audio/ossaudio.c | 68 | ||||
-rw-r--r-- | block.c | 14 | ||||
-rw-r--r-- | block/qcow2-cluster.c | 1 | ||||
-rw-r--r-- | block/qcow2-refcount.c | 334 | ||||
-rw-r--r-- | block/qcow2.c | 14 | ||||
-rw-r--r-- | default-configs/sh4-softmmu.mak | 1 | ||||
-rw-r--r-- | default-configs/sh4eb-softmmu.mak | 1 | ||||
-rw-r--r-- | dyngen-exec.h | 6 | ||||
-rw-r--r-- | hw/fdc.c | 20 | ||||
-rw-r--r-- | hw/fw_cfg.c | 2 | ||||
-rw-r--r-- | hw/ide/cmd646.c | 7 | ||||
-rw-r--r-- | hw/ide/internal.h | 1 | ||||
-rw-r--r-- | hw/ide/piix.c | 1 | ||||
-rw-r--r-- | hw/lsi53c895a.c | 176 | ||||
-rw-r--r-- | hw/scsi-disk.c | 4 | ||||
-rw-r--r-- | hw/sh7750.c | 7 | ||||
-rw-r--r-- | hw/sh_pci.c | 111 | ||||
-rw-r--r-- | hw/usb-uhci.c | 7 | ||||
-rw-r--r-- | json-parser.c | 2 | ||||
-rw-r--r-- | linux-user/main.c | 2 | ||||
-rw-r--r-- | net.c | 20 | ||||
-rw-r--r-- | net.h | 1 | ||||
-rw-r--r-- | qemu-char.c | 5 | ||||
-rw-r--r-- | qemu-common.h | 4 | ||||
-rw-r--r-- | qemu-options.hx | 2 | ||||
-rw-r--r-- | target-i386/translate.c | 15 | ||||
-rw-r--r-- | target-sh4/cpu.h | 2 | ||||
-rw-r--r-- | target-sh4/helper.c | 22 | ||||
-rw-r--r-- | target-sh4/translate.c | 2 | ||||
-rw-r--r-- | tcg/arm/tcg-target.c | 11 | ||||
-rw-r--r-- | tcg/mips/tcg-target.c | 54 | ||||
-rw-r--r-- | tcg/mips/tcg-target.h | 6 | ||||
-rw-r--r-- | vl.c | 26 | ||||
-rw-r--r-- | vnc.c | 6 |
36 files changed, 605 insertions, 402 deletions
@@ -1,3 +1,53 @@ +version 0.12.4 + - Workaround for broken OSS_GETVERSION on FreeBSD, part two (Juergen Lock) + - oss: fix fragment setting (malc) + - oss: issue OSS_GETVERSION ioctl only when needed (malc) + - oss: refactor code around policy setting (malc) + - oss: workaround for cases when OSS_GETVERSION is not defined (malc) + - block: Free iovec arrays allocated by multiwrite_merge() (Stefan Hajnoczi) + - lsi: fix segfault in lsi_command_complete (Gerd Hoffmann) + - lsi: pass lsi_request to lsi_reselect (Gerd Hoffmann) + - lsi: move dma_len+dma_buf into lsi_request (Gerd Hoffmann) + - lsi: move current_dev into lsi_request (Gerd Hoffmann) + - lsi: have lsi_request for the whole life time of the request. (Gerd Hoffmann) + - lsi: use QTAILQ for lsi_queue (Gerd Hoffmann) + - tcp/mips: Change TCG_AREG0 (fp -> s0) (Stefan Weil) + - sh_pci: fix memory and I/O access (Aurelien Jarno) + - Fix incoming migration with iothread (Marcelo Tosatti) + - Fix SIGFPE for vnc display of width/height = 1 (Chris Webb) + - net: remove broken net_set_boot_mask() boot device validation (Eduardo Habkost) + - qcow2: Remove request from in-flight list after error (Kevin Wolf) + - qcow2: Don't ignore immediate read/write failures (Kevin Wolf) + - block: Fix multiwrite memory leak in error case (Kevin Wolf) + - block: Fix error code in multiwrite for immediate failures (Kevin Wolf) + - block: Fix multiwrite error handling (Kevin Wolf) + - scsi-disk: fix buffer overflow (Gerd Hoffmann) + - qcow2: Rewrite alloc_refcount_block/grow_refcount_table (Kevin Wolf) + - qcow2: Factor next_refcount_table_size out (Kevin Wolf) + - block: avoid creating too large iovecs in multiwrite_merge (Christoph Hellwig) + - json-parser: Fix segfault on malformed input (Kevin Wolf) + - linux-user: switch default ppc64 CPU to 970fx from 970 (Aurelien Jarno) + - target-sh4: MMU: fix store queue addresses (Aurelien Jarno) + - target-sh4: MMU: fix ITLB priviledge check (Aurelien Jarno) + - target-sh4: MMU: fix mem_idx computation (Aurelien Jarno) + - sh7750: handle MMUCR TI bit (Aurelien Jarno) + - UHCI spurious interrut fix (Paul Brook) + - tcg/mips: fix branch offset during retranslation (Aurelien Jarno) + - tcg/arm: correctly save/restore registers in prologue/epilogue (Aurelien Jarno) + - workaround for cmd646 bmdma register access while no dma is active (Igor V. Kovalenko) + - Fix corner case in chardev udp: parameter (Jan Kiszka) + - Don't set default monitor when there is a mux'ed one (Jan Kiszka) + - spelling typo (compatibilty) in hw/fw_cfg.c (Vagrant Cascadian) + - fdc: fix drive property handling. (Gerd Hoffmann) + - target-i386: fix commit c22549204a6edc431e8e4358e61bd56386ff6957 (TeLeMan) + - target-i386: fix SIB decoding with index = 4 (Aurelien Jarno) + - Fix segfault with ram_size > 4095M without kvm (Ryan Harper) + - target-i386: Fix long jumps/calls in long mode with REX.W set (malc) + - target-i386: fix lddqu SSE instruction (Aurelien Jarno) + - qemu-char.c: drop debug printfs from qemu_chr_parse_compat (Jan Kiszka) + - fix undefined shifts by >32 (Paolo Bonzini) + - Fix qemu -net user,hostfwd= example (Aurelien Jarno) + version 0.12.3 - kvm: Fix eflags corruption in kvm mode (Jan Kiszka) - qcow2: Fix access after end of array (Kevin Wolf) @@ -1 +1 @@ -0.12.3 +0.12.4 diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 4002f1467..42bffaeaf 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -38,6 +38,10 @@ #define AUDIO_CAP "oss" #include "audio_int.h" +#if defined OSS_GETVERSION && defined SNDCTL_DSP_POLICY +#define USE_DSP_POLICY +#endif + typedef struct OSSVoiceOut { HWVoiceOut hw; void *pcm_buf; @@ -236,14 +240,39 @@ 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) { int fd; - int version; int oflags = conf.exclusive ? O_EXCL : 0; audio_buf_info abinfo; int fmt, freq, nchannels; + int setfragment = 1; const char *dspname = in ? conf.devpath_in : conf.devpath_out; const char *typ = in ? "ADC" : "DAC"; @@ -281,27 +310,30 @@ static int oss_open (int in, struct oss_params *req, goto err; } - if (ioctl (fd, OSS_GETVERSION, &version)) { - oss_logerr2 (errno, typ, "Failed to get OSS version\n"); - version = 0; - } +#ifdef USE_DSP_POLICY + if (conf.policy >= 0) { + int version; - if (conf.debug) { - dolog ("OSS version = %#x\n", version); - } + if (!oss_get_version (fd, &version, typ)) { + if (conf.debug) { + dolog ("OSS version = %#x\n", version); + } -#ifdef SNDCTL_DSP_POLICY - if (conf.policy >= 0 && version >= 0x040000) { - int policy = conf.policy; - if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) { - oss_logerr2 (errno, typ, "Failed to set timing policy to %d\n", - conf.policy); - goto err; + if (version >= 0x040000) { + int policy = conf.policy; + if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) { + oss_logerr2 (errno, typ, + "Failed to set timing policy to %d\n", + conf.policy); + goto err; + } + setfragment = 0; + } } } - else #endif - { + + if (setfragment) { int mmmmssss = (req->nfrags << 16) | ctz32 (req->fragsize); if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) { oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n", @@ -857,7 +889,7 @@ static struct audio_option oss_options[] = { .valp = &conf.exclusive, .descr = "Open device in exclusive mode (vmix wont work)" }, -#ifdef SNDCTL_DSP_POLICY +#ifdef USE_DSP_POLICY { .name = "POLICY", .tag = AUD_OPT_INT, @@ -1608,6 +1608,9 @@ static void multiwrite_user_cb(MultiwriteCB *mcb) for (i = 0; i < mcb->num_callbacks; i++) { mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error); + if (mcb->callbacks[i].free_qiov) { + qemu_iovec_destroy(mcb->callbacks[i].free_qiov); + } qemu_free(mcb->callbacks[i].free_qiov); qemu_vfree(mcb->callbacks[i].free_buf); } @@ -1617,7 +1620,7 @@ static void multiwrite_cb(void *opaque, int ret) { MultiwriteCB *mcb = opaque; - if (ret < 0) { + if (ret < 0 && !mcb->error) { mcb->error = ret; multiwrite_user_cb(mcb); } @@ -1669,6 +1672,10 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs, merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]); } + if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) { + merge = 0; + } + if (merge) { size_t size; QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov)); @@ -1754,10 +1761,11 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // submitted yet. Otherwise we'll wait for the submitted AIOs to // complete and report the error in the callback. if (mcb->num_requests == 0) { - reqs[i].error = EIO; + reqs[i].error = -EIO; goto fail; } else { - mcb->error = EIO; + mcb->num_requests++; + multiwrite_cb(mcb, -EIO); break; } } else { diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index b13b6935f..c7057b166 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -811,6 +811,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size); if (cluster_offset < 0) { + QLIST_REMOVE(m, next_in_flight); return cluster_offset; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index c2a5c0471..5ebbcb63d 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -27,7 +27,7 @@ #include "block/qcow2.h" static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size); -static int update_refcount(BlockDriverState *bs, +static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, int64_t offset, int64_t length, int addend); @@ -123,124 +123,266 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) return be16_to_cpu(s->refcount_block_cache[block_index]); } -static int grow_refcount_table(BlockDriverState *bs, int min_size) +/* + * Rounds the refcount table size up to avoid growing the table for each single + * refcount block that is allocated. + */ +static unsigned int next_refcount_table_size(BDRVQcowState *s, + unsigned int min_size) +{ + unsigned int min_clusters = (min_size >> (s->cluster_bits - 3)) + 1; + unsigned int refcount_table_clusters = + MAX(1, s->refcount_table_size >> (s->cluster_bits - 3)); + + while (min_clusters > refcount_table_clusters) { + refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2; + } + + return refcount_table_clusters << (s->cluster_bits - 3); +} + + +/* Checks if two offsets are described by the same refcount block */ +static int in_same_refcount_block(BDRVQcowState *s, uint64_t offset_a, + uint64_t offset_b) +{ + uint64_t block_a = offset_a >> (2 * s->cluster_bits - REFCOUNT_SHIFT); + uint64_t block_b = offset_b >> (2 * s->cluster_bits - REFCOUNT_SHIFT); + + return (block_a == block_b); +} + +/* + * Loads a refcount block. If it doesn't exist yet, it is allocated first + * (including growing the refcount table if needed). + * + * Returns the offset of the refcount block on success or -errno in error case + */ +static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) { BDRVQcowState *s = bs->opaque; - int new_table_size, new_table_size2, refcount_table_clusters, i, ret; - uint64_t *new_table; - int64_t table_offset; - uint8_t data[12]; - int old_table_size; - int64_t old_table_offset; + unsigned int refcount_table_index; + int ret; - if (min_size <= s->refcount_table_size) - return 0; - /* compute new table size */ - refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3); - for(;;) { - if (refcount_table_clusters == 0) { - refcount_table_clusters = 1; - } else { - refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2; + /* Find the refcount block for the given cluster */ + refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); + + if (refcount_table_index < s->refcount_table_size) { + + uint64_t refcount_block_offset = + s->refcount_table[refcount_table_index]; + + /* If it's already there, we're done */ + if (refcount_block_offset) { + if (refcount_block_offset != s->refcount_block_cache_offset) { + ret = load_refcount_block(bs, refcount_block_offset); + if (ret < 0) { + return ret; + } + } + return refcount_block_offset; + } + } + + /* + * If we came here, we need to allocate something. Something is at least + * a cluster for the new refcount block. It may also include a new refcount + * table if the old refcount table is too small. + * + * Note that allocating clusters here needs some special care: + * + * - We can't use the normal qcow2_alloc_clusters(), it would try to + * increase the refcount and very likely we would end up with an endless + * recursion. Instead we must place the refcount blocks in a way that + * they can describe them themselves. + * + * - We need to consider that at this point we are inside update_refcounts + * and doing the initial refcount increase. This means that some clusters + * have already been allocated by the caller, but their refcount isn't + * accurate yet. free_cluster_index tells us where this allocation ends + * as long as we don't overwrite it by freeing clusters. + * + * - alloc_clusters_noref and qcow2_free_clusters may load a different + * refcount block into the cache + */ + + if (cache_refcount_updates) { + ret = write_refcount_block(s); + if (ret < 0) { + return ret; + } + } + + /* Allocate the refcount block itself and mark it as used */ + uint64_t new_block = alloc_clusters_noref(bs, s->cluster_size); + memset(s->refcount_block_cache, 0, s->cluster_size); + s->refcount_block_cache_offset = new_block; + +#ifdef DEBUG_ALLOC2 + fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64 + " at %" PRIx64 "\n", + refcount_table_index, cluster_index << s->cluster_bits, new_block); +#endif + + if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) { + /* The block describes itself, need to update the cache */ + int block_index = (new_block >> s->cluster_bits) & + ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); + s->refcount_block_cache[block_index] = cpu_to_be16(1); + } else { + /* Described somewhere else. This can recurse at most twice before we + * arrive at a block that describes itself. */ + ret = update_refcount(bs, new_block, s->cluster_size, 1); + if (ret < 0) { + goto fail_block; + } + } + + /* Now the new refcount block needs to be written to disk */ + ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache, + s->cluster_size); + if (ret < 0) { + goto fail_block; + } + + /* If the refcount table is big enough, just hook the block up there */ + if (refcount_table_index < s->refcount_table_size) { + uint64_t data64 = cpu_to_be64(new_block); + ret = bdrv_pwrite(s->hd, + s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), + &data64, sizeof(data64)); + if (ret < 0) { + goto fail_block; } - new_table_size = refcount_table_clusters << (s->cluster_bits - 3); - if (min_size <= new_table_size) - break; + + s->refcount_table[refcount_table_index] = new_block; + return new_block; } + + /* + * If we come here, we need to grow the refcount table. Again, a new + * refcount table needs some space and we can't simply allocate to avoid + * endless recursion. + * + * Therefore let's grab new refcount blocks at the end of the image, which + * will describe themselves and the new refcount table. This way we can + * reference them only in the new table and do the switch to the new + * refcount table at once without producing an inconsistent state in + * between. + */ + /* Calculate the number of refcount blocks needed so far */ + uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT); + uint64_t blocks_used = (s->free_cluster_index + + refcount_block_clusters - 1) / refcount_block_clusters; + + /* And now we need at least one block more for the new metadata */ + uint64_t table_size = next_refcount_table_size(s, blocks_used + 1); + uint64_t last_table_size; + uint64_t blocks_clusters; + do { + uint64_t table_clusters = size_to_clusters(s, table_size); + blocks_clusters = 1 + + ((table_clusters + refcount_block_clusters - 1) + / refcount_block_clusters); + uint64_t meta_clusters = table_clusters + blocks_clusters; + + last_table_size = table_size; + table_size = next_refcount_table_size(s, blocks_used + + ((meta_clusters + refcount_block_clusters - 1) + / refcount_block_clusters)); + + } while (last_table_size != table_size); + #ifdef DEBUG_ALLOC2 - printf("grow_refcount_table from %d to %d\n", - s->refcount_table_size, - new_table_size); + fprintf(stderr, "qcow2: Grow refcount table %" PRId32 " => %" PRId64 "\n", + s->refcount_table_size, table_size); #endif - new_table_size2 = new_table_size * sizeof(uint64_t); - new_table = qemu_mallocz(new_table_size2); + + /* Create the new refcount table and blocks */ + uint64_t meta_offset = (blocks_used * refcount_block_clusters) * + s->cluster_size; + uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size; + uint16_t *new_blocks = qemu_mallocz(blocks_clusters * s->cluster_size); + uint64_t *new_table = qemu_mallocz(table_size * sizeof(uint64_t)); + + assert(meta_offset >= (s->free_cluster_index * s->cluster_size)); + + /* Fill the new refcount table */ memcpy(new_table, s->refcount_table, - s->refcount_table_size * sizeof(uint64_t)); - for(i = 0; i < s->refcount_table_size; i++) + s->refcount_table_size * sizeof(uint64_t)); + new_table[refcount_table_index] = new_block; + + int i; + for (i = 0; i < blocks_clusters; i++) { + new_table[blocks_used + i] = meta_offset + (i * s->cluster_size); + } + + /* Fill the refcount blocks */ + uint64_t table_clusters = size_to_clusters(s, table_size * sizeof(uint64_t)); + int block = 0; + for (i = 0; i < table_clusters + blocks_clusters; i++) { + new_blocks[block++] = cpu_to_be16(1); + } + + /* Write refcount blocks to disk */ + ret = bdrv_pwrite(s->hd, meta_offset, new_blocks, + blocks_clusters * s->cluster_size); + qemu_free(new_blocks); + if (ret < 0) { + goto fail_table; + } + + /* Write refcount table to disk */ + for(i = 0; i < table_size; i++) { cpu_to_be64s(&new_table[i]); - /* Note: we cannot update the refcount now to avoid recursion */ - table_offset = alloc_clusters_noref(bs, new_table_size2); - ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2); - if (ret != new_table_size2) - goto fail; - for(i = 0; i < s->refcount_table_size; i++) - be64_to_cpus(&new_table[i]); + } + ret = bdrv_pwrite(s->hd, table_offset, new_table, + table_size * sizeof(uint64_t)); + if (ret < 0) { + goto fail_table; + } + + for(i = 0; i < table_size; i++) { + cpu_to_be64s(&new_table[i]); + } + + /* Hook up the new refcount table in the qcow2 header */ + uint8_t data[12]; cpu_to_be64w((uint64_t*)data, table_offset); - cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters); + cpu_to_be32w((uint32_t*)(data + 8), table_clusters); ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset), - data, sizeof(data)); - if (ret != sizeof(data)) { - goto fail; + data, sizeof(data)); + if (ret < 0) { + goto fail_table; } + /* And switch it in memory */ + uint64_t old_table_offset = s->refcount_table_offset; + uint64_t old_table_size = s->refcount_table_size; + qemu_free(s->refcount_table); - old_table_offset = s->refcount_table_offset; - old_table_size = s->refcount_table_size; s->refcount_table = new_table; - s->refcount_table_size = new_table_size; + s->refcount_table_size = table_size; s->refcount_table_offset = table_offset; - update_refcount(bs, table_offset, new_table_size2, 1); + /* Free old table. Remember, we must not change free_cluster_index */ + uint64_t old_free_cluster_index = s->free_cluster_index; qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t)); - return 0; - fail: - qemu_free(new_table); - return ret < 0 ? ret : -EIO; -} + s->free_cluster_index = old_free_cluster_index; - -static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) -{ - BDRVQcowState *s = bs->opaque; - int64_t offset, refcount_block_offset; - unsigned int refcount_table_index; - int ret; - uint64_t data64; - int cache = cache_refcount_updates; - - /* Find L1 index and grow refcount table if needed */ - refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); - if (refcount_table_index >= s->refcount_table_size) { - ret = grow_refcount_table(bs, refcount_table_index + 1); - if (ret < 0) - return ret; + ret = load_refcount_block(bs, new_block); + if (ret < 0) { + goto fail_block; } - /* Load or allocate the refcount block */ - refcount_block_offset = s->refcount_table[refcount_table_index]; - if (!refcount_block_offset) { - if (cache_refcount_updates) { - write_refcount_block(s); - cache_refcount_updates = 0; - } - /* create a new refcount block */ - /* Note: we cannot update the refcount now to avoid recursion */ - offset = alloc_clusters_noref(bs, s->cluster_size); - memset(s->refcount_block_cache, 0, s->cluster_size); - ret = bdrv_pwrite(s->hd, offset, s->refcount_block_cache, s->cluster_size); - if (ret != s->cluster_size) - return -EINVAL; - s->refcount_table[refcount_table_index] = offset; - data64 = cpu_to_be64(offset); - ret = bdrv_pwrite(s->hd, s->refcount_table_offset + - refcount_table_index * sizeof(uint64_t), - &data64, sizeof(data64)); - if (ret != sizeof(data64)) - return -EINVAL; - - refcount_block_offset = offset; - s->refcount_block_cache_offset = offset; - update_refcount(bs, offset, s->cluster_size, 1); - cache_refcount_updates = cache; - } else { - if (refcount_block_offset != s->refcount_block_cache_offset) { - if (load_refcount_block(bs, refcount_block_offset) < 0) - return -EIO; - } - } + return new_block; - return refcount_block_offset; +fail_table: + qemu_free(new_table); +fail_block: + s->refcount_block_cache_offset = 0; + return ret; } #define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT) diff --git a/block/qcow2.c b/block/qcow2.c index 4ae8f193d..5d33d6c79 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -467,8 +467,10 @@ static void qcow_aio_read_cb(void *opaque, int ret) acb->hd_aiocb = bdrv_aio_readv(s->hd, (acb->cluster_offset >> 9) + index_in_cluster, &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); - if (acb->hd_aiocb == NULL) + if (acb->hd_aiocb == NULL) { + ret = -EIO; goto done; + } } return; @@ -620,11 +622,17 @@ static void qcow_aio_write_cb(void *opaque, int ret) (acb->cluster_offset >> 9) + index_in_cluster, &acb->hd_qiov, acb->n, qcow_aio_write_cb, acb); - if (acb->hd_aiocb == NULL) - goto done; + if (acb->hd_aiocb == NULL) { + ret = -EIO; + goto fail; + } return; +fail: + if (acb->l2meta.nb_clusters != 0) { + QLIST_REMOVE(&acb->l2meta, next_in_flight); + } done: if (acb->qiov->niov > 1) qemu_vfree(acb->orig_buf); diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak index 4f912eccd..a89f52b16 100644 --- a/default-configs/sh4-softmmu.mak +++ b/default-configs/sh4-softmmu.mak @@ -2,3 +2,4 @@ CONFIG_USB_OHCI=y CONFIG_PTIMER=y +CONFIG_ISA_MMIO=y diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak index 93d0c76f2..762385be3 100644 --- a/default-configs/sh4eb-softmmu.mak +++ b/default-configs/sh4eb-softmmu.mak @@ -2,3 +2,4 @@ CONFIG_USB_OHCI=y CONFIG_PTIMER=y +CONFIG_ISA_MMIO=y diff --git a/dyngen-exec.h b/dyngen-exec.h index 0353f36cd..3f1c43196 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -69,9 +69,9 @@ extern int printf(const char *, ...); #define AREG1 "r14" #define AREG2 "r15" #elif defined(__mips__) -#define AREG0 "fp" -#define AREG1 "s0" -#define AREG2 "s1" +#define AREG0 "s0" +#define AREG1 "s1" +#define AREG2 "fp" #elif defined(__sparc__) #ifdef CONFIG_SOLARIS #define AREG0 "g2" @@ -1860,8 +1860,12 @@ fdctrl_t *fdctrl_init_isa(DriveInfo **fds) ISADevice *dev; dev = isa_create("isa-fdc"); - qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]); - qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]); + if (fds[0]) { + qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]); + } + if (fds[1]) { + qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]); + } if (qdev_init(&dev->qdev) < 0) return NULL; return &(DO_UPCAST(fdctrl_isabus_t, busdev, dev)->state); @@ -1879,8 +1883,12 @@ fdctrl_t *fdctrl_init_sysbus(qemu_irq irq, int dma_chann, sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev); fdctrl = &sys->state; fdctrl->dma_chann = dma_chann; /* FIXME */ - qdev_prop_set_drive(dev, "driveA", fds[0]); - qdev_prop_set_drive(dev, "driveB", fds[1]); + if (fds[0]) { + qdev_prop_set_drive(dev, "driveA", fds[0]); + } + if (fds[1]) { + qdev_prop_set_drive(dev, "driveB", fds[1]); + } qdev_init_nofail(dev); sysbus_connect_irq(&sys->busdev, 0, irq); sysbus_mmio_map(&sys->busdev, 0, mmio_base); @@ -1896,7 +1904,9 @@ fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, fdctrl_t *fdctrl; dev = qdev_create(NULL, "SUNW,fdtwo"); - qdev_prop_set_drive(dev, "drive", fds[0]); + if (fds[0]) { + qdev_prop_set_drive(dev, "drive", fds[0]); + } qdev_init_nofail(dev); sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev); fdctrl = &sys->state; diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index ea120ba55..c62bf522d 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -179,7 +179,7 @@ static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size) static void put_unused(QEMUFile *f, void *pv, size_t size) { - fprintf(stderr, "uint32_as_uint16 is only used for backward compatibilty.\n"); + fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n"); fprintf(stderr, "This functions shouldn't be called.\n"); } diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index e1e626e2a..835c98d72 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -70,11 +70,7 @@ static void ide_map(PCIDevice *pci_dev, int region_num, static PCIIDEState *pci_from_bm(BMDMAState *bm) { - if (bm->unit == 0) { - return container_of(bm, PCIIDEState, bmdma[0]); - } else { - return container_of(bm, PCIIDEState, bmdma[1]); - } + return bm->pci_dev; } static uint32_t bmdma_readb(void *opaque, uint32_t addr) @@ -145,6 +141,7 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num, BMDMAState *bm = &d->bmdma[i]; d->bus[i].bmdma = bm; bm->bus = d->bus+i; + bm->pci_dev = d; qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm); register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 8869a0834..8615d1a1f 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -481,6 +481,7 @@ struct BMDMAState { uint8_t status; uint32_t addr; + struct PCIIDEState *pci_dev; IDEBus *bus; /* current transfer state */ uint32_t cur_addr; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index de3648023..2776ac365 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -78,6 +78,7 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num, BMDMAState *bm = &d->bmdma[i]; d->bus[i].bmdma = bm; bm->bus = d->bus+i; + bm->pci_dev = d; qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm); register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 014c85dbd..e0ade1e54 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -173,11 +173,15 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0) /* Flag set if this is a tagged command. */ #define LSI_TAG_VALID (1 << 16) -typedef struct { +typedef struct lsi_request { uint32_t tag; + SCSIDevice *dev; + uint32_t dma_len; + uint8_t *dma_buf; uint32_t pending; int out; -} lsi_queue; + QTAILQ_ENTRY(lsi_request) next; +} lsi_request; typedef struct { PCIDevice dev; @@ -198,16 +202,13 @@ typedef struct { * 3 if a DMA operation is in progress. */ int waiting; SCSIBus bus; - SCSIDevice *current_dev; + SCSIDevice *select_dev; int current_lun; /* The tag is a combination of the device ID and the SCSI tag. */ - uint32_t current_tag; - uint32_t current_dma_len; + uint32_t select_tag; int command_complete; - uint8_t *dma_buf; - lsi_queue *queue; - int queue_len; - int active_commands; + QTAILQ_HEAD(, lsi_request) queue; + lsi_request *current; uint32_t dsa; uint32_t temp; @@ -370,7 +371,7 @@ static int lsi_dma_64bit(LSIState *s) static uint8_t lsi_reg_readb(LSIState *s, int offset); static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); static void lsi_execute_script(LSIState *s); -static void lsi_reselect(LSIState *s, uint32_t tag); +static void lsi_reselect(LSIState *s, lsi_request *p); static inline uint32_t read_dword(LSIState *s, uint32_t addr) { @@ -391,9 +392,9 @@ static void lsi_stop_script(LSIState *s) static void lsi_update_irq(LSIState *s) { - int i; int level; static int last_level; + lsi_request *p; /* It's unclear whether the DIP/SIP bits should be cleared when the Interrupt Status Registers are cleared or when istat0 is read. @@ -427,9 +428,9 @@ static void lsi_update_irq(LSIState *s) if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) { DPRINTF("Handled IRQs & disconnected, looking for pending " "processes\n"); - for (i = 0; i < s->active_commands; i++) { - if (s->queue[i].pending) { - lsi_reselect(s, s->queue[i].tag); + QTAILQ_FOREACH(p, &s->queue, next) { + if (p->pending) { + lsi_reselect(s, p); break; } } @@ -508,15 +509,16 @@ static void lsi_do_dma(LSIState *s, int out) uint32_t count; target_phys_addr_t addr; - if (!s->current_dma_len) { + assert(s->current); + if (!s->current->dma_len) { /* Wait until data is available. */ DPRINTF("DMA no data available\n"); return; } count = s->dbc; - if (count > s->current_dma_len) - count = s->current_dma_len; + if (count > s->current->dma_len) + count = s->current->dma_len; addr = s->dnad; /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */ @@ -532,29 +534,29 @@ static void lsi_do_dma(LSIState *s, int out) s->dnad += count; s->dbc -= count; - if (s->dma_buf == NULL) { - s->dma_buf = s->current_dev->info->get_buf(s->current_dev, - s->current_tag); + if (s->current->dma_buf == NULL) { + s->current->dma_buf = s->current->dev->info->get_buf(s->current->dev, + s->current->tag); } /* ??? Set SFBR to first data byte. */ if (out) { - cpu_physical_memory_read(addr, s->dma_buf, count); + cpu_physical_memory_read(addr, s->current->dma_buf, count); } else { - cpu_physical_memory_write(addr, s->dma_buf, count); + cpu_physical_memory_write(addr, s->current->dma_buf, count); } - s->current_dma_len -= count; - if (s->current_dma_len == 0) { - s->dma_buf = NULL; + s->current->dma_len -= count; + if (s->current->dma_len == 0) { + s->current->dma_buf = NULL; if (out) { /* Write the data. */ - s->current_dev->info->write_data(s->current_dev, s->current_tag); + s->current->dev->info->write_data(s->current->dev, s->current->tag); } else { /* Request any remaining data. */ - s->current_dev->info->read_data(s->current_dev, s->current_tag); + s->current->dev->info->read_data(s->current->dev, s->current->tag); } } else { - s->dma_buf += count; + s->current->dma_buf += count; lsi_resume_script(s); } } @@ -563,15 +565,14 @@ static void lsi_do_dma(LSIState *s, int out) /* Add a command to the queue. */ static void lsi_queue_command(LSIState *s) { - lsi_queue *p; + lsi_request *p = s->current; DPRINTF("Queueing tag=0x%x\n", s->current_tag); - if (s->queue_len == s->active_commands) { - s->queue_len++; - s->queue = qemu_realloc(s->queue, s->queue_len * sizeof(lsi_queue)); - } - p = &s->queue[s->active_commands++]; - p->tag = s->current_tag; + assert(s->current != NULL); + assert(s->current->dma_len == 0); + QTAILQ_INSERT_TAIL(&s->queue, s->current, next); + s->current = NULL; + p->pending = 0; p->out = (s->sstat1 & PHASE_MASK) == PHASE_DO; } @@ -588,45 +589,29 @@ static void lsi_add_msg_byte(LSIState *s, uint8_t data) } /* Perform reselection to continue a command. */ -static void lsi_reselect(LSIState *s, uint32_t tag) +static void lsi_reselect(LSIState *s, lsi_request *p) { - lsi_queue *p; - int n; int id; - p = NULL; - for (n = 0; n < s->active_commands; n++) { - p = &s->queue[n]; - if (p->tag == tag) - break; - } - if (n == s->active_commands) { - BADF("Reselected non-existant command tag=0x%x\n", tag); - return; - } - id = (tag >> 8) & 0xf; + assert(s->current == NULL); + QTAILQ_REMOVE(&s->queue, p, next); + s->current = p; + + id = (p->tag >> 8) & 0xf; s->ssid = id | 0x80; /* LSI53C700 Family Compatibility, see LSI53C895A 4-73 */ if (!s->dcntl & LSI_DCNTL_COM) { s->sfbr = 1 << (id & 0x7); } DPRINTF("Reselected target %d\n", id); - s->current_dev = s->bus.devs[id]; - s->current_tag = tag; s->scntl1 |= LSI_SCNTL1_CON; lsi_set_phase(s, PHASE_MI); s->msg_action = p->out ? 2 : 3; - s->current_dma_len = p->pending; - s->dma_buf = NULL; + s->current->dma_len = p->pending; lsi_add_msg_byte(s, 0x80); - if (s->current_tag & LSI_TAG_VALID) { + if (s->current->tag & LSI_TAG_VALID) { lsi_add_msg_byte(s, 0x20); - lsi_add_msg_byte(s, tag & 0xff); - } - - s->active_commands--; - if (n != s->active_commands) { - s->queue[n] = s->queue[s->active_commands]; + lsi_add_msg_byte(s, p->tag & 0xff); } if (lsi_irq_on_rsl(s)) { @@ -638,10 +623,9 @@ static void lsi_reselect(LSIState *s, uint32_t tag) the device was reselected, nonzero if the IO is deferred. */ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg) { - lsi_queue *p; - int i; - for (i = 0; i < s->active_commands; i++) { - p = &s->queue[i]; + lsi_request *p; + + QTAILQ_FOREACH(p, &s->queue, next) { if (p->tag == tag) { if (p->pending) { BADF("Multiple IO pending for tag %d\n", tag); @@ -656,10 +640,10 @@ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg) (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) && !(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) { /* Reselect device. */ - lsi_reselect(s, tag); + lsi_reselect(s, p); return 0; } else { - DPRINTF("Queueing IO tag=0x%x\n", tag); + DPRINTF("Queueing IO tag=0x%x\n", tag); p->pending = arg; return 1; } @@ -687,11 +671,15 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag, } else { lsi_set_phase(s, PHASE_ST); } + + qemu_free(s->current); + s->current = NULL; + lsi_resume_script(s); return; } - if (s->waiting == 1 || tag != s->current_tag || + if (s->waiting == 1 || !s->current || tag != s->current->tag || (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) { if (lsi_queue_tag(s, tag, arg)) return; @@ -699,7 +687,7 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag, /* host adapter (re)connected */ DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg); - s->current_dma_len = arg; + s->current->dma_len = arg; s->command_complete = 1; if (!s->waiting) return; @@ -721,14 +709,20 @@ static void lsi_do_command(LSIState *s) cpu_physical_memory_read(s->dnad, buf, s->dbc); s->sfbr = buf[0]; s->command_complete = 0; - n = s->current_dev->info->send_command(s->current_dev, s->current_tag, buf, - s->current_lun); + + assert(s->current == NULL); + s->current = qemu_mallocz(sizeof(lsi_request)); + s->current->tag = s->select_tag; + s->current->dev = s->select_dev; + + n = s->current->dev->info->send_command(s->current->dev, s->current->tag, buf, + s->current_lun); if (n > 0) { lsi_set_phase(s, PHASE_DI); - s->current_dev->info->read_data(s->current_dev, s->current_tag); + s->current->dev->info->read_data(s->current->dev, s->current->tag); } else if (n < 0) { lsi_set_phase(s, PHASE_DO); - s->current_dev->info->write_data(s->current_dev, s->current_tag); + s->current->dev->info->write_data(s->current->dev, s->current->tag); } if (!s->command_complete) { @@ -851,16 +845,16 @@ static void lsi_do_msgout(LSIState *s) } break; case 0x20: /* SIMPLE queue */ - s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; + s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; DPRINTF("SIMPLE queue tag=0x%x\n", s->current_tag & 0xff); break; case 0x21: /* HEAD of queue */ BADF("HEAD queue not implemented\n"); - s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; + s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; break; case 0x22: /* ORDERED queue */ BADF("ORDERED queue not implemented\n"); - s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; + s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; break; default: if ((msg & 0x80) == 0) { @@ -905,17 +899,17 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count) static void lsi_wait_reselect(LSIState *s) { - int i; + lsi_request *p; + DPRINTF("Wait Reselect\n"); - if (s->current_dma_len) - BADF("Reselect with pending DMA\n"); - for (i = 0; i < s->active_commands; i++) { - if (s->queue[i].pending) { - lsi_reselect(s, s->queue[i].tag); + + QTAILQ_FOREACH(p, &s->queue, next) { + if (p->pending) { + lsi_reselect(s, p); break; } } - if (s->current_dma_len == 0) { + if (s->current == NULL) { s->waiting = 1; } } @@ -1093,8 +1087,8 @@ again: /* ??? Linux drivers compain when this is set. Maybe it only applies in low-level mode (unimplemented). lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */ - s->current_dev = s->bus.devs[id]; - s->current_tag = id << 8; + s->select_dev = s->bus.devs[id]; + s->select_tag = id << 8; s->scntl1 |= LSI_SCNTL1_CON; if (insn & (1 << 3)) { s->socl |= LSI_SOCL_ATN; @@ -2006,9 +2000,11 @@ static void lsi_pre_save(void *opaque) { LSIState *s = opaque; - assert(s->dma_buf == NULL); - assert(s->current_dma_len == 0); - assert(s->active_commands == 0); + if (s->current) { + assert(s->current->dma_buf == NULL); + assert(s->current->dma_len == 0); + } + assert(QTAILQ_EMPTY(&s->queue)); } static const VMStateDescription vmstate_lsi_scsi = { @@ -2101,8 +2097,6 @@ static int lsi_scsi_uninit(PCIDevice *d) cpu_unregister_io_memory(s->mmio_io_addr); cpu_unregister_io_memory(s->ram_io_addr); - qemu_free(s->queue); - return 0; } @@ -2138,9 +2132,7 @@ static int lsi_scsi_init(PCIDevice *dev) PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc); pci_register_bar((struct PCIDevice *)s, 2, 0x2000, PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc); - s->queue = qemu_malloc(sizeof(lsi_queue)); - s->queue_len = 1; - s->active_commands = 0; + QTAILQ_INIT(&s->queue); lsi_soft_reset(s); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index b34fbaa67..a79201213 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -434,7 +434,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) memcpy(&outbuf[16], "QEMU HARDDISK ", 16); } memcpy(&outbuf[8], "QEMU ", 8); - memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION, 4); + memset(&outbuf[32], 0, 4); + memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION, + MIN(4, strlen(s->version ? s->version : QEMU_VERSION))); /* Identify device as SCSI-3 rev 1. Some later commands are also implemented. */ outbuf[2] = 3; diff --git a/hw/sh7750.c b/hw/sh7750.c index 933bbc0c7..9c39f4b68 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -396,8 +396,11 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr, portb_changed(s, temp); return; case SH7750_MMUCR_A7: - s->cpu->mmucr = mem_value; - return; + if (mem_value & MMUCR_TI) { + cpu_sh4_invalidate_tlb(s->cpu); + } + s->cpu->mmucr = mem_value & ~MMUCR_TI; + return; case SH7750_PTEH_A7: /* If asid changes, clear all registered tlb entries. */ if ((s->cpu->pteh & 0xff) != (mem_value & 0xff)) diff --git a/hw/sh_pci.c b/hw/sh_pci.c index abe4c7568..441879a9d 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -47,10 +47,15 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val) pcic->par = val; break; case 0x1c4: - pcic->mbr = val; + pcic->mbr = val & 0xff000001; break; case 0x1c8: - pcic->iobr = val; + if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) { + cpu_register_physical_memory(pcic->iobr & 0xfffc0000, 0x40000, + IO_MEM_UNASSIGNED); + pcic->iobr = val & 0xfffc0001; + isa_mmio_init(pcic->iobr & 0xfffc0000, 0x40000); + } break; case 0x220: pci_data_write(pcic->bus, pcic->par, val, 4); @@ -66,89 +71,16 @@ static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr) return le32_to_cpup((uint32_t*)(pcic->dev->config + addr)); case 0x1c0: return pcic->par; + case 0x1c4: + return pcic->mbr; + case 0x1c8: + return pcic->iobr; case 0x220: return pci_data_read(pcic->bus, pcic->par, 4); } return 0; } -static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr, - uint32_t val, int size) -{ - pci_data_write(pcic->bus, addr + pcic->mbr, val, size); -} - -static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr, - int size) -{ - return pci_data_read(pcic->bus, addr + pcic->mbr, size); -} - -static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val) -{ - sh_pci_data_write(p, addr, val, 1); -} - -static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val) -{ - sh_pci_data_write(p, addr, val, 2); -} - -static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val) -{ - sh_pci_data_write(p, addr, val, 4); -} - -static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr) -{ - return sh_pci_mem_read(p, addr, 1); -} - -static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr) -{ - return sh_pci_mem_read(p, addr, 2); -} - -static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr) -{ - return sh_pci_mem_read(p, addr, 4); -} - -static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr) -{ - return addr + pcic->iobr; -} - -static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val) -{ - cpu_outb(sh_pci_addr2port(p, addr), val); -} - -static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val) -{ - cpu_outw(sh_pci_addr2port(p, addr), val); -} - -static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val) -{ - cpu_outl(sh_pci_addr2port(p, addr), val); -} - -static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr) -{ - return cpu_inb(sh_pci_addr2port(p, addr)); -} - -static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr) -{ - return cpu_inw(sh_pci_addr2port(p, addr)); -} - -static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr) -{ - return cpu_inl(sh_pci_addr2port(p, addr)); -} - typedef struct { CPUReadMemoryFunc * const r[3]; CPUWriteMemoryFunc * const w[3]; @@ -159,21 +91,11 @@ static MemOp sh_pci_reg = { { NULL, NULL, sh_pci_reg_write }, }; -static MemOp sh_pci_mem = { - { sh_pci_readb, sh_pci_readw, sh_pci_readl }, - { sh_pci_writeb, sh_pci_writew, sh_pci_writel }, -}; - -static MemOp sh_pci_iop = { - { sh_pci_inb, sh_pci_inw, sh_pci_inl }, - { sh_pci_outb, sh_pci_outw, sh_pci_outl }, -}; - PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *opaque, int devfn_min, int nirq) { SHPCIC *p; - int mem, reg, iop; + int reg; p = qemu_mallocz(sizeof(SHPCIC)); p->bus = pci_register_bus(NULL, "pci", @@ -182,14 +104,11 @@ PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice), -1, NULL, NULL); reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p); - iop = cpu_register_io_memory(sh_pci_iop.r, sh_pci_iop.w, p); - mem = cpu_register_io_memory(sh_pci_mem.r, sh_pci_mem.w, p); cpu_register_physical_memory(0x1e200000, 0x224, reg); - cpu_register_physical_memory(0x1e240000, 0x40000, iop); - cpu_register_physical_memory(0x1d000000, 0x1000000, mem); cpu_register_physical_memory(0xfe200000, 0x224, reg); - cpu_register_physical_memory(0xfe240000, 0x40000, iop); - cpu_register_physical_memory(0xfd000000, 0x1000000, mem); + + p->iobr = 0xfe240000; + isa_mmio_init(p->iobr, 0x40000); pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI); pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R); diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index dc52737ae..cfd77ebed 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -677,9 +677,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ ret = async->packet.len; - if (td->ctrl & TD_CTRL_IOC) - *int_mask |= 0x01; - if (td->ctrl & TD_CTRL_IOS) td->ctrl &= ~TD_CTRL_ACTIVE; @@ -693,6 +690,8 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ here. The docs are somewhat unclear, but win2k relies on this behavior. */ td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK); + if (td->ctrl & TD_CTRL_IOC) + *int_mask |= 0x01; if (pid == USB_TOKEN_IN) { if (len > max_len) { @@ -750,6 +749,8 @@ out: if (err == 0) { td->ctrl &= ~TD_CTRL_ACTIVE; s->status |= UHCI_STS_USBERR; + if (td->ctrl & TD_CTRL_IOC) + *int_mask |= 0x01; uhci_update_irq(s); } } diff --git a/json-parser.c b/json-parser.c index 2ab6f6c11..3497cd365 100644 --- a/json-parser.c +++ b/json-parser.c @@ -266,7 +266,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l peek = qlist_peek(working); key = parse_value(ctxt, &working, ap); - if (qobject_type(key) != QTYPE_QSTRING) { + if (!key || qobject_type(key) != QTYPE_QSTRING) { parse_error(ctxt, peek, "key is not a string in object"); goto out; } diff --git a/linux-user/main.c b/linux-user/main.c index e51539eff..802bd8852 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2684,7 +2684,7 @@ int main(int argc, char **argv, char **envp) #endif #elif defined(TARGET_PPC) #ifdef TARGET_PPC64 - cpu_model = "970"; + cpu_model = "970fx"; #else cpu_model = "750"; #endif @@ -1187,26 +1187,6 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict) qemu_del_vlan_client(vc); } -void net_set_boot_mask(int net_boot_mask) -{ - int i; - - /* Only the first four NICs may be bootable */ - net_boot_mask = net_boot_mask & 0xF; - - for (i = 0; i < nb_nics; i++) { - if (net_boot_mask & (1 << i)) { - nd_table[i].bootable = 1; - net_boot_mask &= ~(1 << i); - } - } - - if (net_boot_mask) { - fprintf(stderr, "Cannot boot from non-existent NIC\n"); - exit(1); - } -} - void do_info_network(Monitor *mon) { VLANState *vlan; @@ -163,7 +163,6 @@ int net_client_parse(QemuOptsList *opts_list, const char *str); int net_init_clients(void); void net_check_clients(void); void net_cleanup(void); -void net_set_boot_mask(int boot_mask); void net_host_device_add(Monitor *mon, const QDict *qdict); void net_host_device_remove(Monitor *mon, const QDict *qdict); diff --git a/qemu-char.c b/qemu-char.c index 5a1b535bd..30f39caae 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2317,8 +2317,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) qemu_opt_set(opts, "backend", "udp"); if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) { host[0] = 0; - if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) { - fprintf(stderr, "udp #1\n"); + if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) { goto fail; } } @@ -2329,7 +2328,6 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { host[0] = 0; if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) { - fprintf(stderr, "udp #2\n"); goto fail; } } @@ -2357,7 +2355,6 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) } fail: - fprintf(stderr, "%s: fail on \"%s\"\n", __FUNCTION__, filename); qemu_opts_del(opts); return NULL; } diff --git a/qemu-common.h b/qemu-common.h index 1c5c0b222..b604ddfa0 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -54,6 +54,10 @@ struct iovec { void *iov_base; size_t iov_len; }; +/* + * Use the same value as Linux for now. + */ +#define IOV_MAX 1024 #else #include <sys/uio.h> #endif diff --git a/qemu-options.hx b/qemu-options.hx index e2fbebd9b..65bb11115 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -969,7 +969,7 @@ the guest, use the following: @example # on the host -qemu -net user,hostfwd=tcp:5555::23 [...] +qemu -net user,hostfwd=tcp::5555-:23 [...] telnet localhost 5555 @end example diff --git a/target-i386/translate.c b/target-i386/translate.c index 511a4eae9..3de65bd1d 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2047,8 +2047,8 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ gen_op_movl_A0_im(disp); } } - /* XXX: index == 4 is always invalid */ - if (havesib && (index != 4 || scale != 0)) { + /* index == 4 means no index */ + if (havesib && (index != 4)) { #ifdef TARGET_X86_64 if (s->aflag == 2) { gen_op_addq_A0_reg_sN(scale, index); @@ -3165,12 +3165,17 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x1e7: /* movntdq */ case 0x02b: /* movntps */ case 0x12b: /* movntps */ - case 0x3f0: /* lddqu */ if (mod == 3) goto illegal_op; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); break; + case 0x3f0: /* lddqu */ + if (mod == 3) + goto illegal_op; + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); + gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg])); + break; case 0x22b: /* movntss */ case 0x32b: /* movntsd */ if (mod == 3) @@ -4591,9 +4596,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* operand size for jumps is 64 bit */ ot = OT_QUAD; } else if (op == 3 || op == 5) { - /* for call calls, the operand is 16 or 32 bit, even - in long mode */ - ot = dflag ? OT_LONG : OT_WORD; + ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD; } else if (op == 6) { /* default push size is 64 bit */ ot = dflag ? OT_QUAD : OT_WORD; diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 366e7986e..015d59845 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -167,6 +167,7 @@ int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw, void do_interrupt(CPUSH4State * env); void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); +void cpu_sh4_invalidate_tlb(CPUSH4State *s); void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value); @@ -222,6 +223,7 @@ enum { /* MMU control register */ #define MMUCR 0x1F000010 #define MMUCR_AT (1<<0) +#define MMUCR_TI (1<<2) #define MMUCR_SV (1<<8) #define MMUCR_URC_BITS (6) #define MMUCR_URC_OFFSET (10) diff --git a/target-sh4/helper.c b/target-sh4/helper.c index 088d36a5f..29b681398 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -377,7 +377,7 @@ static int get_mmu_address(CPUState * env, target_ulong * physical, n = find_itlb_entry(env, address, use_asid, 1); if (n >= 0) { matching = &env->itlb[n]; - if ((env->sr & SR_MD) & !(matching->pr & 2)) + if (!(env->sr & SR_MD) && !(matching->pr & 2)) n = MMU_ITLB_VIOLATION; else *prot = PAGE_READ; @@ -430,7 +430,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical, if ((address >= 0x80000000 && address < 0xc0000000) || address >= 0xe0000000) { if (!(env->sr & SR_MD) - && (address < 0xe0000000 || address > 0xe4000000)) { + && (address < 0xe0000000 || address >= 0xe4000000)) { /* Unauthorized access in user mode (only store queues are available) */ fprintf(stderr, "Unauthorized access\n"); if (rw == 0) @@ -574,6 +574,24 @@ void cpu_load_tlb(CPUSH4State * env) entry->tc = (uint8_t)cpu_ptea_tc(env->ptea); } + void cpu_sh4_invalidate_tlb(CPUSH4State *s) +{ + int i; + + /* UTLB */ + for (i = 0; i < UTLB_SIZE; i++) { + tlb_t * entry = &s->utlb[i]; + entry->v = 0; + } + /* ITLB */ + for (i = 0; i < UTLB_SIZE; i++) { + tlb_t * entry = &s->utlb[i]; + entry->v = 0; + } + + tlb_flush(s, 1); +} + void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 895b978d3..7f9527a83 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1905,7 +1905,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, ctx.bstate = BS_NONE; ctx.sr = env->sr; ctx.fpscr = env->fpscr; - ctx.memidx = (env->sr & SR_MD) ? 1 : 0; + ctx.memidx = (env->sr & SR_MD) == 0 ? 1 : 0; /* We don't know if the delayed pc came from a dynamic or static branch, so assume it is a dynamic branch. */ ctx.delayed_pc = -1; /* use delayed pc from env pointer */ diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index f8d626d02..81f533f73 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1697,12 +1697,15 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, void tcg_target_qemu_prologue(TCGContext *s) { - /* stmdb sp!, { r9 - r11, lr } */ - tcg_out32(s, (COND_AL << 28) | 0x092d4e00); + /* Theoretically there is no need to save r12, but an + even number of registers to be saved as per EABI */ + + /* stmdb sp!, { r4 - r12, lr } */ + tcg_out32(s, (COND_AL << 28) | 0x092d5ff0); tcg_out_bx(s, COND_AL, TCG_REG_R0); tb_ret_addr = s->code_ptr; - /* ldmia sp!, { r9 - r11, pc } */ - tcg_out32(s, (COND_AL << 28) | 0x08bd8e00); + /* ldmia sp!, { r4 - r12, pc } */ + tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0); } diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 807b8fdfa..79ba9a662 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -340,6 +340,17 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i } /* + * Type branch + */ +static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs) +{ + /* We need to keep the offset unchanged for retranslation */ + uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr); + + tcg_out_opc_imm(s, opc, rt, rs, offset); +} + +/* * Type sa */ static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa) @@ -469,42 +480,42 @@ static void tcg_out_brcond(TCGContext *s, int cond, int arg1, switch (cond) { case TCG_COND_EQ: - tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0); + tcg_out_opc_br(s, OPC_BEQ, arg1, arg2); break; case TCG_COND_NE: - tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0); + tcg_out_opc_br(s, OPC_BNE, arg1, arg2); break; case TCG_COND_LT: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); - tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_LTU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); - tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_GE: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2); - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_GEU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2); - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_LE: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_LEU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_GT: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1); - tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); break; case TCG_COND_GTU: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1); - tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO); break; default: tcg_abort(); @@ -553,7 +564,7 @@ static void tcg_out_brcond2(TCGContext *s, int cond, int arg1, } label_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0); + tcg_out_opc_br(s, OPC_BNE, arg2, arg4); tcg_out_nop(s); switch(cond) { @@ -670,20 +681,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, # if TARGET_LONG_BITS == 64 label3_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT); tcg_out_nop(s); tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0, offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh); label1_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0); + tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT); tcg_out_nop(s); reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr); # else label1_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT); tcg_out_nop(s); # endif @@ -725,7 +736,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } label2_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO); tcg_out_nop(s); /* label1: fast path */ @@ -857,20 +868,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, # if TARGET_LONG_BITS == 64 label3_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0); + tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT); tcg_out_nop(s); tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0, offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh); label1_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0); + tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT); tcg_out_nop(s); reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr); # else label1_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT); tcg_out_nop(s); # endif @@ -911,7 +922,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, tcg_out_nop(s); label2_ptr = s->code_ptr; - tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0); + tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO); tcg_out_nop(s); /* label1: fast path */ @@ -1262,7 +1273,9 @@ static const TCGTargetOpDef mips_op_defs[] = { }; static int tcg_target_callee_save_regs[] = { +#if 0 /* used for the global env (TCG_AREG0), so no need to save */ TCG_REG_S0, +#endif TCG_REG_S1, TCG_REG_S2, TCG_REG_S3, @@ -1271,8 +1284,7 @@ static int tcg_target_callee_save_regs[] = { TCG_REG_S6, TCG_REG_S7, TCG_REG_GP, - /* TCG_REG_FP, */ /* currently used for the global env, so np - need to save */ + TCG_REG_FP, TCG_REG_RA, /* should be last for ABI compliance */ }; diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 46760a50e..baae6d85c 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -92,9 +92,9 @@ enum { #undef TCG_TARGET_HAS_ext16u_i32 /* andi rt, rs, 0xffff */ /* Note: must be synced with dyngen-exec.h */ -#define TCG_AREG0 TCG_REG_FP -#define TCG_AREG1 TCG_REG_S0 -#define TCG_AREG2 TCG_REG_S1 +#define TCG_AREG0 TCG_REG_S0 +#define TCG_AREG1 TCG_REG_S1 +#define TCG_AREG2 TCG_REG_FP #include <sys/cachectl.h> @@ -2597,9 +2597,9 @@ static void numa_add(const char *optarg) fprintf(stderr, "only 63 CPUs in NUMA mode supported.\n"); } - value = (1 << (endvalue + 1)) - (1 << value); + value = (2ULL << endvalue) - (1ULL << value); } else { - value = 1 << value; + value = 1ULL << value; } } node_cpumask[nodenr] = value; @@ -3515,6 +3515,8 @@ static int cpu_can_run(CPUState *env) return 0; if (env->stopped) return 0; + if (!vm_running) + return 0; return 1; } @@ -4909,7 +4911,7 @@ int main(int argc, char **argv, char **envp) const char *gdbstub_dev = NULL; uint32_t boot_devices_bitmap = 0; int i; - int snapshot, linux_boot, net_boot; + int snapshot, linux_boot; const char *initrd_filename; const char *kernel_filename, *kernel_cmdline; char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ @@ -5428,6 +5430,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_serial: add_device_config(DEV_SERIAL, optarg); default_serial = 0; + if (strncmp(optarg, "mon:", 4) == 0) { + default_monitor = 0; + } break; case QEMU_OPTION_watchdog: if (watchdog) { @@ -5446,10 +5451,16 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_virtiocon: add_device_config(DEV_VIRTCON, optarg); default_virtcon = 0; + if (strncmp(optarg, "mon:", 4) == 0) { + default_monitor = 0; + } break; case QEMU_OPTION_parallel: add_device_config(DEV_PARALLEL, optarg); default_parallel = 0; + if (strncmp(optarg, "mon:", 4) == 0) { + default_monitor = 0; + } break; case QEMU_OPTION_loadvm: loadvm = optarg; @@ -5905,6 +5916,12 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "Could not initialize KVM, will disable KVM support\n"); kvm_allowed = 0; } + } else { + /* without kvm enabled, we can only support 4095 MB RAM */ + if (ram_size > (4095UL << 20)) { + fprintf(stderr, "qemu: without kvm support at most 4095 MB RAM can be simulated\n"); + exit(1); + } } if (qemu_init_main_loop()) { @@ -5948,9 +5965,6 @@ int main(int argc, char **argv, char **envp) exit(1); } - net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF; - net_set_boot_mask(net_boot); - /* init the bluetooth world */ if (foreach_device_config(DEV_BT, bt_parse)) exit(1); @@ -1421,8 +1421,10 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) dz = 1; if (vs->absolute) { - kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1), - y * 0x7FFF / (ds_get_height(vs->ds) - 1), + kbd_mouse_event(ds_get_width(vs->ds) > 1 ? + x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000, + ds_get_height(vs->ds) > 1 ? + y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000, dz, buttons); } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { x -= 0x7FFF; |