aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-09-23 10:29:56 +0300
committerAvi Kivity <avi@redhat.com>2009-09-23 10:30:02 +0300
commitb6fffd0208b8aa80ce271e5ab7efc50f7236ba40 (patch)
treebdd4dc840b3b05218aae23b136d9c4a64facce46
parentc5863ce628d07d3adcc8df52ecba6e915f7eb4d9 (diff)
parent1bec86a0bcaac7fa07f3081b3e26b9c7e1ec072c (diff)
Merge branch 'stable-0.11' of git://git.sv.gnu.org/qemu into stable-0.11qemu-kvm-0.11.0
* 'stable-0.11' of git://git.sv.gnu.org/qemu: Update version and changelog for 0.11.0 release RTC polling mode broken qcow2: Order concurrent AIO requests on the same unallocated cluster qemu-io: Improve portability (win32 now supported). target-alpha: fix extlh instruction tcg: fix size of local variables in tcg_gen_bswap64_i64 net: Fix send queue ordering escc: fix IRQ routing, broken by 6c319c82223a1766c5d64a20051e5c6ab7b53951 Fix Linux task preemption on Versatile board curses: save 250MB of memory Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Changelog11
-rw-r--r--VERSION2
-rw-r--r--block/qcow2-cluster.c39
-rw-r--r--block/qcow2.c50
-rw-r--r--block/qcow2.h7
-rw-r--r--cmd.c23
-rwxr-xr-xconfigure2
-rw-r--r--curses.c3
-rw-r--r--hw/arm_sysctl.c5
-rw-r--r--hw/escc.c4
-rw-r--r--hw/mc146818rtc.c5
-rw-r--r--net.c29
-rw-r--r--net.h5
-rw-r--r--qemu-io.c2
-rw-r--r--target-alpha/translate.c11
-rw-r--r--tcg/tcg-op.h9
16 files changed, 162 insertions, 45 deletions
diff --git a/Changelog b/Changelog
index c45822f00..857cbb27e 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,14 @@
+version 0.11.0
+ - fix rtc polling mode (Bernhard Kauer)
+ - qcow2: order concurrent aio requests (Kevin Wolf)
+ - qemu-io: port to win32 (Stefan Weil)
+ - alpha: fix extlh instruction (Vince Weaver)
+ - tcg: fix size of local variables in tcg_gen_bswap64_i64 (Stefan Weil)
+ - net: fix send ordering (Jan Kiszka)
+ - escc: fix IRQ routing (Aurelien Jarno)
+ - versatile: fix Linux task preemption (Aurelien Jarno)
+ - curses: reduce memory usage by 250MB (Aurelien Jarno)
+
version 0.11.0-rc2
- mips: fix conditional move off fp conditions codes (Nath Froyd)
- fix migration to obey -S (Paolo Bonzini)
diff --git a/VERSION b/VERSION
index 699094777..d9df1bbc0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.10.92
+0.11.0
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 057dac573..d4631c397 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -684,6 +684,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
int l2_index, ret;
uint64_t l2_offset, *l2_table, cluster_offset;
int nb_clusters, i = 0;
+ QCowL2Meta *old_alloc;
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
if (ret == 0)
@@ -732,6 +733,44 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
}
nb_clusters = i;
+ /*
+ * Check if there already is an AIO write request in flight which allocates
+ * the same cluster. In this case we need to wait until the previous
+ * request has completed and updated the L2 table accordingly.
+ */
+ LIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) {
+
+ uint64_t end_offset = offset + nb_clusters * s->cluster_size;
+ uint64_t old_offset = old_alloc->offset;
+ uint64_t old_end_offset = old_alloc->offset +
+ old_alloc->nb_clusters * s->cluster_size;
+
+ if (end_offset < old_offset || offset > old_end_offset) {
+ /* No intersection */
+ } else {
+ if (offset < old_offset) {
+ /* Stop at the start of a running allocation */
+ nb_clusters = (old_offset - offset) >> s->cluster_bits;
+ } else {
+ nb_clusters = 0;
+ }
+
+ if (nb_clusters == 0) {
+ /* Set dependency and wait for a callback */
+ m->depends_on = old_alloc;
+ m->nb_clusters = 0;
+ *num = 0;
+ return 0;
+ }
+ }
+ }
+
+ if (!nb_clusters) {
+ abort();
+ }
+
+ LIST_INSERT_HEAD(&s->cluster_allocs, m, next_in_flight);
+
/* allocate a new cluster */
cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
diff --git a/block/qcow2.c b/block/qcow2.c
index a5bf20522..dd32ea207 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -219,6 +219,8 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
if (qcow2_refcount_init(bs) < 0)
goto fail;
+ LIST_INIT(&s->cluster_allocs);
+
/* read qcow2 extensions */
if (header.backing_file_offset)
ext_end = header.backing_file_offset;
@@ -338,6 +340,7 @@ typedef struct QCowAIOCB {
QEMUIOVector hd_qiov;
QEMUBH *bh;
QCowL2Meta l2meta;
+ LIST_ENTRY(QCowAIOCB) next_depend;
} QCowAIOCB;
static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
@@ -500,6 +503,7 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
acb->n = 0;
acb->cluster_offset = 0;
acb->l2meta.nb_clusters = 0;
+ LIST_INIT(&acb->l2meta.dependent_requests);
return acb;
}
@@ -517,6 +521,33 @@ static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
return &acb->common;
}
+static void qcow_aio_write_cb(void *opaque, int ret);
+
+static void run_dependent_requests(QCowL2Meta *m)
+{
+ QCowAIOCB *req;
+ QCowAIOCB *next;
+
+ /* Take the request off the list of running requests */
+ if (m->nb_clusters != 0) {
+ LIST_REMOVE(m, next_in_flight);
+ }
+
+ /*
+ * Restart all dependent requests.
+ * Can't use LIST_FOREACH here - the next link might not be the same
+ * any more after the callback (request could depend on a different
+ * request now)
+ */
+ for (req = m->dependent_requests.lh_first; req != NULL; req = next) {
+ next = req->next_depend.le_next;
+ qcow_aio_write_cb(req, 0);
+ }
+
+ /* Empty the list for the next part of the request */
+ LIST_INIT(&m->dependent_requests);
+}
+
static void qcow_aio_write_cb(void *opaque, int ret)
{
QCowAIOCB *acb = opaque;
@@ -528,14 +559,15 @@ static void qcow_aio_write_cb(void *opaque, int ret)
acb->hd_aiocb = NULL;
+ if (ret >= 0) {
+ ret = qcow2_alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta);
+ }
+
+ run_dependent_requests(&acb->l2meta);
+
if (ret < 0)
goto done;
- if (qcow2_alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta) < 0) {
- qcow2_free_any_clusters(bs, acb->cluster_offset, acb->l2meta.nb_clusters);
- goto done;
- }
-
acb->nb_sectors -= acb->n;
acb->sector_num += acb->n;
acb->buf += acb->n * 512;
@@ -555,6 +587,14 @@ static void qcow_aio_write_cb(void *opaque, int ret)
acb->cluster_offset = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9,
index_in_cluster,
n_end, &acb->n, &acb->l2meta);
+
+ /* Need to wait for another request? If so, we are done for now. */
+ if (!acb->cluster_offset && acb->l2meta.depends_on != NULL) {
+ LIST_INSERT_HEAD(&acb->l2meta.depends_on->dependent_requests,
+ acb, next_depend);
+ return;
+ }
+
if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) {
ret = -EIO;
goto done;
diff --git a/block/qcow2.h b/block/qcow2.h
index c99b374bd..965a2f45c 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -98,6 +98,7 @@ typedef struct BDRVQcowState {
uint8_t *cluster_cache;
uint8_t *cluster_data;
uint64_t cluster_cache_offset;
+ LIST_HEAD(QCowClusterAlloc, QCowL2Meta) cluster_allocs;
uint64_t *refcount_table;
uint64_t refcount_table_offset;
@@ -128,6 +129,8 @@ typedef struct QCowCreateState {
int64_t refcount_block_offset;
} QCowCreateState;
+struct QCowAIOCB;
+
/* XXX This could be private for qcow2-cluster.c */
typedef struct QCowL2Meta
{
@@ -135,6 +138,10 @@ typedef struct QCowL2Meta
int n_start;
int nb_available;
int nb_clusters;
+ struct QCowL2Meta *depends_on;
+ LIST_HEAD(QCowAioDependencies, QCowAIOCB) dependent_requests;
+
+ LIST_ENTRY(QCowL2Meta) next_in_flight;
} QCowL2Meta;
static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
diff --git a/cmd.c b/cmd.c
index f3f438564..d86ba7ccb 100644
--- a/cmd.c
+++ b/cmd.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <sys/time.h>
#include "cmd.h"
@@ -283,6 +284,26 @@ fetchline(void)
}
#endif
+static char *qemu_strsep(char **input, const char *delim)
+{
+ char *result = *input;
+ if (result != NULL) {
+ char *p = result;
+ for (p = result; *p != '\0'; p++) {
+ if (strchr(delim, *p)) {
+ break;
+ }
+ }
+ if (*p == '\0') {
+ *input = NULL;
+ } else {
+ *p = '\0';
+ *input = p + 1;
+ }
+ }
+ return result;
+}
+
char **
breakline(
char *input,
@@ -292,7 +313,7 @@ breakline(
char *p;
char **rval = calloc(sizeof(char *), 1);
- while (rval && (p = strsep(&input, " ")) != NULL) {
+ while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
if (!*p)
continue;
c++;
diff --git a/configure b/configure
index c1adceab5..02afe65cd 100755
--- a/configure
+++ b/configure
@@ -1954,6 +1954,8 @@ if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
tools="qemu-img\$(EXESUF) $tools"
if [ "$linux" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) qemu-io\$(EXESUF) $tools"
+ elif test "$mingw32" = "yes" ; then
+ tools="qemu-io\$(EXESUF) $tools"
fi
fi
echo "TOOLS=$tools" >> $config_host_mak
diff --git a/curses.c b/curses.c
index 89680e6fb..3ce12b923 100644
--- a/curses.c
+++ b/curses.c
@@ -368,7 +368,4 @@ void curses_display_init(DisplayState *ds, int full_screen)
ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
invalidate = 1;
-
- /* Standard VGA initial text mode dimensions */
- curses_resize(ds);
}
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index bb005c801..cf5d46e97 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -7,6 +7,8 @@
* This code is licenced under the GPL.
*/
+#include "hw.h"
+#include "qemu-timer.h"
#include "sysbus.h"
#include "primecell.h"
#include "sysemu.h"
@@ -71,8 +73,7 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
case 0x58: /* BOOTCS */
return 0;
case 0x5c: /* 24MHz */
- /* ??? not implemented. */
- return 0;
+ return muldiv64(qemu_get_clock(vm_clock), 24000000, ticks_per_sec);
case 0x60: /* MISC */
return 0;
case 0x84: /* PROCID0 */
diff --git a/hw/escc.c b/hw/escc.c
index 2264f5d3a..1f7ec606a 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -743,8 +743,8 @@ int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
qdev_prop_set_uint32(dev, "chnAtype", ser);
qdev_init(dev);
s = sysbus_from_qdev(dev);
- sysbus_connect_irq(s, 0, irqA);
- sysbus_connect_irq(s, 1, irqB);
+ sysbus_connect_irq(s, 0, irqB);
+ sysbus_connect_irq(s, 1, irqA);
if (base) {
sysbus_mmio_map(s, 0, base);
}
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2022548f3..2b040a715 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -421,9 +421,10 @@ static void rtc_update_second2(void *opaque)
}
/* update ended interrupt */
+ s->cmos_data[RTC_REG_C] |= REG_C_UF;
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
- s->cmos_data[RTC_REG_C] |= 0x90;
- rtc_irq_raise(s->irq);
+ s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+ rtc_irq_raise(s->irq);
}
/* clear update in progress bit */
diff --git a/net.c b/net.c
index 61c96491d..a1c111140 100644
--- a/net.c
+++ b/net.c
@@ -470,34 +470,29 @@ qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size, int r
void qemu_purge_queued_packets(VLANClientState *vc)
{
- VLANPacket **pp = &vc->vlan->send_queue;
-
- while (*pp != NULL) {
- VLANPacket *packet = *pp;
+ VLANPacket *packet, *next;
+ TAILQ_FOREACH_SAFE(packet, &vc->vlan->send_queue, entry, next) {
if (packet->sender == vc) {
- *pp = packet->next;
+ TAILQ_REMOVE(&vc->vlan->send_queue, packet, entry);
qemu_free(packet);
- } else {
- pp = &packet->next;
}
}
}
void qemu_flush_queued_packets(VLANClientState *vc)
{
- VLANPacket *packet;
-
- while ((packet = vc->vlan->send_queue) != NULL) {
+ while (!TAILQ_EMPTY(&vc->vlan->send_queue)) {
+ VLANPacket *packet;
int ret;
- vc->vlan->send_queue = packet->next;
+ packet = TAILQ_FIRST(&vc->vlan->send_queue);
+ TAILQ_REMOVE(&vc->vlan->send_queue, packet, entry);
ret = qemu_deliver_packet(packet->sender, packet->data,
packet->size, packet->raw);
if (ret == 0 && packet->sent_cb != NULL) {
- packet->next = vc->vlan->send_queue;
- vc->vlan->send_queue = packet;
+ TAILQ_INSERT_HEAD(&vc->vlan->send_queue, packet, entry);
break;
}
@@ -515,13 +510,13 @@ static void qemu_enqueue_packet(VLANClientState *sender,
VLANPacket *packet;
packet = qemu_malloc(sizeof(VLANPacket) + size);
- packet->next = sender->vlan->send_queue;
packet->sender = sender;
packet->size = size;
packet->raw = raw;
packet->sent_cb = sent_cb;
memcpy(packet->data, buf, size);
- sender->vlan->send_queue = packet;
+
+ TAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry);
}
static ssize_t qemu_send_packet_async2(VLANClientState *sender,
@@ -645,7 +640,6 @@ static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender,
max_len = calc_iov_length(iov, iovcnt);
packet = qemu_malloc(sizeof(VLANPacket) + max_len);
- packet->next = sender->vlan->send_queue;
packet->sender = sender;
packet->sent_cb = sent_cb;
packet->size = 0;
@@ -658,7 +652,7 @@ static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender,
packet->size += len;
}
- sender->vlan->send_queue = packet;
+ TAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry);
return packet->size;
}
@@ -2530,6 +2524,7 @@ VLANState *qemu_find_vlan(int id, int allocate)
}
vlan = qemu_mallocz(sizeof(VLANState));
vlan->id = id;
+ TAILQ_INIT(&vlan->send_queue);
vlan->next = NULL;
pvlan = &first_vlan;
while (*pvlan != NULL)
diff --git a/net.h b/net.h
index b172691be..57ab031bf 100644
--- a/net.h
+++ b/net.h
@@ -1,6 +1,7 @@
#ifndef QEMU_NET_H
#define QEMU_NET_H
+#include "sys-queue.h"
#include "qemu-common.h"
/* VLANs support */
@@ -38,7 +39,7 @@ typedef struct VLANPacket VLANPacket;
typedef void (NetPacketSent) (VLANClientState *, ssize_t);
struct VLANPacket {
- struct VLANPacket *next;
+ TAILQ_ENTRY(VLANPacket) entry;
VLANClientState *sender;
int size;
int raw;
@@ -51,7 +52,7 @@ struct VLANState {
VLANClientState *first_client;
struct VLANState *next;
unsigned int nb_guest_devs, nb_host_devs;
- VLANPacket *send_queue;
+ TAILQ_HEAD(send_queue, VLANPacket) send_queue;
int delivering;
};
diff --git a/qemu-io.c b/qemu-io.c
index 880378c1b..cd9c9599c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -7,10 +7,12 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include <sys/time.h>
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <getopt.h>
+#include <libgen.h>
#include "qemu-common.h"
#include "block_int.h"
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1fc5119cb..049c2cdf6 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -526,14 +526,15 @@ static always_inline void gen_ext_h(void (*tcg_gen_ext_i64)(TCGv t0, TCGv t1),
else
tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
} else {
- TCGv tmp1, tmp2;
+ TCGv tmp1;
tmp1 = tcg_temp_new();
+
tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
tcg_gen_shli_i64(tmp1, tmp1, 3);
- tmp2 = tcg_const_i64(64);
- tcg_gen_sub_i64(tmp1, tmp2, tmp1);
- tcg_temp_free(tmp2);
+ tcg_gen_neg_i64(tmp1, tmp1);
+ tcg_gen_andi_i64(tmp1, tmp1, 0x3f);
tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
+
tcg_temp_free(tmp1);
}
if (tcg_gen_ext_i64)
@@ -1320,7 +1321,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
break;
case 0x6A:
/* EXTLH */
- gen_ext_h(&tcg_gen_ext16u_i64, ra, rb, rc, islit, lit);
+ gen_ext_h(&tcg_gen_ext32u_i64, ra, rb, rc, islit, lit);
break;
case 0x72:
/* MSKQH */
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index f3f2f711f..7cb693414 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -1441,9 +1441,8 @@ static inline void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
#ifdef TCG_TARGET_HAS_bswap64_i64
tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
#else
- TCGv_i32 t0, t1;
- t0 = tcg_temp_new_i32();
- t1 = tcg_temp_new_i32();
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
tcg_gen_shli_i64(t0, arg, 56);
@@ -1473,8 +1472,8 @@ static inline void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
tcg_gen_shri_i64(t1, arg, 56);
tcg_gen_or_i64(ret, t0, t1);
- tcg_temp_free_i32(t0);
- tcg_temp_free_i32(t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
#endif
}