Compare commits

...

28 Commits

Author SHA1 Message Date
Aurelien Jarno
9badf5579d target-mips: fix save_cpu_state() calls
The rule is:
- don't save PC if the exception is only triggered by softmmu.
- save PC if the exception can be triggered by an helper.

Fix a 64-bit kernel crash when loading modules.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit b835e919f0)
2011-01-24 20:52:19 +01:00
Aurelien Jarno
4a9048a914 target-sparc: fix udiv(cc) and sdiv(cc)
Since commit 5a4bb580cd, Xorg crashes on
a Debian Etch image. The commit itself is fine, but it triggers a bug
due to wrong computation of flags for udiv(cc) and sdiv(cc).

This patch only compute cc_src2 for the cc version of udiv/sdiv. It
also moves the update of cc_dst and cc_op to the helper, as it is
faster doing it here when there is already an helper.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 0fcec41eec)

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-12-28 23:18:37 +01:00
Aurelien Jarno
0282ff4d61 target-arm: fix bug in translation of REVSH
The translation of REVSH shifted the low byte 8 steps left before performing
an 8-bit sign extend, causing this part of the expression to alwas be 0.

Reported-by: Johan Bengtsson <teofrastius@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 1a855029af)

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-12-27 21:38:05 +01:00
Paul Brook
f0acb38015 Add missing dependency.
Teach Makefile that cmd.o depends on a generated header (specifically
config-host.h).

Signed-off-by: Paul Brook <paul@codesourcery.com>
(cherry picked from commit 6e14404aab)

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-12-26 00:06:30 +01:00
Anthony Liguori
6ed912999d Update for 0.13.0 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-10-14 10:00:59 -05:00
Michael S. Tsirkin
da5aeb8aeb vhost: error code
fix up errors returned to include errno, not just -1

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit c885212109)
2010-10-12 16:10:00 -05:00
Michael S. Tsirkin
7c763827a5 virtio: change set guest notifier to per-device
When using irqfd with vhost-net to inject interrupts,
a single evenfd might inject multiple interrupts.
Implementing this is much easier with a single
per-device callback to set guest notifiers.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 54dd932128)
2010-10-12 16:09:52 -05:00
Stefan Weil
e74f86377a eepro100: Add support for multiple individual addresses (multiple IA)
I reviewed the latest sources of Linux, FreeBSD and NetBSD.
They all reset the multiple IA bit (multi_ia in BSD) to zero,
but I did not find code which sets this bit to one
(like it is done by some routers).

Running Windows guests also did not set this bit.

Intel's Open Source Software Developer Manual does not
give much information on the semantics related to this bit,
so I had to guess how it works. The guess was good enough
to make the router emulation work.

Related changes in this patch:
* Update naming and documentation of the internal hash register.
  It is not limited to multicast, but also used for multiple IA.
* Dump complete configuration register when debug traces are enabled.
* Debug output when multiple IA bit is set during CmdConfigure.
* Debug output when frames are received because multiple IA bit is set,
  or when they are ignored although it is set.

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Stefan Weil <weil@mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 010ec62934)
2010-10-12 16:09:45 -05:00
Michael S. Tsirkin
286409ad63 virtio-net: unify vhost-net start/stop
Move all of vhost-net start/stop logic to a single routine,
and call it from everywhere.

Additionally, start/stop vhost-net on link up/down:
we should not transmit anything if user asked us to
put the link down.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Alex Williamson <alex.williamson@redhat.com>
2010-10-12 16:09:35 -05:00
Michael S. Tsirkin
8006040d47 virtio: invoke set_status callback on reset
As status is set to 0 on reset, invoke the relevant callback. This makes
for a cleaner code in devices as they don't need to duplicate the code
in their reset routine, as well as excercises this path a little more.

In particular this makes it possible to unify
vhost-net handling code with the following patch.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit e0c472d8c2)
2010-10-12 16:09:26 -05:00
Michael S. Tsirkin
456496e225 net: delay freeing peer host device
With -netdev, virtio devices present offload
features to guest, depending on the backend used.
Thus, removing host netdev peer while guest is
active leads to guest-visible inconsistency and/or crashes.

As a solution, while guest (NIC) peer device exists,
we prevent the host peer from being deleted.
This patch does this by adding peer_deleted flag in nic state:
if host device is going away while guest device
is around, set this flag and keep a shell of
the host device around for as long as guest device exists.

The link is put down so all packets will get discarded.

At the moment, management can detect that device deletion
is delayed by doing info net. As a next step, we shall add
commands that control hotplug/unplug without
removing the device, and an event to report that
guest has responded to the hotplug event.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Alex Williamson <alex.williamson@redhat.com>
(cherry picked from commit a083a89d72)
2010-10-12 16:09:19 -05:00
Anthony Liguori
a62e5f4120 Merge remote branch 'qmp/for-stable-0.13' into stable-0.13 2010-10-11 19:01:41 -05:00
Yoshiaki Tamura
c2ccc98ceb vnc: check fd before calling qemu_set_fd_handler2() in vnc_client_write()
Setting fd = -1 to qemu_set_fd_handler2() causes bus error at FD_SET
in main_loop_wait().

Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki@lab.ntt.co.jp>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit ac71103dc6)
2010-10-11 18:22:45 -05:00
Eduardo Habkost
8b84b68e7d disable guest-provided stats on "info balloon" command
The addition of memory stats reporting to the virtio balloon causes
the 'info balloon' command to become asynchronous.  This is a regression
because in some cases it can hang the user monitor.

This is an alternative to Adam Litke's patch. Adam's patch disabled the
corresponding (guest-visible) virtio feature bit, causing issues for migration.
Original discussion is available at:
http://marc.info/?l=qemu-devel&m=128448124328314&w=2

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Adam Litke <agl@us.ibm.com
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 07b0403dfc)
2010-10-11 18:22:18 -05:00
Anthony Liguori
14a0b95684 Revert "Make default invocation of block drivers safer (v3)"
This reverts commit 79368c81bf.

Conflicts:

	block.c

