Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b04c3db504 | ||
|
|
d04d7cf158 | ||
|
|
2b8bdd5c7f | ||
|
|
2a44494726 | ||
|
|
8f30db54d9 | ||
|
|
b09ac1abe7 | ||
|
|
012d4869c1 | ||
|
|
3597c9c1d5 | ||
|
|
3b4bef0696 | ||
|
|
d899303743 | ||
|
|
5773685183 | ||
|
|
d40ba77ebf | ||
|
|
a8c46d182c | ||
|
|
d80e20a1c3 | ||
|
|
1ce4fad939 | ||
|
|
9167a242db | ||
|
|
09e96924ec | ||
|
|
69ff4e9dbd | ||
|
|
0434349d6a | ||
|
|
e007221223 | ||
|
|
4622317288 | ||
|
|
ffac613ff9 | ||
|
|
aba5288247 | ||
|
|
4f7cb96931 | ||
|
|
fafc2e4b33 | ||
|
|
83ef70f24a | ||
|
|
de17c16e1f | ||
|
|
9462695b64 | ||
|
|
5eb089588e | ||
|
|
2039f70c23 | ||
|
|
082a9fc256 | ||
|
|
36a013c956 | ||
|
|
c4c4b32b81 | ||
|
|
804b6ab08d | ||
|
|
81b168a702 | ||
|
|
5c6892078a | ||
|
|
18a21890ff | ||
|
|
6629fa6473 | ||
|
|
2a7996ce0e | ||
|
|
8ec131fb59 | ||
|
|
30d061750d | ||
|
|
c5f5dc5bad | ||
|
|
d2df336c58 | ||
|
|
b299b12b17 | ||
|
|
c248df6161 | ||
|
|
7d5625d5f7 | ||
|
|
cc21d131e3 | ||
|
|
41a5bda61f | ||
|
|
5163f6e864 |
No files matched your search
@@ -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)
|
||||
|
||||
+50
-18
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+239
-97
@@ -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)
|
||||
{
|
||||
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 min_clusters = (min_size >> (s->cluster_bits - 3)) + 1;
|
||||
unsigned int refcount_table_clusters =
|
||||
MAX(1, s->refcount_table_size >> (s->cluster_bits - 3));
|
||||
|
||||
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;
|
||||
}
|
||||
new_table_size = refcount_table_clusters << (s->cluster_bits - 3);
|
||||
if (min_size <= new_table_size)
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_ALLOC2
|
||||
printf("grow_refcount_table from %d to %d\n",
|
||||
s->refcount_table_size,
|
||||
new_table_size);
|
||||
#endif
|
||||
new_table_size2 = new_table_size * sizeof(uint64_t);
|
||||
new_table = qemu_mallocz(new_table_size2);
|
||||
memcpy(new_table, s->refcount_table,
|
||||
s->refcount_table_size * sizeof(uint64_t));
|
||||
for(i = 0; i < s->refcount_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]);
|
||||
|
||||
cpu_to_be64w((uint64_t*)data, table_offset);
|
||||
cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters);
|
||||
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
|
||||
data, sizeof(data));
|
||||
if (ret != sizeof(data)) {
|
||||
goto fail;
|
||||
while (min_clusters > refcount_table_clusters) {
|
||||
refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;
|
||||
}
|
||||
|
||||
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_offset = table_offset;
|
||||
|
||||
update_refcount(bs, table_offset, new_table_size2, 1);
|
||||
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;
|
||||
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;
|
||||
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 */
|
||||
/* 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) {
|
||||
ret = grow_refcount_table(bs, refcount_table_index + 1);
|
||||
if (ret < 0)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
|
||||
refcount_block_offset = offset;
|
||||
s->refcount_block_cache_offset = offset;
|
||||
update_refcount(bs, offset, s->cluster_size, 1);
|
||||
cache_refcount_updates = cache;
|
||||
#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 {
|
||||
if (refcount_block_offset != s->refcount_block_cache_offset) {
|
||||
if (load_refcount_block(bs, refcount_block_offset) < 0)
|
||||
return -EIO;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
return refcount_block_offset;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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
|
||||
fprintf(stderr, "qcow2: Grow refcount table %" PRId32 " => %" PRId64 "\n",
|
||||
s->refcount_table_size, table_size);
|
||||
#endif
|
||||
|
||||
/* 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));
|
||||
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]);
|
||||
}
|
||||
|
||||
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), table_clusters);
|
||||
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
|
||||
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);
|
||||
s->refcount_table = new_table;
|
||||
s->refcount_table_size = table_size;
|
||||
s->refcount_table_offset = table_offset;
|
||||
|
||||
/* 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));
|
||||
s->free_cluster_index = old_free_cluster_index;
|
||||
|
||||
ret = load_refcount_block(bs, new_block);
|
||||
if (ret < 0) {
|
||||
goto fail_block;
|
||||
}
|
||||
|
||||
return new_block;
|
||||
|
||||
fail_table:
|
||||
qemu_free(new_table);
|
||||
fail_block:
|
||||
s->refcount_block_cache_offset = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
|
||||
|
||||
+11
-3
@@ -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);
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
|
||||
CONFIG_USB_OHCI=y
|
||||
CONFIG_PTIMER=y
|
||||
CONFIG_ISA_MMIO=y
|
||||
@@ -2,3 +2,4 @@
|
||||
|
||||
CONFIG_USB_OHCI=y
|
||||
CONFIG_PTIMER=y
|
||||
CONFIG_ISA_MMIO=y
|
||||
+3
-3
@@ -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;
|
||||
|
||||
+1
-1
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+84
-92
@@ -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);
|
||||
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
+5
-2
@@ -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))
|
||||
|
||||
+15
-96
@@ -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);
|
||||
|
||||
+4
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
|
||||
+1
-4
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -968,7 +968,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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
+20
-2
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+33
-21
@@ -339,6 +339,17 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
|
||||
tcg_out32(s, inst);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -2573,9 +2573,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;
|
||||
@@ -3471,6 +3471,8 @@ static int cpu_can_run(CPUState *env)
|
||||
return 0;
|
||||
if (env->stopped)
|
||||
return 0;
|
||||
if (!vm_running)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4851,7 +4853,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 */
|
||||
@@ -5368,6 +5370,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) {
|
||||
@@ -5386,10 +5391,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;
|
||||
@@ -5792,6 +5803,12 @@ int main(int argc, char **argv, char **envp)
|
||||
fprintf(stderr, "failed to initialize KVM\n");
|
||||
exit(1);
|
||||
}
|
||||
} 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()) {
|
||||
@@ -5835,9 +5852,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;
|
||||
|
||||
Reference in new issue
Block a user