aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--Makefile.objs22
-rw-r--r--Makefile.target4
-rwxr-xr-xQMP/qom-fuse138
-rw-r--r--async.c2
-rw-r--r--audio/paaudio.c3
-rw-r--r--balloon.c2
-rw-r--r--block.c35
-rw-r--r--block/nbd.c2
-rw-r--r--block/stream.c22
-rw-r--r--block_int.h19
-rw-r--r--blockdev.c26
-rwxr-xr-xconfigure8
-rw-r--r--fpu/softfloat-macros.h18
-rw-r--r--fpu/softfloat.c122
-rw-r--r--fpu/softfloat.h13
-rw-r--r--hmp-commands.hx8
-rw-r--r--hmp.c4
-rw-r--r--hw/e1000.c167
-rw-r--r--hw/e1000_hw.h12
-rw-r--r--hw/eepro100.c28
-rw-r--r--hw/hda-audio.c243
-rw-r--r--hw/highbank.c15
-rw-r--r--hw/pc_sysfw.c8
-rw-r--r--hw/usb/core.c1
-rw-r--r--hw/usb/desc.c32
-rw-r--r--hw/usb/desc.h1
-rw-r--r--hw/usb/dev-audio.c1
-rw-r--r--hw/usb/dev-bluetooth.c1
-rw-r--r--hw/usb/dev-hub.c1
-rw-r--r--hw/usb/dev-network.c1
-rw-r--r--hw/usb/dev-serial.c1
-rw-r--r--hw/usb/dev-smartcard-reader.c1
-rw-r--r--hw/usb/dev-storage.c6
-rw-r--r--hw/usb/dev-wacom.c1
-rw-r--r--hw/usb/hcd-ehci.c23
-rw-r--r--hw/usb/hcd-uhci.c1
-rw-r--r--hw/usb/hcd-xhci.c192
-rw-r--r--hw/usb/host-linux.c12
-rw-r--r--hw/usb/redirect.c9
-rw-r--r--hw/virtio-serial-bus.c57
-rw-r--r--hw/virtio.c11
-rw-r--r--main-loop.c30
-rw-r--r--main-loop.h2
-rw-r--r--os-posix.c4
-rw-r--r--osdep.h7
-rw-r--r--pc-bios/qemu-icon.bmpbin0 -> 630 bytes
-rw-r--r--qapi-schema.json12
-rw-r--r--qemu-barrier.h35
-rw-r--r--qemu-timer.c127
-rw-r--r--qemu-timer.h14
-rw-r--r--qemu-tool.c4
-rw-r--r--qmp-commands.hx4
-rw-r--r--rules.mak3
-rw-r--r--slirp/libslirp.h1
-rw-r--r--slirp/slirp.c7
-rw-r--r--target-arm/cpu-qom.h2
-rw-r--r--target-arm/cpu.c6
-rw-r--r--target-arm/cpu.h7
-rw-r--r--target-arm/helper.c4
-rw-r--r--target-arm/translate.c8
-rw-r--r--target-i386/cpu.c318
-rw-r--r--target-i386/cpu.h2
-rw-r--r--target-i386/helper.c2
-rw-r--r--target-mips/cpu.h7
-rw-r--r--tests/libqtest.c7
-rwxr-xr-xtests/qemu-iotests/03085
-rw-r--r--tests/qemu-iotests/030.out4
68 files changed, 1415 insertions, 569 deletions
diff --git a/Makefile b/Makefile
index 4f43793866..08ec7586a3 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@ ifeq ($(TRACE_BACKEND),dtrace)
GENERATED_HEADERS += trace-dtrace.h
endif
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
-GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c trace.c
# Don't try to regenerate Makefile or configure
# We don't generate any of them
@@ -220,11 +220,11 @@ clean:
rm -f qom/*.o qom/*.d
rm -f qemu-img-cmds.h
rm -f trace/*.o trace/*.d
- rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
+ @# May not be present in GENERATED_HEADERS
rm -f trace-dtrace.h trace-dtrace.h-timestamp
- rm -f $(GENERATED_HEADERS)
- rm -f $(GENERATED_SOURCES)
+ rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp)
+ rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
rm -rf $(qapi-dir)
$(MAKE) -C tests/tcg clean
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
@@ -257,6 +257,7 @@ vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
+qemu-icon.bmp \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
mpc8544ds.dtb \
multiboot.bin linuxboot.bin kvmvapic.bin \
diff --git a/Makefile.objs b/Makefile.objs
index 6d6f24d9d3..70c5c79a6e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -373,17 +373,22 @@ libdis-$(CONFIG_LM32_DIS) += lm32-dis.o
# trace
ifeq ($(TRACE_BACKEND),dtrace)
-trace.h: trace.h-timestamp trace-dtrace.h
-else
-trace.h: trace.h-timestamp
+TRACE_H_EXTRA_DEPS=trace-dtrace.h
endif
+trace.h: trace.h-timestamp $(TRACE_H_EXTRA_DEPS)
trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h")
+ $(call quiet-command,$(TRACETOOL) \
+ --format=h \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN trace.h")
@cmp -s $@ trace.h || cp $@ trace.h
trace.c: trace.c-timestamp
trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c")
+ $(call quiet-command,$(TRACETOOL) \
+ --format=c \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN trace.c")
@cmp -s $@ trace.c || cp $@ trace.c
trace.o: trace.c $(GENERATED_HEADERS)
@@ -396,11 +401,14 @@ trace-dtrace.h: trace-dtrace.dtrace
# rule file. So we use '.dtrace' instead
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace")
+ $(call quiet-command,$(TRACETOOL) \
+ --format=d \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN trace-dtrace.dtrace")
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
- $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
+ $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
ifeq ($(LIBTOOL),)
trace-dtrace.lo: trace-dtrace.dtrace
diff --git a/Makefile.target b/Makefile.target
index 364aea2f5c..af1cdbc4ab 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -59,13 +59,13 @@ TARGET_TYPE=system
endif
$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \
+ $(call quiet-command,$(TRACETOOL) \
--format=stap \
--backend=$(TRACE_BACKEND) \
--binary=$(bindir)/$(QEMU_PROG) \
--target-arch=$(TARGET_ARCH) \
--target-type=$(TARGET_TYPE) \
- < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp")
+ < $< > $@," GEN $(QEMU_PROG).stp")
else
stap:
endif
diff --git a/QMP/qom-fuse b/QMP/qom-fuse
new file mode 100755
index 0000000000..5c6754aa63
--- /dev/null
+++ b/QMP/qom-fuse
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+##
+# QEMU Object Model test tools
+#
+# Copyright IBM, Corp. 2012
+#
+# Authors:
+# Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later. See
+# the COPYING file in the top-level directory.
+##
+
+import fuse, stat
+from fuse import Fuse
+import os, posix
+from errno import *
+from qmp import QEMUMonitorProtocol
+
+fuse.fuse_python_api = (0, 2)
+
+class QOMFS(Fuse):
+ def __init__(self, qmp, *args, **kwds):
+ Fuse.__init__(self, *args, **kwds)
+ self.qmp = qmp
+ self.qmp.connect()
+ self.ino_map = {}
+ self.ino_count = 1
+
+ def get_ino(self, path):
+ if self.ino_map.has_key(path):
+ return self.ino_map[path]
+ self.ino_map[path] = self.ino_count
+ self.ino_count += 1
+ return self.ino_map[path]
+
+ def is_object(self, path):
+ try:
+ items = self.qmp.command('qom-list', path=path)
+ return True
+ except:
+ return False
+
+ def is_property(self, path):
+ try:
+ path, prop = path.rsplit('/', 1)
+ for item in self.qmp.command('qom-list', path=path):
+ if item['name'] == prop:
+ return True
+ return False
+ except:
+ return False
+
+ def is_link(self, path):
+ try:
+ path, prop = path.rsplit('/', 1)
+ for item in self.qmp.command('qom-list', path=path):
+ if item['name'] == prop:
+ if item['type'].startswith('link<'):
+ return True
+ return False
+ return False
+ except:
+ return False
+
+ def read(self, path, length, offset):
+ if not self.is_property(path):
+ return -ENOENT
+
+ path, prop = path.rsplit('/', 1)
+ try:
+ data = str(self.qmp.command('qom-get', path=path, property=prop))
+ data += '\n' # make values shell friendly
+ except:
+ return -EPERM
+
+ if offset > len(data):
+ return ''
+
+ return str(data[offset:][:length])
+
+ def readlink(self, path):
+ if not self.is_link(path):
+ return False
+ path, prop = path.rsplit('/', 1)
+ prefix = '/'.join(['..'] * (len(path.split('/')) - 1))
+ return prefix + str(self.qmp.command('qom-get', path=path,
+ property=prop))
+
+ def getattr(self, path):
+ if self.is_link(path):
+ value = posix.stat_result((0755 | stat.S_IFLNK,
+ self.get_ino(path),
+ 0,
+ 2,
+ 1000,
+ 1000,
+ 4096,
+ 0,
+ 0,
+ 0))
+ elif self.is_object(path):
+ value = posix.stat_result((0755 | stat.S_IFDIR,
+ self.get_ino(path),
+ 0,
+ 2,
+ 1000,
+ 1000,
+ 4096,
+ 0,
+ 0,
+ 0))
+ elif self.is_property(path):
+ value = posix.stat_result((0644 | stat.S_IFREG,
+ self.get_ino(path),
+ 0,
+ 1,
+ 1000,
+ 1000,
+ 4096,
+ 0,
+ 0,
+ 0))
+ else:
+ value = -ENOENT
+ return value
+
+ def readdir(self, path, offset):
+ yield fuse.Direntry('.')
+ yield fuse.Direntry('..')
+ for item in self.qmp.command('qom-list', path=path):
+ yield fuse.Direntry(str(item['name']))
+
+if __name__ == '__main__':
+ import sys, os
+
+ fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET']))
+ fs.main(sys.argv)
diff --git a/async.c b/async.c
index 332d511ed5..ecdaf15887 100644
--- a/async.c
+++ b/async.c
@@ -120,7 +120,7 @@ void qemu_bh_delete(QEMUBH *bh)
bh->deleted = 1;
}
-void qemu_bh_update_timeout(int *timeout)
+void qemu_bh_update_timeout(uint32_t *timeout)
{
QEMUBH *bh;
diff --git a/audio/paaudio.c b/audio/paaudio.c
index e6708d0db5..aa15f16ec7 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -505,8 +505,7 @@ fail:
pa_stream_unref (stream);
}
- qpa_logerr (pa_context_errno (g->context),
- "stream_new() failed\n");
+ *rerror = pa_context_errno (g->context);
return NULL;
}
diff --git a/balloon.c b/balloon.c
index 0166744aa8..aa354f7554 100644
--- a/balloon.c
+++ b/balloon.c
@@ -108,7 +108,7 @@ void qmp_balloon(int64_t value, Error **errp)
}
if (value <= 0) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size");
return;
}
diff --git a/block.c b/block.c
index fe74dddb13..43c794c4d7 100644
--- a/block.c
+++ b/block.c
@@ -4083,11 +4083,13 @@ out:
}
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque)
+ int64_t speed, BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp)
{
BlockJob *job;
if (bs->job || bdrv_in_use(bs)) {
+ error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
return NULL;
}
bdrv_set_in_use(bs, 1);
@@ -4098,6 +4100,20 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
job->cb = cb;
job->opaque = opaque;
bs->job = job;
+
+ /* Only set speed when necessary to avoid NotSupported error */
+ if (speed != 0) {
+ Error *local_err = NULL;
+
+ block_job_set_speed(job, speed, &local_err);
+ if (error_is_set(&local_err)) {
+ bs->job = NULL;
+ g_free(job);
+ bdrv_set_in_use(bs, 0);
+ error_propagate(errp, local_err);
+ return NULL;
+ }
+ }
return job;
}
@@ -4112,18 +4128,21 @@ void block_job_complete(BlockJob *job, int ret)
bdrv_set_in_use(bs, 0);
}
-int block_job_set_speed(BlockJob *job, int64_t value)
+void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
- int rc;
+ Error *local_err = NULL;
if (!job->job_type->set_speed) {
- return -ENOTSUP;
+ error_set(errp, QERR_NOT_SUPPORTED);
+ return;
}
- rc = job->job_type->set_speed(job, value);
- if (rc == 0) {
- job->speed = value;
+ job->job_type->set_speed(job, speed, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
}
- return rc;
+
+ job->speed = speed;
}
void block_job_cancel(BlockJob *job)
diff --git a/block/nbd.c b/block/nbd.c
index 56dbf6ef86..1212614223 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -284,7 +284,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
/* Now that we're connected, set the socket to be non-blocking and
* kick the reply mechanism. */
socket_set_nonblock(sock);
- qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
+ qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
nbd_have_request, s);
s->sock = sock;
diff --git a/block/stream.c b/block/stream.c
index 0efe1adfd5..6724af2764 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -263,15 +263,15 @@ retry:
block_job_complete(&s->common, ret);
}
-static int stream_set_speed(BlockJob *job, int64_t value)
+static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
StreamBlockJob *s = container_of(job, StreamBlockJob, common);
- if (value < 0) {
- return -EINVAL;
+ if (speed < 0) {
+ error_set(errp, QERR_INVALID_PARAMETER, "speed");
+ return;
}
- ratelimit_set_speed(&s->limit, value / BDRV_SECTOR_SIZE);
- return 0;
+ ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE);
}
static BlockJobType stream_job_type = {
@@ -280,16 +280,17 @@ static BlockJobType stream_job_type = {
.set_speed = stream_set_speed,
};
-int stream_start(BlockDriverState *bs, BlockDriverState *base,
- const char *base_id, BlockDriverCompletionFunc *cb,
- void *opaque)
+void stream_start(BlockDriverState *bs, BlockDriverState *base,
+ const char *base_id, int64_t speed,
+ BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp)
{
StreamBlockJob *s;
Coroutine *co;
- s = block_job_create(&stream_job_type, bs, cb, opaque);
+ s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp);
if (!s) {
- return -EBUSY; /* bs must already be in use */
+ return;
}
s->base = base;
@@ -300,5 +301,4 @@ int stream_start(BlockDriverState *bs, BlockDriverState *base,
co = qemu_coroutine_create(stream_run);
trace_stream_start(bs, base, s, co, opaque);
qemu_coroutine_enter(co, s);
- return 0;
}
diff --git a/block_int.h b/block_int.h
index 0acb49f100..086832aab9 100644
--- a/block_int.h
+++ b/block_int.h
@@ -79,7 +79,7 @@ typedef struct BlockJobType {
const char *job_type;
/** Optional callback for job types that support setting a speed limit */
- int (*set_speed)(BlockJob *job, int64_t value);
+ void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
} BlockJobType;
/**
@@ -344,8 +344,10 @@ int is_windows_drive(const char *filename);
* block_job_create:
* @job_type: The class object for the newly-created job.
* @bs: The block
+ * @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
+ * @errp: Error object.
*
* Create a new long-running block device job and return it. The job
* will call @cb asynchronously when the job completes. Note that
@@ -357,7 +359,8 @@ int is_windows_drive(const char *filename);
* called from a wrapper that is specific to the job type.
*/
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque);
+ int64_t speed, BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp);
/**
* block_job_complete:
@@ -373,11 +376,12 @@ void block_job_complete(BlockJob *job, int ret);
* block_job_set_speed:
* @job: The job to set the speed for.
* @speed: The new value
+ * @errp: Error object.
*
* Set a rate-limiting parameter for the job; the actual meaning may
* vary depending on the job type.
*/
-int block_job_set_speed(BlockJob *job, int64_t value);
+void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
/**
* block_job_cancel:
@@ -415,8 +419,10 @@ void block_job_cancel_sync(BlockJob *job);
* flatten the whole backing file chain onto @bs.
* @base_id: The file name that will be written to @bs as the new
* backing file if the job completes. Ignored if @base is %NULL.
+ * @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
+ * @errp: Error object.
*
* Start a streaming operation on @bs. Clusters that are unallocated
* in @bs, but allocated in any image between @base and @bs (both
@@ -424,8 +430,9 @@ void block_job_cancel_sync(BlockJob *job);
* streaming job, the backing file of @bs will be changed to
* @base_id in the written image and to @base in the live BlockDriverState.
*/
-int stream_start(BlockDriverState *bs, BlockDriverState *base,
- const char *base_id, BlockDriverCompletionFunc *cb,
- void *opaque);
+void stream_start(BlockDriverState *bs, BlockDriverState *base,
+ const char *base_id, int64_t speed,
+ BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp);
#endif /* BLOCK_INT_H */
diff --git a/blockdev.c b/blockdev.c
index 0c2440e249..d25ffea926 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1091,11 +1091,12 @@ static void block_stream_cb(void *opaque, int ret)
}
void qmp_block_stream(const char *device, bool has_base,
- const char *base, Error **errp)
+ const char *base, bool has_speed,
+ int64_t speed, Error **errp)
{
BlockDriverState *bs;
BlockDriverState *base_bs = NULL;
- int ret;
+ Error *local_err = NULL;
bs = bdrv_find(device);
if (!bs) {
@@ -1111,16 +1112,11 @@ void qmp_block_stream(const char *device, bool has_base,
}
}
- ret = stream_start(bs, base_bs, base, block_stream_cb, bs);
- if (ret < 0) {
- switch (ret) {
- case -EBUSY:
- error_set(errp, QERR_DEVICE_IN_USE, device);
- return;
- default:
- error_set(errp, QERR_NOT_SUPPORTED);
- return;
- }
+ stream_start(bs, base_bs, base, has_speed ? speed : 0,
+ block_stream_cb, bs, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
}
/* Grab a reference so hotplug does not delete the BlockDriverState from
@@ -1142,7 +1138,7 @@ static BlockJob *find_block_job(const char *device)
return bs->job;
}
-void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp)
+void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
{
BlockJob *job = find_block_job(device);
@@ -1151,9 +1147,7 @@ void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp)
return;
}
- if (block_job_set_speed(job, value) < 0) {
- error_set(errp, QERR_NOT_SUPPORTED);
- }
+ block_job_set_speed(job, speed, errp);
}
void qmp_block_job_cancel(const char *device, Error **errp)
diff --git a/configure b/configure
index dd09f1a18f..25697bb590 100755
--- a/configure
+++ b/configure
@@ -498,8 +498,8 @@ esac
if [ "$bsd" = "yes" ] ; then
if [ "$darwin" != "yes" ] ; then
usb="bsd"
+ bsd_user="yes"
fi
- bsd_user="yes"
fi
: ${make=${MAKE-make}}
@@ -2898,11 +2898,9 @@ tools=
if test "$softmmu" = yes ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
if test "$virtfs" != no ; then
- if test "$linux" = yes && test "$attr" = yes ; then
+ if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then
virtfs=yes
- if test "$cap" = yes ; then
- tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
- fi
+ tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
else
if test "$virtfs" = yes; then
feature_not_found "virtfs"
diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index e82ce2332d..b5164af7fa 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -55,7 +55,7 @@ these four paragraphs for those parts of this code that are retained.
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
-INLINE void shift32RightJamming( uint32_t a, int16 count, uint32_t *zPtr )
+INLINE void shift32RightJamming(uint32_t a, int_fast16_t count, uint32_t *zPtr)
{
uint32_t z;
@@ -81,7 +81,7 @@ INLINE void shift32RightJamming( uint32_t a, int16 count, uint32_t *zPtr )
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
-INLINE void shift64RightJamming( uint64_t a, int16 count, uint64_t *zPtr )
+INLINE void shift64RightJamming(uint64_t a, int_fast16_t count, uint64_t *zPtr)
{
uint64_t z;
@@ -117,7 +117,7 @@ INLINE void shift64RightJamming( uint64_t a, int16 count, uint64_t *zPtr )
INLINE void
shift64ExtraRightJamming(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
uint64_t z0, z1;
int8 negCount = ( - count ) & 63;
@@ -154,7 +154,7 @@ INLINE void
INLINE void
shift128Right(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
uint64_t z0, z1;
int8 negCount = ( - count ) & 63;
@@ -189,7 +189,7 @@ INLINE void
INLINE void
shift128RightJamming(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
uint64_t z0, z1;
int8 negCount = ( - count ) & 63;
@@ -243,7 +243,7 @@ INLINE void
uint64_t a0,
uint64_t a1,
uint64_t a2,
- int16 count,
+ int_fast16_t count,
uint64_t *z0Ptr,
uint64_t *z1Ptr,
uint64_t *z2Ptr
@@ -298,7 +298,7 @@ INLINE void
INLINE void
shortShift128Left(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
*z1Ptr = a1<<count;
@@ -320,7 +320,7 @@ INLINE void
uint64_t a0,
uint64_t a1,
uint64_t a2,
- int16 count,
+ int_fast16_t count,
uint64_t *z0Ptr,
uint64_t *z1Ptr,
uint64_t *z2Ptr
@@ -591,7 +591,7 @@ static uint64_t estimateDiv128To64( uint64_t a0, uint64_t a1, uint64_t b )
| value.
*----------------------------------------------------------------------------*/
-static uint32_t estimateSqrt32( int16 aExp, uint32_t a )
+static uint32_t estimateSqrt32(int_fast16_t aExp, uint32_t a)
{
static const uint16_t sqrtOddAdjustments[] = {
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 9e1b5f9cab..b29256a8eb 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -87,7 +87,7 @@ INLINE uint32_t extractFloat16Frac(float16 a)
| Returns the exponent bits of the half-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-INLINE int16 extractFloat16Exp(float16 a)
+INLINE int_fast16_t extractFloat16Exp(float16 a)
{
return (float16_val(a) >> 10) & 0x1f;
}
@@ -218,7 +218,7 @@ INLINE uint32_t extractFloat32Frac( float32 a )
| Returns the exponent bits of the single-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-INLINE int16 extractFloat32Exp( float32 a )
+INLINE int_fast16_t extractFloat32Exp(float32 a)
{
return ( float32_val(a)>>23 ) & 0xFF;
@@ -259,7 +259,7 @@ static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
*----------------------------------------------------------------------------*/
static void
- normalizeFloat32Subnormal( uint32_t aSig, int16 *zExpPtr, uint32_t *zSigPtr )
+ normalizeFloat32Subnormal(uint32_t aSig, int_fast16_t *zExpPtr, uint32_t *zSigPtr)
{
int8 shiftCount;
@@ -280,7 +280,7 @@ static void
| significand.
*----------------------------------------------------------------------------*/
-INLINE float32 packFloat32( flag zSign, int16 zExp, uint32_t zSig )
+INLINE float32 packFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig)
{
return make_float32(
@@ -310,7 +310,7 @@ INLINE float32 packFloat32( flag zSign, int16 zExp, uint32_t zSig )
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float32 roundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM)
+static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig STATUS_PARAM)
{
int8 roundingMode;
flag roundNearestEven;
@@ -376,7 +376,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS
*----------------------------------------------------------------------------*/
static float32
- normalizeRoundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM)
+ normalizeRoundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig STATUS_PARAM)
{
int8 shiftCount;
@@ -400,7 +400,7 @@ INLINE uint64_t extractFloat64Frac( float64 a )
| Returns the exponent bits of the double-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-INLINE int16 extractFloat64Exp( float64 a )
+INLINE int_fast16_t extractFloat64Exp(float64 a)
{
return ( float64_val(a)>>52 ) & 0x7FF;
@@ -441,7 +441,7 @@ static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
*----------------------------------------------------------------------------*/
static void
- normalizeFloat64Subnormal( uint64_t aSig, int16 *zExpPtr, uint64_t *zSigPtr )
+ normalizeFloat64Subnormal(uint64_t aSig, int_fast16_t *zExpPtr, uint64_t *zSigPtr)
{
int8 shiftCount;
@@ -462,7 +462,7 @@ static void
| significand.
*----------------------------------------------------------------------------*/
-INLINE float64 packFloat64( flag zSign, int16 zExp, uint64_t zSig )
+INLINE float64 packFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig)
{
return make_float64(
@@ -492,11 +492,11 @@ INLINE float64 packFloat64( flag zSign, int16 zExp, uint64_t zSig )
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float64 roundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM)
+static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig STATUS_PARAM)
{
int8 roundingMode;
flag roundNearestEven;
- int16 roundIncrement, roundBits;
+ int_fast16_t roundIncrement, roundBits;
flag isTiny;
roundingMode = STATUS(float_rounding_mode);
@@ -558,7 +558,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS
*----------------------------------------------------------------------------*/
static float64
- normalizeRoundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM)
+ normalizeRoundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig STATUS_PARAM)
{
int8 shiftCount;
@@ -1345,7 +1345,7 @@ float128 int64_to_float128( int64 a STATUS_PARAM )
int32 float32_to_int32( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
uint64_t aSig64;
@@ -1376,7 +1376,7 @@ int32 float32_to_int32( float32 a STATUS_PARAM )
int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
int32_t z;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -1416,10 +1416,10 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
| returned.
*----------------------------------------------------------------------------*/
-int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
+int_fast16_t float32_to_int16_round_to_zero(float32 a STATUS_PARAM)
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
int32 z;
@@ -1468,7 +1468,7 @@ int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
int64 float32_to_int64( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
uint64_t aSig64, aSigExtra;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -1505,7 +1505,7 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
uint64_t aSig64;
int64 z;
@@ -1549,7 +1549,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
float64 float32_to_float64( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -1579,7 +1579,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -1609,7 +1609,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
float128 float32_to_float128( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -1639,7 +1639,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
float32 float32_round_to_int( float32 a STATUS_PARAM)
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t lastBitMask, roundBitsMask;
int8 roundingMode;
uint32_t z;
@@ -1699,9 +1699,9 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1778,9 +1778,9 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1898,7 +1898,7 @@ float32 float32_sub( float32 a, float32 b STATUS_PARAM )
float32 float32_mul( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig;
uint64_t zSig64;
uint32_t zSig;
@@ -1961,7 +1961,7 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM )
float32 float32_div( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig, zSig;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
@@ -2025,7 +2025,7 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM )
float32 float32_rem( float32 a, float32 b STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp, bExp, expDiff;
+ int_fast16_t aExp, bExp, expDiff;
uint32_t aSig, bSig;
uint32_t q;
uint64_t aSig64, bSig64, q64;
@@ -2131,7 +2131,7 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM)
{
flag aSign, bSign, cSign, zSign;
- int aExp, bExp, cExp, pExp, zExp, expDiff;
+ int_fast16_t aExp, bExp, cExp, pExp, zExp, expDiff;
uint32_t aSig, bSig, cSig;
flag pInf, pZero, pSign;
uint64_t pSig64, cSig64, zSig64;
@@ -2333,7 +2333,7 @@ float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM)
float32 float32_sqrt( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, zExp;
+ int_fast16_t aExp, zExp;
uint32_t aSig, zSig;
uint64_t rem, term;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -2419,7 +2419,7 @@ static const float64 float32_exp2_coefficients[15] =
float32 float32_exp2( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
float64 r, x, xn;
int i;
@@ -2467,7 +2467,7 @@ float32 float32_exp2( float32 a STATUS_PARAM )
float32 float32_log2( float32 a STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig, zSig, i;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -2732,7 +2732,7 @@ int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM )
int32 float64_to_int32( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -2760,7 +2760,7 @@ int32 float64_to_int32( float64 a STATUS_PARAM )
int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig, savedASig;
int32_t z;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -2804,10 +2804,10 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
| returned.
*----------------------------------------------------------------------------*/
-int16 float64_to_int16_round_to_zero( float64 a STATUS_PARAM )
+int_fast16_t float64_to_int16_round_to_zero(float64 a STATUS_PARAM)
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig, savedASig;
int32 z;
@@ -2858,7 +2858,7 @@ int16 float64_to_int16_round_to_zero( float64 a STATUS_PARAM )
int64 float64_to_int64( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig, aSigExtra;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -2901,7 +2901,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM )
int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig;
int64 z;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -2951,7 +2951,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
float32 float64_to_float32( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig;
uint32_t zSig;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -2984,7 +2984,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
| than the desired result exponent whenever `zSig' is a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
-static float16 packFloat16(flag zSign, int16 zExp, uint16_t zSig)
+static float16 packFloat16(flag zSign, int_fast16_t zExp, uint16_t zSig)
{
return make_float16(
(((uint32_t)zSign) << 15) + (((uint32_t)zExp) << 10) + zSig);
@@ -2996,7 +2996,7 @@ static float16 packFloat16(flag zSign, int16 zExp, uint16_t zSig)
float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
aSign = extractFloat16Sign(a);
@@ -3026,7 +3026,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
uint32_t mask;
uint32_t increment;
@@ -3127,7 +3127,7 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3158,7 +3158,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
float128 float64_to_float128( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig, zSig0, zSig1;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3189,7 +3189,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
float64 float64_round_to_int( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t lastBitMask, roundBitsMask;
int8 roundingMode;
uint64_t z;
@@ -3262,9 +3262,9 @@ float64 float64_trunc_to_int( float64 a STATUS_PARAM)
static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -3341,9 +3341,9 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -3461,7 +3461,7 @@ float64 float64_sub( float64 a, float64 b STATUS_PARAM )
float64 float64_mul( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig0, zSig1;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3522,7 +3522,7 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM )
float64 float64_div( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig;
uint64_t rem0, rem1;
uint64_t term0, term1;
@@ -3594,7 +3594,7 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM )
float64 float64_rem( float64 a, float64 b STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp, bExp, expDiff;
+ int_fast16_t aExp, bExp, expDiff;
uint64_t aSig, bSig;
uint64_t q, alternateASig;
int64_t sigMean;
@@ -3685,7 +3685,7 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM )
float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM)
{
flag aSign, bSign, cSign, zSign;
- int aExp, bExp, cExp, pExp, zExp, expDiff;
+ int_fast16_t aExp, bExp, cExp, pExp, zExp, expDiff;
uint64_t aSig, bSig, cSig;
flag pInf, pZero, pSign;
uint64_t pSig0, pSig1, cSig0, cSig1, zSig0, zSig1;
@@ -3900,7 +3900,7 @@ float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM)
float64 float64_sqrt( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, zExp;
+ int_fast16_t aExp, zExp;
uint64_t aSig, zSig, doubleZSig;
uint64_t rem0, rem1, term0, term1;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -3951,7 +3951,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
float64 float64_log2( float64 a STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig, aSig0, aSig1, zSig, i;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -4428,7 +4428,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig, zSig0, zSig1;
aSig = extractFloatx80Frac( a );
@@ -6443,10 +6443,10 @@ uint32 float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
return res;
}
-uint16 float32_to_uint16_round_to_zero( float32 a STATUS_PARAM )
+uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
{
int64_t v;
- uint16 res;
+ uint_fast16_t res;
v = float32_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
@@ -6497,10 +6497,10 @@ uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
return res;
}
-uint16 float64_to_uint16_round_to_zero( float64 a STATUS_PARAM )
+uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
{
int64_t v;
- uint16 res;
+ uint_fast16_t res;
v = float64_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 2ce4110c07..feec3a180e 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -44,6 +44,7 @@ these four paragraphs for those parts of this code that are retained.
#include <inttypes.h>
#include "config-host.h"
+#include "osdep.h"
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines the most convenient type that holds
@@ -56,10 +57,6 @@ these four paragraphs for those parts of this code that are retained.
typedef uint8_t flag;
typedef uint8_t uint8;
typedef int8_t int8;
-#ifndef _AIX
-typedef int uint16;
-typedef int int16;
-#endif
typedef unsigned int uint32;
typedef signed int int32;
typedef uint64_t uint64;
@@ -262,8 +259,8 @@ extern const float16 float16_default_nan;
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
-int16 float32_to_int16_round_to_zero( float32 STATUS_PARAM );
-uint16 float32_to_uint16_round_to_zero( float32 STATUS_PARAM );
+int_fast16_t float32_to_int16_round_to_zero(float32 STATUS_PARAM);
+uint_fast16_t float32_to_uint16_round_to_zero(float32 STATUS_PARAM);
int32 float32_to_int32( float32 STATUS_PARAM );
int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM );
uint32 float32_to_uint32( float32 STATUS_PARAM );
@@ -366,8 +363,8 @@ extern const float32 float32_default_nan;
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
-int16 float64_to_int16_round_to_zero( float64 STATUS_PARAM );
-uint16 float64_to_uint16_round_to_zero( float64 STATUS_PARAM );
+int_fast16_t float64_to_int16_round_to_zero(float64 STATUS_PARAM);
+uint_fast16_t float64_to_uint16_round_to_zero(float64 STATUS_PARAM);
int32 float64_to_int32( float64 STATUS_PARAM );
int32 float64_to_int32_round_to_zero( float64 STATUS_PARAM );
uint32 float64_to_uint32( float64 STATUS_PARAM );
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 461fa597d4..18cb415ac4 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -71,8 +71,8 @@ ETEXI
{
.name = "block_stream",
- .args_type = "device:B,base:s?",
- .params = "device [base]",
+ .args_type = "device:B,speed:o?,base:s?",
+ .params = "device [speed [base]]",
.help = "copy data from a backing file into a block device",
.mhandler.cmd = hmp_block_stream,
},
@@ -85,8 +85,8 @@ ETEXI
{
.name = "block_job_set_speed",
- .args_type = "device:B,value:o",
- .params = "device value",
+ .args_type = "device:B,speed:o",
+ .params = "device speed",
.help = "set maximum speed for a background block operation",
.mhandler.cmd = hmp_block_job_set_speed,
},
diff --git a/hmp.c b/hmp.c
index f3e5163f1e..eb96618e1e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -835,8 +835,10 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
Error *error = NULL;
const char *device = qdict_get_str(qdict, "device");
const char *base = qdict_get_try_str(qdict, "base");
+ int64_t speed = qdict_get_try_int(qdict, "speed", 0);
- qmp_block_stream(device, base != NULL, base, &error);
+ qmp_block_stream(device, base != NULL, base,
+ qdict_haskey(qdict, "speed"), speed, &error);
hmp_handle_error(mon, &error);
}
diff --git a/hw/e1000.c b/hw/e1000.c
index 9c764624f9..4573f1301e 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -42,7 +42,7 @@ enum {
DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT,
DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM,
DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR,
- DEBUG_RXFILTER, DEBUG_NOTYET,
+ DEBUG_RXFILTER, DEBUG_PHY, DEBUG_NOTYET,
};
#define DBGBIT(x) (1<<DEBUG_##x)
static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
@@ -125,6 +125,8 @@ typedef struct E1000State_st {
uint16_t reading;
uint32_t old_eecd;
} eecd_state;
+
+ QEMUTimer *autoneg_timer;
} E1000State;
#define defreg(x) x = (E1000_##x>>2)
@@ -142,6 +144,48 @@ enum {
defreg(VET),
};
+static void
+e1000_link_down(E1000State *s)
+{
+ s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+}
+
+static void
+e1000_link_up(E1000State *s)
+{
+ s->mac_reg[STATUS] |= E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+}
+
+static void
+set_phy_ctrl(E1000State *s, int index, uint16_t val)
+{
+ if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
+ s->nic->nc.link_down = true;
+ e1000_link_down(s);
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Start link auto negotiation\n");
+ qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+ }
+}
+
+static void
+e1000_autoneg_timer(void *opaque)
+{
+ E1000State *s = opaque;
+ s->nic->nc.link_down = false;
+ e1000_link_up(s);
+ s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Auto negotiation is completed\n");
+}
+
+static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = {
+ [PHY_CTRL] = set_phy_ctrl,
+};
+
+enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) };
+
enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
static const char phy_regcap[0x20] = {
[PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
@@ -152,11 +196,37 @@ static const char phy_regcap[0x20] = {
[PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R
};
+static const uint16_t phy_reg_init[] = {
+ [PHY_CTRL] = 0x1140,
+ [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
+ [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
+ [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
+ [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
+ [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
+ [M88E1000_PHY_SPEC_STATUS] = 0xac00,
+};
+
+static const uint32_t mac_reg_init[] = {
+ [PBA] = 0x00100030,
+ [LEDCTL] = 0x602,
+ [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
+ E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
+ [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
+ E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
+ E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
+ E1000_STATUS_LU,
+ [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
+ E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
+ E1000_MANC_RMCP_EN,
+};
+
static void
set_interrupt_cause(E1000State *s, int index, uint32_t val)
{
- if (val)
+ if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
+ /* Only for 8257x */
val |= E1000_ICR_INT_ASSERTED;
+ }
s->mac_reg[ICR] = val;
s->mac_reg[ICS] = val;
qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
@@ -193,6 +263,23 @@ rxbufsize(uint32_t v)
return 2048;
}
+static void e1000_reset(void *opaque)
+{
+ E1000State *d = opaque;
+
+ qemu_del_timer(d->autoneg_timer);
+ memset(d->phy_reg, 0, sizeof d->phy_reg);
+ memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
+ memset(d->mac_reg, 0, sizeof d->mac_reg);
+ memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
+ d->rxbuf_min_shift = 1;
+ memset(&d->tx, 0, sizeof d->tx);
+
+ if (d->nic->nc.link_down) {
+ e1000_link_down(d);
+ }
+}
+
static void
set_ctrl(E1000State *s, int index, uint32_t val)
{
@@ -230,11 +317,18 @@ set_mdic(E1000State *s, int index, uint32_t val)
if (!(phy_regcap[addr] & PHY_W)) {
DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
val |= E1000_MDIC_ERROR;
- } else
+ } else {
+ if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
+ phyreg_writeops[addr](s, index, data);
+ }
s->phy_reg[addr] = data;
+ }
}
s->mac_reg[MDIC] = val | E1000_MDIC_READY;
- set_ics(s, 0, E1000_ICR_MDAC);
+
+ if (val & E1000_MDIC_INT_EN) {
+ set_ics(s, 0, E1000_ICR_MDAC);
+ }
}
static uint32_t
@@ -349,6 +443,16 @@ fcs_len(E1000State *s)
}
static void
+e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
+{
+ if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
+ s->nic->nc.info->receive(&s->nic->nc, buf, size);
+ } else {
+ qemu_send_packet(&s->nic->nc, buf, size);
+ }
+}
+
+static void
xmit_seg(E1000State *s)
{
uint16_t len, *sp;
@@ -397,9 +501,9 @@ xmit_seg(E1000State *s)
memmove(tp->vlan, tp->data, 4);
memmove(tp->data, tp->data + 4, 8);
memcpy(tp->data + 8, tp->vlan_header, 4);
- qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4);
+ e1000_send_packet(s, tp->vlan, tp->size + 4);
} else
- qemu_send_packet(&s->nic->nc, tp->data, tp->size);
+ e1000_send_packet(s, tp->data, tp->size);
s->mac_reg[TPT]++;
s->mac_reg[GPTC]++;
n = s->mac_reg[TOTL];
@@ -622,11 +726,9 @@ e1000_set_link_status(VLANClientState *nc)
uint32_t old_status = s->mac_reg[STATUS];
if (nc->link_down) {
- s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
- s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+ e1000_link_down(s);
} else {
- s->mac_reg[STATUS] |= E1000_STATUS_LU;
- s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+ e1000_link_up(s);
}
if (s->mac_reg[STATUS] != old_status)
@@ -901,6 +1003,7 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
[MTA ... MTA+127] = &mac_writereg,
[VFTA ... VFTA+127] = &mac_writereg,
};
+
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
static void
@@ -1061,29 +1164,6 @@ static const uint16_t e1000_eeprom_template[64] = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
};
-static const uint16_t phy_reg_init[] = {
- [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up
- [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
- [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
- [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
- [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
- [M88E1000_PHY_SPEC_STATUS] = 0xac00,
-};
-
-static const uint32_t mac_reg_init[] = {
- [PBA] = 0x00100030,
- [LEDCTL] = 0x602,
- [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
- E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
- [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
- E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
- E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
- E1000_STATUS_LU,
- [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
- E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
- E1000_MANC_RMCP_EN,
-};
-
/* PCI interface */
static void
@@ -1117,29 +1197,14 @@ pci_e1000_uninit(PCIDevice *dev)
{
E1000State *d = DO_UPCAST(E1000State, dev, dev);
+ qemu_del_timer(d->autoneg_timer);
+ qemu_free_timer(d->autoneg_timer);
memory_region_destroy(&d->mmio);
memory_region_destroy(&d->io);
qemu_del_vlan_client(&d->nic->nc);
return 0;
}
-static void e1000_reset(void *opaque)
-{
- E1000State *d = opaque;
-
- memset(d->phy_reg, 0, sizeof d->phy_reg);
- memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
- memset(d->mac_reg, 0, sizeof d->mac_reg);
- memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
- d->rxbuf_min_shift = 1;
- memset(&d->tx, 0, sizeof d->tx);
-
- if (d->nic->nc.link_down) {
- d->mac_reg[STATUS] &= ~E1000_STATUS_LU;
- d->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
- }
-}
-
static NetClientInfo net_e1000_info = {
.type = NET_CLIENT_TYPE_NIC,
.size = sizeof(NICState),
@@ -1188,6 +1253,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+ d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d);
+
return 0;
}
diff --git a/hw/e1000_hw.h b/hw/e1000_hw.h
index 9e29af8c82..c9cb79e64d 100644
--- a/hw/e1000_hw.h
+++ b/hw/e1000_hw.h
@@ -349,6 +349,18 @@
#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+
/* PHY Status Register */
#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 02e6f7ef31..6279ae36ec 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -322,8 +322,32 @@ static const uint16_t eepro100_mdi_mask[] = {
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
+#define POLYNOMIAL 0x04c11db6
+
static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
+/* From FreeBSD (locally modified). */
+static unsigned e100_compute_mcast_idx(const uint8_t *ep)
+{
+ uint32_t crc;
+ int carry, i, j;
+ uint8_t b;
+
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ b = *ep++;
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+ crc <<= 1;
+ b >>= 1;
+ if (carry) {
+ crc = ((crc ^ POLYNOMIAL) | carry);
+ }
+ }
+ }
+ return (crc & BITS(7, 2)) >> 2;
+}
+
/* Read a 16 bit control/status (CSR) register. */
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
{
@@ -823,7 +847,7 @@ static void set_multicast_list(EEPRO100State *s)
uint8_t multicast_addr[6];
pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
- unsigned mcast_idx = compute_mcast_idx(multicast_addr);
+ unsigned mcast_idx = e100_compute_mcast_idx(multicast_addr);
assert(mcast_idx < 64);
s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
}
@@ -1650,7 +1674,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
if (s->configuration[21] & BIT(3)) {
/* Multicast all bit is set, receive all multicast frames. */
} else {
- unsigned mcast_idx = compute_mcast_idx(buf);
+ unsigned mcast_idx = e100_compute_mcast_idx(buf);
assert(mcast_idx < 64);
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
/* Multicast frame is allowed in hash table. */
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index 8995519573..36761dd2de 100644
--- a/hw/hda-audio.c
+++ b/hw/hda-audio.c
@@ -113,22 +113,25 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
/* some defines */
#define QEMU_HDA_ID_VENDOR 0x1af4
-#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x10)
-#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x20)
-
#define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 | \
0x1fc /* 16 -> 96 kHz */)
#define QEMU_HDA_AMP_NONE (0)
#define QEMU_HDA_AMP_STEPS 0x4a
#ifdef CONFIG_MIXEMU
-#define QEMU_HDA_AMP_CAPS \
+# define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12)
+# define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22)
+# define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32)
+# define QEMU_HDA_AMP_CAPS \
(AC_AMPCAP_MUTE | \
(QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \
(QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \
(3 << AC_AMPCAP_STEP_SIZE_SHIFT))
#else
-#define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE
+# define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
+# define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
+# define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x31)
+# define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE
#endif
/* common: audio output widget */
@@ -155,6 +158,34 @@ static const desc_param common_params_audio_dac[] = {
},
};
+/* common: audio input widget */
+static const desc_param common_params_audio_adc[] = {
+ {
+ .id = AC_PAR_AUDIO_WIDGET_CAP,
+ .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
+ AC_WCAP_CONN_LIST |
+ AC_WCAP_FORMAT_OVRD |
+ AC_WCAP_AMP_OVRD |
+ AC_WCAP_IN_AMP |
+ AC_WCAP_STEREO),
+ },{
+ .id = AC_PAR_CONNLIST_LEN,
+ .val = 1,
+ },{
+ .id = AC_PAR_PCM,
+ .val = QEMU_HDA_PCM_FORMATS,
+ },{
+ .id = AC_PAR_STREAM,
+ .val = AC_SUPFMT_PCM,
+ },{
+ .id = AC_PAR_AMP_IN_CAP,
+ .val = QEMU_HDA_AMP_CAPS,
+ },{
+ .id = AC_PAR_AMP_OUT_CAP,
+ .val = QEMU_HDA_AMP_NONE,
+ },
+};
+
/* common: pin widget (line-out) */
static const desc_param common_params_audio_lineout[] = {
{
@@ -177,6 +208,24 @@ static const desc_param common_params_audio_lineout[] = {
},
};
+/* common: pin widget (line-in) */
+static const desc_param common_params_audio_linein[] = {
+ {
+ .id = AC_PAR_AUDIO_WIDGET_CAP,
+ .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
+ AC_WCAP_STEREO),
+ },{
+ .id = AC_PAR_PIN_CAP,
+ .val = AC_PINCAP_IN,
+ },{
+ .id = AC_PAR_AMP_IN_CAP,
+ .val = QEMU_HDA_AMP_NONE,
+ },{
+ .id = AC_PAR_AMP_OUT_CAP,
+ .val = QEMU_HDA_AMP_NONE,
+ },
+};
+
/* output: root node */
static const desc_param output_params_root[] = {
{
@@ -287,19 +336,17 @@ static const desc_param duplex_params_root[] = {
},
};
-/* duplex: audio input widget */
-static const desc_param duplex_params_audio_adc[] = {
+/* duplex: audio function */
+static const desc_param duplex_params_audio_func[] = {
{
- .id = AC_PAR_AUDIO_WIDGET_CAP,
- .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
- AC_WCAP_CONN_LIST |
- AC_WCAP_FORMAT_OVRD |
- AC_WCAP_AMP_OVRD |
- AC_WCAP_IN_AMP |
- AC_WCAP_STEREO),
+ .id = AC_PAR_FUNCTION_TYPE,
+ .val = AC_GRP_AUDIO_FUNCTION,
},{
- .id = AC_PAR_CONNLIST_LEN,
- .val = 1,
+ .id = AC_PAR_SUBSYSTEM_ID,
+ .val = QEMU_HDA_ID_DUPLEX,
+ },{
+ .id = AC_PAR_NODE_COUNT,
+ .val = 0x00020004,
},{
.id = AC_PAR_PCM,
.val = QEMU_HDA_PCM_FORMATS,
@@ -308,39 +355,106 @@ static const desc_param duplex_params_audio_adc[] = {
.val = AC_SUPFMT_PCM,
},{
.id = AC_PAR_AMP_IN_CAP,
- .val = QEMU_HDA_AMP_CAPS,
+ .val = QEMU_HDA_AMP_NONE,
},{
.id = AC_PAR_AMP_OUT_CAP,
.val = QEMU_HDA_AMP_NONE,
+ },{
+ .id = AC_PAR_GPIO_CAP,
+ .val = 0,
+ },{
+ .id = AC_PAR_AUDIO_FG_CAP,
+ .val = 0x00000808,
+ },{
+ .id = AC_PAR_POWER_STATE,
+ .val = 0,
},
};
-/* duplex: pin widget (line-in) */
-static const desc_param duplex_params_audio_linein[] = {
+/* duplex: nodes */
+static const desc_node duplex_nodes[] = {
{
- .id = AC_PAR_AUDIO_WIDGET_CAP,
- .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
- AC_WCAP_STEREO),
+ .nid = AC_NODE_ROOT,
+ .name = "root",
+ .params = duplex_params_root,
+ .nparams = ARRAY_SIZE(duplex_params_root),
},{
- .id = AC_PAR_PIN_CAP,
- .val = AC_PINCAP_IN,
+ .nid = 1,
+ .name = "func",
+ .params = duplex_params_audio_func,
+ .nparams = ARRAY_SIZE(duplex_params_audio_func),
},{
- .id = AC_PAR_AMP_IN_CAP,
- .val = QEMU_HDA_AMP_NONE,
+ .nid = 2,
+ .name = "dac",
+ .params = common_params_audio_dac,
+ .nparams = ARRAY_SIZE(common_params_audio_dac),
+ .stindex = 0,
},{
- .id = AC_PAR_AMP_OUT_CAP,
- .val = QEMU_HDA_AMP_NONE,
+ .nid = 3,
+ .name = "out",
+ .params = common_params_audio_lineout,
+ .nparams = ARRAY_SIZE(common_params_audio_lineout),
+ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+ (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+ (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
+ 0x10),
+ .pinctl = AC_PINCTL_OUT_EN,
+ .conn = (uint32_t[]) { 2 },
+ },{
+ .nid = 4,
+ .name = "adc",
+ .params = common_params_audio_adc,
+ .nparams = ARRAY_SIZE(common_params_audio_adc),
+ .stindex = 1,
+ .conn = (uint32_t[]) { 5 },
+ },{
+ .nid = 5,
+ .name = "in",
+ .params = common_params_audio_linein,
+ .nparams = ARRAY_SIZE(common_params_audio_linein),
+ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+ (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+ (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
+ 0x20),
+ .pinctl = AC_PINCTL_IN_EN,
+ }
+};
+
+/* duplex: codec */
+static const desc_codec duplex = {
+ .name = "duplex",
+ .iid = QEMU_HDA_ID_DUPLEX,
+ .nodes = duplex_nodes,
+ .nnodes = ARRAY_SIZE(duplex_nodes),
+};
+
+/* micro: root node */
+static const desc_param micro_params_root[] = {
+ {
+ .id = AC_PAR_VENDOR_ID,
+ .val = QEMU_HDA_ID_MICRO,
+ },{
+ .id = AC_PAR_SUBSYSTEM_ID,
+ .val = QEMU_HDA_ID_MICRO,
+ },{
+ .id = AC_PAR_REV_ID,
+ .val = 0x00100101,
+ },{
+ .id = AC_PAR_NODE_COUNT,
+ .val = 0x00010001,
},
};
-/* duplex: audio function */
-static const desc_param duplex_params_audio_func[] = {
+/* micro: audio function */
+static const desc_param micro_params_audio_func[] = {
{
.id = AC_PAR_FUNCTION_TYPE,
.val = AC_GRP_AUDIO_FUNCTION,
},{
.id = AC_PAR_SUBSYSTEM_ID,
- .val = QEMU_HDA_ID_DUPLEX,
+ .val = QEMU_HDA_ID_MICRO,
},{
.id = AC_PAR_NODE_COUNT,
.val = 0x00020004,
@@ -368,18 +482,18 @@ static const desc_param duplex_params_audio_func[] = {
},
};
-/* duplex: nodes */
-static const desc_node duplex_nodes[] = {
+/* micro: nodes */
+static const desc_node micro_nodes[] = {
{
.nid = AC_NODE_ROOT,
.name = "root",
- .params = duplex_params_root,
- .nparams = ARRAY_SIZE(duplex_params_root),
+ .params = micro_params_root,
+ .nparams = ARRAY_SIZE(micro_params_root),
},{
.nid = 1,
.name = "func",
- .params = duplex_params_audio_func,
- .nparams = ARRAY_SIZE(duplex_params_audio_func),
+ .params = micro_params_audio_func,
+ .nparams = ARRAY_SIZE(micro_params_audio_func),
},{
.nid = 2,
.name = "dac",
@@ -392,7 +506,7 @@ static const desc_node duplex_nodes[] = {
.params = common_params_audio_lineout,
.nparams = ARRAY_SIZE(common_params_audio_lineout),
.config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
- (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) |
(AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
(AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
0x10),
@@ -401,17 +515,17 @@ static const desc_node duplex_nodes[] = {
},{
.nid = 4,
.name = "adc",
- .params = duplex_params_audio_adc,
- .nparams = ARRAY_SIZE(duplex_params_audio_adc),
+ .params = common_params_audio_adc,
+ .nparams = ARRAY_SIZE(common_params_audio_adc),
.stindex = 1,
.conn = (uint32_t[]) { 5 },
},{
.nid = 5,
.name = "in",
- .params = duplex_params_audio_linein,
- .nparams = ARRAY_SIZE(duplex_params_audio_linein),
+ .params = common_params_audio_linein,
+ .nparams = ARRAY_SIZE(common_params_audio_linein),
.config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
- (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) |
(AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
(AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
0x20),
@@ -419,12 +533,12 @@ static const desc_node duplex_nodes[] = {
}
};
-/* duplex: codec */
-static const desc_codec duplex = {
- .name = "duplex",
- .iid = QEMU_HDA_ID_DUPLEX,
- .nodes = duplex_nodes,
- .nnodes = ARRAY_SIZE(duplex_nodes),
+/* micro: codec */
+static const desc_codec micro = {
+ .name = "micro",
+ .iid = QEMU_HDA_ID_MICRO,
+ .nodes = micro_nodes,
+ .nnodes = ARRAY_SIZE(micro_nodes),
};
/* -------------------------------------------------------------------------- */
@@ -906,6 +1020,11 @@ static int hda_audio_init_duplex(HDACodecDevice *hda)
return hda_audio_init(hda, &duplex);
}
+static int hda_audio_init_micro(HDACodecDevice *hda)
+{
+ return hda_audio_init(hda, &micro);
+}
+
static void hda_audio_output_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -915,7 +1034,7 @@ static void hda_audio_output_class_init(ObjectClass *klass, void *data)
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
- dc->desc = "HDA Audio Codec, output-only";
+ dc->desc = "HDA Audio Codec, output-only (line-out)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
}
@@ -936,7 +1055,7 @@ static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
- dc->desc = "HDA Audio Codec, duplex";
+ dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
}
@@ -948,10 +1067,32 @@ static TypeInfo hda_audio_duplex_info = {
.class_init = hda_audio_duplex_class_init,
};
+static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
+
+ k->init = hda_audio_init_micro;
+ k->exit = hda_audio_exit;
+ k->command = hda_audio_command;
+ k->stream = hda_audio_stream;
+ dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
+ dc->vmsd = &vmstate_hda_audio;
+ dc->props = hda_audio_properties;
+}
+
+static TypeInfo hda_audio_micro_info = {
+ .name = "hda-micro",
+ .parent = TYPE_HDA_CODEC_DEVICE,
+ .instance_size = sizeof(HDAAudioState),
+ .class_init = hda_audio_micro_class_init,
+};
+
static void hda_audio_register_types(void)
{
type_register_static(&hda_audio_output_info);
type_register_static(&hda_audio_duplex_info);
+ type_register_static(&hda_audio_micro_info);
}
type_init(hda_audio_register_types)
diff --git a/hw/highbank.c b/hw/highbank.c
index 906eed5a47..4d6d728a28 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -35,12 +35,6 @@
#define NIRQ_GIC 160
/* Board init. */
-static void highbank_cpu_reset(void *opaque)
-{
- CPUARMState *env = opaque;
-
- env->cp15.c15_config_base_address = GIC_BASE_ADDR;
-}
static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info)
{
@@ -213,14 +207,17 @@ static void highbank_init(ram_addr_t ram_size,
}
for (n = 0; n < smp_cpus; n++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ ARMCPU *cpu;
+ cpu = cpu_arm_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+ /* This will become a QOM property eventually */
+ cpu->reset_cbar = GIC_BASE_ADDR;
irqp = arm_pic_init_cpu(env);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
- qemu_register_reset(highbank_cpu_reset, env);
}
sysmem = get_system_memory();
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index abf9004182..fafdf9b1c1 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -190,6 +190,8 @@ void pc_system_firmware_init(MemoryRegion *rom_memory)
sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
+ qdev_init_nofail(DEVICE(sysfw_dev));
+
if (sysfw_dev->rom_only) {
old_pc_system_rom_init(rom_memory);
return;
@@ -230,11 +232,17 @@ static Property pcsysfw_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static int pcsysfw_init(DeviceState *dev)
+{
+ return 0;
+}
+
static void pcsysfw_class_init (ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS (klass);
dc->desc = "PC System Firmware";
+ dc->init = pcsysfw_init;
dc->props = pcsysfw_properties;
}
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 9a14a53852..0e02da7601 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -501,6 +501,7 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state)
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
{
assert(!usb_packet_is_inflight(p));
+ assert(p->iov.iov != NULL);
p->pid = pid;
p->ep = ep;
p->result = 0;
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 3c77368cb0..e8a3c6af3d 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -1,3 +1,5 @@
+#include <ctype.h>
+
#include "hw/usb.h"
#include "hw/usb/desc.h"
#include "trace.h"
@@ -412,6 +414,36 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
s->str = g_strdup(str);
}
+/*
+ * This function creates a serial number for a usb device.
+ * The serial number should:
+ * (a) Be unique within the virtual machine.
+ * (b) Be constant, so you don't get a new one each
+ * time the guest is started.
+ * So we are using the physical location to generate a serial number
+ * from it. It has three pieces: First a fixed, device-specific
+ * prefix. Second the device path of the host controller (which is
+ * the pci address in most cases). Third the physical port path.
+ * Results in serial numbers like this: "314159-0000:00:1d.7-3".
+ */
+void usb_desc_create_serial(USBDevice *dev)
+{
+ DeviceState *hcd = dev->qdev.parent_bus->parent;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
+ int index = desc->id.iSerialNumber;
+ char serial[64];
+ int dst;
+
+ assert(index != 0 && desc->str[index] != NULL);
+ dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
+ if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
+ char *path = hcd->parent_bus->info->get_dev_path(hcd);
+ dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path);
+ }
+ dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);
+ usb_desc_set_string(dev, index, serial);
+}
+
const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
{
USBDescString *s;
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index d164e8f891..7cf5442945 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -171,6 +171,7 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
void usb_desc_init(USBDevice *dev);
void usb_desc_attach(USBDevice *dev);
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
+void usb_desc_create_serial(USBDevice *dev);
const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 426b95c82b..79b75fb628 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -648,6 +648,7 @@ static int usb_audio_initfn(USBDevice *dev)
{
USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->dev.opaque = s;
AUD_register_card("usb-audio", &s->card);
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 195370c24a..6b74eff4ad 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -494,6 +494,7 @@ static void usb_bt_handle_destroy(USBDevice *dev)
static int usb_bt_initfn(USBDevice *dev)
{
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
return 0;
}
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 9c9166551e..b5962da72a 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -520,6 +520,7 @@ static int usb_hub_initfn(USBDevice *dev)
USBHubPort *port;
int i;
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
for (i = 0; i < NUM_PORTS; i++) {
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index cff55f223e..b238a0973d 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1324,6 +1324,7 @@ static int usb_net_initfn(USBDevice *dev)
{
USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->rndis_state = RNDIS_UNINITIALIZED;
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 8dcac8bc88..56743ee020 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -479,6 +479,7 @@ static int usb_serial_initfn(USBDevice *dev)
{
USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
if (!s->cs) {
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 8e66675d86..3b7604e8b1 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1189,6 +1189,7 @@ static int ccid_initfn(USBDevice *dev)
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index d865a5ef93..ae22fb1c97 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -268,7 +268,6 @@ static void usb_msd_request_cancelled(SCSIRequest *req)
if (req == s->req) {
scsi_req_unref(s->req);
s->req = NULL;
- s->packet = NULL;
s->scsi_len = 0;
}
}
@@ -330,6 +329,9 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
{
MSDState *s = DO_UPCAST(MSDState, dev, dev);
+ assert(s->packet == p);
+ s->packet = NULL;
+
if (s->req) {
scsi_req_cancel(s->req);
}
@@ -544,6 +546,8 @@ static int usb_msd_initfn(USBDevice *dev)
}
if (s->serial) {
usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
+ } else {
+ usb_desc_create_serial(dev);
}
usb_desc_init(dev);
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index c1cfd74403..3b51d458f4 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -339,6 +339,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
static int usb_wacom_initfn(USBDevice *dev)
{
USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->changed = 1;
return 0;
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 23631a47c9..4ff4d40a8c 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -133,7 +133,6 @@
#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
#define NB_PORTS 6 // Number of downstream ports
#define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction
-#define MAX_ITERATIONS 20 // Max number of QH before we break the loop
#define MAX_QH 100 // Max allowable queue heads in a chain
/* Internal periodic / asynchronous schedule state machine states
@@ -665,6 +664,7 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
+ usb_packet_init(&q->packet);
QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
@@ -1101,6 +1101,10 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
val &= USBINTR_MASK;
break;
+ case FRINDEX:
+ val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */
+ break;
+
case CONFIGFLAG:
val &= 0x1;
if (val) {
@@ -1931,24 +1935,8 @@ static void ehci_advance_state(EHCIState *ehci,
{
EHCIQueue *q = NULL;
int again;
- int iter = 0;
do {
- if (ehci_get_state(ehci, async) == EST_FETCHQH) {
- iter++;
- /* if we are roaming a lot of QH without executing a qTD
- * something is wrong with the linked list. TO-DO: why is
- * this hack needed?
- */
- assert(iter < MAX_ITERATIONS);
-#if 0
- if (iter > MAX_ITERATIONS) {
- DPRINTF("\n*** advance_state: bailing on MAX ITERATIONS***\n");
- ehci_set_state(ehci, async, EST_ACTIVE);
- break;
- }
-#endif
- }
switch(ehci_get_state(ehci, async)) {
case EST_WAITLISTHEAD:
again = ehci_state_waitlisthead(ehci, async);
@@ -1984,7 +1972,6 @@ static void ehci_advance_state(EHCIState *ehci,
break;
case EST_EXECUTE:
- iter = 0;
again = ehci_state_execute(q, async);
break;
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 266d550b9c..9e211a0bb4 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -369,6 +369,7 @@ static void uhci_reset(void *opaque)
}
uhci_async_cancel_all(s);
+ uhci_update_irq(s);
}
static void uhci_pre_save(void *opaque)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 73b0c7f5e5..5cf1a64699 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -22,7 +22,6 @@
#include "qemu-timer.h"
#include "hw/usb.h"
#include "hw/pci.h"
-#include "hw/qdev-addr.h"
#include "hw/msi.h"
//#define DEBUG_XHCI
@@ -140,7 +139,7 @@ typedef struct XHCITRB {
uint64_t parameter;
uint32_t status;
uint32_t control;
- target_phys_addr_t addr;
+ dma_addr_t addr;
bool ccs;
} XHCITRB;
@@ -291,8 +290,8 @@ typedef enum EPType {
} EPType;
typedef struct XHCIRing {
- target_phys_addr_t base;
- target_phys_addr_t dequeue;
+ dma_addr_t base;
+ dma_addr_t dequeue;
bool ccs;
} XHCIRing;
@@ -345,7 +344,7 @@ typedef struct XHCIEPContext {
unsigned int next_bg;
XHCITransfer bg_transfers[BG_XFERS];
EPType type;
- target_phys_addr_t pctx;
+ dma_addr_t pctx;
unsigned int max_psize;
bool has_bg;
uint32_t state;
@@ -353,7 +352,7 @@ typedef struct XHCIEPContext {
typedef struct XHCISlot {
bool enabled;
- target_phys_addr_t ctx;
+ dma_addr_t ctx;
unsigned int port;
unsigned int devaddr;
XHCIEPContext * eps[31];
@@ -402,7 +401,7 @@ struct XHCIState {
uint32_t erdp_low;
uint32_t erdp_high;
- target_phys_addr_t er_start;
+ dma_addr_t er_start;
uint32_t er_size;
bool er_pcs;
unsigned int er_ep_idx;
@@ -479,22 +478,22 @@ static const char *trb_name(XHCITRB *trb)
static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
unsigned int epid);
-static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high)
+static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high)
{
-#if TARGET_PHYS_ADDR_BITS > 32
- return low | ((target_phys_addr_t)high << 32);
-#else
- return low;
-#endif
+ if (sizeof(dma_addr_t) == 4) {
+ return low;
+ } else {
+ return low | (((dma_addr_t)high << 16) << 16);
+ }
}
-static inline target_phys_addr_t xhci_mask64(uint64_t addr)
+static inline dma_addr_t xhci_mask64(uint64_t addr)
{
-#if TARGET_PHYS_ADDR_BITS > 32
- return addr;
-#else
- return addr & 0xffffffff;
-#endif
+ if (sizeof(dma_addr_t) == 4) {
+ return addr & 0xffffffff;
+ } else {
+ return addr;
+ }
}
static void xhci_irq_update(XHCIState *xhci)
@@ -502,7 +501,7 @@ static void xhci_irq_update(XHCIState *xhci)
int level = 0;
if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
- xhci->usbcmd && USBCMD_INTE) {
+ xhci->usbcmd & USBCMD_INTE) {
level = 1;
}
@@ -532,7 +531,7 @@ static void xhci_die(XHCIState *xhci)
static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
{
XHCITRB ev_trb;
- target_phys_addr_t addr;
+ dma_addr_t addr;
ev_trb.parameter = cpu_to_le64(event->ptr);
ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
@@ -548,7 +547,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
trb_name(&ev_trb));
addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
- cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
+ pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
xhci->er_ep_idx++;
if (xhci->er_ep_idx >= xhci->er_size) {
@@ -559,7 +558,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
static void xhci_events_update(XHCIState *xhci)
{
- target_phys_addr_t erdp;
+ dma_addr_t erdp;
unsigned int dp_idx;
bool do_irq = 0;
@@ -570,8 +569,8 @@ static void xhci_events_update(XHCIState *xhci)
erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
if (erdp < xhci->er_start ||
erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
- fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
- fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+ fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
+ fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n",
xhci->er_start, xhci->er_size);
xhci_die(xhci);
return;
@@ -630,7 +629,7 @@ static void xhci_events_update(XHCIState *xhci)
static void xhci_event(XHCIState *xhci, XHCIEvent *event)
{
- target_phys_addr_t erdp;
+ dma_addr_t erdp;
unsigned int dp_idx;
if (xhci->er_full) {
@@ -649,8 +648,8 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event)
erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
if (erdp < xhci->er_start ||
erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
- fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
- fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+ fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
+ fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n",
xhci->er_start, xhci->er_size);
xhci_die(xhci);
return;
@@ -686,7 +685,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event)
}
static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
- target_phys_addr_t base)
+ dma_addr_t base)
{
ring->base = base;
ring->dequeue = base;
@@ -694,18 +693,18 @@ static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
}
static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
- target_phys_addr_t *addr)
+ dma_addr_t *addr)
{
while (1) {
TRBType type;
- cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE);
+ pci_dma_read(&xhci->pci_dev, ring->dequeue, trb, TRB_SIZE);
trb->addr = ring->dequeue;
trb->ccs = ring->ccs;
le64_to_cpus(&trb->parameter);
le32_to_cpus(&trb->status);
le32_to_cpus(&trb->control);
- DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: "
+ DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: "
"%016" PRIx64 " %08x %08x %s\n",
ring->dequeue, trb->parameter, trb->status, trb->control,
trb_name(trb));
@@ -735,19 +734,19 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
{
XHCITRB trb;
int length = 0;
- target_phys_addr_t dequeue = ring->dequeue;
+ dma_addr_t dequeue = ring->dequeue;
bool ccs = ring->ccs;
/* hack to bundle together the two/three TDs that make a setup transfer */
bool control_td_set = 0;
while (1) {
TRBType type;
- cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE);
+ pci_dma_read(&xhci->pci_dev, dequeue, &trb, TRB_SIZE);
le64_to_cpus(&trb.parameter);
le32_to_cpus(&trb.status);
le32_to_cpus(&trb.control);
- DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: "
+ DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: "
"%016" PRIx64 " %08x %08x\n",
dequeue, trb.parameter, trb.status, trb.control);
@@ -790,8 +789,8 @@ static void xhci_er_reset(XHCIState *xhci)
xhci_die(xhci);
return;
}
- target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
- cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg));
+ dma_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
+ pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg));
le32_to_cpus(&seg.addr_low);
le32_to_cpus(&seg.addr_high);
le32_to_cpus(&seg.size);
@@ -807,7 +806,7 @@ static void xhci_er_reset(XHCIState *xhci)
xhci->er_pcs = 1;
xhci->er_full = 0;
- DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n",
+ DPRINTF("xhci: event ring:" DMA_ADDR_FMT " [%d]\n",
xhci->er_start, xhci->er_size);
}
@@ -833,24 +832,24 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
return;
}
- cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+ pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx));
ctx[0] &= ~EP_STATE_MASK;
ctx[0] |= state;
ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
- DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n",
+ DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
epctx->pctx, state, ctx[3], ctx[2]);
- cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+ pci_dma_write(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx));
epctx->state = state;
}
static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
- unsigned int epid, target_phys_addr_t pctx,
+ unsigned int epid, dma_addr_t pctx,
uint32_t *ctx)
{
XHCISlot *slot;
XHCIEPContext *epctx;
- target_phys_addr_t dequeue;
+ dma_addr_t dequeue;
int i;
assert(slotid >= 1 && slotid <= MAXSLOTS);
@@ -1087,7 +1086,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
{
XHCISlot *slot;
XHCIEPContext *epctx;
- target_phys_addr_t dequeue;
+ dma_addr_t dequeue;
assert(slotid >= 1 && slotid <= MAXSLOTS);
@@ -1142,7 +1141,7 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
for (i = 0; i < xfer->trb_count; i++) {
XHCITRB *trb = &xfer->trbs[i];
- target_phys_addr_t addr;
+ dma_addr_t addr;
unsigned int chunk = 0;
switch (TRB_TYPE(*trb)) {
@@ -1173,11 +1172,11 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
memcpy(data, &idata, chunk);
} else {
DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at "
- TARGET_FMT_plx "\n", in_xfer, chunk, addr);
+ DMA_ADDR_FMT "\n", in_xfer, chunk, addr);
if (in_xfer) {
- cpu_physical_memory_write(addr, data, chunk);
+ pci_dma_write(&xhci->pci_dev, addr, data, chunk);
} else {
- cpu_physical_memory_read(addr, data, chunk);
+ pci_dma_read(&xhci->pci_dev, addr, data, chunk);
}
#ifdef DEBUG_DATA
unsigned int count = chunk;
@@ -1240,7 +1239,7 @@ static void xhci_stall_ep(XHCITransfer *xfer)
epctx->ring.ccs = xfer->trbs[0].ccs;
xhci_set_ep_state(xhci, epctx, EP_HALTED);
DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid);
- DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue);
+ DPRINTF("xhci: will continue at "DMA_ADDR_FMT"\n", epctx->ring.dequeue);
}
static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
@@ -1802,7 +1801,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
{
XHCISlot *slot;
USBDevice *dev;
- target_phys_addr_t ictx, octx, dcbaap;
+ dma_addr_t ictx, octx, dcbaap;
uint64_t poctx;
uint32_t ictl_ctx[2];
uint32_t slot_ctx[4];
@@ -1815,15 +1814,14 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
DPRINTF("xhci_address_slot(%d)\n", slotid);
dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
- cpu_physical_memory_read(dcbaap + 8*slotid,
- (uint8_t *) &poctx, sizeof(poctx));
+ pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx));
ictx = xhci_mask64(pictx);
octx = xhci_mask64(le64_to_cpu(poctx));
- DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
- cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
@@ -1831,8 +1829,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
return CC_TRB_ERROR;
}
- cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx));
- cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32, slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+64, ep0_ctx, sizeof(ep0_ctx));
DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
@@ -1881,8 +1879,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
- cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
return res;
}
@@ -1891,7 +1889,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
uint64_t pictx, bool dc)
{
- target_phys_addr_t ictx, octx;
+ dma_addr_t ictx, octx;
uint32_t ictl_ctx[2];
uint32_t slot_ctx[4];
uint32_t islot_ctx[4];
@@ -1905,8 +1903,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
ictx = xhci_mask64(pictx);
octx = xhci->slots[slotid-1].ctx;
- DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
if (dc) {
for (i = 2; i <= 31; i++) {
@@ -1915,17 +1913,17 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
}
}
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
return CC_SUCCESS;
}
- cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
@@ -1933,8 +1931,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
return CC_TRB_ERROR;
}
- cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx));
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]);
@@ -1946,8 +1944,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
xhci_disable_ep(xhci, slotid, i);
}
if (ictl_ctx[1] & (1<<i)) {
- cpu_physical_memory_read(ictx+32+(32*i),
- (uint8_t *) ep_ctx, sizeof(ep_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32+(32*i), ep_ctx,
+ sizeof(ep_ctx));
DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
ep_ctx[3], ep_ctx[4]);
@@ -1959,8 +1957,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
ep_ctx[3], ep_ctx[4]);
- cpu_physical_memory_write(octx+(32*i),
- (uint8_t *) ep_ctx, sizeof(ep_ctx));
+ pci_dma_write(&xhci->pci_dev, octx+(32*i), ep_ctx, sizeof(ep_ctx));
}
}
@@ -1972,7 +1969,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
return CC_SUCCESS;
}
@@ -1981,7 +1978,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
uint64_t pictx)
{
- target_phys_addr_t ictx, octx;
+ dma_addr_t ictx, octx;
uint32_t ictl_ctx[2];
uint32_t iep0_ctx[5];
uint32_t ep0_ctx[5];
@@ -1994,10 +1991,10 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
ictx = xhci_mask64(pictx);
octx = xhci->slots[slotid-1].ctx;
- DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
- cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
@@ -2006,13 +2003,12 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
}
if (ictl_ctx[1] & 0x1) {
- cpu_physical_memory_read(ictx+32,
- (uint8_t *) islot_ctx, sizeof(islot_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx));
DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
slot_ctx[1] &= ~0xFFFF; /* max exit latency */
slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
@@ -2022,18 +2018,17 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
}
if (ictl_ctx[1] & 0x2) {
- cpu_physical_memory_read(ictx+64,
- (uint8_t *) iep0_ctx, sizeof(iep0_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+64, iep0_ctx, sizeof(iep0_ctx));
DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
iep0_ctx[3], iep0_ctx[4]);
- cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_read(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;
@@ -2041,8 +2036,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
- cpu_physical_memory_write(octx+32,
- (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
}
return CC_SUCCESS;
@@ -2051,7 +2045,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
{
uint32_t slot_ctx[4];
- target_phys_addr_t octx;
+ dma_addr_t octx;
int i;
assert(slotid >= 1 && slotid <= MAXSLOTS);
@@ -2059,7 +2053,7 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
octx = xhci->slots[slotid-1].ctx;
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
for (i = 2; i <= 31; i++) {
if (xhci->slots[slotid-1].eps[i-1]) {
@@ -2067,12 +2061,12 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
}
}
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
return CC_SUCCESS;
}
@@ -2095,19 +2089,19 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr
static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
{
- target_phys_addr_t ctx;
+ dma_addr_t ctx;
uint8_t bw_ctx[MAXPORTS+1];
DPRINTF("xhci_get_port_bandwidth()\n");
ctx = xhci_mask64(pctx);
- DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx);
+ DPRINTF("xhci: bandwidth context at "DMA_ADDR_FMT"\n", ctx);
/* TODO: actually implement real values here */
bw_ctx[0] = 0;
memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
- cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx));
+ pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx));
return CC_SUCCESS;
}
@@ -2128,13 +2122,13 @@ static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo)
return ~val;
}
-static void xhci_via_challenge(uint64_t addr)
+static void xhci_via_challenge(XHCIState *xhci, uint64_t addr)
{
uint32_t buf[8];
uint32_t obuf[8];
- target_phys_addr_t paddr = xhci_mask64(addr);
+ dma_addr_t paddr = xhci_mask64(addr);
- cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32);
+ pci_dma_read(&xhci->pci_dev, paddr, &buf, 32);
memcpy(obuf, buf, sizeof(obuf));
@@ -2150,7 +2144,7 @@ static void xhci_via_challenge(uint64_t addr)
obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593;
}
- cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32);
+ pci_dma_write(&xhci->pci_dev, paddr, &obuf, 32);
}
static void xhci_process_commands(XHCIState *xhci)
@@ -2158,7 +2152,7 @@ static void xhci_process_commands(XHCIState *xhci)
XHCITRB trb;
TRBType type;
XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
- target_phys_addr_t addr;
+ dma_addr_t addr;
unsigned int i, slotid = 0;
DPRINTF("xhci_process_commands()\n");
@@ -2247,7 +2241,7 @@ static void xhci_process_commands(XHCIState *xhci)
event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
break;
case CR_VENDOR_VIA_CHALLENGE_RESPONSE:
- xhci_via_challenge(trb.parameter);
+ xhci_via_challenge(xhci, trb.parameter);
break;
case CR_VENDOR_NEC_FIRMWARE_REVISION:
event.type = 48; /* NEC reply */
@@ -2537,7 +2531,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
xhci_event(xhci, &event);
DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
} else {
- target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
+ dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
xhci_ring_init(xhci, &xhci->cmd_ring, base);
}
xhci->crcr_low &= ~(CRCR_CA | CRCR_CS);
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index 061a1b7825..048f8ffa8b 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -884,16 +884,16 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
}
v = 0;
- prem = p->iov.iov[v].iov_len;
- pbuf = p->iov.iov[v].iov_base;
+ prem = 0;
+ pbuf = NULL;
rem = p->iov.size;
- while (rem) {
- if (prem == 0) {
- v++;
+ do {
+ if (prem == 0 && rem > 0) {
assert(v < p->iov.niov);
prem = p->iov.iov[v].iov_len;
pbuf = p->iov.iov[v].iov_base;
assert(prem <= rem);
+ v++;
}
aurb = async_alloc(s);
aurb->packet = p;
@@ -938,7 +938,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
return USB_RET_STALL;
}
}
- }
+ } while (rem > 0);
return USB_RET_ASYNC;
}
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 94ab4632ca..51c27b4051 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -39,6 +39,7 @@
#include "hw/usb.h"
#define MAX_ENDPOINTS 32
+#define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */
#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
@@ -276,7 +277,7 @@ static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
return aurb;
}
}
- ERROR("could not find async urb for packet_id %u\n", packet_id);
+ DPRINTF("could not find async urb for packet_id %u\n", packet_id);
return NULL;
}
@@ -970,7 +971,7 @@ static void usbredir_handle_destroy(USBDevice *udev)
static int usbredir_check_filter(USBRedirDevice *dev)
{
- if (dev->interface_info.interface_count == 0) {
+ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) {
ERROR("No interface info for device\n");
goto error;
}
@@ -1134,7 +1135,9 @@ static void usbredir_device_disconnect(void *priv)
QTAILQ_INIT(&dev->endpoint[i].bufpq);
}
usb_ep_init(&dev->dev);
- dev->interface_info.interface_count = 0;
+ dev->interface_info.interface_count = NO_INTERFACE_INFO;
+ dev->dev.addr = 0;
+ dev->dev.speed = 0;
}
static void usbredir_interface_info(void *priv,
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index e22940ecb2..ffbdfc2de1 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -528,6 +528,53 @@ static void set_config(VirtIODevice *vdev, const uint8_t *config_data)
memcpy(&config, config_data, sizeof(config));
}
+static void guest_reset(VirtIOSerial *vser)
+{
+ VirtIOSerialPort *port;
+ VirtIOSerialPortClass *vsc;
+
+ QTAILQ_FOREACH(port, &vser->ports, next) {
+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+ if (port->guest_connected) {
+ port->guest_connected = false;
+
+ if (vsc->guest_close)
+ vsc->guest_close(port);
+ }
+ }
+}
+
+static void set_status(VirtIODevice *vdev, uint8_t status)
+{
+ VirtIOSerial *vser;
+ VirtIOSerialPort *port;
+
+ vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+ port = find_port_by_id(vser, 0);
+
+ if (port && !use_multiport(port->vser)
+ && (status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ /*
+ * Non-multiport guests won't be able to tell us guest
+ * open/close status. Such guests can only have a port at id
+ * 0, so set guest_connected for such ports as soon as guest
+ * is up.
+ */
+ port->guest_connected = true;
+ }
+ if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ guest_reset(vser);
+ }
+}
+
+static void vser_reset(VirtIODevice *vdev)
+{
+ VirtIOSerial *vser;
+
+ vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+ guest_reset(vser);
+}
+
static void virtio_serial_save(QEMUFile *f, void *opaque)
{
VirtIOSerial *s = opaque;
@@ -798,14 +845,6 @@ static int virtser_port_qdev_init(DeviceState *qdev)
return ret;
}
- if (!use_multiport(port->vser)) {
- /*
- * Allow writes to guest in this case; we have no way of
- * knowing if a guest port is connected.
- */
- port->guest_connected = true;
- }
-
port->elem.out_num = 0;
QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
@@ -905,6 +944,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
vser->vdev.get_features = get_features;
vser->vdev.get_config = get_config;
vser->vdev.set_config = set_config;
+ vser->vdev.set_status = set_status;
+ vser->vdev.reset = vser_reset;
vser->qdev = dev;
diff --git a/hw/virtio.c b/hw/virtio.c
index 314abf8a18..168abe4864 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -209,6 +209,10 @@ void virtio_queue_set_notification(VirtQueue *vq, int enable)
} else {
vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
}
+ if (enable) {
+ /* Expose avail event/used flags before caller checks the avail idx. */
+ smp_mb();
+ }
}
int virtio_queue_ready(VirtQueue *vq)
@@ -283,6 +287,11 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
idx, vring_avail_idx(vq));
exit(1);
}
+ /* On success, callers read a descriptor at vq->last_avail_idx.
+ * Make sure descriptor read does not bypass avail index read. */
+ if (num_heads) {
+ smp_rmb();
+ }
return num_heads;
}
@@ -700,6 +709,8 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
{
uint16_t old, new;
bool v;
+ /* We need to expose used array entries before checking used event. */
+ smp_mb();
/* Always notify when queue is empty (when feature acknowledge) */
if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) &&
!vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) {
diff --git a/main-loop.c b/main-loop.c
index 4887c732fa..24cf540e66 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -226,7 +226,7 @@ static int max_priority;
#ifndef _WIN32
static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
- fd_set *xfds, int *cur_timeout)
+ fd_set *xfds, uint32_t *cur_timeout)
{
GMainContext *context = g_main_context_default();
int i;
@@ -288,20 +288,24 @@ static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
}
}
-static int os_host_main_loop_wait(int timeout)
+static int os_host_main_loop_wait(uint32_t timeout)
{
- struct timeval tv;
+ struct timeval tv, *tvarg = NULL;
int ret;
glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
+ if (timeout < UINT32_MAX) {
+ tvarg = &tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ }
+
if (timeout > 0) {
qemu_mutex_unlock_iothread();
}
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+ ret = select(nfds + 1, &rfds, &wfds, &xfds, tvarg);
if (timeout > 0) {
qemu_mutex_lock_iothread();
@@ -400,12 +404,13 @@ void qemu_fd_register(int fd)
FD_CONNECT | FD_WRITE | FD_OOB);
}
-static int os_host_main_loop_wait(int timeout)
+static int os_host_main_loop_wait(uint32_t timeout)
{
GMainContext *context = g_main_context_default();
int ret, i;
PollingEntry *pe;
WaitObjects *w = &wait_objects;
+ gint poll_timeout;
static struct timeval tv0;
/* XXX: need to suppress polling by better using win32 events */
@@ -420,12 +425,12 @@ static int os_host_main_loop_wait(int timeout)
if (nfds >= 0) {
ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
if (ret != 0) {
- timeout = 0;
+ /* TODO. */
}
}
g_main_context_prepare(context, &max_priority);
- n_poll_fds = g_main_context_query(context, max_priority, &timeout,
+ n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout,
poll_fds, ARRAY_SIZE(poll_fds));
g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
@@ -435,7 +440,7 @@ static int os_host_main_loop_wait(int timeout)
}
qemu_mutex_unlock_iothread();
- ret = g_poll(poll_fds, n_poll_fds + w->num, timeout);
+ ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout);
qemu_mutex_lock_iothread();
if (ret > 0) {
for (i = 0; i < w->num; i++) {
@@ -463,12 +468,12 @@ static int os_host_main_loop_wait(int timeout)
int main_loop_wait(int nonblocking)
{
- int ret, timeout;
+ int ret;
+ uint32_t timeout = UINT32_MAX;
if (nonblocking) {
timeout = 0;
} else {
- timeout = qemu_calculate_timeout();
qemu_bh_update_timeout(&timeout);
}
@@ -480,6 +485,7 @@ int main_loop_wait(int nonblocking)
FD_ZERO(&xfds);
#ifdef CONFIG_SLIRP
+ slirp_update_timeout(&timeout);
slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
#endif
qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
diff --git a/main-loop.h b/main-loop.h
index e743aa0cf6..c06b8bc441 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -365,6 +365,6 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc
void qemu_bh_schedule_idle(QEMUBH *bh);
int qemu_bh_poll(void);
-void qemu_bh_update_timeout(int *timeout);
+void qemu_bh_update_timeout(uint32_t *timeout);
#endif
diff --git a/os-posix.c b/os-posix.c
index e3ed497224..daf3d6f6f3 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -44,6 +44,10 @@
#include <sys/prctl.h>
#endif
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#endif
+
static struct passwd *user_pwd;
static const char *chroot_dir;
static int daemonize;
diff --git a/osdep.h b/osdep.h
index 428285c7e0..9db8766964 100644
--- a/osdep.h
+++ b/osdep.h
@@ -10,6 +10,13 @@
#include <sys/time.h>
+#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
+/* [u]int_fast*_t not in <sys/int_types.h> */
+typedef unsigned char uint_fast8_t;
+typedef unsigned int uint_fast16_t;
+typedef signed int int_fast16_t;
+#endif
+
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
diff --git a/pc-bios/qemu-icon.bmp b/pc-bios/qemu-icon.bmp
new file mode 100644
index 0000000000..72d9a2f561
--- /dev/null
+++ b/pc-bios/qemu-icon.bmp
Binary files differ
diff --git a/qapi-schema.json b/qapi-schema.json
index 64998959db..9193fb9968 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1571,15 +1571,19 @@
#
# @base: #optional the common backing file name
#
+# @speed: #optional the maximum speed, in bytes per second
+#
# Returns: Nothing on success
# If streaming is already active on this device, DeviceInUse
# If @device does not exist, DeviceNotFound
# If image streaming is not supported by this device, NotSupported
# If @base does not exist, BaseNotFound
+# If @speed is invalid, InvalidParameter
#
# Since: 1.1
##
-{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str' } }
+{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str',
+ '*speed': 'int' } }
##
# @block-job-set-speed:
@@ -1592,16 +1596,18 @@
#
# @device: the device name
#
-# @value: the maximum speed, in bytes per second
+# @speed: the maximum speed, in bytes per second, or 0 for unlimited.
+# Defaults to 0.
#
# Returns: Nothing on success
# If the job type does not support throttling, NotSupported
+# If the speed value is invalid, InvalidParameter
# If streaming is not active on this device, DeviceNotActive
#
# Since: 1.1
##
{ 'command': 'block-job-set-speed',
- 'data': { 'device': 'str', 'value': 'int' } }
+ 'data': { 'device': 'str', 'speed': 'int' } }
##
# @block-job-cancel:
diff --git a/qemu-barrier.h b/qemu-barrier.h
index c11bb2b59f..7e11197814 100644
--- a/qemu-barrier.h
+++ b/qemu-barrier.h
@@ -4,34 +4,61 @@
/* Compiler barrier */
#define barrier() asm volatile("" ::: "memory")
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
/*
- * Because of the strongly ordered x86 storage model, wmb() is a nop
+ * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops
* on x86(well, a compiler barrier only). Well, at least as long as
* qemu doesn't do accesses to write-combining memory or non-temporal
* load/stores from C code.
*/
#define smp_wmb() barrier()
+#define smp_rmb() barrier()
+/*
+ * We use GCC builtin if it's available, as that can use
+ * mfence on 32 bit as well, e.g. if built with -march=pentium-m.
+ * However, on i386, there seem to be known bugs as recently as 4.3.
+ * */
+#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define smp_mb() __sync_synchronize()
+#else
+#define smp_mb() asm volatile("lock; addl $0,0(%%esp) " ::: "memory")
+#endif
+
+#elif defined(__x86_64__)
+
+#define smp_wmb() barrier()
+#define smp_rmb() barrier()
+#define smp_mb() asm volatile("mfence" ::: "memory")
#elif defined(_ARCH_PPC)
/*
- * We use an eieio() for a wmb() on powerpc. This assumes we don't
+ * We use an eieio() for wmb() on powerpc. This assumes we don't
* need to order cacheable and non-cacheable stores with respect to
* each other
*/
#define smp_wmb() asm volatile("eieio" ::: "memory")
+#if defined(__powerpc64__)
+#define smp_rmb() asm volatile("lwsync" ::: "memory")
+#else
+#define smp_rmb() asm volatile("sync" ::: "memory")
+#endif
+
+#define smp_mb() asm volatile("sync" ::: "memory")
+
#else
/*
* For (host) platforms we don't have explicit barrier definitions
* for, we use the gcc __sync_synchronize() primitive to generate a
* full barrier. This should be safe on all platforms, though it may
- * be overkill.
+ * be overkill for wmb() and rmb().
*/
#define smp_wmb() __sync_synchronize()
+#define smp_mb() __sync_synchronize()
+#define smp_rmb() __sync_synchronize()
#endif
diff --git a/qemu-timer.c b/qemu-timer.c
index 17915df22d..8eadd16aa2 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -29,23 +29,16 @@
#include "hw/hw.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <signal.h>
+#include "qemu-timer.h"
+
#ifdef __FreeBSD__
#include <sys/param.h>
#endif
#ifdef _WIN32
-#include <windows.h>
#include <mmsystem.h>
#endif
-#include "qemu-timer.h"
-
/***********************************************************/
/* timers */
@@ -54,22 +47,22 @@
#define QEMU_CLOCK_HOST 2
struct QEMUClock {
- int type;
- int enabled;
-
QEMUTimer *active_timers;
NotifierList reset_notifiers;
int64_t last;
+
+ int type;
+ bool enabled;
};
struct QEMUTimer {
- QEMUClock *clock;
int64_t expire_time; /* in nanoseconds */
- int scale;
+ QEMUClock *clock;
QEMUTimerCB *cb;
void *opaque;
- struct QEMUTimer *next;
+ QEMUTimer *next;
+ int scale;
};
struct qemu_alarm_timer {
@@ -78,13 +71,13 @@ struct qemu_alarm_timer {
void (*stop)(struct qemu_alarm_timer *t);
void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
#if defined(__linux__)
- int fd;
timer_t timer;
+ int fd;
#elif defined(_WIN32)
HANDLE timer;
#endif
- char expired;
- char pending;
+ bool expired;
+ bool pending;
};
static struct qemu_alarm_timer *alarm_timer;
@@ -94,35 +87,23 @@ static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
return timer_head && (timer_head->expire_time <= current_time);
}
-int qemu_alarm_pending(void)
-{
- return alarm_timer->pending;
-}
-
-static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
-{
- return !!t->rearm;
-}
-
static int64_t qemu_next_alarm_deadline(void)
{
- int64_t delta;
+ int64_t delta = INT64_MAX;
int64_t rtdelta;
- if (!use_icount && vm_clock->active_timers) {
+ if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
delta = vm_clock->active_timers->expire_time -
qemu_get_clock_ns(vm_clock);
- } else {
- delta = INT32_MAX;
}
- if (host_clock->active_timers) {
+ if (host_clock->enabled && host_clock->active_timers) {
int64_t hdelta = host_clock->active_timers->expire_time -
qemu_get_clock_ns(host_clock);
if (hdelta < delta) {
delta = hdelta;
}
}
- if (rt_clock->active_timers) {
+ if (rt_clock->enabled && rt_clock->active_timers) {
rtdelta = (rt_clock->active_timers->expire_time -
qemu_get_clock_ns(rt_clock));
if (rtdelta < delta) {
@@ -136,7 +117,6 @@ static int64_t qemu_next_alarm_deadline(void)
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
{
int64_t nearest_delta_ns;
- assert(alarm_has_dynticks(t));
if (!rt_clock->active_timers &&
!vm_clock->active_timers &&
!host_clock->active_timers) {
@@ -263,13 +243,13 @@ static QEMUClock *qemu_new_clock(int type)
clock = g_malloc0(sizeof(QEMUClock));
clock->type = type;
- clock->enabled = 1;
+ clock->enabled = true;
clock->last = INT64_MIN;
notifier_list_init(&clock->reset_notifiers);
return clock;
}
-void qemu_clock_enable(QEMUClock *clock, int enabled)
+void qemu_clock_enable(QEMUClock *clock, bool enabled)
{
bool old = clock->enabled;
clock->enabled = enabled;
@@ -382,17 +362,18 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
qemu_mod_timer_ns(ts, expire_time * ts->scale);
}
-int qemu_timer_pending(QEMUTimer *ts)
+bool qemu_timer_pending(QEMUTimer *ts)
{
QEMUTimer *t;
for (t = ts->clock->active_timers; t != NULL; t = t->next) {
- if (t == ts)
- return 1;
+ if (t == ts) {
+ return true;
+ }
}
- return 0;
+ return false;
}
-int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
+bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
{
return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
}
@@ -470,7 +451,7 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
void qemu_run_all_timers(void)
{
- alarm_timer->pending = 0;
+ alarm_timer->pending = false;
/* vm time timers */
qemu_run_timers(vm_clock);
@@ -479,7 +460,7 @@ void qemu_run_all_timers(void)
/* rearm timer, if not periodic */
if (alarm_timer->expired) {
- alarm_timer->expired = 0;
+ alarm_timer->expired = false;
qemu_rearm_alarm_timer(alarm_timer);
}
}
@@ -494,12 +475,9 @@ static void host_alarm_handler(int host_signum)
if (!t)
return;
- if (alarm_has_dynticks(t) ||
- qemu_next_alarm_deadline () <= 0) {
- t->expired = alarm_has_dynticks(t);
- t->pending = 1;
- qemu_notify_event();
- }
+ t->expired = true;
+ t->pending = true;
+ qemu_notify_event();
}
#if defined(__linux__)
@@ -535,10 +513,6 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
perror("timer_create");
-
- /* disable dynticks */
- fprintf(stderr, "Dynamic Ticks disabled\n");
-
return -1;
}
@@ -647,17 +621,14 @@ static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
if (!t) {
return;
}
- if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {
- t->expired = alarm_has_dynticks(t);
- t->pending = 1;
- qemu_notify_event();
- }
+ t->expired = true;
+ t->pending = true;
+ qemu_notify_event();
}
static int mm_start_timer(struct qemu_alarm_timer *t)
{
TIMECAPS tc;
- UINT flags;
memset(&tc, 0, sizeof(tc));
timeGetDevCaps(&tc, sizeof(tc));
@@ -665,18 +636,11 @@ static int mm_start_timer(struct qemu_alarm_timer *t)
mm_period = tc.wPeriodMin;
timeBeginPeriod(mm_period);
- flags = TIME_CALLBACK_FUNCTION;
- if (alarm_has_dynticks(t)) {
- flags |= TIME_ONESHOT;
- } else {
- flags |= TIME_PERIODIC;
- }
-
mm_timer = timeSetEvent(1, /* interval (ms) */
mm_period, /* resolution */
mm_alarm_handler, /* function */
(DWORD_PTR)t, /* parameter */
- flags);
+ TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
if (!mm_timer) {
fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
@@ -696,13 +660,17 @@ static void mm_stop_timer(struct qemu_alarm_timer *t)
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
{
- int nearest_delta_ms = (delta + 999999) / 1000000;
+ int64_t nearest_delta_ms = delta / 1000000;
if (nearest_delta_ms < 1) {
nearest_delta_ms = 1;
}
+ /* UINT_MAX can be 32 bit */
+ if (nearest_delta_ms > UINT_MAX) {
+ nearest_delta_ms = UINT_MAX;
+ }
timeKillEvent(mm_timer);
- mm_timer = timeSetEvent(nearest_delta_ms,
+ mm_timer = timeSetEvent((unsigned int) nearest_delta_ms,
mm_period,
mm_alarm_handler,
(DWORD_PTR)t,
@@ -731,7 +699,7 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
host_alarm_handler,
t,
1,
- alarm_has_dynticks(t) ? 3600000 : 1,
+ 3600000,
WT_EXECUTEINTIMERTHREAD);
if (!success) {
@@ -757,16 +725,20 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t,
int64_t nearest_delta_ns)
{
HANDLE hTimer = t->timer;
- int nearest_delta_ms;
+ int64_t nearest_delta_ms;
BOOLEAN success;
- nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;
+ nearest_delta_ms = nearest_delta_ns / 1000000;
if (nearest_delta_ms < 1) {
nearest_delta_ms = 1;
}
+ /* ULONG_MAX can be 32 bit */
+ if (nearest_delta_ms > ULONG_MAX) {
+ nearest_delta_ms = ULONG_MAX;
+ }
success = ChangeTimerQueueTimer(NULL,
hTimer,
- nearest_delta_ms,
+ (unsigned long) nearest_delta_ms,
3600000);
if (!success) {
@@ -806,7 +778,7 @@ int init_timer_alarm(void)
/* first event is at time 0 */
atexit(quit_timers);
- t->pending = 1;
+ t->pending = true;
alarm_timer = t;
return 0;
@@ -815,8 +787,3 @@ fail:
return err;
}
-int qemu_calculate_timeout(void)
-{
- return 1000;
-}
-
diff --git a/qemu-timer.h b/qemu-timer.h
index 661bbe76b2..5175419e5f 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -4,12 +4,6 @@
#include "qemu-common.h"
#include "main-loop.h"
#include "notify.h"
-#include <time.h>
-#include <sys/time.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
/* timers */
@@ -42,7 +36,7 @@ int64_t qemu_get_clock_ns(QEMUClock *clock);
int64_t qemu_clock_has_timers(QEMUClock *clock);
int64_t qemu_clock_expired(QEMUClock *clock);
int64_t qemu_clock_deadline(QEMUClock *clock);
-void qemu_clock_enable(QEMUClock *clock, int enabled);
+void qemu_clock_enable(QEMUClock *clock, bool enabled);
void qemu_clock_warp(QEMUClock *clock);
void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
@@ -55,15 +49,13 @@ void qemu_free_timer(QEMUTimer *ts);
void qemu_del_timer(QEMUTimer *ts);
void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
-int qemu_timer_pending(QEMUTimer *ts);
-int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
+bool qemu_timer_pending(QEMUTimer *ts);
+bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
void qemu_run_timers(QEMUClock *clock);
void qemu_run_all_timers(void);
-int qemu_alarm_pending(void);
void configure_alarms(char const *opt);
-int qemu_calculate_timeout(void);
void init_clocks(void);
int init_timer_alarm(void);
diff --git a/qemu-tool.c b/qemu-tool.c
index 6579b00552..07fc4f201a 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -90,6 +90,10 @@ int qemu_init_main_loop(void)
return main_loop_init();
}
+void slirp_update_timeout(uint32_t *timeout)
+{
+}
+
void slirp_select_fill(int *pnfds, fd_set *readfds,
fd_set *writefds, fd_set *xfds)
{
diff --git a/qmp-commands.hx b/qmp-commands.hx
index f97233223d..c810c74c11 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -688,13 +688,13 @@ EQMP
{
.name = "block-stream",
- .args_type = "device:B,base:s?",
+ .args_type = "device:B,base:s?,speed:o?",
.mhandler.cmd_new = qmp_marshal_input_block_stream,
},
{
.name = "block-job-set-speed",
- .args_type = "device:B,value:o",
+ .args_type = "device:B,speed:o",
.mhandler.cmd_new = qmp_marshal_input_block_job_set_speed,
},
diff --git a/rules.mak b/rules.mak
index c30093c116..efef6f242d 100644
--- a/rules.mak
+++ b/rules.mak
@@ -59,6 +59,9 @@ find-in-path = $(if $(find-string /, $1), \
$(wildcard $1), \
$(wildcard $(patsubst %, %/$1, $(subst :, ,$(PATH)))))
+# Generate files with tracetool
+TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py
+
# Generate timestamp files for .h include files
%.h: %.h-timestamp
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 890fd86c3c..77527ad922 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -15,6 +15,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
struct in_addr vnameserver, void *opaque);
void slirp_cleanup(Slirp *slirp);
+void slirp_update_timeout(uint32_t *timeout);
void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 1502830978..90473eb74a 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -258,6 +258,13 @@ void slirp_cleanup(Slirp *slirp)
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
+void slirp_update_timeout(uint32_t *timeout)
+{
+ if (!QTAILQ_EMPTY(&slirp_instances)) {
+ *timeout = MIN(1000, *timeout);
+ }
+}
+
void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index b6c044a251..a61c68d21b 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -21,7 +21,6 @@
#define QEMU_ARM_CPU_QOM_H
#include "qemu/cpu.h"
-#include "cpu.h"
#define TYPE_ARM_CPU "arm-cpu"
@@ -94,6 +93,7 @@ typedef struct ARMCPU {
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
*/
uint32_t ccsidr[16];
+ uint32_t reset_cbar;
} ARMCPU;
static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index cc67d4d9f4..7eb323ae4d 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -18,7 +18,7 @@
* <http://www.gnu.org/licenses/gpl-2.0.html>
*/
-#include "cpu-qom.h"
+#include "cpu.h"
#include "qemu-common.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
@@ -30,7 +30,6 @@ static void arm_cpu_reset(CPUState *s)
ARMCPU *cpu = ARM_CPU(s);
ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
CPUARMState *env = &cpu->env;
- uint32_t tmp = 0;
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
@@ -39,9 +38,8 @@ static void arm_cpu_reset(CPUState *s)
acc->parent_reset(s);
- tmp = env->cp15.c15_config_base_address;
memset(env, 0, offsetof(CPUARMState, breakpoints));
- env->cp15.c15_config_base_address = tmp;
+ env->cp15.c15_config_base_address = cpu->reset_cbar;
env->cp15.c0_cpuid = cpu->midr;
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 01e0e36c2f..5eac070379 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -238,7 +238,9 @@ typedef struct CPUARMState {
const struct arm_boot_info *boot_info;
} CPUARMState;
-CPUARMState *cpu_arm_init(const char *cpu_model);
+#include "cpu-qom.h"
+
+ARMCPU *cpu_arm_init(const char *cpu_model);
void arm_translate_init(void);
int cpu_arm_exec(CPUARMState *s);
void do_interrupt(CPUARMState *);
@@ -456,7 +458,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
#define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32
-#define cpu_init cpu_arm_init
+#define cpu_init(model) (&cpu_arm_init(model)->env)
#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#define cpu_signal_handler cpu_arm_signal_handler
@@ -483,7 +485,6 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
#endif
#include "cpu-all.h"
-#include "cpu-qom.h"
/* Bit usage in the TB flags field: */
#define ARM_TBFLAG_THUMB_SHIFT 0
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 101031dd75..7e1c2c06bd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -61,7 +61,7 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
-CPUARMState *cpu_arm_init(const char *cpu_model)
+ARMCPU *cpu_arm_init(const char *cpu_model)
{
ARMCPU *cpu;
CPUARMState *env;
@@ -92,7 +92,7 @@ CPUARMState *cpu_arm_init(const char *cpu_model)
19, "arm-vfp.xml", 0);
}
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
typedef struct ARMCPUListState {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 7a3c7d650c..437d9dbf0e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6767,8 +6767,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if ((insn & 0x0ffffdff) == 0x01010000) {
ARCH(6);
/* setend */
- if (insn & (1 << 9)) {
- /* BE8 mode not implemented. */
+ if (((insn >> 9) & 1) != s->bswap_code) {
+ /* Dynamic endianness switching not implemented. */
goto illegal_op;
}
return;
@@ -9710,8 +9710,8 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
case 2:
/* setend */
ARCH(6);
- if (insn & (1 << 3)) {
- /* BE8 mode not implemented. */
+ if (((insn >> 3) & 1) != s->bswap_code) {
+ /* Dynamic endianness switching not implemented. */
goto illegal_op;
}
break;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 3df53ca74b..65d9af6ac7 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -27,6 +27,8 @@
#include "qemu-option.h"
#include "qemu-config.h"
+#include "qapi/qapi-visit-core.h"
+
#include "hyperv.h"
/* feature flags taken from "Intel Processor Identification and the CPUID
@@ -597,36 +599,252 @@ static int check_features_against_host(x86_def_t *guest_def)
return rv;
}
-static void x86_cpuid_version_set_family(CPUX86State *env, int family)
+static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = (env->cpuid_version >> 8) & 0xf;
+ if (value == 0xf) {
+ value += (env->cpuid_version >> 20) & 0xff;
+ }
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xff + 0xf;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
env->cpuid_version &= ~0xff00f00;
- if (family > 0x0f) {
- env->cpuid_version |= 0xf00 | ((family - 0x0f) << 20);
+ if (value > 0x0f) {
+ env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
} else {
- env->cpuid_version |= family << 8;
+ env->cpuid_version |= value << 8;
}
}
-static void x86_cpuid_version_set_model(CPUX86State *env, int model)
+static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = (env->cpuid_version >> 4) & 0xf;
+ value |= ((env->cpuid_version >> 16) & 0xf) << 4;
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xff;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
env->cpuid_version &= ~0xf00f0;
- env->cpuid_version |= ((model & 0xf) << 4) | ((model >> 4) << 16);
+ env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
}
-static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping)
+static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = env->cpuid_version & 0xf;
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xf;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
env->cpuid_version &= ~0xf;
- env->cpuid_version |= stepping & 0xf;
+ env->cpuid_version |= value & 0xf;
}
-static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id)
+static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value;
+
+ value = cpu->env.cpuid_level;
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ const int64_t min = 0;
+ const int64_t max = UINT32_MAX;
+ int64_t value;
+
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ cpu->env.cpuid_level = value;
+}
+
+static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value;
+
+ value = cpu->env.cpuid_xlevel;
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ const int64_t min = 0;
+ const int64_t max = UINT32_MAX;
+ int64_t value;
+
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ cpu->env.cpuid_xlevel = value;
+}
+
+static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ char *value;
+ int i;
+
+ value = (char *)g_malloc(12 + 1);
+ for (i = 0; i < 4; i++) {
+ value[i ] = env->cpuid_vendor1 >> (8 * i);
+ value[i + 4] = env->cpuid_vendor2 >> (8 * i);
+ value[i + 8] = env->cpuid_vendor3 >> (8 * i);
+ }
+ value[12] = '\0';
+ return value;
+}
+
+static void x86_cpuid_set_vendor(Object *obj, const char *value,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int i;
+
+ if (strlen(value) != 12) {
+ error_set(errp, QERR_PROPERTY_VALUE_BAD, "",
+ "vendor", value);
+ return;
+ }
+
+ env->cpuid_vendor1 = 0;
+ env->cpuid_vendor2 = 0;
+ env->cpuid_vendor3 = 0;
+ for (i = 0; i < 4; i++) {
+ env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i);
+ env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
+ env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
+ }
+ env->cpuid_vendor_override = 1;
+}
+
+static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ char *value;
+ int i;
+
+ value = g_malloc(48 + 1);
+ for (i = 0; i < 48; i++) {
+ value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
+ }
+ value[48] = '\0';
+ return value;
+}
+
+static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
int c, len, i;
if (model_id == NULL) {
model_id = "";
}
len = strlen(model_id);
+ memset(env->cpuid_model, 0, 48);
for (i = 0; i < 48; i++) {
if (i >= len) {
c = '\0';
@@ -637,6 +855,37 @@ static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id)
}
}
+static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value;
+
+ value = cpu->env.tsc_khz * 1000;
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ const int64_t min = 0;
+ const int64_t max = INT_MAX;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ cpu->env.tsc_khz = value / 1000;
+}
+
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
{
unsigned int i;
@@ -690,7 +939,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
if (!strcmp(featurestr, "family")) {
char *err;
numvalue = strtoul(val, &err, 0);
- if (!*val || *err) {
+ if (!*val || *err || numvalue > 0xff + 0xf) {
fprintf(stderr, "bad numerical value %s\n", val);
goto error;
}
@@ -904,9 +1153,11 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
}
}
-int cpu_x86_register (CPUX86State *env, const char *cpu_model)
+int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
{
+ CPUX86State *env = &cpu->env;
x86_def_t def1, *def = &def1;
+ Error *error = NULL;
memset(def, 0, sizeof(*def));
@@ -922,20 +1173,21 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
}
env->cpuid_vendor_override = def->vendor_override;
- env->cpuid_level = def->level;
- x86_cpuid_version_set_family(env, def->family);
- x86_cpuid_version_set_model(env, def->model);
- x86_cpuid_version_set_stepping(env, def->stepping);
+ object_property_set_int(OBJECT(cpu), def->level, "level", &error);
+ object_property_set_int(OBJECT(cpu), def->family, "family", &error);
+ object_property_set_int(OBJECT(cpu), def->model, "model", &error);
+ object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error);
env->cpuid_features = def->features;
env->cpuid_ext_features = def->ext_features;
env->cpuid_ext2_features = def->ext2_features;
env->cpuid_ext3_features = def->ext3_features;
- env->cpuid_xlevel = def->xlevel;
+ object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error);
env->cpuid_kvm_features = def->kvm_features;
env->cpuid_svm_features = def->svm_features;
env->cpuid_ext4_features = def->ext4_features;
env->cpuid_xlevel2 = def->xlevel2;
- env->tsc_khz = def->tsc_khz;
+ object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
+ "tsc-frequency", &error);
if (!kvm_enabled()) {
env->cpuid_features &= TCG_FEATURES;
env->cpuid_ext_features &= TCG_EXT_FEATURES;
@@ -947,7 +1199,11 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
env->cpuid_svm_features &= TCG_SVM_FEATURES;
}
- x86_cpuid_set_model_id(env, def->model_id);
+ object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error);
+ if (error_is_set(&error)) {
+ error_free(error);
+ return -1;
+ }
return 0;
}
@@ -1472,6 +1728,32 @@ static void x86_cpu_initfn(Object *obj)
CPUX86State *env = &cpu->env;
cpu_exec_init(env);
+
+ object_property_add(obj, "family", "int",
+ x86_cpuid_version_get_family,
+ x86_cpuid_version_set_family, NULL, NULL, NULL);
+ object_property_add(obj, "model", "int",
+ x86_cpuid_version_get_model,
+ x86_cpuid_version_set_model, NULL, NULL, NULL);
+ object_property_add(obj, "stepping", "int",
+ x86_cpuid_version_get_stepping,
+ x86_cpuid_version_set_stepping, NULL, NULL, NULL);
+ object_property_add(obj, "level", "int",
+ x86_cpuid_get_level,
+ x86_cpuid_set_level, NULL, NULL, NULL);
+ object_property_add(obj, "xlevel", "int",
+ x86_cpuid_get_xlevel,
+ x86_cpuid_set_xlevel, NULL, NULL, NULL);
+ object_property_add_str(obj, "vendor",
+ x86_cpuid_get_vendor,
+ x86_cpuid_set_vendor, NULL);
+ object_property_add_str(obj, "model-id",
+ x86_cpuid_get_model_id,
+ x86_cpuid_set_model_id, NULL);
+ object_property_add(obj, "tsc-frequency", "int",
+ x86_cpuid_get_tsc_freq,
+ x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
+
env->cpuid_apic_id = env->cpu_index;
mce_init(cpu);
}
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 4bb4592db5..b5b9a50695 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -901,7 +901,7 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo,
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx);
-int cpu_x86_register (CPUX86State *env, const char *cpu_model);
+int cpu_x86_register(X86CPU *cpu, const char *cpu_model);
void cpu_clear_apic_feature(CPUX86State *env);
void host_cpuid(uint32_t function, uint32_t count,
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 87954f0919..0b22582ed6 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1176,7 +1176,7 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
cpu_set_debug_excp_handler(breakpoint_handler);
#endif
}
- if (cpu_x86_register(env, cpu_model) < 0) {
+ if (cpu_x86_register(cpu, cpu_model) < 0) {
object_delete(OBJECT(cpu));
return NULL;
}
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 99b416c47f..c0f882659c 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -15,13 +15,6 @@
#include "cpu-defs.h"
#include "softfloat.h"
-// uint_fast8_t and uint_fast16_t not in <sys/int_types.h>
-// XXX: move that elsewhere
-#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
-typedef unsigned char uint_fast8_t;
-typedef unsigned int uint_fast16_t;
-#endif
-
struct CPUMIPSState;
typedef struct r4k_tlb_t r4k_tlb_t;
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 1ce6fa10df..295c6d49d0 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <string.h>
+#include "compiler.h"
#include "osdep.h"
#define MAX_IRQ 256
@@ -130,7 +131,7 @@ void qtest_quit(QTestState *s)
}
}
-static void qtest_sendf(QTestState *s, const char *fmt, ...)
+static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
{
va_list ap;
gchar *str;
@@ -356,7 +357,7 @@ void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)
gchar **args;
size_t i;
- qtest_sendf(s, "read 0x%" PRIx64 " 0x%x\n", addr, size);
+ qtest_sendf(s, "read 0x%" PRIx64 " 0x%zx\n", addr, size);
args = qtest_rsp(s, 2);
for (i = 0; i < size; i++) {
@@ -378,7 +379,7 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)
const uint8_t *ptr = data;
size_t i;
- qtest_sendf(s, "write 0x%" PRIx64 " 0x%x 0x", addr, size);
+ qtest_sendf(s, "write 0x%" PRIx64 " 0x%zx 0x", addr, size);
for (i = 0; i < size; i++) {
qtest_sendf(s, "%02x", ptr[i]);
}
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 978fd82224..38abc2ce77 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -32,6 +32,21 @@ class ImageStreamingTestCase(iotests.QMPTestCase):
result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return', [])
+ def cancel_and_wait(self, drive='drive0'):
+ '''Cancel a block job and wait for it to finish'''
+ result = self.vm.qmp('block-job-cancel', device=drive)
+ self.assert_qmp(result, 'return', {})
+
+ cancelled = False
+ while not cancelled:
+ for event in self.vm.get_qmp_events(wait=True):
+ if event['event'] == 'BLOCK_JOB_CANCELLED':
+ self.assert_qmp(event, 'data/type', 'stream')
+ self.assert_qmp(event, 'data/device', drive)
+ cancelled = True
+
+ self.assert_no_active_streams()
+
class TestSingleDrive(ImageStreamingTestCase):
image_len = 1 * 1024 * 1024 # MB
@@ -97,21 +112,8 @@ class TestStreamStop(ImageStreamingTestCase):
events = self.vm.get_qmp_events(wait=False)
self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
- self.vm.qmp('block-job-cancel', device='drive0')
- self.assert_qmp(result, 'return', {})
+ self.cancel_and_wait()
- cancelled = False
- while not cancelled:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_CANCELLED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- cancelled = True
-
- self.assert_no_active_streams()
-
-# This is a short performance test which is not run by default.
-# Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_set_speed"
class TestSetSpeed(ImageStreamingTestCase):
image_len = 80 * 1024 * 1024 # MB
@@ -126,13 +128,15 @@ class TestSetSpeed(ImageStreamingTestCase):
os.remove(test_img)
os.remove(backing_img)
- def perf_test_set_speed(self):
+ # This is a short performance test which is not run by default.
+ # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
+ def perf_test_throughput(self):
self.assert_no_active_streams()
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('block-job-set-speed', device='drive0', value=8 * 1024 * 1024)
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
self.assert_qmp(result, 'return', {})
completed = False
@@ -147,5 +151,54 @@ class TestSetSpeed(ImageStreamingTestCase):
self.assert_no_active_streams()
+ def test_set_speed(self):
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block-stream', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ # Default speed is 0
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+ self.assert_qmp(result, 'return[0]/speed', 0)
+
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
+ self.assert_qmp(result, 'return', {})
+
+ # Ensure the speed we set was accepted
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+ self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
+
+ self.cancel_and_wait()
+
+ # Check setting speed in block-stream works
+ result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+ self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
+
+ self.cancel_and_wait()
+
+ def test_set_speed_invalid(self):
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block-stream', device='drive0', speed=-1)
+ self.assert_qmp(result, 'error/class', 'InvalidParameter')
+ self.assert_qmp(result, 'error/data/name', 'speed')
+
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block-stream', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
+ self.assert_qmp(result, 'error/class', 'InvalidParameter')
+ self.assert_qmp(result, 'error/data/name', 'speed')
+
+ self.cancel_and_wait()
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out
index 8d7e996700..914e3737bd 100644
--- a/tests/qemu-iotests/030.out
+++ b/tests/qemu-iotests/030.out
@@ -1,5 +1,5 @@
-...
+.....
----------------------------------------------------------------------
-Ran 3 tests
+Ran 5 tests
OK