I haven't been able to come up with a solution yet for the corruption caused by
unaligned requests from the IDE disk so revert until a solution can be written.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 8b33d9eeba)
2010-10-11 18:20:59 -05:00
Avi Kivity
cb03355a26 QEMUFileBuffered: indicate that we're ready when the underlying file is ready
QEMUFileBuffered stops writing when the underlying QEMUFile is not ready,
and tells its producer so.  However, when the underlying QEMUFile becomes
ready, it neglects to pass that information along, resulting in stoppage
of all data until the next tick (a tenths of a second).

Usually this doesn't matter, because most QEMUFiles used with QEMUFileBuffered
are almost always ready, but in the case of exec: migration this is not true,
due to the small pipe buffers used to connect to the target process.  The
result is very slow migration.

Fix by detecting the readiness notification and propagating it.  The detection
is a little ugly since QEMUFile overloads put_buffer() to send it, but that's
the suject for a different patch.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 5e77aaa0d7)
2010-10-11 18:20:52 -05:00
Artyom Tarasenko
ddfe317152 sparc escc IUS improvements (SunOS 4.1.4 fix)
According to scc_escc_um.pdf:
 - Reset Highest IUS must update irq status to allow processing
   of the next priority interrupt.
 - rx interrupt has always higher priority than tx on same channel

The documentation only explicitly says that Reset Highest IUS
command (0x38) clears IUS bits, not that it clears the corresponding
interrupt too, so don't clear interrupts on this command.

The patch allows SunOS 4.1.4 to use the serial ports

Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 9fc391f8b5)
2010-10-11 18:20:45 -05:00
Artyom Tarasenko
9f20b55b9a fix last cpu timer initialization
The timer #0 is the system timer, so the timer #num_cpu is the
timer of the last CPU, and it must be initialized in slavio_timer_reset.

Don't mark non-existing timers as running.

Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 5933e8a96a)
2010-10-11 18:20:39 -05:00
Luiz Capitulino
a0a90b92c9 QMP/README: Update QMP homepage address
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit a18b2ce2ed)
2010-10-11 19:53:58 -03:00
Eduardo Habkost
7bd11bc311 disable guest-provided stats on "info balloon" command
The addition of memory stats reporting to the virtio balloon causes
the 'info balloon' command to become asynchronous.  This is a regression
because in some cases it can hang the user monitor.

This is an alternative to Adam Litke's patch. Adam's patch disabled the
corresponding (guest-visible) virtio feature bit, causing issues for migration.
Original discussion is available at:
http://marc.info/?l=qemu-devel&m=128448124328314&w=2

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Adam Litke <agl@us.ibm.com
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 07b0403dfc)
2010-10-11 19:53:31 -03:00
Luiz Capitulino
30811f0d94 QMP: Update README file
A number of changes I prefer to do in one shot:

- Fix example
- Small clarifications
- Add multiple monitors example
- Add 'Development Process' section

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d29f3196af)
2010-10-11 19:53:18 -03:00
Luiz Capitulino
0d88bb1bab QMP doc: Add 'Stability Considerations' section
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 05705ce2f8)
2010-10-11 19:53:13 -03:00
Miguel Di Ciurcio Filho
b73e06943b QMP/monitor: update do_info_version() to output broken down version string
This code was originally developed by Daniel P. Berrange <berrange@redhat.com>

Signed-off-by: Miguel Di Ciurcio Filho <miguel.filho@gmail.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 0ec0291d67)
2010-10-11 19:53:07 -03:00
Miguel Di Ciurcio Filho
f8e3ee1a7d QMP: update 'query-version' documentation
Update the documentation of 'query-version' to output the string version broken
down.

Signed-off-by: Miguel Di Ciurcio Filho <miguel.filho@gmail.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6597e1a6dc)
2010-10-11 19:53:01 -03:00
Alex Williamson
c082082c76 savevm: Reset last block info at beginning of each save
If we save more than once we need to reset the last block info or else
only the first save has the actual block info and each subsequent save
will only use continue flags, making them unloadable independently.

Found-by: Miguel Di Ciurcio Filho <miguel.filho@gmail.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 760e77eab5)
2010-10-11 19:52:37 -03:00
Marcelo Tosatti
c4127fbf17 set proper migration status on ->write error (v5)
If ->write fails, declare migration status as MIG_STATE_ERROR.

Also, in buffered_file.c, ->close the object in case of an
error.

Fixes "migrate -d "exec:dd of=file", where dd fails to open file.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e447b1a603)
2010-10-11 19:52:25 -03:00
Amit Shah
fc4e0c7018 migration: Accept 'cont' only after successful incoming migration
When a 'cont' is issued on a VM that's just waiting for an incoming
migration, the VM reboots and boots into the guest, possibly corrupting
its storage since it could be shared with another VM running elsewhere.

Ensure that a VM started with '-incoming' is only run when an incoming
migration successfully completes.

A new qerror, QERR_MIGRATION_EXPECTED, is added to signal that 'cont'
failed due to no incoming migration has been attempted yet.

Reported-by: Laine Stump <laine@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 8e84865e54)
2010-10-11 19:52:01 -03:00
Anthony Liguori
d25de8db83 Update for v0.13.0-rc3
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-10-11 17:09:10 -05:00
33 changed files with 416 additions and 322 deletions

View File

@@ -1,3 +1,5 @@
See git history for Changelogs of recent releases.
version 0.12.0:
- Update to SeaBIOS 0.5.0

View File

@@ -107,7 +107,7 @@ bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
######################################################################
qemu-img.o: qemu-img-cmds.h
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o: $(GENERATED_HEADERS)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(block-obj-y) $(qobject-obj-y)

View File

@@ -7,60 +7,85 @@ Introduction
The QEMU Monitor Protocol (QMP) allows applications to communicate with
QEMU's Monitor.
QMP is JSON[1] based and has the following features:
QMP is JSON[1] based and currently has the following features:
- Lightweight, text-based, easy to parse data format
- Asynchronous events support
- Stability
- Asynchronous messages support (ie. events)
- Capabilities Negotiation
For more information, please, refer to the following files:
For detailed information on QMP's usage, please, refer to the following files:
o qmp-spec.txt QEMU Monitor Protocol current specification
o qmp-commands.txt QMP supported commands
o qmp-commands.txt QMP supported commands (auto-generated at build-time)
o qmp-events.txt List of available asynchronous events
There are also two simple Python scripts available:
o qmp-shell A shell
o vm-info Show some information about the Virtual Machine
o qmp-shell A shell
o vm-info Show some information about the Virtual Machine
IMPORTANT: It's strongly recommended to read the 'Stability Considerations'
section in the qmp-commands.txt file before making any serious use of QMP.
[1] http://www.json.org
Usage
-----
To enable QMP, QEMU has to be started in "control mode". There are
two ways of doing this, the simplest one is using the the '-qmp'
command-line option.
To enable QMP, you need a QEMU monitor instance in "control mode". There are
two ways of doing this.
For example:
The simplest one is using the '-qmp' command-line option. The following
example makes QMP available on localhost port 4444:
$ qemu [...] -qmp tcp:localhost:4444,server
$ qemu [...] -qmp tcp:localhost:4444,server
Will start QEMU in control mode, waiting for a client TCP connection
on localhost port 4444.
However, in order to have more complex combinations, like multiple monitors,
the '-mon' command-line option should be used along with the '-chardev' one.
For instance, the following example creates one user monitor on stdio and one
QMP monitor on localhost port 4444.
It is also possible to use the '-mon' command-line option to have
more complex combinations. Please, refer to the QEMU's manpage for
more information.
$ qemu [...] -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \
-chardev socket,id=mon1,host=localhost,port=4444,server \
-mon chardev=mon1,mode=control
Please, refer to QEMU's manpage for more information.
Simple Testing
--------------
To manually test QMP one can connect with telnet and issue commands:
To manually test QMP one can connect with telnet and issue commands by hand:
$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
{"QMP": {"version": {"qemu": "0.12.50", "package": ""}, "capabilities": []}}
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 13, "major": 0}, "package": ""}, "capabilities": []}}
{ "execute": "qmp_capabilities" }
{"return": {}}
{ "execute": "query-version" }
{"return": {"qemu": "0.12.50", "package": ""}}
{"return": {"qemu": {"micro": 50, "minor": 13, "major": 0}, "package": ""}}
Contact
-------
Development Process
-------------------
http://www.linux-kvm.org/page/MonitorProtocol
Luiz Fernando N. Capitulino <lcapitulino@redhat.com>
When changing QMP's interface (by adding new commands, events or modifying
existing ones) it's mandatory to update the relevant documentation, which is
one (or more) of the files listed in the 'Introduction' section*.
Also, it's strongly recommended to send the documentation patch first, before
doing any code change. This is so because:
1. Avoids the code dictating the interface
2. Review can improve your interface. Letting that happen before
you implement it can save you work.
* The qmp-commands.txt file is generated from the qemu-monitor.hx one, which
is the file that should be edited.
Homepage
--------
http://wiki.qemu.org/QMP

View File

@@ -1 +1 @@
0.12.92
0.13.0

View File

@@ -104,10 +104,11 @@ static int is_dup_page(uint8_t *page, uint8_t ch)
return 1;
}
static RAMBlock *last_block;
static ram_addr_t last_offset;
static int ram_save_block(QEMUFile *f)
{
static RAMBlock *last_block = NULL;
static ram_addr_t last_offset = 0;
RAMBlock *block = last_block;
ram_addr_t offset = last_offset;
ram_addr_t current_addr;
@@ -231,6 +232,8 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
if (stage == 1) {
RAMBlock *block;
bytes_transferred = 0;
last_block = NULL;
last_offset = 0;
/* Make sure all dirty bits are set */
QLIST_FOREACH(block, &ram_list.blocks, next) {

View File

@@ -523,7 +523,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv)
{
int ret;
int probed = 0;
if (flags & BDRV_O_SNAPSHOT) {
BlockDriverState *bs1;
@@ -584,7 +583,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
/* Find the right image format driver */
if (!drv) {
ret = find_image_format(filename, &drv);
probed = 1;
}
if (!drv) {
@@ -597,8 +595,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
goto unlink_and_fail;
}
bs->probed = probed;
/* If there is a backing file, use it */
if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
char backing_filename[PATH_MAX];

View File

@@ -9,82 +9,15 @@ static int raw_open(BlockDriverState *bs, int flags)
return 0;
}
/* check for the user attempting to write something that looks like a
block format header to the beginning of the image and fail out.
*/
static int check_for_block_signature(BlockDriverState *bs, const uint8_t *buf)
{
static const uint8_t signatures[][4] = {
{ 'Q', 'F', 'I', 0xfb }, /* qcow/qcow2 */
{ 'C', 'O', 'W', 'D' }, /* VMDK3 */
{ 'V', 'M', 'D', 'K' }, /* VMDK4 */
{ 'O', 'O', 'O', 'M' }, /* UML COW */
{}
};
int i;
for (i = 0; signatures[i][0] != 0; i++) {
if (memcmp(buf, signatures[i], 4) == 0) {
return 1;
}
}
return 0;
}
static int check_write_unsafe(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
/* assume that if the user specifies the format explicitly, then assume
that they will continue to do so and provide no safety net */
if (!bs->probed) {
return 0;
}
if (sector_num == 0 && nb_sectors > 0) {
return check_for_block_signature(bs, buf);
}
return 0;
}
static int raw_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
return bdrv_read(bs->file, sector_num, buf, nb_sectors);
}
static int raw_write_scrubbed_bootsect(BlockDriverState *bs,
const uint8_t *buf)
{
uint8_t bootsect[512];
/* scrub the dangerous signature */
memcpy(bootsect, buf, 512);
memset(bootsect, 0, 4);
return bdrv_write(bs->file, 0, bootsect, 1);
}
static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
if (check_write_unsafe(bs, sector_num, buf, nb_sectors)) {
int ret;
ret = raw_write_scrubbed_bootsect(bs, buf);
if (ret < 0) {
return ret;
}
ret = bdrv_write(bs->file, 1, buf + 512, nb_sectors - 1);
if (ret < 0) {
return ret;
}
return ret + 512;
}
return bdrv_write(bs->file, sector_num, buf, nb_sectors);
}
@@ -95,73 +28,10 @@ static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
}
typedef struct RawScrubberBounce
{
BlockDriverCompletionFunc *cb;
void *opaque;
QEMUIOVector qiov;
} RawScrubberBounce;
static void raw_aio_writev_scrubbed(void *opaque, int ret)
{
RawScrubberBounce *b = opaque;
if (ret < 0) {
b->cb(b->opaque, ret);
} else {
b->cb(b->opaque, ret + 512);
}
qemu_iovec_destroy(&b->qiov);
qemu_free(b);
}
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
const uint8_t *first_buf;
int first_buf_index = 0, i;
/* This is probably being paranoid, but handle cases of zero size
vectors. */
for (i = 0; i < qiov->niov; i++) {
if (qiov->iov[i].iov_len) {
assert(qiov->iov[i].iov_len >= 512);
first_buf_index = i;
break;
}
}
first_buf = qiov->iov[first_buf_index].iov_base;
if (check_write_unsafe(bs, sector_num, first_buf, nb_sectors)) {
RawScrubberBounce *b;
int ret;
/* write the first sector using sync I/O */
ret = raw_write_scrubbed_bootsect(bs, first_buf);
if (ret < 0) {
return NULL;
}
/* adjust request to be everything but first sector */
b = qemu_malloc(sizeof(*b));
b->cb = cb;
b->opaque = opaque;
qemu_iovec_init(&b->qiov, qiov->nalloc);
qemu_iovec_concat(&b->qiov, qiov, qiov->size);
b->qiov.size -= 512;
b->qiov.iov[first_buf_index].iov_base += 512;
b->qiov.iov[first_buf_index].iov_len -= 512;
return bdrv_aio_writev(bs->file, sector_num + 1, &b->qiov,
nb_sectors - 1, raw_aio_writev_scrubbed, b);
}
return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
}

View File

@@ -148,7 +148,6 @@ struct BlockDriverState {
int encrypted; /* if true, the media is encrypted */
int valid_key; /* if true, a valid encryption key has been set */
int sg; /* if true, the device is a /dev/sg* */
int probed; /* if true, format was probed automatically */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque);
void *change_opaque;

View File

@@ -156,6 +156,14 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
offset = size;
}
if (pos == 0 && size == 0) {
DPRINTF("file is ready\n");
if (s->bytes_xfer <= s->xfer_limit) {
DPRINTF("notifying client\n");
s->put_ready(s->opaque);
}
}
return offset;
}
@@ -222,8 +230,10 @@ static void buffered_rate_tick(void *opaque)
{
QEMUFileBuffered *s = opaque;
if (s->has_error)
if (s->has_error) {
buffered_close(s);
return;
}
qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);

View File

@@ -219,7 +219,8 @@ typedef enum {
typedef struct {
PCIDevice dev;
uint8_t mult[8]; /* multicast mask array */
/* Hash register (multicast mask array, multiple individual addresses). */
uint8_t mult[8];
int mmio_index;
NICState *nic;
NICConf conf;
@@ -599,7 +600,7 @@ static void nic_reset(void *opaque)
{
EEPRO100State *s = opaque;
TRACE(OTHER, logout("%p\n", s));
/* TODO: Clearing of multicast table for selective reset, too? */
/* TODO: Clearing of hash register for selective reset, too? */
memset(&s->mult[0], 0, sizeof(s->mult));
nic_selective_reset(s);
}
@@ -851,7 +852,14 @@ static void action_command(EEPRO100State *s)
case CmdConfigure:
cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
sizeof(s->configuration));
TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
TRACE(OTHER, logout("configuration: %s\n",
nic_dump(&s->configuration[0], 16)));
TRACE(OTHER, logout("configuration: %s\n",
nic_dump(&s->configuration[16],
ARRAY_SIZE(s->configuration) - 16)));
if (s->configuration[20] & BIT(6)) {
TRACE(OTHER, logout("Multiple IA bit\n"));
}
break;
case CmdMulticastList:
set_multicast_list(s);
@@ -1647,12 +1655,6 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
static const uint8_t broadcast_macaddr[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
/* TODO: check multiple IA bit. */
if (s->configuration[20] & BIT(6)) {
missing("Multiple IA bit");
return -1;
}
if (s->configuration[8] & 0x80) {
/* CSMA is disabled. */
logout("%p received while CSMA is disabled\n", s);
@@ -1702,6 +1704,16 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
/* Promiscuous: receive all. */
TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size));
rfd_status |= 0x0004;
} else if (s->configuration[20] & BIT(6)) {
/* Multiple IA bit set. */
unsigned mcast_idx = compute_mcast_idx(buf);
assert(mcast_idx < 64);
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s));
} else {
TRACE(RXTX, logout("%p frame ignored, multiple IA bit set\n", s));
return -1;
}
} else {
TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size,
nic_dump(buf, size)));

View File

@@ -65,6 +65,8 @@
* 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented
* serial mouse queue.
* Implemented serial mouse protocol.
*
* 2010-May-23 Artyom Tarasenko: Reworked IUS logic
*/
#ifdef DEBUG_SERIAL
@@ -279,7 +281,7 @@ static uint32_t get_queue(void *opaque)
static int escc_update_irq_chn(ChannelState *s)
{
if ((((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||
if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
// tx ints enabled, pending
((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
@@ -342,24 +344,22 @@ static void escc_reset(DeviceState *d)
static inline void set_rxint(ChannelState *s)
{
s->rxint = 1;
if (!s->txint_under_svc) {
s->rxint_under_svc = 1;
if (s->chn == chn_a) {
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
else
s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
} else {
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->rregs[R_IVEC] = IVEC_HIRXINTB;
else
s->rregs[R_IVEC] = IVEC_LORXINTB;
}
}
if (s->chn == chn_a)
/* XXX: missing daisy chainnig: chn_b rx should have a lower priority
than chn_a rx/tx/special_condition service*/
s->rxint_under_svc = 1;
if (s->chn == chn_a) {
s->rregs[R_INTR] |= INTR_RXINTA;
else
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
else
s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
} else {
s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->rregs[R_IVEC] = IVEC_HIRXINTB;
else
s->rregs[R_IVEC] = IVEC_LORXINTB;
}
escc_update_irq(s);
}
@@ -369,19 +369,17 @@ static inline void set_txint(ChannelState *s)
if (!s->rxint_under_svc) {
s->txint_under_svc = 1;
if (s->chn == chn_a) {
s->rregs[R_INTR] |= INTR_TXINTA;
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
else
s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
} else {
s->rregs[R_IVEC] = IVEC_TXINTB;
s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
}
}
if (s->chn == chn_a)
s->rregs[R_INTR] |= INTR_TXINTA;
else
s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
escc_update_irq(s);
}
}
static inline void clr_rxint(ChannelState *s)
@@ -417,6 +415,7 @@ static inline void clr_txint(ChannelState *s)
s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
s->rregs[R_INTR] &= ~INTR_TXINTA;
} else {
s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->rregs[R_IVEC] = IVEC_HINOINT;
else
@@ -515,10 +514,15 @@ static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
clr_txint(s);
break;
case CMD_CLR_IUS:
if (s->rxint_under_svc)
clr_rxint(s);
else if (s->txint_under_svc)
clr_txint(s);
if (s->rxint_under_svc) {
s->rxint_under_svc = 0;
if (s->txint) {
set_txint(s);
}
} else if (s->txint_under_svc) {
s->txint_under_svc = 0;
}
escc_update_irq(s);
break;
default:
break;

View File

@@ -377,12 +377,12 @@ static void slavio_timer_reset(DeviceState *d)
curr_timer->limit = 0;
curr_timer->count = 0;
curr_timer->reached = 0;
if (i < s->num_cpus) {
if (i <= s->num_cpus) {
ptimer_set_limit(curr_timer->timer,
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
ptimer_run(curr_timer->timer, 0);
curr_timer->running = 1;
}
curr_timer->running = 1;
}
s->cputimer_mode = 0;
}

View File

@@ -456,11 +456,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
};
struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
if (!vdev->binding->set_guest_notifier) {
fprintf(stderr, "binding does not support guest notifiers\n");
return -ENOSYS;
}
if (!vdev->binding->set_host_notifier) {
fprintf(stderr, "binding does not support host notifiers\n");
return -ENOSYS;
@@ -513,12 +508,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
r = -errno;
goto fail_alloc;
}
r = vdev->binding->set_guest_notifier(vdev->binding_opaque, idx, true);
if (r < 0) {
fprintf(stderr, "Error binding guest notifier: %d\n", -r);
goto fail_guest_notifier;
}
r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, true);
if (r < 0) {
fprintf(stderr, "Error binding host notifier: %d\n", -r);
@@ -528,12 +517,14 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
if (r) {
r = -errno;
goto fail_kick;
}
file.fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq));
r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
if (r) {
r = -errno;
goto fail_call;
}
@@ -543,8 +534,6 @@ fail_call:
fail_kick:
vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false);
fail_host_notifier:
vdev->binding->set_guest_notifier(vdev->binding_opaque, idx, false);
fail_guest_notifier:
fail_alloc:
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
0, 0);
@@ -570,13 +559,6 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
.index = idx,
};
int r;
r = vdev->binding->set_guest_notifier(vdev->binding_opaque, idx, false);
if (r < 0) {
fprintf(stderr, "vhost VQ %d guest cleanup failed: %d\n", idx, r);
fflush(stderr);
}
assert (r >= 0);
r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false);
if (r < 0) {
fprintf(stderr, "vhost VQ %d host cleanup failed: %d\n", idx, r);
@@ -649,15 +631,26 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
{
int i, r;
if (!vdev->binding->set_guest_notifiers) {
fprintf(stderr, "binding does not support guest notifiers\n");
r = -ENOSYS;
goto fail;
}
r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, true);
if (r < 0) {
fprintf(stderr, "Error binding guest notifier: %d\n", -r);
goto fail_notifiers;
}
r = vhost_dev_set_features(hdev, hdev->log_enabled);
if (r < 0) {
goto fail;
goto fail_features;
}
r = ioctl(hdev->control, VHOST_SET_MEM_TABLE, hdev->mem);
if (r < 0) {
r = -errno;
goto fail;
goto fail_mem;
}
for (i = 0; i < hdev->nvqs; ++i) {
r = vhost_virtqueue_init(hdev,
@@ -677,13 +670,14 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
(uint64_t)(unsigned long)hdev->log);
if (r < 0) {
r = -errno;
goto fail_vq;
goto fail_log;
}
}
hdev->started = true;
return 0;
fail_log:
fail_vq:
while (--i >= 0) {
vhost_virtqueue_cleanup(hdev,
@@ -691,13 +685,18 @@ fail_vq:
hdev->vqs + i,
i);
}
fail_mem:
fail_features:
vdev->binding->set_guest_notifiers(vdev->binding_opaque, false);
fail_notifiers:
fail:
return r;
}
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
{
int i;
int i, r;
for (i = 0; i < hdev->nvqs; ++i) {
vhost_virtqueue_cleanup(hdev,
vdev,
@@ -706,6 +705,13 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
}
vhost_client_sync_dirty_bitmap(&hdev->client, 0,
(target_phys_addr_t)~0x0ull);
r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false);
if (r < 0) {
fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
fflush(stderr);
}
assert (r >= 0);
hdev->started = false;
qemu_free(hdev->log);
hdev->log_size = 0;

View File

@@ -29,6 +29,10 @@
#include <sys/mman.h>
#endif
/* Disable guest-provided stats by now (https://bugzilla.redhat.com/show_bug.cgi?id=623903) */
#define ENABLE_GUEST_STATS 0
typedef struct VirtIOBalloon
{
VirtIODevice vdev;
@@ -83,12 +87,14 @@ static QObject *get_stats_qobject(VirtIOBalloon *dev)
VIRTIO_BALLOON_PFN_SHIFT);
stat_put(dict, "actual", actual);
#if ENABLE_GUEST_STATS
stat_put(dict, "mem_swapped_in", dev->stats[VIRTIO_BALLOON_S_SWAP_IN]);
stat_put(dict, "mem_swapped_out", dev->stats[VIRTIO_BALLOON_S_SWAP_OUT]);
stat_put(dict, "major_page_faults", dev->stats[VIRTIO_BALLOON_S_MAJFLT]);
stat_put(dict, "minor_page_faults", dev->stats[VIRTIO_BALLOON_S_MINFLT]);
stat_put(dict, "free_mem", dev->stats[VIRTIO_BALLOON_S_MEMFREE]);
stat_put(dict, "total_mem", dev->stats[VIRTIO_BALLOON_S_MEMTOT]);
#endif
return QOBJECT(dict);
}
@@ -214,7 +220,7 @@ static void virtio_balloon_to_target(void *opaque, ram_addr_t target,
}
dev->stats_callback = cb;
dev->stats_opaque_callback_data = cb_data;
if (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ)) {
if (ENABLE_GUEST_STATS && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset);
virtio_notify(&dev->vdev, dev->svq);
} else {

View File

@@ -51,6 +51,7 @@ typedef struct VirtIONet
uint8_t nouni;
uint8_t nobcast;
uint8_t vhost_started;
bool vm_running;
VMChangeStateEntry *vmstate;
struct {
int in_use;
@@ -95,6 +96,38 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
}
}
static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
{
VirtIONet *n = to_virtio_net(vdev);
if (!n->nic->nc.peer) {
return;
}
if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
return;
}
if (!tap_get_vhost_net(n->nic->nc.peer)) {
return;
}
if (!!n->vhost_started == ((status & VIRTIO_CONFIG_S_DRIVER_OK) &&
(n->status & VIRTIO_NET_S_LINK_UP) &&
n->vm_running)) {
return;
}
if (!n->vhost_started) {
int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
if (r < 0) {
fprintf(stderr, "unable to start vhost net: %d: "
"falling back on userspace virtio\n", -r);
} else {
n->vhost_started = 1;
}
} else {
vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
n->vhost_started = 0;
}
}
static void virtio_net_set_link_status(VLANClientState *nc)
{
VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
@@ -107,6 +140,8 @@ static void virtio_net_set_link_status(VLANClientState *nc)
if (n->status != old_status)
virtio_notify_config(&n->vdev);
virtio_net_set_status(&n->vdev, n->vdev.status);
}
static void virtio_net_reset(VirtIODevice *vdev)
@@ -120,10 +155,6 @@ static void virtio_net_reset(VirtIODevice *vdev)
n->nomulti = 0;
n->nouni = 0;
n->nobcast = 0;
if (n->vhost_started) {
vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
n->vhost_started = 0;
}
/* Flush any MAC and VLAN filter table state */
n->mac_table.in_use = 0;
@@ -726,12 +757,9 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
{
VirtIONet *n = opaque;
if (n->vhost_started) {
/* TODO: should we really stop the backend?
* If we don't, it might keep writing to memory. */
vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
n->vhost_started = 0;
}
/* At this point, backend must be stopped, otherwise
* it might keep writing to memory. */
assert(!n->vhost_started);
virtio_save(&n->vdev, f);
qemu_put_buffer(f, n->mac, ETH_ALEN);
@@ -863,44 +891,14 @@ static NetClientInfo net_virtio_info = {
.link_status_changed = virtio_net_set_link_status,
};
static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
{
VirtIONet *n = to_virtio_net(vdev);
if (!n->nic->nc.peer) {
return;
}
if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
return;
}
if (!tap_get_vhost_net(n->nic->nc.peer)) {
return;
}
if (!!n->vhost_started == !!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
return;
}
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), vdev);
if (r < 0) {
fprintf(stderr, "unable to start vhost net: %d: "
"falling back on userspace virtio\n", -r);
} else {
n->vhost_started = 1;
}
} else {
vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
n->vhost_started = 0;
}
}
static void virtio_net_vmstate_change(void *opaque, int running, int reason)
{
VirtIONet *n = opaque;
uint8_t status = running ? VIRTIO_CONFIG_S_DRIVER_OK : 0;
n->vm_running = running;
/* This is called when vm is started/stopped,
* it will start/stop vhost backend if * appropriate
* it will start/stop vhost backend if appropriate
* e.g. after migration. */
virtio_net_set_status(&n->vdev, n->vdev.status & status);
virtio_net_set_status(&n->vdev, n->vdev.status);
}
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
@@ -951,9 +949,8 @@ void virtio_net_exit(VirtIODevice *vdev)
VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
qemu_del_vm_change_state_handler(n->vmstate);
if (n->vhost_started) {
vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
}
/* This will stop vhost backend if appropriate. */
virtio_net_set_status(vdev, 0);
qemu_purge_queued_packets(&n->nic->nc);

View File

@@ -449,6 +449,33 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
return 0;
}
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
VirtIODevice *vdev = proxy->vdev;
int r, n;
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
if (!virtio_queue_get_num(vdev, n)) {
break;
}
r = virtio_pci_set_guest_notifier(opaque, n, assign);
if (r < 0) {
goto assign_error;
}
}
return 0;
assign_error:
/* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
while (--n >= 0) {
virtio_pci_set_guest_notifier(opaque, n, !assign);
}
return r;
}
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
@@ -486,7 +513,7 @@ static const VirtIOBindings virtio_pci_bindings = {
.load_queue = virtio_pci_load_queue,
.get_features = virtio_pci_get_features,
.set_host_notifier = virtio_pci_set_host_notifier,
.set_guest_notifier = virtio_pci_set_guest_notifier,
.set_guest_notifiers = virtio_pci_set_guest_notifiers,
};
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,

View File

@@ -453,6 +453,8 @@ void virtio_reset(void *opaque)
VirtIODevice *vdev = opaque;
int i;
virtio_set_status(vdev, 0);
if (vdev->reset)
vdev->reset(vdev);

View File

@@ -93,7 +93,7 @@ typedef struct {
int (*load_config)(void * opaque, QEMUFile *f);
int (*load_queue)(void * opaque, int n, QEMUFile *f);
unsigned (*get_features)(void * opaque);
int (*set_guest_notifier)(void * opaque, int n, bool assigned);
int (*set_guest_notifiers)(void * opaque, bool assigned);
int (*set_host_notifier)(void * opaque, int n, bool assigned);
} VirtIOBindings;

View File

@@ -67,6 +67,8 @@ void process_incoming_migration(QEMUFile *f)
qemu_announce_self();
DPRINTF("successfully loaded vm state\n");
incoming_expected = false;
if (autostart)
vm_start();
}
@@ -314,8 +316,14 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
if (ret == -1)
ret = -(s->get_error(s));
if (ret == -EAGAIN)
if (ret == -EAGAIN) {
qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
} else if (ret < 0) {
if (s->mon) {
monitor_resume(s->mon);
}
s->state = MIG_STATE_ERROR;
}
return ret;
}

View File

@@ -669,17 +669,32 @@ help:
static void do_info_version_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
QDict *qemu;
qdict = qobject_to_qdict(data);
qemu = qdict_get_qdict(qdict, "qemu");
monitor_printf(mon, "%s%s\n", qdict_get_str(qdict, "qemu"),
qdict_get_str(qdict, "package"));
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
qdict_get_int(qemu, "major"),
qdict_get_int(qemu, "minor"),
qdict_get_int(qemu, "micro"),
qdict_get_str(qdict, "package"));
}
static void do_info_version(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
QEMU_VERSION, QEMU_PKGVERSION);
const char *version = QEMU_VERSION;
int major = 0, minor = 0, micro = 0;
char *tmp;
major = strtol(version, &tmp, 10);
tmp++;
minor = strtol(tmp, &tmp, 10);
tmp++;
micro = strtol(tmp, &tmp, 10);
*ret_data = qobject_from_jsonf("{ 'qemu': { 'major': %d, 'minor': %d, \
'micro': %d }, 'package': %s }", major, minor, micro, QEMU_PKGVERSION);
}
static void do_info_name_print(Monitor *mon, const QObject *data)
@@ -1056,6 +1071,10 @@ static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
struct bdrv_iterate_context context = { mon, 0 };
if (incoming_expected) {
qerror_report(QERR_MIGRATION_EXPECTED);
return -1;
}
bdrv_iterate(encrypted_bdrv_it, &context);
/* only resume the vm if all keys are set and valid */
if (!context.err) {

49
net.c
View File

@@ -281,29 +281,64 @@ NICState *qemu_new_nic(NetClientInfo *info,
return nic;
}
void qemu_del_vlan_client(VLANClientState *vc)
static void qemu_cleanup_vlan_client(VLANClientState *vc)
{
if (vc->vlan) {
QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
} else {
if (vc->send_queue) {
qemu_del_net_queue(vc->send_queue);
}
QTAILQ_REMOVE(&non_vlan_clients, vc, next);
if (vc->peer) {
vc->peer->peer = NULL;
}
}
if (vc->info->cleanup) {
vc->info->cleanup(vc);
}
}
static void qemu_free_vlan_client(VLANClientState *vc)
{
if (!vc->vlan) {
if (vc->send_queue) {
qemu_del_net_queue(vc->send_queue);
}
if (vc->peer) {
vc->peer->peer = NULL;
}
}
qemu_free(vc->name);
qemu_free(vc->model);
qemu_free(vc);
}
void qemu_del_vlan_client(VLANClientState *vc)
{
/* If there is a peer NIC, delete and cleanup client, but do not free. */
if (!vc->vlan && vc->peer && vc->peer->info->type == NET_CLIENT_TYPE_NIC) {
NICState *nic = DO_UPCAST(NICState, nc, vc->peer);
if (nic->peer_deleted) {
return;
}
nic->peer_deleted = true;
/* Let NIC know peer is gone. */
vc->peer->link_down = true;
if (vc->peer->info->link_status_changed) {
vc->peer->info->link_status_changed(vc->peer);
}
qemu_cleanup_vlan_client(vc);
return;
}
/* If this is a peer NIC and peer has already been deleted, free it now. */
if (!vc->vlan && vc->peer && vc->info->type == NET_CLIENT_TYPE_NIC) {
NICState *nic = DO_UPCAST(NICState, nc, vc);
if (nic->peer_deleted) {
qemu_free_vlan_client(vc->peer);
}
}
qemu_cleanup_vlan_client(vc);
qemu_free_vlan_client(vc);
}
VLANClientState *
qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
const char *client_str)

1
net.h
View File

@@ -72,6 +72,7 @@ typedef struct NICState {
VLANClientState nc;
NICConf *conf;
void *opaque;
bool peer_deleted;
} NICState;
struct VLANState {

View File

@@ -35,7 +35,29 @@ information on the Server command and response formats.
NOTE: This document is temporary and will be replaced soon.
1. Regular Commands
1. Stability Considerations
===========================
The current QMP command set (described in this file) may be useful for a
number of use cases, however it's limited and several commands have bad
defined semantics, specially with regard to command completion.
These problems are going to be solved incrementally in the next QEMU releases
and we're going to establish a deprecation policy for badly defined commands.
If you're planning to adopt QMP, please observe the following:
1. The deprecation policy will take efect and be documented soon, please
check the documentation of each used command as soon as a new release of
QEMU is available
2. DO NOT rely on anything which is not explicit documented
3. Errors, in special, are not documented. Applications should NOT check
for specific errors classes or data (it's strongly recommended to only
check for the "error" key)
2. Regular Commands
===================
Server's responses in the examples below are always a success response, please
@@ -1592,7 +1614,7 @@ HXCOMM This is required for the QMP documentation layout.
SQMP
2. Query Commands
3. Query Commands
=================
EQMP
@@ -1623,13 +1645,25 @@ Show QEMU version.
Return a json-object with the following information:
- "qemu": QEMU's version (json-string)
- "qemu": A json-object containing three integer values:
- "major": QEMU's major version (json-int)
- "minor": QEMU's minor version (json-int)
- "micro": QEMU's micro version (json-int)
- "package": package's version (json-string)
Example:
-> { "execute": "query-version" }
<- { "return": { "qemu": "0.11.50", "package": "" } }
<- {
"return":{
"qemu":{
"major":0,
"minor":11,
"micro":5
},
"package":""
}
}
EQMP

View File

@@ -140,6 +140,10 @@ static const QErrorStringTable qerror_table[] = {
.error_fmt = QERR_KVM_MISSING_CAP,
.desc = "Using KVM without %(capability), %(feature) unavailable",
},
{
.error_fmt = QERR_MIGRATION_EXPECTED,
.desc = "An incoming migration is expected before this command can be executed",
},
{
.error_fmt = QERR_MISSING_PARAMETER,
.desc = "Parameter '%(name)' is missing",

View File

@@ -121,6 +121,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
#define QERR_MIGRATION_EXPECTED \
"{ 'class': 'MigrationExpected', 'data': {} }"
#define QERR_MISSING_PARAMETER \
"{ 'class': 'MissingParameter', 'data': { 'name': %s } }"

View File

@@ -99,6 +99,7 @@ typedef enum DisplayType
} DisplayType;
extern int autostart;
extern int incoming_expected;
extern int bios_size;
typedef enum {

View File

@@ -250,13 +250,9 @@ static void gen_rev16(TCGv var)
/* Byteswap low halfword and sign extend. */
static void gen_revsh(TCGv var)
{
TCGv tmp = new_tmp();
tcg_gen_shri_i32(tmp, var, 8);
tcg_gen_andi_i32(tmp, tmp, 0x00ff);
tcg_gen_shli_i32(var, var, 8);
tcg_gen_ext8s_i32(var, var);
tcg_gen_or_i32(var, var, tmp);
dead_tmp(tmp);
tcg_gen_ext16u_i32(var, var);
tcg_gen_bswap16_i32(var, var);
tcg_gen_ext16s_i32(var, var);
}
/* Unsigned bitfield extract. */

View File

@@ -1066,7 +1066,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
opn = "ld";
break;
case OPC_LLD:
save_cpu_state(ctx, 0);
save_cpu_state(ctx, 1);
op_ld_lld(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lld";
@@ -1086,7 +1086,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
opn = "ldr";
break;
case OPC_LDPC:
save_cpu_state(ctx, 1);
save_cpu_state(ctx, 0);
tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
op_ld_ld(t0, t0, ctx);
@@ -1095,7 +1095,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
break;
#endif
case OPC_LWPC:
save_cpu_state(ctx, 1);
save_cpu_state(ctx, 0);
tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
op_ld_lw(t0, t0, ctx);
@@ -1236,7 +1236,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
switch (opc) {
#if defined(TARGET_MIPS64)
case OPC_SCD:
save_cpu_state(ctx, 0);
save_cpu_state(ctx, 1);
op_st_scd(t1, t0, rt, ctx);
opn = "scd";
break;
@@ -9939,7 +9939,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
opn = "lwp";
break;
case SWP:
save_cpu_state(ctx, 1);
save_cpu_state(ctx, 0);
gen_load_gpr(t1, rd);
op_st_sw(t1, t0, ctx);
tcg_gen_movi_tl(t1, 4);
@@ -9960,7 +9960,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
opn = "ldp";
break;
case SDP:
save_cpu_state(ctx, 1);
save_cpu_state(ctx, 0);
gen_load_gpr(t1, rd);
op_st_sd(t1, t0, ctx);
tcg_gen_movi_tl(t1, 8);

View File

@@ -37,7 +37,9 @@ DEF_HELPER_0(save, void)
DEF_HELPER_0(restore, void)
DEF_HELPER_1(flush, void, tl)
DEF_HELPER_2(udiv, tl, tl, tl)
DEF_HELPER_2(udiv_cc, tl, tl, tl)
DEF_HELPER_2(sdiv, tl, tl, tl)
DEF_HELPER_2(sdiv_cc, tl, tl, tl)
DEF_HELPER_2(stdf, void, tl, int)
DEF_HELPER_2(lddf, void, tl, int)
DEF_HELPER_2(ldqf, void, tl, int)

View File

@@ -3300,8 +3300,9 @@ void helper_rett(void)
}
#endif
target_ulong helper_udiv(target_ulong a, target_ulong b)
static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
{
int overflow = 0;
uint64_t x0;
uint32_t x1;
@@ -3314,16 +3315,31 @@ target_ulong helper_udiv(target_ulong a, target_ulong b)
x0 = x0 / x1;
if (x0 > 0xffffffff) {
env->cc_src2 = 1;
return 0xffffffff;
} else {
env->cc_src2 = 0;
return x0;
x0 = 0xffffffff;
overflow = 1;
}
if (cc) {
env->cc_dst = x0;
env->cc_src2 = overflow;
env->cc_op = CC_OP_DIV;
}
return x0;
}
target_ulong helper_sdiv(target_ulong a, target_ulong b)
target_ulong helper_udiv(target_ulong a, target_ulong b)
{
return helper_udiv_common(a, b, 0);
}
target_ulong helper_udiv_cc(target_ulong a, target_ulong b)
{
return helper_udiv_common(a, b, 1);
}
static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
{
int overflow = 0;
int64_t x0;
int32_t x1;
@@ -3336,12 +3352,26 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b)
x0 = x0 / x1;
if ((int32_t) x0 != x0) {
env->cc_src2 = 1;
return x0 < 0? 0x80000000: 0x7fffffff;
} else {
env->cc_src2 = 0;
return x0;
x0 = x0 < 0 ? 0x80000000: 0x7fffffff;
overflow = 1;
}
if (cc) {
env->cc_dst = x0;
env->cc_src2 = overflow;
env->cc_op = CC_OP_DIV;
}
return x0;
}
target_ulong helper_sdiv(target_ulong a, target_ulong b)
{
return helper_sdiv_common(a, b, 0);
}
target_ulong helper_sdiv_cc(target_ulong a, target_ulong b)
{
return helper_sdiv_common(a, b, 1);
}
void helper_stdf(target_ulong addr, int mem_idx)

View File

@@ -3162,20 +3162,20 @@ static void disas_sparc_insn(DisasContext * dc)
#endif
case 0xe: /* udiv */
CHECK_IU_FEATURE(dc, DIV);
gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
if (xop & 0x10) {
tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
gen_helper_udiv_cc(cpu_dst, cpu_src1, cpu_src2);
dc->cc_op = CC_OP_DIV;
} else {
gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
}
break;
case 0xf: /* sdiv */
CHECK_IU_FEATURE(dc, DIV);
gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
if (xop & 0x10) {
tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
gen_helper_sdiv_cc(cpu_dst, cpu_src1, cpu_src2);
dc->cc_op = CC_OP_DIV;
} else {
gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
}
break;
default:

View File

@@ -1184,7 +1184,7 @@ void vnc_client_write(void *opaque)
vnc_lock_output(vs);
if (vs->output.offset) {
vnc_client_write_locked(opaque);
} else {
} else if (vs->csock != -1) {
qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
}
vnc_unlock_output(vs);

2
vl.c
View File

@@ -182,6 +182,7 @@ int nb_nics;
NICInfo nd_table[MAX_NICS];
int vm_running;
int autostart;
int incoming_expected; /* Started with -incoming and waiting for incoming */
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
@@ -2557,6 +2558,7 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_incoming:
incoming = optarg;
incoming_expected = true;
break;
case QEMU_OPTION_nodefaults:
default_serial = 0;