Compare commits

...
193 Commits
Author SHA1 Message Date
Michael Roth 4ce5bc2dd1 update VERSION for 1.1.2
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:38:39 -05:00
Ian Campbell 113f4cd9e9 console: bounds check whenever changing the cursor due to an escape code
This is XSA-17 / CVE-2012-3515

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-09-05 10:38:39 -05:00
Paolo Bonzini f965d237b5 qemu-timer: properly arm alarm timer for timers set by device initialization
QEMU will hang when fed the following command-line

  qemu-system-mips -kernel vmlinux-2.6.32-5-4kc-malta -append "console=ttyS0" -nographic -net none

The -net none is important otherwise it seems some events are generated
causing the things to work. When it doesn't work, the guest hangs when
measuring the CPU frequency, after the following line:

  [    0.000000] NR_IRQS:256

Pressing a key on the serial port unblocks it, hinting that the problem
is due to the recent elimination of the 1 second timeout in the main
loop.

The problem is that because init_timer_alarm sets the timer's pending
flag to true, the alarm timer is never armed until after the first time
through the main loop.  Thus the bug started when QEMU started testing
the pending flag in qemu_mod_timer (commit 1828be3, more alarm timer
cleanup, 2010-03-10).

But actually, it isn't true at all that a timer is pending when the
alarm timer is created, and the real bug has been latent forever: the
fix is to remove the bogus setting of pending flag.

Reported-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit de188751da)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:38:39 -05:00
Max Filippov 5a16dd9bc8 target-xtensa: return ENOSYS for unimplemented simcalls
This prevents guest from proceeding with uninitialised garbage returned
from unimplemented simcalls.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit e7eee62a90)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:38:39 -05:00
Max Filippov c7580c1034 target-xtensa: fix big-endian BBS/BBC implementation
Quote from ISA, 2.1:

For most Xtensa instructions, bit numbering is irrelevant; only the BBC
and BBS instructions assign bit numbers to values on which the processor
operates. The BBC/BBS instructions use big-endian bit ordering (0 is the
most-significant bit) on a big-endian processor configuration.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 7ff7563fc1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:38:39 -05:00
Hans de Goede a8cd6f7ddf ehci: Fix NULL ptr deref when unplugging an USB dev with an iso stream active
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 7ce86aa1aa)

Conflicts:

	hw/usb/hcd-ehci.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:30:38 -05:00
Michael S. Tsirkin ce4fc986e5 msix: make [un]use vectors on reset/load optional
The facility to use/unuse vectors dynamically is helpful
for virtio but little else: everyone just seems to use
vectors in their init function.

Avoid clearing msix vector use info on reset and load.
For virtio, clear it explicitly.
This should fix regressions reported with ivshmem - though
I didn't test this, I verified that virtio keeps
working like it did.

Tested-by: Cam Macdonell <cam@cs.ualberta.ca>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 3cac001e5a)

Conflicts:

	hw/msix.c
	hw/virtio-pci.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:30:38 -05:00
Gleb Natapov 219a7482ab reset PMBA and PMREGMISC PIIX4 registers.
The bug causes Windows + OVMF hang after reboot since OVMF
checks PMREGMISC to see if IO space is enabled and skip
configuration if it is.

Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4d09d37c6a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:30:38 -05:00
Stefano Stabellini 28846ad3b5 qemu_rearm_alarm_timer: do not call rearm if the next deadline is INT64_MAX
qemu_rearm_alarm_timer partially duplicates the code in
qemu_next_alarm_deadline to figure out if it needs to rearm the timer.
If it calls qemu_next_alarm_deadline, it always rearms the timer even if
the next deadline is INT64_MAX.

This patch simplifies the behavior of qemu_rearm_alarm_timer and removes
the duplicated code, always calling qemu_next_alarm_deadline and only
rearming the timer if the deadline is less than INT64_MAX.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Tested-by: Andreas Färber <andreas.faerber@web.de>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 8227421e04)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-09-05 10:30:38 -05:00
Stefan Weil cccb5446a6 qemu-ga: Fix null pointer passed to unlink in failure branch
Clang reports this warning:

Null pointer passed as an argument to a 'nonnull' parameter

Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4bdb1a3059)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-30 14:54:16 -05:00
Jan Kiszka 25c0807e3c memory: Fix copy&paste mistake in memory_region_iorange_write
The last argument of find_portio is "write", so this must be true here.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7e2a62d82a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-30 14:54:16 -05:00
Cam Macdonell 57fa9fb4ef ivshmem: remove redundant ioeventfd configuration
setup_ioeventfds() is unnecessary and actually causes a segfault when used
ioeventfd=on is used on the command-line.  Since ioeventfds are handled within
the memory API, it can be removed.

Signed-off-by: Cam Macdonell <cam@cs.ualberta.ca>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7e7de876ae)

Conflicts:

	hw/ivshmem.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-30 14:54:16 -05:00
Peter Maydell 450ead742a hw/arm_gic.c: Define .class_size in arm_gic_info TypeInfo
Add the missing .class_size definition to the arm_gic_info TypeInfo.
This fixes the memory corruption and possible segfault that otherwise
results when the class struct is allocated at too small a size and
the class init function writes off the end of it.

Reported-by: Adam Lackorzynski <adam@os.inf.tu-dresden.de>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 998a74bcda)

 - ARMGICClass isn't in 1.1, set class size to SysBusDeviceClass instead

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-30 14:54:16 -05:00
Aurelien Jarno 69c67eca97 tcg/mips: fix broken CONFIG_TCG_PASS_AREG0 code
The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers was
broken in that it did not respect the ABI requirement that 64
bit values were passed in even-odd register pairs. The simplest
way to fix this is to implement some new utility functions
for marshalling function arguments into the correct registers
and stack, so that the code which sets up the address and
data arguments does not need to care whether there has been
a preceding env argument.

Based on commit 9716ef3b for ARM by Peter Maydell.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 18fec301cd)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 14:38:44 -05:00
munkyu.im 256c899432 audio/winwave: previous audio buffer should be flushed
Winwave audio backend has problem with pausing and restart audio out.
Unlike other backends, Winwave pausing API does not flush audio buffer.
As a result, the previous audio data are played in front of
user expected sound when user restart audio.
So changes it to waveOutReset()

Signed-off-by: Munkyu Im <munkyu.im@samsung.com>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 13ef70f64e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 14:38:44 -05:00
Eric Johnson 849c865155 target-mips: allow microMIPS SWP and SDP to have RD equal to BASE
The microMIPS SWP and SDP instructions do not modify GPRs.  So their
behavior is well defined when RD equals BASE.  The MIPS Architecture
Verification Programs (AVPs) check that they work as expected.  This
is required for AVPs to pass.

Signed-off-by: Eric Johnson <ericj@mips.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 36c6711bbe)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 14:38:44 -05:00
Eric Johnson 57708c532f target-mips: add privilege level check to several Cop0 instructions
The MIPS Architecture Verification Programs (AVPs) check privileged
instructions for the required privilege level.  These changes are needed
to pass the AVP suite.

Signed-off-by: Eric Johnson <ericj@mips.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 2e15497c5b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 14:38:44 -05:00
Richard Henderson 8d45ae8352 mips-linux-user: Always support rdhwr.
The kernel will emulate this instruction if it's not supported
natively.  This insn is used for TLS, among other things, and
so is required by modern glibc.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Cc: Riku Voipio <riku.voipio@iki.fi>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit b316728836)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:03 -05:00
Richard Henderson 2f0f684cce target-mips: Streamline indexed cp1 memory addressing.
We've already eliminated both base and index being zero.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 0516867450)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:03 -05:00
Richard Sandiford bc4321e754 Fix order of CVT.PS.S operands
The FS input to CVT.PS.S is the high half and FT is the low half.
tcg_gen_concat_i32_i64 takes the low half first, so the operands
were in the wrong order.

Signed-off-by: Richard Sandiford <rdsandiford@googlemail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 13d24f4972)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:03 -05:00
Richard Sandiford 9a32fb2824 Fix operands of RECIP2.S and RECIP2.PS
Read the second input operand of RECIP2.S and RECIP2.PS from FT rather
than FD.  RECIP2.D is already correct.

Signed-off-by: Richard Sandiford <rdsandiford@googlemail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit d22d728987)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:03 -05:00
Aurelien Jarno 50462f2ca8 tcg/ia64: fix and optimize ld/st slow path
Store slow path has been broken in e141ab52d:
- the arguments are shifted before the last one (mem_index) is written.
- the shift is done for both slow and fast paths.

Fix that. Also optimize a bit by bundling the move together. This still
can be optimized, but it's better to wait for a decision to be taken on
the arguments order.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit d03c98d80f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:03 -05:00
Aurelien Jarno ec16f35e4e tcg/ia64: fix prologue/epilogue
Prologue and epilogue code has been broken in cea5f9a28.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 18d445b443)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Peter Maydell 0ba3d50242 tcg/arm: Fix broken CONFIG_TCG_PASS_AREG0 code
The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers was
broken in that it did not respect the ABI requirement that 64
bit values were passed in even-odd register pairs. The simplest
way to fix this is to implement some new utility functions
for marshalling function arguments into the correct registers
and stack, so that the code which sets up the address and
data arguments does not need to care whether there has been
a preceding env argument.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 9716ef3b1b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Matthew Ogilvie 0214b6b4de target-i386/translate.c: mov to/from crN/drN: ignore mod bits
> This instruction is always treated as a register-to-register (MOD = 11)
> instruction, regardless of the encoding of the MOD field in the MODR/M
> byte.

Also, Microport UNIX System V/386 v 2.1 (ca 1987) runs fine on
real Intel 386 and 486 CPU's (at least), but does not run in qemu without
this patch.

Signed-off-by: Matthew Ogilvie <mmogilvi_qemu@miniinfo.net>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 5c73b757e3)

Conflicts:

	target-i386/translate.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Paolo Bonzini 63f7166a80 ivshmem: fix memory_region_del_eventfd assertion failure
We do not register ioeventfds unless the IVSHMEM_IOEVENTFD feature
is set.  The same feature must be checked before releasing the eventfds.
Regression introduced by commit 563027c (ivshmem: use EventNotifier and
memory API, 2012-07-05).

Reported-by: Cam Macdonnell <cam@cs.ualberta.ca>
Tested-by: Cam Macdonnell <cam@cs.ualberta.ca>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 98609cd8fc)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Paolo Bonzini 1d34dff02f qom: object_delete should unparent the object first
object_deinit is only called when the reference count goes to zero,
and yet tries to do an object_unparent.  Now, object_unparent
either does nothing or it will decrease the reference count.
Because we know the reference count is zero, the object_unparent
call in object_deinit is useless.

Instead, we need to disconnect the object from its parent just
before we remove the last reference apart from the parent's.  This
happens in object_delete.  Once we do this, all calls to
object_unparent peppered through QEMU can go away.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit da5a44e8b0)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Anthony Liguori 5330a894ed monitor: don't try to initialize json parser when monitor is HMP
Reported-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 26efaca377)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Stefan Weil cdcf2aa41c target-mips: Fix some helper functions (VR54xx multiplication)
Commits b5dc7732e1 and
be24bb4f30 optimized the code
and removed the correct setting of t0. Fix this.

gcc-4.7 detected this bug because parameter arg1 was unused
but set in set_HIT0_LO and set_HI_LOT0.

Cc: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 6fc97fafce)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Meador Inge 5ea33884f6 target-mips: Enable access to required RDHWR hardware registers
While running in the usermode emulator all of the required*
MIPS32r2 RDHWR hardware registers should be accessible (the
Linux kernel enables access to these same registers).  Note
that these registers are still enabled when the MIPS ISA is
not release 2.  This is OK since the Linux kernel emulates
access to them when they are not available in hardware.

* There is also the ULR register which is only recommended
  for full release 2 compliance.  Incidentally, accessing
  this register in the current implementation works fine
  without flipping its access bit.

Signed-off-by: Meador Inge <meadori@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 94159135cb)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Anthony Liguori 50d0184cb7 monitor: move json init from OPEN event to init
At some point in the past, the OPEN event was changed to be issued from a
bottom half.  This creates a small window whereas a data callback registered in
init may be invoked before the OPEN event has been issued.

This is reproducible with:

 echo "{'execute': 'qmp_capabilities'}" | qemu-system-x86_64 -M none -qmp stdio

We can fix this for the monitor by moving the parser initialization to init.

The remaining state that is set in OPEN appears harmless.

Reported-by: Daniel Berrange <berrange@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 58617a795c)

Conflicts:

	monitor.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Jim Meyering c068d37020 softmmu-semi: fix lock_user* functions not to deref NULL upon OOM
Return NULL upon malloc failure.

Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 15d9e3bc6a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Jim Meyering cc5caf7df4 arm-semi: don't leak 1KB user string lock buffer upon TARGET_SYS_OPEN
Always call unlock_user before returning.

Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 396bef4b38)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Jim Meyering b68e45c686 sheepdog: don't leak socket file descriptor upon connection failure
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a7e47d4bfc)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Jim Meyering df60f451b3 linux-user: do_msgrcv: don't leak host_mb upon TARGET_EFAULT failure
Also, use g_malloc to avoid NULL-deref upon OOM.

Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 0d07fe47d4)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Jim Meyering 1bc6332461 qemu-ga: don't leak a file descriptor upon failed lockf
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4144f122b4)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Dongxiao Xu 07548727b3 xen-all.c: fix multiply issue for int and uint types
If the two multiply operands are int and uint types separately,
the int type will be transformed to uint firstly, which is not the
intent in our code piece. The fix is to add (int64_t) transform
for the uint type before the multiply.

Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
(cherry picked from commit 14d4018372)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Frediano Ziglio c7e6d6b115 Fix invalidate if memory requested was not bucket aligned
When memory is mapped in qemu_map_cache with lock != 0 a reverse mapping
is created pointing to the virtual address of location requested.
The cached mapped entry is saved in last_address_vaddr with the memory
location of the base virtual address (without bucket offset).
However when this entry is invalidated the virtual address saved in the
reverse mapping is used. This cause that the mapping is freed but the
last_address_vaddr is not reset.

Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
(cherry picked from commit 27b7652ef5)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:02 -05:00
Jan Kiszka 886c62a3ff i82378: Remove bogus MMIO coalescing
This MMIO area is an entry gate to legacy PC ISA devices, addressed via
PIO over there. Quite a few of the PIO ports have side effects on access
like starting/stopping timers that must be executed properly ordered
/wrt the CPU. So we have to remove the coalescing mark.

Acked-by: Hervé Poussineau <hpoussin@reactos.org>
Acked-by: Andreas Färber <andreas.faerber@web.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 0ec64507a5)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Alexey Kardashevskiy b598cb2214 eventfd: making it thread safe
QEMU uses IO handlers to run select() in the main loop.
The handlers list is managed by qemu_set_fd_handler() helper
which works fine when called from the main thread as it is
called when select() is not waiting.

However IO handlers list can be changed in the thread other than
the main one doing os_host_main_loop_wait(), for example, as a result
of a hypercall which changes PCI config space (VFIO on POWER is the case)
and enables/disabled MSI/MSIX which closes/creates eventfd handles.
As the main loop should be waiting on the newly created eventfds,
it has to be restarted.

The patch adds the qemu_notify_event() call to interrupt select()
to make main_loop() restart select() with the updated IO handlers
list.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 55ce75faf2)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Paolo Bonzini 799c27e124 iscsi: fix races between task completion and abort
This patch fixes two main issues with block/iscsi.c:

1) iscsi_task_mgmt_abort_task_async calls iscsi_scsi_task_cancel which
was also directly called in iscsi_aio_cancel

2) a race between task completion and task abortion could happen cause
the scsi_free_scsi_task were done before iscsi_schedule_bh has finished.
To fix this, all the freeing of IscsiTasks and releasing of the AIOCBs
is centralized in iscsi_bh_cb, independent of whether the SCSI command
has completed or was cancelled.

3) iscsi_aio_cancel was not synchronously waiting for the end of the
command.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 1bd075f29e)

Conflicts:

	block/iscsi.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Paolo Bonzini b90d717b64 iscsi: simplify iscsi_schedule_bh
It is always used with the same callback, remove the argument.  And
its return value is never used, assume allocation succeeds.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit cfb3f5064a)

Conflicts:

	block/iscsi.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Paolo Bonzini a410be59b5 iscsi: move iscsi_schedule_bh and iscsi_readv_writev_bh_cb
Put these functions at the beginning, to avoid forward references
in the next patches.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 27cbd828c6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Kevin Wolf f946f010f5 Documentation: Warn against qemu-img on active image
People have repeatedly expected that you can do things like snapshotting
an image with qemu-img while a qemu instance is running. Maybe we need
to consider locking the files while they are in use, but having a
warning in the qemu-img manpage is doable for 1.2 and can't hurt anyway.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 48467328c6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Kevin Wolf d438650fa5 vmdk: Read footer for streamOptimized images
The footer takes precedence over the header when it exists. It contains
the real grain directory offset that is missing in the header. Without
this patch, streamOptimized images with a footer cannot be read.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
(cherry picked from commit 65bd155c73)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Kevin Wolf 07ab4fc1ef vmdk: Fix header structure
Commit bb45ded9 swapped gd_offset and rgd_offset. This is wrong.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 7a736bfa4e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-28 01:50:01 -05:00
Markus Armbruster fd21cc14f5 vl: Round argument of -m up to multiple of 8KiB
Partial pages make little sense and don't work.  Ensure the RAM size
is a multiple of any possible target's page size.

Fixes

    $ qemu-system-x86_64 -nodefaults -S -vnc :0 -m 0.8
    qemu-system-x86_64: /work/armbru/qemu/exec.c:2255: register_subpage: Assertion `existing->mr->subpage || existing->mr == &io_mem_unassigned' failed.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit ff96101552)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:42:32 -05:00
Markus Armbruster cfeb9958c8 pc: Fix RTC CMOS info on RAM for ram_size < 1MiB
pc_cmos_init() always claims 640KiB base memory, and ram_size - 1MiB
extended memory.  The latter can underflow to "lots of extended
memory".  Fix both, and clean up some.

Note: SeaBIOS currently requires 1MiB of RAM, and doesn't check
whether it got enough.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit e89001f72e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:42:32 -05:00
Jan Kiszka ffc7565c81 kvm: i8254: Finish time conversion fix
0cdd3d1444 fixed reading back the counter load time from the kernel
while assuming the kernel would always update its load time on writing
the state. That is only true for channel 1, and so pit_get_channel_info
returned wrong output pin states for high counter values.

Fix this by applying the offset also on kvm_pit_put. Now we also need to
update the offset when we write the state while the VM is stopped as it
keeps on changing in that state.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
(cherry picked from commit 050a46065d)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:42:32 -05:00
Jan Kiszka 393d4c9214 kvm: i8254: Cache kernel clock offset in KVMPITState
To prepare the final fix for clock calibration issues with the in-kernel
PIT, we want to cache the offset between vmclock and the clock used by
the in-kernel PIT. So far, we only need to update it when the VM state
changes between running and stopped because we only read the in-kernel
PIT state while the VM is running.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
(cherry picked from commit 205df4d1a8)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:42:32 -05:00
Jason Baron 5ae1c7ca0a ahci: Fix ahci cdrom read corruptions for reads > 128k
While testing q35, which has its cdrom attached to the ahci controller, I found
that the Fedora 17 install would panic on boot. The panic occurs while
squashfs is trying to read from the cdrom. The errors are:

[    8.622711] SQUASHFS error: xz_dec_run error, data probably corrupt
[    8.625180] SQUASHFS error: squashfs_read_data failed to read block
0x20be48a

I was also able to produce corrupt data reads using an installed piix based
qemu machine, using 'dd'. I found that the corruptions were only occuring when
then read size was greater than 128k. For example, the following command
results in corrupted reads:

dd if=/dev/sr0 of=/tmp/blah bs=256k iflag=direct

The > 128k size reads exercise a different code path than 128k and below. In
ide_atapi_cmd_read_dma_cb() s->io_buffer_size is capped at 128k. Thus,
ide_atapi_cmd_read_dma_cb() is called a second time when the read is > 128k.
However, ahci_dma_rw_buf() restart the read from offset 0, instead of at 128k.
Thus, resulting in a corrupted read.

To fix this, I've introduced 'io_buffer_offset' field in IDEState to keep
track of the offset. I've also modified ahci_populate_sglist() to take a new
3rd offset argument, so that the sglist is property initialized.

I've tested this patch using 'dd' testing, and Fedora 17 now correctly boots
and installs on q35 with the cdrom ahci controller.

Signed-off-by: Jason Baron <jbaron@redhat.com>
Tested-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 61f52e06f0)

Conflicts:

	hw/ide/ahci.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:59 -05:00
Jason Baron c094d3d818 ahci: Fix sglist memleak in ahci_dma_rw_buf()
I noticed that in hw/ide/ahci:ahci_dma_rw_buf() we do not free the sglist. Thus,
I've added a call to qemu_sglist_destroy() to fix this memory leak.

In addition, I've adeed a call in qemu_sglist_destroy() to 0 all of the sglist
fields, in case there is some other codepath that tries to free the sglist.

Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit ea8d82a1ed)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:40 -05:00
Jan Kiszka a473439574 apic: Defer interrupt updates to VCPU thread
KVM performs TPR raising asynchronously to QEMU, specifically outside
QEMU's global lock. When an interrupt is injected into the APIC and TPR
is checked to decide if this can be delivered, a stale TPR value may be
used, causing spurious interrupts in the end.

Fix this by deferring apic_update_irq to the context of the target VCPU.
We introduce a new interrupt flag for this, CPU_INTERRUPT_POLL. When it
is set, the VCPU calls apic_poll_irq before checking for further pending
interrupts. To avoid special-casing KVM, we also implement this logic
for TCG mode.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 5d62c43a17)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Jan Kiszka 2a93a89400 apic: Reevaluate pending interrupts on LVT_LINT0 changes
When the guest modifies the LVT_LINT0 register, we need to check if some
pending PIC interrupt can now be delivered.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit a94820ddc3)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Jan Kiszka c337db8cc9 apic: Resolve potential endless loop around apic_update_irq
Commit d96e173769 refactored the reinjection of pending PIC interrupts.
However, it missed the potential loop of apic_update_irq ->
apic_deliver_pic_intr -> apic_local_deliver -> apic_set_irq ->
apic_update_irq that /could/ occur if LINT0 is injected as APIC_DM_FIXED
and that vector is currently blocked via TPR.

Resolve this by reinjecting only where it matters: inside
apic_get_interrupt. This function may clear a vector while a
PIC-originated reason still exists.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 3db3659bf6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Jan Kiszka 44a42fd2b6 slirp: Improve error reporting of inaccessible smb directories
Instead of guessing, print the error code returned by access.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 22a61f365d)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Dunrong Huang 1a933e4801 slirp: Ensure smbd and shared directory exist when enable smb
Users may pass the following parameters to qemu:
    $ qemu-kvm -net nic -net user,smb= ...
    $ qemu-kvm -net nic -net user,smb ...
    $ qemu-kvm -net nic -net user,smb=bad_directory ...

In these cases, qemu started successfully while samba server
failed to start. Users will confuse since samba server
failed silently without any indication of what it did wrong.

To avoid it, we check whether the shared directory exist and
if users have permission to access this directory when QEMU's
"built-in" SMB server is enabled.

Signed-off-by: Dunrong Huang <riegamaths@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 927d811b28)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Jan Kiszka 55e64b6ddd slirp: Enforce host-side user of smb share
Windows 7 (and possibly other versions) cannot connect to the samba
share if the exported host directory is not world-readable. This can be
resolved by forcing the username used for access checks to the one
under which QEMU and smbd are running.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 1cb1c5d10b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Michael Roth b83883e2db check-qjson: add test for large JSON objects
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7109edfeb6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Michael Roth 9c7e3b98aa json-parser: don't replicate tokens at each level of recursion
Currently, when parsing a stream of tokens we make a copy of the token
list at the beginning of each level of recursion so that we do not
modify the original list in cases where we need to fall back to an
earlier state.

In the worst case, we will only read 1 or 2 tokens off the list before
recursing again, which means an upper bound of roughly N^2 token allocations.

For a "reasonably" sized QMP request (in this a QMP representation of
cirrus_vga's device state, generated via QIDL, being passed in via
qom-set), this caused my 16GB's of memory to be exhausted before any
noticeable progress was made by the parser.

This patch works around the issue by using single copy of the token list
in the form of an indexable array so that we can save/restore state by
manipulating indices.

A subsequent commit adds a "large_dict" test case which exhibits the
same behavior as above. With this patch applied the test case successfully
completes in under a second.

Tested with valgrind, make check, and QMP.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 65c0f1e955)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Michael Roth 8a869baa08 qlist: add qlist_size()
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a86a4c2f7b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Hans de Goede dbeb6c22d7 usb-ehci: Fix an assert whenever isoc transfers are used
hcd-ehci.c is missing an usb_packet_init() call for the ipacket UsbPacket
it uses for isoc transfers, triggering an assert (taking the entire vm down)
in usb_packet_setup as soon as any isoc transfers are done by a high speed
USB device.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 7341ea075c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Hans de Goede b00201d402 usb-redir: Correctly handle the usb_redir_babble usbredir status
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit adae502c0a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Gerd Hoffmann a1a17b1d5a usb: restore USBDevice->attached on vmload
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 495d544798)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Gerd Hoffmann f49853a4bd uhci: fix uhci_async_cancel_all
We update the QTAILQ in the loop, thus we must use the SAFE version
to make sure we don't touch the queue struct after freeing it.

https://bugzilla.novell.com/show_bug.cgi?id=766310

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 77fa9aee38)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Gerd Hoffmann b10daa61f9 ehci: don't flush cache on doorbell rings.
Commit 4be23939ab makes ehci instantly
zap any unlinked queue heads when the guest rings the doorbell.

While hacking up uas support this turned out to be a problem.  The linux
kernel can unlink and instantly relink the very same queue head, thereby
killing any async packets in flight.  That alone isn't an issue yet, the
packet will canceled and resubmitted and everything is fine.  We'll run
into trouble though in case the async packet is completed already, so we
can't cancel it any more.  The transaction is simply lost then.

usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f0c2 qtds 29dbce40,29dbc4e0,00000009
usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: alloc
usb_packet_state_change bus 0, port 2, ep 1, packet 0x7f95fdec32e0, state undef -> setup
usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: process
usb_uas_command dev 2, tag 0x2, lun 0, lun64 00000000-00000000
scsi_req_parsed target 0 lun 0 tag 2 command 42 dir 2 length 16384
scsi_req_parsed_lba target 0 lun 0 tag 2 command 42 lba 5933312
scsi_req_alloc target 0 lun 0 tag 2
scsi_req_continue target 0 lun 0 tag 2
scsi_req_data target 0 lun 0 tag 2 len 16384
usb_uas_scsi_data dev 2, tag 0x2, bytes 16384
usb_uas_write_ready dev 2, tag 0x2
usb_packet_state_change bus 0, port 2, ep 1, packet 0x7f95fdec32e0, state setup -> complete
usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: free
usb_ehci_qh_ptrs q 0x7f95fdec3210 - QH @ 39c4f0c0: next 39c4f002 qtds 29dbce40,00000001,00000009
usb_ehci_qh_fields QH @ 39c4f0c0 - rl 4, mplen 512, eps 2, ep 2, dev 2
usb_ehci_queue_action q 0x7f95fe5152a0: free
usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state async -> complete
^^^ async packets completes.
usb_ehci_packet_action q 0x7f95fdec3210 p 0x7f95feba9130: wakeup

usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f002 qtds 29dbc4e0,29dbc8a0,00000009
usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
usb_ehci_queue_action q 0x7f95fdec3210: free
usb_ehci_packet_action q 0x7f95fdec3210 p 0x7f95feba9130: free
^^^ endpoint #2 queue head removed from schedule, doorbell makes ehci zap the queue,
    the (completed) usb packet is freed too and gets lost.

usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f0c2 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f0c2 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_queue_action q 0x7f9600dff570: alloc
usb_ehci_qh_ptrs q 0x7f9600dff570 - QH @ 39c4f0c0: next 39c4f122 qtds 29dbce40,00000001,00000009
usb_ehci_qh_fields QH @ 39c4f0c0 - rl 4, mplen 512, eps 2, ep 2, dev 2
usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: alloc
usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state undef -> setup
usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: process
usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state setup -> async
usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: async
^^^ linux kernel relinked the queue head, ehci creates a new usb packet,
    but we should have delivered the completed one instead.
usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f002 qtds 29dbc4e0,29dbc8a0,00000009
usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2

So instead of instantly zapping the queue we'll set a flag that the
queue needs revalidation in case we'll see it again in the schedule.
ehci then checks that the queue head fields addressing / describing the
endpoint and the qtd pointer match the cached content before reusing it.

Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 9bc3a3a216)

Conflicts:

	hw/usb/hcd-ehci.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Gerd Hoffmann 34b41ed15d ehci: fix reset
Check for the reset bit first when processing USBCMD register writes.
Also break out of the switch, there is no need to check the other bits.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 7046530c36)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Avi Kivity 3b38972743 virtio-blk: fix use-after-free while handling scsi commands
The scsi passthrough handler falls through after completing a
request into the failure path, resulting in a use after free.

Reproducible by running a guest with aio=native on a block device.

Reported-by: Stefan Priebe <s.priebe@profihost.ag>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 730a9c53b4)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Anthony Liguori 36ed337845 qdev: fix use-after-free in the error path of qdev_init_nofail
From Markus:

Before:

    $ qemu-system-x86_64 -display none -drive if=ide
    qemu-system-x86_64: Device needs media, but drive is empty
    qemu-system-x86_64: Initialization of device ide-hd failed
    [Exit 1 ]

After:

    $ qemu-system-x86_64 -display none -drive if=ide
    qemu-system-x86_64: Device needs media, but drive is empty
    Segmentation fault (core dumped)
    [Exit 139 (SIGSEGV)]

This error always existed as qdev_init() frees the object.  But QOM
goes a bit further and purposefully sets the class pointer to NULL to
help find use-after-free.  It worked :-)

Cc: Andreas Faerber <afaerber@suse.de>
Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7de3abe505)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:35 -05:00
Jan Kiszka 5a1800cf1c kvmvapic: Disable if there is insufficient memory
We need at least 1M of RAM to map the option ROM. Otherwise, we will
corrupt host memory or even crash:

    $ qemu-system-x86_64 -nodefaults --enable-kvm -vnc :0 -m 640k
    Segmentation fault (core dumped)

Reported-and-tested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
(cherry picked from commit a9605e0317)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:34 -05:00
Christian Borntraeger 97ac3b1af5 s390: Fix error handling and condition code of service call
Invalid sccb addresses will cause specification or addressing exception.
Lets add those checks. Furthermore, the good case (cc=0) was incorrect
for KVM, we did not set the CC at all. We now use return codes < 0
as program checks and return codes > 0 as condition code values.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit 9abf567d95)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:34 -05:00
David Gibson 08e642c00e ppc: Fix bug in handling of PAPR hypercall exits
Currently for powerpc, kvm_arch_handle_exit() always returns 1, meaning
that its caller - kvm_cpu_exec() - will always exit immediately afterwards
to the loop in qemu_kvm_cpu_thread_fn().

There's no need to do this.  Once we've handled the hypercall there's no
reason we can't go straight around and KVM_RUN again, which is what ret = 0
will signal.  The only exception might be for hypercalls which affect the
state of cpu_can_run(), however the only one that might do this is H_CEDE
and for kvm that is always handled in the kernel, not qemu.

Furtherm setting ret = 0 means that when exit_requested is set from a
hypercall, we will enter KVM_RUN once more with a signal which lets the
the kernel do its internal logic to complete the hypercall with out
actually executing any more guest code.  This is important if our hypercall
also triggered a reset, which previously would re-initialize everything
without completing the hypercall.  This caused the kernel to get confused
because it thought the guest was still in the middle of a hypercall when
it has actually been reset.

This patch therefore changes to ret = 0, which is both a bugfix and a small
optimization.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit 78e8fde26c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:34 -05:00
Peter Maydell 7940c766d4 configure: Don't override user's --cpu on MacOS and Solaris
Both MacOS and Solaris have special case handling for the CPU
type, because the check_define probes will return i386 even if
the hardware is 64 bit and x86_64 would be preferable. Move
these checks earlier in the configure probing so that we can
do them only if the user didn't specify a CPU with --cpu. This
fixes a bug where the user's command line argument was being
ignored.

Reviewed-by: Andreas F=E4rber <afaerber@suse.de>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bbea405080)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:34 -05:00
Anthony Liguori f408f49165 qtest: fix infinite loop when QEMU aborts abruptly
From Markus:

Makes "make check" hang:

    QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 gtester -k --verbose -m=quick tests/crash-test tests/rtc-test
    TEST: tests/crash-test... (pid=972)
    qemu-system-x86_64: Device needs media, but drive is empty
[Nothing happens, wait a while, then hit ^C]
    make: *** [check-qtest-x86_64] Interrupt

This was due to the fact that we weren't checked for errors when
reading from the QMP socket.  This patch adds appropriate error
checking.

Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 039380a8e1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-08-21 15:36:34 -05:00
Michael Roth 785adb09b9 update VERSION for v1.1.1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-07-12 13:36:53 -05:00
Michael Roth f52d0d639e Merge remote-tracking branch 'agraf/s390-for-upstream-1.1' into HEAD 2012-07-10 14:08:37 -05:00
Alexander Graf 4082e889ee s390x: fix s390 virtio aliases
Some of the virtio devices have the same frontend name, but actually
implement different devices behind the scenes through aliases.

The indicator which device type to use is the architecture. On s390, we
want s390 virtio devices. On everything else, we want PCI devices.

Reflect this in the alias selection code. This way we fix commands like
-device virtio-blk on s390x which with this patch applied select the
correct virtio-blk-s390 device rather than virtio-blk-pci.

Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2012-07-10 18:29:29 +02:00
Jason Wang b7093f294c rtl8139: validate rx ring before receiving packets
Commit ff71f2e8ca prevent the possible
crash during initialization of linux driver by checking the operating
mode.This seems too strict as:

- the real card could still work in mode other than normal
- some buggy driver who does not set correct opmode after eeprom
 access

So, considering rx ring address were reset to zero (which could be
safely trated as an address not intened to DMA to), in order to
both letting old guest work and preventing the unexpected DMA to
guest, we can forbid packet receiving when rx ring address is zero.

Tested-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit fcce6fd25f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-29 10:22:30 -05:00
Daniel Verkamp cd63a77e99 ahci: SATA FIS is 20 bytes, not 0x20
As in the SATA and AHCI specifications, a FIS is 5 Dwords of 4 bytes
each, which comes to 20 bytes (decimal), not 0x20.

Signed-off-by: Daniel Verkamp <daniel@drv.nu>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 4bb9c939a5)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 10:58:24 -05:00
Stefan Hajnoczi 8456852657 qemu-img: document qed format on qemu-img man page
The qemu-img.1 man page is missing the qed format from its list of
supported formats.  Document the image creation options for qed.

Suggested-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit f085800e24)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 09:04:33 -05:00
Stefan Weil 7d440f20bd virtio: Fix compiler warning for non Linux hosts
The local variables ret, i are only used if __linux__ is defined.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 47ce9ef7f8)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 09:04:04 -05:00
MORITA Kazutaka feba8ae20b sheepdog: fix return value of do_load_save_vm_state
bdrv_save_vmstate and bdrv_load_vmstate should return the vmstate size
on success, and -errno on error.

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 6f3c714eb7)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 09:03:33 -05:00
Jan Beulich c9c2479289 qemu/xendisk: set maximum number of grants to be used
Legacy (non-pvops) gntdev drivers may require this to be done when the
number of grants intended to be used simultaneously exceeds a certain
driver specific default limit.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
(cherry picked from commit 64c27e5b1f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 09:00:42 -05:00
Bruce Rogers 4c45bf61d3 build: install qmp-commands.txt
File is targeted for install, but is never installed.

Signed-off-by: Bruce Rogers <brogers@suse.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 0cd23fcc0a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:50 -05:00
Pavel Hrdina 70d582074f fdc: fix implied seek while there is no media in drive
The Windows uses 'READ' command at the start of an instalation
without checking the 'dir' register. We have to abort the transfer
with an abnormal termination if there is no media in the drive.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit c52acf60b6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:44 -05:00
Stefan Hajnoczi 0da4c07322 qcow2: fix autoclear image header update
The autoclear feature bits can be used for qcow2 file format features
that are safe to "drop" by old programs that do not understand the
feature.  Upon opening the image file unknown autoclear feature bits are
cleared and the image file header is rewritten, but this was happening
too early in the code when critical header fields were not yet loaded.

Process autoclear feature bits after all necessary header information
has been loaded.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit af7b708db2)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:38 -05:00
Pavel Dovgaluk ee7735fa63 Prevent disk data loss when closing qemu
Prevent disk data loss when closing qemu console window
under Windows 7.

v3. Comment for Sleep() parameter was updated.

Signed-off-by: Pavel Dovgalyuk<pavel.dovgaluk@gmail.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit b75a02829d)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:33 -05:00
Zhi Yong Wu 02fe741375 qcow2: fix endianness conversion
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 87267753a3)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:25 -05:00
Jason Baron dbe4ac16bb pci_bridge_dev: fix error path in pci_bridge_dev_initfn()
Currently, we do not properly cleanup, if pci_bridge_dev_initfn
fails to initialize properly. Make sure to call pci_bridge_exitfn()
in the error path.

Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 80aa796bf3)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:19 -05:00
Jason Baron f63e60327b qdev: release parent properties on dc->init failure
While looking into hot-plugging bridges, I can create a qemu segfault via:

$ device_add pci-bridge

Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0.
**
ERROR:qom/object.c:389:object_delete: assertion failed: (obj->ref == 0)

I'm proposing to fix this by adding a call to 'object_unparent()', before the
call to qdev_free(). I see there is already a precedent for this usage pattern as
seen in qdev_simple_unplug_cb():

/* can be used as ->unplug() callback for the simple cases */
int qdev_simple_unplug_cb(DeviceState *dev)
{
    /* just zap it */
    object_unparent(OBJECT(dev));
    qdev_free(dev);
    return 0;
}

Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 266ca11a04)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:12 -05:00
Jan Kiszka 0ec3907571 intel-hda: Fix reset of MSI function
Call msi_reset on device reset as still required by the core.

CC: Gerd Hoffmann <kraxel@redhat.com>
CC: qemu-stable@nongnu.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 8e729e3b52)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:06 -05:00
Jan Kiszka 1658e3cd89 ahci: Fix reset of MSI function
Call msi_reset on device reset as still required by the core.

CC: Alexander Graf <agraf@suse.de>
CC: qemu-stable@nongnu.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 868a1a5226)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:55:00 -05:00
Fernando Luis Vazquez Cao 065436479b rtl8139: honor RxOverflow flag in can_receive method
Some drivers (Linux' 8139too among them) rely on the NIC
injecting an interrupt in the event of a receive buffer overflow
and, accordingly, set the RxOverflow bit in the interrupt
mask. Unfortunately rtl8139's can_receive method ignores the
RxOverflow flag, which may lead to a situation where rtl8139
stops receiving packets (can_receive returns 0) when the receive
buffer becomes full.

If the driver eventually read from the receive buffer or reset
the card the emulator could recover from this situation. However
some implementations only do this upon receiving an interrupt
with either RxOK or RxOverflow set in the ISR; interrupt that
will never come because QEMU's flow control mechanisms would
prevent rtl8139 from receiving any packet.

Letting packets go through when the overflow interrupt is enabled
makes the QEMU emulator compliant to the spec and solves the
problem.

This patch should fix a relatively common (in our experience)
network stall observed when running enterprise distros with
rtl8139 as the NIC; in some cases the 8139too device driver gets
loaded and when under heavy load the network eventually stops
working.

Reported-by: Hayato Kakuta <kakuta.hayato@oss.ntt.co.jp>
Tested-by: Hayato Kakuta <kakuta.hayato@oss.ntt.co.jp>
Acked-by: Igor Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit fee9d348ff)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:54:55 -05:00
Stefan Weil f6db26e4f8 configure: Fix build for some versions of glibc (9pfs)
Some versions declare open_by_handle_at, but don't define AT_EMPTY_PATH.
Extend the check in configure to test both preconditions.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
(cherry picked from commit acc55ba8b1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:54:44 -05:00
Stefan Weil c49dd1bf64 monitor: Fix memory leak with readline completion
Each string which is shown during readline completion in the QEMU monitor
is allocated dynamically but currently never deallocated.

Add the missing loop which calls g_free for the allocated strings.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit fc9fa4bd0a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:53:25 -05:00
Kevin Wolf b4fcb4b499 qcow2: Silence false warning
Some gcc versions seem not to be able to figure out that the switch
statement covers all possible values and that c is therefore always
initialised. Add a default branch for them.

Reported-by: malc <av1474@comtv.ru>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 1417d7e40e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:53:20 -05:00
Jan Kiszka 7672b714b2 kvm: i8254: Fix conversion of in-kernel to userspace state
Due to a offset between the clock used to generate the in-kernel
count_load_time (CLOCK_MONOTONIC) and the clock used for processing this
in userspace (vm_clock), reading back the output of PIT channel 2 via
port 0x61 was broken. One use cases that suffered from it was the CPU
frequency calibration of SeaBIOS, which also affected IDE/AHCI timeouts.

This fixes it by calibrating the offset between both clocks on
kvm_pit_get and adjusting the kernel value before saving it in the
userspace state. As the calibration only works while the vm_clock is
running, we cache the in-kernel state across stopped phases.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 0cdd3d1444)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:53:13 -05:00
Jim Meyering ca09717e8e kvm/apic: correct short memset
kvm_put_apic_state's attempt to clear *kapic before setting its
bits cleared sizeof(void*) bytes (no more than 8) rather than the
intended 1024 (KVM_APIC_REG_SIZE) bytes. Spotted by coverity.

Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 0614cb82ca)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:53:05 -05:00
Harsh Prateek Bora 0cc21de484 configure: report missing libraries for virtfs
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 263ddcc81b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:52:57 -05:00
Harsh Prateek Bora 08375616a0 trace/simple.c: fix deprecated glib2 interface
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 0d665005c7)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:52:44 -05:00
Max Filippov b993b863e7 target-xtensa: fix CCOUNT for conditional branches
Taken conditional branches fail to update CCOUNT register because
accumulated ccount_delta is reset during translation of non-taken
branch. To fix it only update CCOUNT once per conditional branch
instruction translation.

This fixes guest linux freeze on LTP waitpid06 test.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit d865f30739)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:56 -05:00
Max Filippov 07ff37597b exec: fix TB invalidation after breakpoint insertion/deletion
tb_invalidate_phys_addr has to be called with the exact physical address of
the breakpoint we add/remove, not just the page's base address.
Otherwise we easily fail to flush the right TB.

This breakage was introduced by the commit f3705d5329 "memory: make
phys_page_find() return an unadjusted".

This appeared to work for some guest architectures because their
cpu_get_phys_page_debug implementation returns full translated physical
address, not just the base of the TARGET_PAGE_SIZE-sized page.

Reported-by: TeLeMan <geleman@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 9d70c4b7b8)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:46 -05:00
Max Filippov e77326d99c target-xtensa: add MMU pagewalking tests
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit c305e32f43)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:38 -05:00
Max Filippov 8b3ac66120 target-xtensa: control page table lookup explicitly
Hardware pagetable walking may not be nested. Stop guessing and pass
explicit flag to the get_physical_addr_mmu function that controls page
table lookup.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 57705a676c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:31 -05:00
Max Filippov 2eb4d314ce target-xtensa: update autorefill TLB entries conditionally
This is to avoid interference of internal QEMU helpers
(cpu_get_phys_page_debug, tb_invalidate_virtual_addr) with guest-visible
TLB state.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit ae4e7982e6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:23 -05:00
Max Filippov adda59173c target-xtensa: extract TLB entry setting method
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 16bde77a29)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:13 -05:00
Max Filippov b696aeab6a target-xtensa: update EXCVADDR in case of page table lookup
According to ISA, 4.4.2.6, EXCVADDR may be changed by any TLB miss, even
if the miss is handled entirely by processor hardware.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 39e7d37f0f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:48:06 -05:00
Max Filippov 6514fe5047 target-xtensa: flush TLB page for new MMU mapping
Both old and new mappings need flushing because their VPN may be
different in MMU case.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit e323bdeff2)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:47:58 -05:00
Christian Borntraeger c63c453889 virtio-blk: Fix geometry sector calculation
Currently the sector value for the geometry is masked, even if the
user usesa command line parameter that explicitely gives a number.
This breaks dasd devices on s390. A dasd device can have
a physical block size of 4096 (== same for logical block size)
and a typcial geometry of 15 heads and 12 sectors per cyl.
The ibm partition detection relies on a correct geometry
reported by the device. Unfortunately the current code changes
12 to 8. This would be necessary if the total size is
not a multiple of logical sector size,  but for dasd this
is not the case.

This patch checks the device size and only applies sector
mask if necessary.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
CC: Christoph Hellwig <hch@lst.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 136be99e6e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-06-25 08:47:47 -05:00
Anthony Liguori 78260a5f08 Update version for 1.1.0 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-06-01 16:55:34 +08:00
Anthony Liguori b3dbb9546a Update version for 1.1.0-rc4 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-31 08:53:39 +08:00
Anthony Liguori 272d28ecf2 Merge remote-tracking branch 'origin/master' into staging
* origin/master:
  pc-bios: Update OpenBIOS images
2012-05-31 08:49:46 +08:00
Blue Swirl 6f12926142 pc-bios: Update OpenBIOS images
Update OpenBIOS images to r1060 built from submodule.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-05-30 17:04:41 +00:00
Anthony Liguori d6111501c1 Merge remote-tracking branch 'mdroth/qga-pull-5-29-12-v2' into staging
* mdroth/qga-pull-5-29-12-v2:
  qemu-ga: avoid blocking on atime update when reading /etc/mtab
  qemu-ga: Fix use of environ on Darwin
2012-05-30 15:02:03 +08:00
Jim Meyering eba25057b9 block: prevent snapshot mode $TMPDIR symlink attack
In snapshot mode, bdrv_open creates an empty temporary file without
checking for mkstemp or close failure, and ignoring the possibility
of a buffer overrun given a surprisingly long $TMPDIR.
Change the get_tmp_filename function to return int (not void),
so that it can inform its two callers of those failures.
Also avoid the risk of buffer overrun and do not ignore mkstemp
or close failure.
Update both callers (in block.c and vvfat.c) to propagate
temp-file-creation failure to their callers.

get_tmp_filename creates and closes an empty file, while its
callers later open that presumed-existing file with O_CREAT.
The problem was that a malicious user could provoke mkstemp failure
and race to create a symlink with the selected temporary file name,
thus causing the qemu process (usually root owned) to open through
the symlink, overwriting an attacker-chosen file.

This addresses CVE-2012-2652.
http://bugzilla.redhat.com/CVE-2012-2652

Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-30 14:48:40 +08:00
Gerd Hoffmann e78bd5ab07 xhci: add usage info to docs
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-30 10:28:44 +08:00
Gerd Hoffmann 1643f2b232 vnc: fix segfault in vnc_display_pw_expire()
NULL pointer dereference in case no vnc server is configured.
Catch this and return -EINVAL like vnc_display_password() does.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-30 10:28:44 +08:00
Eduardo Habkost 1352672860 Expose CPUID leaf 7 only for -cpu host
Changes v2 -> v3;
  - Check for kvm_enabled() before setting cpuid_7_0_ebx_features

Changes v1 -> v2:
  - Use kvm_arch_get_supported_cpuid() instead of host_cpuid() on
    cpu_x86_fill_host().

  We should use GET_SUPPORTED_CPUID for all bits on "-cpu host"
  eventually, but I am not changing all the other CPUID leaves because
  we may not be able to test such an intrusive change in time for 1.1.

Description of the bug:

Since QEMU 0.15, the CPUID information on CPUID[EAX=7,ECX=0] is being
returned unfiltered to the guest, directly from the GET_SUPPORTED_CPUID
return value.

The problem is that this makes the resulting CPU feature flags
unpredictable and dependent on the host CPU and kernel version. This
breaks live-migration badly if migrating from a host CPU that supports
some features on that CPUID leaf (running a recent kernel) to a kernel
or host CPU that doesn't support it.

Migration also is incorrect (the virtual CPU changes under the guest's
feet) if you migrate in the opposite direction (from an old CPU/kernel
to a new CPU/kernel), but with less serious consequences (guests
normally query CPUID information only once on boot).

Fortunately, the bug affects only users using cpudefs with level >= 7.

The right behavior should be to explicitly enable those features on
[cpudef] config sections or on the "-cpu" command-line arguments. Right
now there is no predefined CPU model on QEMU that has those features:
the latest Intel model we have is Sandy Bridge.

I would like to get this fixed on 1.1, so I am submitting this patch,
that enables those features only if "-cpu host" is being used (as we
don't have any pre-defined CPU model that actually have those features).
After 1.1 is released, we can make those features properly configurable
on [cpudef] and -cpu configuration.

One problem is: with this patch, users with the following setup:
- Running QEMU 1.0;
- Using a cpudef having level >= 7;
- Running a kernel that supports the features on CPUID leaf 7; and
- Running on a CPU that supports some features on CPUID leaf 7
won't be able to live-migrate to QEMU 1.1. But for these users
live-migration is already broken (they can't live-migrate to hosts with
older CPUs or older kernels, already), I don't see how to avoid this
problem.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-30 10:28:44 +08:00
Michael Roth 9e2fa418fb qemu-ga: avoid blocking on atime update when reading /etc/mtab
Currently we re-read/re-process /etc/mtab to get an updated list of
mounts when guest-fsfreeze-thaw is called. This can cause an atime
update on /etc/mtab, which will block if we're in a frozen state.

Instead, use /proc's version of mtab, which may not be up-to-date with
options passed via -o remount, but is compatible for our use cases since
we only care about the filesystem type.

Reported-by: Matsuda, Daiki <matsudadik@intellilink.co.jp>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-29 21:00:42 -05:00
Andreas Färber eecae14724 qemu-ga: Fix use of environ on Darwin
Use _NSGetEnviron() helper to access the environment.

Signed-off-by: Andreas Färber <andreas.faerber@web.de>
Cc: Charlie Somerville <charlie@charliesomerville.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-29 21:00:40 -05:00
Amos Kong a6de8ed80e pci: call object_unparent() before free_qdev()
Start VM with 8 multiple-function block devs, hot-removing
those block devs by 'device_del ...' would cause qemu abort.

| (qemu) device_del virti0-0-0
| (qemu) **
|ERROR:qom/object.c:389:object_delete: assertion failed: (obj->ref == 0)

It's a regression introduced by commit 57c9fafe

The whole PCI slot should be removed once. Currently only one func
is cleaned in pci_unplug_device(), if you try to remove a single
func by monitor cmd.

free_qdev() are called for all functions in slot,
but unparent_delete() is only called for one
function.

Signed-off-by: XXXX
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-29 20:19:24 -05:00
Scott Moser 9c3a596a03 fix multiboot loading if load_end_addr == 0
The previous multiboot load code did not treat the case where
load_end_addr was 0 specially.  The multiboot specification says the
following:
 * load_end_addr
   Contains the physical address of the end of the data segment.
   (load_end_addr - load_addr) specifies how much data to load. This
   implies that the text and data segments must be consecutive in the
   OS image; this is true for existing a.out executable formats. If
   this field is zero, the boot loader assumes that the text and data
   segments occupy the whole OS image file.

Signed-off-by: Scott Moser <smoser@ubuntu.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-29 20:19:24 -05:00
Avi Kivity 8294a64d7f vga: fix vram double-mapping with -vga std and -M pc-0.12
With pc-0.12, we map the video RAM both through the PCI BAR (the guest does
this) and through a fixed mapping at 0xe0000000.  The memory API doesn't allow
this double map, and aborts.

Fix by using an alias.

Reported-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-29 20:19:24 -05:00
Anthony Liguori 1c4ad9d2b4 Merge remote-tracking branch 'afaerber-or/cocoa-for-upstream' into staging
* afaerber-or/cocoa-for-upstream:
  cocoa: Suppress Cocoa frontend for -qtest
  arch_init: Fix AltiVec build on Darwin/ppc
2012-05-29 06:54:16 -05:00
Andreas Färber 60b46aa2f3 cocoa: Suppress Cocoa frontend for -qtest
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2012-05-29 11:40:27 +02:00
Andreas Färber f283edc482 arch_init: Fix AltiVec build on Darwin/ppc
Commit f29a56147b (implement
-no-user-config command-line option (v3)) introduced uses of bool
in arch_init.c. Shortly before that usage is support code for
AltiVec (conditional to __ALTIVEC__).

GCC's altivec.h may in a !__APPLE_ALTIVEC__ code path redefine bool,
leading to type mismatches. altivec.h recommends to #undef for C++
compatibility, but doing so in C leads to bool remaining undefined.

Fix by redefining bool to _Bool as mandated for stdbool.h by POSIX.

Signed-off-by: Andreas Färber <andreas.faerber@web.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2012-05-29 11:38:07 +02:00
Anthony Liguori dd86df756e Merge remote-tracking branch 'sstabellini/for_1.1_rc3' into staging
* sstabellini/for_1.1_rc3:
  Call xc_domain_shutdown with the reboot flag when the guest requests a reboot.
  xen: Fix PV-on-HVM
  xen_disk: properly update stats in ioreq_release()
  xen_disk: use bdrv_aio_flush instead of bdrv_flush
  xen_disk: remove syncwrite option
  xen: disable rtc_clock
  xen: do not initialize the interval timer and PCSPK emulator
2012-05-29 04:32:13 -05:00
Anthony Liguori 422831fc81 Merge remote-tracking branch 'mdroth/qga-pull-5-24-12' into staging
* mdroth/qga-pull-5-24-12:
  qemu-ga: Fix missing environ declaration
  configure: check if environ is declared
2012-05-29 04:31:29 -05:00
Anthony Liguori 306761537f Merge remote-tracking branch 'kwolf/for-anthony' into staging
* kwolf/for-anthony:
  fdc-test: introduced qtest no_media_on_start and cmos qtest for floppy
  fdc: fix media detection
  fdc: floppy drive should be visible after start without media
  qemu-iotests: mark 035 qcow2-only
  qcow2: Check qcow2_alloc_clusters_at() return value
  sheepdog: use heap instead of stack for BDRVSheepdogState
  sheepdog: return -errno on error
  sheepdog: mark image as snapshot when tag is specified
  qemu-img: Explain how rebase operation can be used to perform a 'diff' operation.
  qcow2: don't leak buffer for unexpected qcow_version in header
2012-05-29 04:30:49 -05:00
Anthony Liguori 7943df571a Merge remote-tracking branch 'kiszka/queues/slirp' into staging
* kiszka/queues/slirp:
  slirp: Avoid redefining MAX_TCPOPTLEN
  slirp: Avoid statements without effect on Big Endian host
  slirp: Untangle TCPOLEN_* from TCPOPT_*
2012-05-29 04:30:00 -05:00
Anthony Liguori d501f8478a Merge remote-tracking branch 'bonzini/scsi-next' into staging
* bonzini/scsi-next:
  ISCSI: Switch to using READ16/WRITE16 for I/O to the LUN
  ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMC
  ISCSI: get device type at connection time
  ISCSI: change num_blocks to 64-bit
  ISCSI: redo how we set up the events
  scsi: declare vmstate_info_scsi_requests to be static
2012-05-29 04:28:59 -05:00
Andreas Färber 917cfc1f26 slirp: Avoid redefining MAX_TCPOPTLEN
MAX_TCPOPTLEN is being defined as 32. Darwin already has it as 40,
causing a warning. The value is only used to declare an array,
into which currently 4 bytes are written at most.

Therefore always override MAX_TCPOPTLEN for now.

Suggested-by: Jan Kiszka <jan.kiszka@web.de>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
2012-05-28 22:44:27 +02:00
Andreas Färber 9b24d8e987 slirp: Avoid statements without effect on Big Endian host
Darwin has HTON*/NTOH* macros that on BE simply return the argument.
This is incompatible with SLIRP's use of these macros as a statement.

Undefine the macros in the HOST_WORDS_BIGENDIAN code path to redefine
these macros as no-op, as already done when they were undefined.

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
2012-05-28 22:31:07 +02:00
Ronnie Sahlberg f4dfa67f04 ISCSI: Switch to using READ16/WRITE16 for I/O to the LUN
This allows using LUNs bigger than 2TB.  Keep using READ10 for other
device types such as MMC.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2012-05-28 14:04:16 +02:00
Ronnie Sahlberg 6bcd1346bb ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMC
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2012-05-28 14:04:15 +02:00
Ronnie Sahlberg dbfff6d776 ISCSI: get device type at connection time
This is needed to avoid READ CAPACITY(16) for MMC devices.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-05-28 14:04:14 +02:00
Paolo Bonzini c7b4a95202 ISCSI: change num_blocks to 64-bit
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-05-28 14:04:14 +02:00
Ronnie Sahlberg c9b9f6824f ISCSI: redo how we set up the events
Call qemu_notify_event() after updating events.  Otherwise, If we add
an event for -is-writeable but the socket is already writeable there
may be a delay before the event callback is actually triggered.

Those delays would in particular hurt performance during BIOS boot and
when the GRUB bootloader reads the kernel and initrd.

But first call out to the socket write functions directly, and only set up
the write event if the socket is full.  This will happen very rarely and
this improves performance.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2012-05-28 14:04:06 +02:00
Andreas Färber e20e48a802 slirp: Untangle TCPOLEN_* from TCPOPT_*
Commit b72210568e (slirp: clean up
conflicts with system headers) enclosed TCPOLEN_MAXSEG with an #ifdef
TCPOPT_EOL. This broke the build on illumos, which has TCPOPT_*
but not TCPOLEN_*.

Move them to their own #ifdef TCPOLEN_MAXSEG section to remedy this.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
2012-05-28 13:45:33 +02:00
Andreas Färber 24f50d7ea5 tcg/ppc: Handle _CALL_DARWIN being undefined on Darwin
powerpc-apple-darwin9-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5577)
does not define _CALL_DARWIN, leading to unexpected behavior w.r.t.
register clobbering and stack frame layout.

Since _CALL_DARWIN is a reserved identifier, define a custom
TCG_TARGET_CALL_DARWIN based on either _CALL_DARWIN or __APPLE__.

Signed-off-by: Andreas F?rber <andreas.faerber@web.de>
Signed-off-by: malc <av1474@comtv.ru>
2012-05-27 21:52:56 +04:00
Pavel Hrdina 7cd331617a fdc-test: introduced qtest no_media_on_start and cmos qtest for floppy
As default a guest has always one floppy drive so 0x10 byte in CMOS
has to have 0x40 value. Higher 4 bits means that the first floppy drive
is 1.44 Mb 3"5 drive and lower 4 bits means the second drive is not present.

After the guest starts DSKCHG bit in DIR register should be set. If there
is no media in drive, this bit should be set all the time.

Because we start the guest without media in drive, we have to swap
'eject' and 'change' in 'test_media_change'.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:23:47 +02:00
Pavel Hrdina cfb08fbafc fdc: fix media detection
We have to set up 'media_changed' after guest start so floppy driver
could detect that there is no media in drive. For this purpose we call
'fdctrl_change_cb' instead of 'fd_revalidate' in 'fdctrl_connect_drives'.
'fd_revalidate' is called inside 'fdctrl_change_cb'.

We still have to set default drive geometry in 'fd_revalidate' even
if there is no media in drive. When you try to open (windows) or mount (linux)
floppy the driver tries to seek on track 1. Linux guest stuck in loop then
kernel crashes and windows guest prints error message.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:21:12 +02:00
Pavel Hrdina 9ecd394753 fdc: floppy drive should be visible after start without media
If you start guest with floppy drive but without media inserted, guest
still should see floppy drive pressent.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:18:53 +02:00
Stefan Hajnoczi b84762e245 qemu-iotests: mark 035 qcow2-only
The 035 parallel aio write test relies on knowledge of qcow2 metadata
layout to stress parallel L2 table accesses.  This only works for qcow2
unless we add additional calculations for qed or other formats.

Mark this test as qcow2-only.

Note that the test is strictly speaking non-deterministic although the
output produced is reliable with qcow2.  This is because the aio_write
command returns before the aio write request has completed.  Completions
can occur at any time afterwards and cause a message to be printed.
Therefore the exact output of this test is not deterministic but we seem
to get away with it for qcow2 (maybe due to coroutine and main loop
scheduling).

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:13:44 +02:00
Kevin Wolf df02179189 qcow2: Check qcow2_alloc_clusters_at() return value
When using qcow2_alloc_clusters_at(), the cluster allocation code
checked the wrong variable for an error code.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:12:54 +02:00
MORITA Kazutaka b6fc8245e9 sheepdog: use heap instead of stack for BDRVSheepdogState
bdrv_create() is called in coroutine context now, so we cannot use
more stack than 1 MB in the function if we use ucontext coroutine.
This patch allocates BDRVSheepdogState, whose size is 4 MB, on the
heap in sd_create().

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:12:54 +02:00
MORITA Kazutaka cb595887cc sheepdog: return -errno on error
On error, BlockDriver APIs should return -errno instead of -1.

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:12:54 +02:00
MORITA Kazutaka 622b6057be sheepdog: mark image as snapshot when tag is specified
When a snapshot tag is specified in the filename, the opened image is
a snapshot.

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:12:54 +02:00
Richard W.M. Jones 9fda6ab1d9 qemu-img: Explain how rebase operation can be used to perform a 'diff' operation.
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:12:54 +02:00
Jim Meyering b6c147622d qcow2: don't leak buffer for unexpected qcow_version in header
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-25 18:12:54 +02:00
Jim Meyering 12badfc238 scsi: declare vmstate_info_scsi_requests to be static
Signed-off-by: Jim Meyering <meyering@redhat.com>
2012-05-25 13:00:27 +02:00
Luiz Capitulino 2c02cbf6e9 qemu-ga: Fix missing environ declaration
Commit 3674838cd0 uses the environ global
variable, but is relying on environ to be declared somewhere else.

This worked for me because on F16 environ is declared in <unistd.h>, but
that doesn't happen in OpenBSD for example, causing a build failure.

This commit fixes the build error by declaring environ if it hasn't
being declared yet.

Also fixes a build warning due to a missing <sys/wait.h> include.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-24 13:06:33 -05:00
Luiz Capitulino 8ab1bf120d configure: check if environ is declared
Some systems may declare environ automatically, others don't. Check for it.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-24 13:06:31 -05:00
Jan Kiszka aeb29b6459 audio: Always call fini on exit
Not only clean up enabled voices but any registered one. Backends like
pulsaudio rely on unconditional fini handler invocations.

This fixes "Memory pool destroyed but not all memory blocks freed!"
warnings on VM shutdowns when pa is used and lockups of QEMU on shutdown
as it got stuck on some pa-internal synchronization point.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: malc <av1474@comtv.ru>
2012-05-24 19:35:27 +04:00
Stefan Weil f8687bab91 es1370: Fix debug code
When DEBUG_ES1370 is defined, the compiler shows these warnings:

hw/es1370.c: In function ?es1370_update_voices?:
hw/es1370.c:414: warning: format ?%d? expects type ?int?, but argument 3 has type ?size_t?
hw/es1370.c: In function ?es1370_writel?:
hw/es1370.c:582: warning: format ?%d? expects type ?int?, but argument 3 has type ?long int?
hw/es1370.c:592: warning: format ?%d? expects type ?int?, but argument 3 has type ?long int?
hw/es1370.c:609: warning: format ?%d? expects type ?int?, but argument 3 has type ?long int?
hw/es1370.c: In function ?es1370_readl?:
hw/es1370.c:751: warning: suggest braces around empty body in an ?if? statement

Fix the format strings and add the missing braces.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: malc <av1474@comtv.ru>
2012-05-24 02:03:30 +04:00
Anthony Liguori c48b0c80fc Update version for 1.1.0-rc3
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-22 09:21:01 -05:00
Anthony PERARD 4accd107d0 xen: Fix PV-on-HVM
In the context of PV-on-HVM under Xen, the emulated nics are supposed to be
unplug before the guest drivers are initialized, when the guest write to a
specific IO port.

Without this patch, the guest end up with two nics with the same MAC, the
emulated nic and the PV nic.

Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:51 -05:00
dunrong huang a340046614 qdev: Fix memory leak
The str allocated in visit_type_str was not freed.

The visit_type_str function is an input visitor(<QMP/String/etc>-to-native)
here, it will allocate memory for caller, so the caller is responsible for
freeing the memory.

Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: dunrong huang <riegamaths@gmail.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:51 -05:00
Orit Wassermann 2a633c461e virtio: check virtio_load return code
Otherwise we crash on error.

Signed-off-by: Ulrich Obergfell <uobergfe@redhat.com>
Signed-off-by: Orit Wassermann <owasserm@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:50 -05:00
Paolo Bonzini a6c5c84ae2 virtio-blk: always enable VIRTIO_BLK_F_SCSI
VIRTIO_BLK_F_SCSI is supposed to mean whether the host can *parse*
SCSI requests, not *execute* them.  You could run QEMU with scsi=on
and a file-backed disk, and QEMU would fail all SCSI requests even
though it advertises VIRTIO_BLK_F_SCSI.

Because we need to do this to fix a migration compatibility problem
related to how QEMU is invoked by management, we must do this
unconditionally even on older machine types.  This more or less assumes
that no one ever invoked QEMU with scsi=off.

Here is how testing goes:

- old QEMU, scsi=on -> new QEMU, scsi=on
- new QEMU, scsi=on -> old QEMU, scsi=on
- old QEMU, scsi=off -> new QEMU, scsi=on
- new QEMU, scsi=off -> old QEMU, scsi=on
        ok (new QEMU has VIRTIO_BLK_F_SCSI, adding host features is fine)

- old QEMU, scsi=off -> new QEMU, scsi=off
        ok (new QEMU has VIRTIO_BLK_F_SCSI, adding host features is fine)

- old QEMU, scsi=on -> new QEMU, scsi=off
        ok, bug fixed

- new QEMU, scsi=on -> old QEMU, scsi=off
        doesn't work (same as: old QEMU, scsi=on -> old QEMU, scsi=off)

- new QEMU, scsi=off -> old QEMU, scsi=off
        broken by the patch

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:50 -05:00
Paolo Bonzini 12c5674b84 virtio-blk: define VirtIOBlkConf
We will have to add another field to the virtio-blk configuration in
the next patch.  Avoid a proliferation of arguments to virtio_blk_init.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:50 -05:00
Paolo Bonzini 0e47931b88 virtio-blk: blockdev_mark_auto_del is transport-independent
Move it from virtio_blk_exit_pci to virtio_blk_exit.

This is included here because the next patch removes proxy->block.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:50 -05:00
Paolo Bonzini f34e73cd69 virtio-blk: report non-zero status when failing SG_IO requests
Linux really looks only at scsi->errors for SG_IO requests; it does
not look at the virtio request status at all.  Because of this, when
a SG_IO request is failed early with virtio_blk_req_complete(req,
VIRTIO_BLK_S_UNSUPP), without writing hdr.status, it will look like
a success to the guest.

This is their bug, but we can make it safe for older guests now by
forcing scsi->errors to have a non-zero value whenever a request
has to be failed.

But if we fix the bug in the guest driver, we will have another problem
because QEMU returns VIRTIO_BLK_S_IOERR if the status is non-zero, and
Linux translates that to -EIO.  Rather, the guest should succeed the
request and pass the non-zero status via the userspace-provided SG_IO
structure.  So, remove the case where virtio_blk_handle_scsi can
return VIRTIO_BLK_S_IOERR.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:50 -05:00
Mark Langsdorf 80a2ba3d3c use an uint64_t for the max_sz parameter in load_image_targphys
Allow load_image_targphys to load files on systems with more than 2G of
emulated memory by changing the max_sz parameter from an int to an
uint64_t.

Reviewed-by: Andreas F=E4rber <afaerber@suse.de>
Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:40:50 -05:00
Anthony Liguori b4f1a7ca72 Merge remote-tracking branch 'mdroth/qga-pull-5-15-12' into staging
* mdroth/qga-pull-5-15-12:
  qemu-ga: align versioning with QEMU_VERSION
  qemu-ga: fix segv after failure to open log file
  qemu-ga: guest-shutdown: use only async-signal-safe functions
  qemu-ga: guest-shutdown: become synchronous
  qemu-ga: guest-suspend: make the API synchronous
  qemu-ga: become_daemon(): reopen standard fds to /dev/null
  qemu-ga: make reopen_fd_to_null() public
  qemu-ga: guest-suspend-hybrid: don't emit a success response
  qemu-ga: guest-suspend-ram: don't emit a success response
  qemu-ga: guest-suspend-disk: don't emit a success response
  qemu-ga: guest-shutdown: don't emit a success response
  qemu-ga: don't warn on no command return
  qapi: add support for command options
2012-05-21 15:31:31 -05:00
Stefan Weil fba0c40bb7 tests: Add rtc-test (fix test regression)
Commit 93e9eb6808 added fdc-test,
but accidentally removed rtc-test because check-qtest-i386-y was
not enhanced but set twice.

This patch adds rtc-test again (and sorts both tests alphabetically).

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-05-21 15:31:06 -05:00
Stefan Weil fd4567d9a6 tests: Fix linker failure for fdc-test
When QEMU was built with the simple trace backend, linking failed:

  LINK  tests/fdc-test
oslib-posix.o: In function `trace_qemu_memalign':
qemu/bin/debug/x86/./trace.h:31: undefined reference to `trace3'
oslib-posix.o: In function `trace_qemu_vmalloc':
qemu/bin/debug/x86/./trace.h:35: undefined reference to `trace2'
oslib-posix.o: In function `trace_qemu_vfree':
qemu/bin/debug/x86/./trace.h:39: undefined reference to `trace1'
collect2: error: ld returned 1 exit status
make: *** [tests/fdc-test] Fehler 1

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-05-19 15:53:28 +00:00
Richard Sandiford d7f66b52de mips: Fix BC1ANY[24]F instructions
There's some dodgy application of De Morgan's law in the emulation
of the MIPS BC1ANY[24]F instructions: they end up branching only
if all CCs are false, rather than if one CC is.

Tested on mips64-linux-gnu, where it fixes the GCC MIPS3D tests.

Signed-off-by: Richard Sandiford <rdsandiford@googlemail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-05-19 15:51:44 +00:00
Alexander Graf 77a8f1a512 linux-user: Fix stale tbs after mmap
If we execute linux-user code that does the following:

  * A = mmap()
  * execute code in A
  * munmap(A)
  * B = mmap(), but mmap returns the same address as A
  * execute code in B

we end up executing a stale cached tb that contains translated code
from A, while we want new code from B.

This patch adds a TB flush for mmap'ed regions, before we return them,
avoiding the whole issue. It also adds a flush for munmap, so that we
don't execute stale TBs instead of getting a segfault.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Riku Voipio <riku.voipio@linaro.org>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-05-19 15:49:40 +00:00
Blue Swirl 4636b9d146 virtio-pci: add missing 'static'
There are no outside references to virtio_portio.
Add missing 'static' specifier.

Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-05-19 15:41:14 +00:00
Blue Swirl 5f2bf0fe55 sparc64: fix initrd loading
Initrd load address is too low, it conflicts with kernel load
address:
rom: requested regions overlap (rom phdr #0: /tmp/vmlinux-debian-6.0.4-sparc64. free=0x0000000000742519, addr=0x0000000000400000)
rom loading failed

Fix by making the initrd address variable, load initrd after kernel
image. Use 64 bit variables instead of longs or 32 bit types.

Tested-by: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2012-05-19 15:39:04 +00:00
Roger Pau Monne a28853871d audio: split IN_T into two separate constants
Split IN_T into BSIZE and ITYPE, to avoid expansion if the OS has
defined macros for the intX_t and uintX_t types. The IN_T constant is
then defined in mixeng_template.h so it can be used by the
functions/macros on this header file.

This change has been tested successfully under Debian Linux and NetBSD
6.0BETA.

Cc: Vassili Karpov (malc) <av1474@comtv.ru>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
Signed-off-by: malc <av1474@comtv.ru>
2012-05-18 15:19:28 +04:00
Peter A. G. Crosthwaite ace2e4dad7 target-microblaze: impelemented swapx instructions
Implemented the swapb and swaph byte/halfword reversal instructions added
to microblaze v8.30

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2012-05-18 12:17:52 +02:00
John V. Baboval 180640ea07 Call xc_domain_shutdown with the reboot flag when the guest requests a reboot.
Signed-off-by: John V. Baboval <john.baboval@virtualcomputer.com>
Signed-off-by: Tom Goetz <tom.goetz@virtualcomputer.com>
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2012-05-17 10:52:38 +00:00
Anthony PERARD a4f1a7589a xen: Fix PV-on-HVM
In the context of PV-on-HVM under Xen, the emulated nics are supposed to be
unplug before the guest drivers are initialized, when the guest write to a
specific IO port.

Without this patch, the guest end up with two nics with the same MAC, the
emulated nic and the PV nic.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
2012-05-17 10:52:29 +00:00
Jan Beulich ed54776643 xen_disk: properly update stats in ioreq_release()
While for the "normal" case (called from blk_send_response_all())
decrementing requests_finished is correct, doing so in the parse error
case is wrong; requests_inflight needs to be decremented instead.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
2012-05-17 10:43:33 +00:00
Stefano Stabellini c6961b7d38 xen_disk: use bdrv_aio_flush instead of bdrv_flush
Use bdrv_aio_flush instead of bdrv_flush.

Make sure to call bdrv_aio_writev/readv after the presync bdrv_aio_flush is fully
completed and make sure to call the postsync bdrv_aio_flush after
bdrv_aio_writev/readv is fully completed.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2012-05-17 10:43:33 +00:00
Stefano Stabellini ba1dffed63 xen_disk: remove syncwrite option
This patch removes a dead option.

The same can be achieved removing BDRV_O_NOCACHE and BDRV_O_CACHE_WB
from the flags passed to bdrv_open.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2012-05-17 10:43:33 +00:00
Stefano Stabellini 95d5d75ede xen: disable rtc_clock
rtc_clock is only used by the RTC emulator (mc146818rtc.c), however Xen
has its own RTC emulator in the hypervisor so we can disable it.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2012-05-17 10:43:32 +00:00
Stefano Stabellini c2d8d311c1 xen: do not initialize the interval timer and PCSPK emulator
PIT and PCSPK are emulated by the hypervisor so we don't need to emulate
them in Qemu: this patch prevents Qemu from waking up needlessly at
PIT_FREQ on Xen.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2012-05-17 10:43:32 +00:00
Michael Roth 8efacc43ae qemu-ga: align versioning with QEMU_VERSION
Previously qemu-ga version was defined seperately. Since it is aligned
with QEMU releases, use QEMU_VERSION instead. This also implies the
version bump for 1.1[-rcN] release of qemu-ga.

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:17:06 -05:00
Michael Roth 6c615ec57e qemu-ga: fix segv after failure to open log file
Currently, if we fail to open the specified log file (generally due to a
permissions issue), we'll assign NULL to the logfile handle (stderr,
initially) used by the logging routines, which can cause a segfault to
occur when we attempt to report the error before exiting.

Instead, only re-assign if the open() was successful.

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:16:55 -05:00
Luiz Capitulino 3674838cd0 qemu-ga: guest-shutdown: use only async-signal-safe functions
POSIX mandates[1] that a child process of a multi-thread program uses
only async-signal-safe functions before exec(). We consider qemu-ga
to be multi-thread, because it uses glib.

However, qmp_guest_shutdown() uses functions that are not
async-signal-safe. Fix it the following way:

- fclose() -> reopen_fd_to_null()
- execl() -> execle()
- exit() -> _exit()
- drop slog() usage (which is not safe)

  [1] http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino d5dd3498eb qemu-ga: guest-shutdown: become synchronous
Last commit dropped qemu-ga's SIGCHLD handler, used to automatically
reap terminated children processes. This introduced a bug to
qmp_guest_shutdown(): it will generate zombies.

This problem probably doesn't matter in the success case, as the VM
will shutdown anyway, but let's do the right thing and reap the
created process. This ultimately means that guest-shutdown is now a
synchronous command.

An interesting side effect is that guest-shutdown is now able to
report an error to the client if shutting down fails.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino dc8764f061 qemu-ga: guest-suspend: make the API synchronous
Currently, qemu-ga has a SIGCHLD handler that automatically reaps terminated
children processes. The idea is to avoid having qemu-ga commands blocked
waiting for children to terminate.

That approach has two problems:

 1. qemu-ga is unable to detect errors in the child, meaning that qemu-ga
    returns success even if the child fails to perform its task

 2. if a command does depend on the child exit status, the command has to
    play tricks to bypass the automatic reaper

Case 2 impacts the guest-suspend-* API, because it has to execute an external
program to check for suspend support. Today, to bypass the automatic reaper,
suspend code has to double fork and pass exit status information through a
pipe. Besides being complex, this is prone to race condition bugs. Indeed,
the current code does have such bugs.

Making the guest-suspend-* API synchronous (ie. by dropping the SIGCHLD
handler and calling waitpid() from commands) is a much simpler approach,
which fixes current race conditions bugs and enables commands to detect
errors in the child.

This commit does just that. There's a side effect though, guest-shutdown
will generate zombies if shutting down fails. This will be fixed by the
next commit.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino 226a48949c qemu-ga: become_daemon(): reopen standard fds to /dev/null
This fixes a bug where qemu-ga doesn't suspend the guest because it
fails to detect suspend support even when the guest does support
suspend. This happens because of the way qemu-ga fds are managed in
daemon mode.

When starting qemu-ga with --daemon, become_daemon() will close all
standard fds. This will cause qemu-ga to end up with the following
fds (if started with 'qemu-ga --daemon'):

    0 -> /dev/vport0p1
    3 -> /run/qemu-ga.pid

Then a guest-suspend-* function is issued. They call bios_supports_mode(),
which will call pipe(), and qemu-ga's fd will be:

    0 -> /dev/vport0p1
    1 -> pipe:[16247]
    2 -> pipe:[16247]
    3 -> /run/qemu-ga.pid

bios_supports_mode() forks off a child and blocks waiting for the child
to write something to the pipe. The child, however, closes its reading
end of the pipe _and_ reopen all standard fds to /dev/null. This will
cause the child's fds to be:

    0 -> /dev/null
    1 -> /dev/null
    2 -> /dev/null
    3 -> /run/qemu-ga.pid

In other words, the child's writing end of the pipe is now /dev/null.
It writes there and exits. The parent process (blocked on read()) will
get an EOF and interpret this as "something unexpected happened in
the child, let's assume the guest doesn't support suspend". And suspend
will fail.

To solve this problem we have to reopen standard fds to /dev/null
in become_daemon(), instead of closing them.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino 04b4e75f33 qemu-ga: make reopen_fd_to_null() public
The next commit wants to use it.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino d9fcd2a1c8 qemu-ga: guest-suspend-hybrid: don't emit a success response
Today, qemu-ga may not be able to emit a success response when
guest-suspend-hybrid completes. This happens because the VM may
suspend before qemu-ga is able to emit a response.

This semantic is a bit confusing, as it's not clear for clients if
they should wait for a response or how they should check for success.

This commit solves that problem by changing guest-suspend-hybrid to
never emit a success response and suggests in the documentation
what clients should do to check for success.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino 432d29db0d qemu-ga: guest-suspend-ram: don't emit a success response
Today, qemu-ga may not be able to emit a success response when
guest-suspend-ram completes. This happens because the VM may
suspend before qemu-ga is able to emit a response.

This semantic is a bit confusing, as it's not clear for clients if
they should wait for a response or how they should check for success.

This commit solves that problem by changing guest-suspend-ram to
never emit a success response and suggests in the documentation
what clients should do to check for success.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino c6fcc10ab3 qemu-ga: guest-suspend-disk: don't emit a success response
Today, qemu-ga may not be able to emit a success response when
guest-suspend-disk completes. This happens because the VM may
vanish before qemu-ga is able to emit a response.

This semantic is a bit confusing, as it's not clear for clients if
they should wait for a response or how they should check for success.

This commit solves that problem by changing guest-suspend-disk to
never emit a success response and suggests in the documentation
what clients could do to check for success.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino 8926817219 qemu-ga: guest-shutdown: don't emit a success response
Today, qemu-ga may not be able to emit a success response when
guest-shutdown completes. This happens because the VM may vanish
before qemu-ga is able to emit a response.

This semantic is a bit confusing, as it's not clear for clients if
they should wait for a response or how they should check for success.

This commit solves that problem by changing guest-shutdown to never
emit a success response and suggests in the documentation what
clients could do to check for success.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino ce8c8b7bd8 qemu-ga: don't warn on no command return
This is a valid condition when a command chooses to not emit a
success response.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
Luiz Capitulino d34b867d81 qapi: add support for command options
Options allow for changes in commands behavior. This commit introduces
the QCO_NO_SUCCESS_RESP option, which causes a command to not emit a
success response.

This is needed by commands such as qemu-ga's guest-shutdown, which
may not be able to complete before the VM vanishes. In this case, it's
useful and simpler not to bother sending a success response.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-05-15 09:15:16 -05:00
137 changed files with 2497 additions and 1181 deletions

No files matched your search

+1
View File
@@ -271,6 +271,7 @@ endif
install-doc: $(DOCS)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
+1 -1
View File
@@ -1 +1 @@
1.0.92
1.1.2
+4
View File
@@ -100,6 +100,10 @@ const uint32_t arch_type = QEMU_ARCH;
#define VECTYPE vector unsigned char
#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
/* altivec.h may redefine the bool macro as vector type.
* Reset it to POSIX semantics. */
#undef bool
#define bool _Bool
#elif defined __SSE2__
#include <emmintrin.h>
#define VECTYPE __m128i
+7 -6
View File
@@ -194,18 +194,19 @@ uint32_t do_arm_semihosting(CPUARMState *env)
if (!(s = lock_user_string(ARG(0))))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
if (ARG(1) >= 12)
if (ARG(1) >= 12) {
unlock_user(s, ARG(0), 0);
return (uint32_t)-1;
}
if (strcmp(s, ":tt") == 0) {
if (ARG(1) < 4)
return STDIN_FILENO;
else
return STDOUT_FILENO;
int result_fileno = ARG(1) < 4 ? STDIN_FILENO : STDOUT_FILENO;
unlock_user(s, ARG(0), 0);
return result_fileno;
}
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
(int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
return env->regs[0];
ret = env->regs[0];
} else {
ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
}
+8 -4
View File
@@ -1775,10 +1775,12 @@ static void audio_atexit (void)
HWVoiceOut *hwo = NULL;
HWVoiceIn *hwi = NULL;
while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
SWVoiceCap *sc;
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
if (hwo->enabled) {
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
}
hwo->pcm_ops->fini_out (hwo);
for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
@@ -1791,8 +1793,10 @@ static void audio_atexit (void)
}
}
while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
if (hwi->enabled) {
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
}
hwi->pcm_ops->fini_in (hwi);
}
+24 -12
View File
@@ -33,7 +33,8 @@
#define ENDIAN_CONVERT(v) (v)
/* Signed 8 bit */
#define IN_T int8_t
#define BSIZE 8
#define ITYPE int
#define IN_MIN SCHAR_MIN
#define IN_MAX SCHAR_MAX
#define SIGNED
@@ -42,25 +43,29 @@
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef BSIZE
#undef ITYPE
#undef SHIFT
/* Unsigned 8 bit */
#define IN_T uint8_t
#define BSIZE 8
#define ITYPE uint
#define IN_MIN 0
#define IN_MAX UCHAR_MAX
#define SHIFT 8
#include "mixeng_template.h"
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef BSIZE
#undef ITYPE
#undef SHIFT
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
/* Signed 16 bit */
#define IN_T int16_t
#define BSIZE 16
#define ITYPE int
#define IN_MIN SHRT_MIN
#define IN_MAX SHRT_MAX
#define SIGNED
@@ -78,11 +83,13 @@
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef BSIZE
#undef ITYPE
#undef SHIFT
/* Unsigned 16 bit */
#define IN_T uint16_t
#define BSIZE 16
#define ITYPE uint
#define IN_MIN 0
#define IN_MAX USHRT_MAX
#define SHIFT 16
@@ -98,11 +105,13 @@
#undef ENDIAN_CONVERSION
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef BSIZE
#undef ITYPE
#undef SHIFT
/* Signed 32 bit */
#define IN_T int32_t
#define BSIZE 32
#define ITYPE int
#define IN_MIN INT32_MIN
#define IN_MAX INT32_MAX
#define SIGNED
@@ -120,11 +129,13 @@
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef BSIZE
#undef ITYPE
#undef SHIFT
/* Unsigned 32 bit */
#define IN_T uint32_t
#define BSIZE 32
#define ITYPE uint
#define IN_MIN 0
#define IN_MAX UINT32_MAX
#define SHIFT 32
@@ -140,7 +151,8 @@
#undef ENDIAN_CONVERSION
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef BSIZE
#undef ITYPE
#undef SHIFT
t_sample *mixeng_conv[2][2][2][3] = {
+3 -1
View File
@@ -31,7 +31,8 @@
#define HALF (IN_MAX >> 1)
#endif
#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
#define ET glue (ENDIAN_CONVERSION, glue (glue (glue (_, ITYPE), BSIZE), _t))
#define IN_T glue (glue (ITYPE, BSIZE), _t)
#ifdef FLOAT_MIXENG
static mixeng_real inline glue (conv_, ET) (IN_T v)
@@ -150,3 +151,4 @@ static void glue (glue (clip_, ET), _from_mono)
#undef ET
#undef HALF
#undef IN_T
+3 -9
View File
@@ -349,21 +349,15 @@ static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
else {
hw->poll_mode = 0;
}
if (wave->paused) {
mr = waveOutRestart (wave->hwo);
if (mr != MMSYSERR_NOERROR) {
winwave_logerr (mr, "waveOutRestart");
}
wave->paused = 0;
}
wave->paused = 0;
}
return 0;
case VOICE_DISABLE:
if (!wave->paused) {
mr = waveOutPause (wave->hwo);
mr = waveOutReset (wave->hwo);
if (mr != MMSYSERR_NOERROR) {
winwave_logerr (mr, "waveOutPause");
winwave_logerr (mr, "waveOutReset");
}
else {
wave->paused = 1;
+24 -13
View File
@@ -409,28 +409,36 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
return bdrv_create(drv, filename, options);
}
/*
* Create a uniquely-named empty temporary file.
* Return 0 upon success, otherwise a negative errno value.
*/
int get_tmp_filename(char *filename, int size)
{
#ifdef _WIN32
void get_tmp_filename(char *filename, int size)
{
char temp_dir[MAX_PATH];
GetTempPath(MAX_PATH, temp_dir);
GetTempFileName(temp_dir, "qem", 0, filename);
}
/* GetTempFileName requires that its output buffer (4th param)
have length MAX_PATH or greater. */
assert(size >= MAX_PATH);
return (GetTempPath(MAX_PATH, temp_dir)
&& GetTempFileName(temp_dir, "qem", 0, filename)
? 0 : -GetLastError());
#else
void get_tmp_filename(char *filename, int size)
{
int fd;
const char *tmpdir;
/* XXX: race condition possible */
tmpdir = getenv("TMPDIR");
if (!tmpdir)
tmpdir = "/tmp";
snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
return -EOVERFLOW;
}
fd = mkstemp(filename);
close(fd);
}
if (fd < 0 || close(fd)) {
return -errno;
}
return 0;
#endif
}
/*
* Detect host devices. By convention, /dev/cdrom[N] is always
@@ -753,7 +761,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
bdrv_delete(bs1);
get_tmp_filename(tmp_filename, sizeof(tmp_filename));
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
if (ret < 0) {
return ret;
}
/* Real path is meaningless for protocols */
if (is_protocol)
+257 -93
View File
@@ -25,10 +25,12 @@
#include "config-host.h"
#include <poll.h>
#include <arpa/inet.h>
#include "qemu-common.h"
#include "qemu-error.h"
#include "block_int.h"
#include "trace.h"
#include "hw/scsi-defs.h"
#include <iscsi/iscsi.h>
#include <iscsi/scsi-lowlevel.h>
@@ -37,8 +39,10 @@
typedef struct IscsiLun {
struct iscsi_context *iscsi;
int lun;
enum scsi_inquiry_peripheral_device_type type;
int block_size;
unsigned long num_blocks;
uint64_t num_blocks;
int events;
} IscsiLun;
typedef struct IscsiAIOCB {
@@ -61,10 +65,44 @@ struct IscsiTask {
int complete;
};
static void
iscsi_bh_cb(void *p)
{
IscsiAIOCB *acb = p;
qemu_bh_delete(acb->bh);
if (acb->canceled == 0) {
acb->common.cb(acb->common.opaque, acb->status);
}
if (acb->task != NULL) {
scsi_free_scsi_task(acb->task);
acb->task = NULL;
}
qemu_aio_release(acb);
}
static void
iscsi_schedule_bh(IscsiAIOCB *acb)
{
if (acb->bh) {
return;
}
acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
qemu_bh_schedule(acb->bh);
}
static void
iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
void *private_data)
{
IscsiAIOCB *acb = private_data;
acb->status = -ECANCELED;
iscsi_schedule_bh(acb);
}
static void
@@ -73,15 +111,19 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
IscsiLun *iscsilun = acb->iscsilun;
acb->common.cb(acb->common.opaque, -ECANCELED);
if (acb->status != -EINPROGRESS) {
return;
}
acb->canceled = 1;
/* send a task mgmt call to the target to cancel the task on the target */
iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
iscsi_abort_task_cb, NULL);
iscsi_abort_task_cb, acb);
/* then also cancel the task locally in libiscsi */
iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task);
while (acb->status == -EINPROGRESS) {
qemu_aio_wait();
}
}
static AIOPool iscsi_aio_pool = {
@@ -104,11 +146,27 @@ static void
iscsi_set_events(IscsiLun *iscsilun)
{
struct iscsi_context *iscsi = iscsilun->iscsi;
int ev;
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read,
(iscsi_which_events(iscsi) & POLLOUT)
? iscsi_process_write : NULL,
iscsi_process_flush, iscsilun);
/* We always register a read handler. */
ev = POLLIN;
ev |= iscsi_which_events(iscsi);
if (ev != iscsilun->events) {
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
iscsi_process_read,
(ev & POLLOUT) ? iscsi_process_write : NULL,
iscsi_process_flush,
iscsilun);
}
/* If we just added an event, the callback might be delayed
* unless we call qemu_notify_event().
*/
if (ev & ~iscsilun->events) {
qemu_notify_event();
}
iscsilun->events = ev;
}
static void
@@ -132,61 +190,28 @@ iscsi_process_write(void *arg)
}
static int
iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb)
{
acb->bh = qemu_bh_new(cb, acb);
if (!acb->bh) {
error_report("oom: could not create iscsi bh");
return -EIO;
}
qemu_bh_schedule(acb->bh);
return 0;
}
static void
iscsi_readv_writev_bh_cb(void *p)
{
IscsiAIOCB *acb = p;
qemu_bh_delete(acb->bh);
if (acb->canceled == 0) {
acb->common.cb(acb->common.opaque, acb->status);
}
qemu_aio_release(acb);
}
static void
iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
IscsiAIOCB *acb = opaque;
trace_iscsi_aio_write10_cb(iscsi, status, acb, acb->canceled);
trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
g_free(acb->buf);
if (acb->canceled != 0) {
qemu_aio_release(acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
return;
}
acb->status = 0;
if (status < 0) {
error_report("Failed to write10 data to iSCSI lun. %s",
error_report("Failed to write16 data to iSCSI lun. %s",
iscsi_get_error(iscsi));
acb->status = -EIO;
}
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
iscsi_schedule_bh(acb);
}
static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
@@ -204,12 +229,9 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
struct iscsi_context *iscsi = iscsilun->iscsi;
IscsiAIOCB *acb;
size_t size;
int fua = 0;
/* set FUA on writes when cache mode is write through */
if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
fua = 1;
}
uint32_t num_sectors;
uint64_t lba;
struct iscsi_data data;
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
@@ -218,19 +240,47 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
acb->qiov = qiov;
acb->canceled = 0;
acb->bh = NULL;
acb->status = -EINPROGRESS;
/* XXX we should pass the iovec to write10 to avoid the extra copy */
/* XXX we should pass the iovec to write16 to avoid the extra copy */
/* this will allow us to get rid of 'buf' completely */
size = nb_sectors * BDRV_SECTOR_SIZE;
acb->buf = g_malloc(size);
qemu_iovec_to_buffer(acb->qiov, acb->buf);
acb->task = iscsi_write10_task(iscsi, iscsilun->lun, acb->buf, size,
sector_qemu2lun(sector_num, iscsilun),
fua, 0, iscsilun->block_size,
iscsi_aio_write10_cb, acb);
acb->task = malloc(sizeof(struct scsi_task));
if (acb->task == NULL) {
error_report("iSCSI: Failed to send write10 command. %s",
iscsi_get_error(iscsi));
error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
"command. %s", iscsi_get_error(iscsi));
qemu_aio_release(acb);
return NULL;
}
memset(acb->task, 0, sizeof(struct scsi_task));
acb->task->xfer_dir = SCSI_XFER_WRITE;
acb->task->cdb_size = 16;
acb->task->cdb[0] = 0x8a;
if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
/* set FUA on writes when cache mode is write through */
acb->task->cdb[1] |= 0x04;
}
lba = sector_qemu2lun(sector_num, iscsilun);
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
num_sectors = size / iscsilun->block_size;
*(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
acb->task->expxferlen = size;
data.data = acb->buf;
data.size = size;
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
iscsi_aio_write16_cb,
&data,
acb) != 0) {
scsi_free_scsi_task(acb->task);
g_free(acb->buf);
qemu_aio_release(acb);
return NULL;
@@ -242,30 +292,25 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
}
static void
iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
IscsiAIOCB *acb = opaque;
trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled);
trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
if (acb->canceled != 0) {
qemu_aio_release(acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
return;
}
acb->status = 0;
if (status != 0) {
error_report("Failed to read10 data from iSCSI lun. %s",
error_report("Failed to read16 data from iSCSI lun. %s",
iscsi_get_error(iscsi));
acb->status = -EIO;
}
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
iscsi_schedule_bh(acb);
}
static BlockDriverAIOCB *
@@ -277,8 +322,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
IscsiLun *iscsilun = bs->opaque;
struct iscsi_context *iscsi = iscsilun->iscsi;
IscsiAIOCB *acb;
size_t qemu_read_size, lun_read_size;
size_t qemu_read_size;
int i;
uint64_t lba;
uint32_t num_sectors;
qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
@@ -289,6 +336,8 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
acb->qiov = qiov;
acb->canceled = 0;
acb->bh = NULL;
acb->status = -EINPROGRESS;
acb->read_size = qemu_read_size;
acb->buf = NULL;
@@ -303,16 +352,44 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
acb->read_offset = bdrv_offset % iscsilun->block_size;
}
lun_read_size = (qemu_read_size + iscsilun->block_size
+ acb->read_offset - 1)
/ iscsilun->block_size * iscsilun->block_size;
acb->task = iscsi_read10_task(iscsi, iscsilun->lun,
sector_qemu2lun(sector_num, iscsilun),
lun_read_size, iscsilun->block_size,
iscsi_aio_read10_cb, acb);
num_sectors = (qemu_read_size + iscsilun->block_size
+ acb->read_offset - 1)
/ iscsilun->block_size;
acb->task = malloc(sizeof(struct scsi_task));
if (acb->task == NULL) {
error_report("iSCSI: Failed to send read10 command. %s",
iscsi_get_error(iscsi));
error_report("iSCSI: Failed to allocate task for scsi READ16 "
"command. %s", iscsi_get_error(iscsi));
qemu_aio_release(acb);
return NULL;
}
memset(acb->task, 0, sizeof(struct scsi_task));
acb->task->xfer_dir = SCSI_XFER_READ;
lba = sector_qemu2lun(sector_num, iscsilun);
acb->task->expxferlen = qemu_read_size;
switch (iscsilun->type) {
case TYPE_DISK:
acb->task->cdb_size = 16;
acb->task->cdb[0] = 0x88;
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
*(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
break;
default:
acb->task->cdb_size = 10;
acb->task->cdb[0] = 0x28;
*(uint32_t *)&acb->task->cdb[2] = htonl(lba);
*(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
break;
}
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
iscsi_aio_read16_cb,
NULL,
acb) != 0) {
scsi_free_scsi_task(acb->task);
qemu_aio_release(acb);
return NULL;
}
@@ -336,9 +413,6 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
IscsiAIOCB *acb = opaque;
if (acb->canceled != 0) {
qemu_aio_release(acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
return;
}
@@ -349,9 +423,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
acb->status = -EIO;
}
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
iscsi_schedule_bh(acb);
}
static BlockDriverAIOCB *
@@ -366,6 +438,8 @@ iscsi_aio_flush(BlockDriverState *bs,
acb->iscsilun = iscsilun;
acb->canceled = 0;
acb->bh = NULL;
acb->status = -EINPROGRESS;
acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
0, 0, 0, 0,
@@ -390,9 +464,6 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
IscsiAIOCB *acb = opaque;
if (acb->canceled != 0) {
qemu_aio_release(acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
return;
}
@@ -403,9 +474,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
acb->status = -EIO;
}
iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
scsi_free_scsi_task(acb->task);
acb->task = NULL;
iscsi_schedule_bh(acb);
}
static BlockDriverAIOCB *
@@ -422,6 +491,8 @@ iscsi_aio_discard(BlockDriverState *bs,
acb->iscsilun = iscsilun;
acb->canceled = 0;
acb->bh = NULL;
acb->status = -EINPROGRESS;
list[0].lba = sector_qemu2lun(sector_num, iscsilun);
list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
@@ -490,6 +561,98 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
scsi_free_scsi_task(task);
}
static void
iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
struct IscsiTask *itask = opaque;
struct scsi_readcapacity10 *rc10;
struct scsi_task *task = command_data;
if (status != 0) {
error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
iscsi_get_error(iscsi));
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
rc10 = scsi_datain_unmarshall(task);
if (rc10 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
itask->iscsilun->block_size = rc10->block_size;
itask->iscsilun->num_blocks = rc10->lba + 1;
itask->bs->total_sectors = itask->iscsilun->num_blocks *
itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
itask->status = 0;
itask->complete = 1;
scsi_free_scsi_task(task);
}
static void
iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
void *opaque)
{
struct IscsiTask *itask = opaque;
struct scsi_task *task = command_data;
struct scsi_inquiry_standard *inq;
if (status != 0) {
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
inq = scsi_datain_unmarshall(task);
if (inq == NULL) {
error_report("iSCSI: Failed to unmarshall inquiry data.");
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
itask->iscsilun->type = inq->periperal_device_type;
scsi_free_scsi_task(task);
switch (itask->iscsilun->type) {
case TYPE_DISK:
task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
iscsi_readcapacity16_cb, opaque);
if (task == NULL) {
error_report("iSCSI: failed to send readcapacity16 command.");
itask->status = 1;
itask->complete = 1;
return;
}
break;
case TYPE_ROM:
task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
0, 0,
iscsi_readcapacity10_cb, opaque);
if (task == NULL) {
error_report("iSCSI: failed to send readcapacity16 command.");
itask->status = 1;
itask->complete = 1;
return;
}
break;
default:
itask->status = 0;
itask->complete = 1;
}
}
static void
iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
void *opaque)
@@ -503,10 +666,11 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
return;
}
task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
iscsi_readcapacity16_cb, opaque);
task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
0, 0, 36,
iscsi_inquiry_cb, opaque);
if (task == NULL) {
error_report("iSCSI: failed to send readcapacity16 command.");
error_report("iSCSI: failed to send inquiry command.");
itask->status = 1;
itask->complete = 1;
return;
+15 -10
View File
@@ -471,6 +471,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
*cluster_offset &= L2E_OFFSET_MASK;
break;
default:
abort();
}
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
@@ -762,7 +764,6 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
uint64_t *host_offset, unsigned int *nb_clusters)
{
BDRVQcowState *s = bs->opaque;
int64_t cluster_offset;
QCowL2Meta *old_alloc;
trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
@@ -808,17 +809,21 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
/* Allocate new clusters */
trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
if (*host_offset == 0) {
cluster_offset = qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
int64_t cluster_offset =
qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
if (cluster_offset < 0) {
return cluster_offset;
}
*host_offset = cluster_offset;
return 0;
} else {
cluster_offset = *host_offset;
*nb_clusters = qcow2_alloc_clusters_at(bs, cluster_offset, *nb_clusters);
int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
if (ret < 0) {
return ret;
}
*nb_clusters = ret;
return 0;
}
if (cluster_offset < 0) {
return cluster_offset;
}
*host_offset = cluster_offset;
return 0;
}
/*
+1 -1
View File
@@ -367,7 +367,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
}
for(i = 0; i < table_size; i++) {
cpu_to_be64s(&new_table[i]);
be64_to_cpus(&new_table[i]);
}
/* Hook up the new refcount table in the qcow2 header */
+11 -9
View File
@@ -298,14 +298,6 @@ static int qcow2_open(BlockDriverState *bs, int flags)
goto fail;
}
if (!bs->read_only && s->autoclear_features != 0) {
s->autoclear_features = 0;
ret = qcow2_update_header(bs);
if (ret < 0) {
goto fail;
}
}
/* Check support for various header values */
if (header.refcount_order != 4) {
report_unsupported(bs, "%d bit reference counts",
@@ -411,6 +403,15 @@ static int qcow2_open(BlockDriverState *bs, int flags)
goto fail;
}
/* Clear unknown autoclear feature bits */
if (!bs->read_only && s->autoclear_features != 0) {
s->autoclear_features = 0;
ret = qcow2_update_header(bs);
if (ret < 0) {
goto fail;
}
}
/* Initialise locks */
qemu_co_mutex_init(&s->lock);
@@ -919,7 +920,8 @@ int qcow2_update_header(BlockDriverState *bs)
ret = sizeof(*header);
break;
default:
return -EINVAL;
ret = -EINVAL;
goto fail;
}
buf += ret;
+74 -50
View File
@@ -468,7 +468,7 @@ static int connect_to_sdog(const char *addr, const char *port)
if (ret) {
error_report("unable to get address info %s, %s",
addr, strerror(errno));
return -1;
return -errno;
}
for (res = res0; res; res = res->ai_next) {
@@ -489,13 +489,14 @@ static int connect_to_sdog(const char *addr, const char *port)
if (errno == EINTR) {
goto reconnect;
}
close(fd);
break;
}
dprintf("connected to %s:%s\n", addr, port);
goto success;
}
fd = -1;
fd = -errno;
error_report("failed connect to %s:%s", addr, port);
success:
freeaddrinfo(res0);
@@ -510,12 +511,13 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0);
if (ret < sizeof(*hdr)) {
error_report("failed to send a req, %s", strerror(errno));
return ret;
return -errno;
}
ret = qemu_send_full(sockfd, data, *wlen, 0);
if (ret < *wlen) {
error_report("failed to send a req, %s", strerror(errno));
ret = -errno;
}
return ret;
@@ -553,6 +555,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0);
if (ret < sizeof(*hdr)) {
error_report("failed to get a rsp, %s", strerror(errno));
ret = -errno;
goto out;
}
@@ -564,6 +567,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
ret = qemu_recv_full(sockfd, data, *rlen, 0);
if (ret < *rlen) {
error_report("failed to get the data, %s", strerror(errno));
ret = -errno;
goto out;
}
}
@@ -587,6 +591,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
if (ret < sizeof(*hdr)) {
error_report("failed to get a rsp, %s", strerror(errno));
ret = -errno;
goto out;
}
@@ -598,6 +603,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
ret = qemu_co_recv(sockfd, data, *rlen);
if (ret < *rlen) {
error_report("failed to get the data, %s", strerror(errno));
ret = -errno;
goto out;
}
}
@@ -787,7 +793,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
error_report("%s", strerror(errno));
return -1;
return fd;
}
socket_set_nonblock(fd);
@@ -796,7 +802,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
if (ret) {
error_report("%s", strerror(errno));
closesocket(fd);
return -1;
return -errno;
}
qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
@@ -883,7 +889,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
return -1;
return fd;
}
memset(buf, 0, sizeof(buf));
@@ -904,14 +910,17 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
if (ret) {
ret = -1;
goto out;
}
if (rsp->result != SD_RES_SUCCESS) {
error_report("cannot get vdi info, %s, %s %d %s",
sd_strerror(rsp->result), filename, snapid, tag);
ret = -1;
if (rsp->result == SD_RES_NO_VDI) {
ret = -ENOENT;
} else {
ret = -EIO;
}
goto out;
}
*vid = rsp->vdi_id;
@@ -980,7 +989,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
if (ret < 0) {
qemu_co_mutex_unlock(&s->lock);
error_report("failed to send a req, %s", strerror(errno));
return -EIO;
return -errno;
}
if (wlen) {
@@ -988,7 +997,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
if (ret < 0) {
qemu_co_mutex_unlock(&s->lock);
error_report("failed to send a data, %s", strerror(errno));
return -EIO;
return -errno;
}
}
@@ -1038,7 +1047,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
if (ret) {
error_report("failed to send a request to the sheep");
return -1;
return ret;
}
switch (rsp->result) {
@@ -1046,7 +1055,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
return 0;
default:
error_report("%s", sd_strerror(rsp->result));
return -1;
return -EIO;
}
}
@@ -1082,10 +1091,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
memset(vdi, 0, sizeof(vdi));
memset(tag, 0, sizeof(tag));
if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) {
ret = -EINVAL;
goto out;
}
s->fd = get_sheep_fd(s);
if (s->fd < 0) {
ret = s->fd;
goto out;
}
@@ -1099,11 +1110,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
s->flush_fd = connect_to_sdog(s->addr, s->port);
if (s->flush_fd < 0) {
error_report("failed to connect");
ret = s->flush_fd;
goto out;
}
}
if (snapid) {
if (snapid || tag[0] != '\0') {
dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
s->is_snapshot = 1;
}
@@ -1111,6 +1123,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
error_report("failed to connect");
ret = fd;
goto out;
}
@@ -1139,7 +1152,7 @@ out:
closesocket(s->fd);
}
g_free(buf);
return -1;
return ret;
}
static int do_sd_create(char *filename, int64_t vdi_size,
@@ -1154,7 +1167,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
fd = connect_to_sdog(addr, port);
if (fd < 0) {
return -EIO;
return fd;
}
memset(buf, 0, sizeof(buf));
@@ -1177,7 +1190,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
closesocket(fd);
if (ret) {
return -EIO;
return ret;
}
if (rsp->result != SD_RES_SUCCESS) {
@@ -1237,24 +1250,26 @@ out:
static int sd_create(const char *filename, QEMUOptionParameter *options)
{
int ret;
int ret = 0;
uint32_t vid = 0, base_vid = 0;
int64_t vdi_size = 0;
char *backing_file = NULL;
BDRVSheepdogState s;
BDRVSheepdogState *s;
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
uint32_t snapid;
int prealloc = 0;
const char *vdiname;
s = g_malloc0(sizeof(BDRVSheepdogState));
strstart(filename, "sheepdog:", &vdiname);
memset(&s, 0, sizeof(s));
memset(vdi, 0, sizeof(vdi));
memset(tag, 0, sizeof(tag));
if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) {
error_report("invalid filename");
return -EINVAL;
ret = -EINVAL;
goto out;
}
while (options && options->name) {
@@ -1270,7 +1285,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
} else {
error_report("Invalid preallocation mode: '%s'",
options->value.s);
return -EINVAL;
ret = -EINVAL;
goto out;
}
}
options++;
@@ -1278,7 +1294,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
if (vdi_size > SD_MAX_VDI_SIZE) {
error_report("too big image size");
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (backing_file) {
@@ -1290,31 +1307,37 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
drv = bdrv_find_protocol(backing_file);
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
error_report("backing_file must be a sheepdog image");
return -EINVAL;
ret = -EINVAL;
goto out;
}
ret = bdrv_file_open(&bs, backing_file, 0);
if (ret < 0)
return -EIO;
if (ret < 0) {
goto out;
}
s = bs->opaque;
if (!is_snapshot(&s->inode)) {
error_report("cannot clone from a non snapshot vdi");
bdrv_delete(bs);
return -EINVAL;
ret = -EINVAL;
goto out;
}
base_vid = s->inode.vdi_id;
bdrv_delete(bs);
}
ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s->addr, s->port);
if (!prealloc || ret) {
return ret;
goto out;
}
return sd_prealloc(filename);
ret = sd_prealloc(filename);
out:
g_free(s);
return ret;
}
static void sd_close(BlockDriverState *bs)
@@ -1379,7 +1402,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
return -EIO;
return fd;
}
/* we don't need to update entire object */
@@ -1391,10 +1414,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
if (ret < 0) {
error_report("failed to update an inode.");
return -EIO;
}
return 0;
return ret;
}
/*
@@ -1464,6 +1486,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
error_report("failed to connect");
ret = fd;
goto out;
}
@@ -1606,8 +1629,9 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
if (bs->growable && sector_num + nb_sectors > bs->total_sectors) {
/* TODO: shouldn't block here */
if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) {
return -EIO;
ret = sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE);
if (ret < 0) {
return ret;
}
bs->total_sectors = sector_num + nb_sectors;
}
@@ -1724,7 +1748,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
/* refresh inode. */
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
ret = -EIO;
ret = fd;
goto cleanup;
}
@@ -1732,7 +1756,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
if (ret < 0) {
error_report("failed to write snapshot's inode.");
ret = -EIO;
goto cleanup;
}
@@ -1741,7 +1764,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
if (ret < 0) {
error_report("failed to create inode for snapshot. %s",
strerror(errno));
ret = -EIO;
goto cleanup;
}
@@ -1752,7 +1774,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
if (ret < 0) {
error_report("failed to read new inode info. %s", strerror(errno));
ret = -EIO;
goto cleanup;
}
@@ -1773,7 +1794,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
char *buf = NULL;
uint32_t vid;
uint32_t snapid = 0;
int ret = -ENOENT, fd;
int ret = 0, fd;
old_s = g_malloc(sizeof(BDRVSheepdogState));
@@ -1791,13 +1812,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
if (ret) {
error_report("Failed to find_vdi_name");
ret = -ENOENT;
goto out;
}
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
error_report("failed to connect");
ret = fd;
goto out;
}
@@ -1808,7 +1829,6 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
closesocket(fd);
if (ret) {
ret = -ENOENT;
goto out;
}
@@ -1861,6 +1881,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
ret = fd;
goto out;
}
@@ -1888,6 +1909,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
error_report("failed to connect");
ret = fd;
goto out;
}
@@ -1925,6 +1947,10 @@ out:
g_free(vdi_inuse);
if (ret < 0) {
return ret;
}
return found;
}
@@ -1932,7 +1958,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
int64_t pos, int size, int load)
{
int fd, create;
int ret = 0;
int ret = 0, remaining = size;
unsigned int data_len;
uint64_t vmstate_oid;
uint32_t vdi_index;
@@ -1940,15 +1966,14 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
ret = -EIO;
goto cleanup;
return fd;
}
while (size) {
while (remaining) {
vdi_index = pos / SD_DATA_OBJ_SIZE;
offset = pos % SD_DATA_OBJ_SIZE;
data_len = MIN(size, SD_DATA_OBJ_SIZE);
data_len = MIN(remaining, SD_DATA_OBJ_SIZE);
vmstate_oid = vid_to_vmstate_oid(s->inode.vdi_id, vdi_index);
@@ -1965,14 +1990,13 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
if (ret < 0) {
error_report("failed to save vmstate %s", strerror(errno));
ret = -EIO;
goto cleanup;
}
pos += data_len;
size -= data_len;
ret += data_len;
remaining -= data_len;
}
ret = size;
cleanup:
closesocket(fd);
return ret;
+57 -1
View File
@@ -35,6 +35,7 @@
#define VMDK4_FLAG_RGD (1 << 1)
#define VMDK4_FLAG_COMPRESS (1 << 16)
#define VMDK4_FLAG_MARKER (1 << 17)
#define VMDK4_GD_AT_END 0xffffffffffffffffULL
typedef struct {
uint32_t version;
@@ -57,8 +58,8 @@ typedef struct {
int64_t desc_offset;
int64_t desc_size;
int32_t num_gtes_per_gte;
int64_t gd_offset;
int64_t rgd_offset;
int64_t gd_offset;
int64_t grain_offset;
char filler[1];
char check_bytes[4];
@@ -115,6 +116,13 @@ typedef struct VmdkGrainMarker {
uint8_t data[0];
} VmdkGrainMarker;
enum {
MARKER_END_OF_STREAM = 0,
MARKER_GRAIN_TABLE = 1,
MARKER_GRAIN_DIRECTORY = 2,
MARKER_FOOTER = 3,
};
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
@@ -451,6 +459,54 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
if (header.capacity == 0 && header.desc_offset) {
return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
}
if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
/*
* The footer takes precedence over the header, so read it in. The
* footer starts at offset -1024 from the end: One sector for the
* footer, and another one for the end-of-stream marker.
*/
struct {
struct {
uint64_t val;
uint32_t size;
uint32_t type;
uint8_t pad[512 - 16];
} QEMU_PACKED footer_marker;
uint32_t magic;
VMDK4Header header;
uint8_t pad[512 - 4 - sizeof(VMDK4Header)];
struct {
uint64_t val;
uint32_t size;
uint32_t type;
uint8_t pad[512 - 16];
} QEMU_PACKED eos_marker;
} QEMU_PACKED footer;
ret = bdrv_pread(file,
bs->file->total_sectors * 512 - 1536,
&footer, sizeof(footer));
if (ret < 0) {
return ret;
}
/* Some sanity checks for the footer */
if (be32_to_cpu(footer.magic) != VMDK4_MAGIC ||
le32_to_cpu(footer.footer_marker.size) != 0 ||
le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER ||
le64_to_cpu(footer.eos_marker.val) != 0 ||
le32_to_cpu(footer.eos_marker.size) != 0 ||
le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM)
{
return -EINVAL;
}
header = footer.header;
}
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
* le64_to_cpu(header.granularity);
if (l1_entry_sectors == 0) {
+6 -1
View File
@@ -2808,7 +2808,12 @@ static int enable_write_target(BDRVVVFATState *s)
array_init(&(s->commits), sizeof(commit_t));
s->qcow_filename = g_malloc(1024);
get_tmp_filename(s->qcow_filename, 1024);
ret = get_tmp_filename(s->qcow_filename, 1024);
if (ret < 0) {
g_free(s->qcow_filename);
s->qcow_filename = NULL;
return ret;
}
bdrv_qcow = bdrv_find_format("qcow");
options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
+1 -1
View File
@@ -335,7 +335,7 @@ struct BlockDriverState {
BlockJob *job;
};
void get_tmp_filename(char *filename, int size);
int get_tmp_filename(char *filename, int size);
void bdrv_set_io_limits(BlockDriverState *bs,
BlockIOLimit *io_limits);
Vendored
+60 -26
View File
@@ -275,6 +275,41 @@ EOF
compile_object
}
if check_define __linux__ ; then
targetos="Linux"
elif check_define _WIN32 ; then
targetos='MINGW32'
elif check_define __OpenBSD__ ; then
targetos='OpenBSD'
elif check_define __sun__ ; then
targetos='SunOS'
elif check_define __HAIKU__ ; then
targetos='Haiku'
else
targetos=`uname -s`
fi
# Some host OSes need non-standard checks for which CPU to use.
# Note that these checks are broken for cross-compilation: if you're
# cross-compiling to one of these OSes then you'll need to specify
# the correct CPU with the --cpu option.
case $targetos in
Darwin)
# on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
# run 64-bit userspace code.
# If the user didn't specify a CPU explicitly and the kernel says this is
# 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
cpu="x86_64"
fi
;;
SunOS)
# `uname -m` returns i86pc even on an x86_64 box, so default based on isainfo
if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
cpu="x86_64"
fi
esac
if test ! -z "$cpu" ; then
# command line argument
:
@@ -349,19 +384,6 @@ if test -z "$ARCH"; then
fi
# OS specific
if check_define __linux__ ; then
targetos="Linux"
elif check_define _WIN32 ; then
targetos='MINGW32'
elif check_define __OpenBSD__ ; then
targetos='OpenBSD'
elif check_define __sun__ ; then
targetos='SunOS'
elif check_define __HAIKU__ ; then
targetos='Haiku'
else
targetos=`uname -s`
fi
case $targetos in
CYGWIN*)
@@ -411,12 +433,6 @@ OpenBSD)
Darwin)
bsd="yes"
darwin="yes"
# on Leopard most of the system is 32-bit, so we have to ask the kernel it if we can
# run 64-bit userspace code
if [ "$cpu" = "i386" ] ; then
is_x86_64=`sysctl -n hw.optional.x86_64`
[ "$is_x86_64" = "1" ] && cpu=x86_64
fi
if [ "$cpu" = "x86_64" ] ; then
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
LDFLAGS="-arch x86_64 $LDFLAGS"
@@ -437,12 +453,6 @@ SunOS)
smbd="${SMBD-/usr/sfw/sbin/smbd}"
needs_libsunmath="no"
solarisrev=`uname -r | cut -f2 -d.`
# have to select again, because `uname -m` returns i86pc
# even on an x86_64 box.
solariscpu=`isainfo -k`
if test "${solariscpu}" = "amd64" ; then
cpu="x86_64"
fi
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
if test "$solarisrev" -le 9 ; then
if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
@@ -2811,7 +2821,11 @@ fi
open_by_hande_at=no
cat > $TMPC << EOF
#include <fcntl.h>
#if !defined(AT_EMPTY_PATH)
# error missing definition
#else
int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); }
#endif
EOF
if compile_prog "" "" ; then
open_by_handle_at=yes
@@ -2831,6 +2845,21 @@ if compile_prog "" "" ; then
linux_magic_h=yes
fi
########################################
# check if environ is declared
has_environ=no
cat > $TMPC << EOF
#include <unistd.h>
int main(void) {
environ = environ;
return 0;
}
EOF
if compile_prog "" "" ; then
has_environ=yes
fi
##########################################
# End of CC checks
# After here, no more $cc or $ld runs
@@ -2900,7 +2929,8 @@ if test "$softmmu" = yes ; then
tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
else
if test "$virtfs" = yes; then
feature_not_found "virtfs"
echo "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel"
exit 1
fi
virtfs=no
fi
@@ -3342,6 +3372,10 @@ if test "$linux_magic_h" = "yes" ; then
echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
fi
if test "$has_environ" = "yes" ; then
echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
fi
# USB host support
case "$usb" in
linux)
+28 -29
View File
@@ -847,6 +847,26 @@ static void console_clear_xy(TextConsole *s, int x, int y)
update_xy(s, x, y);
}
/* set cursor, checking bounds */
static void set_cursor(TextConsole *s, int x, int y)
{
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
if (y >= s->height) {
y = s->height - 1;
}
if (x >= s->width) {
x = s->width - 1;
}
s->x = x;
s->y = y;
}
static void console_putchar(TextConsole *s, int ch)
{
TextCell *c;
@@ -918,7 +938,8 @@ static void console_putchar(TextConsole *s, int ch)
s->esc_params[s->nb_esc_params] * 10 + ch - '0';
}
} else {
s->nb_esc_params++;
if (s->nb_esc_params < MAX_ESC_PARAMS)
s->nb_esc_params++;
if (ch == ';')
break;
#ifdef DEBUG_CONSOLE
@@ -932,59 +953,37 @@ static void console_putchar(TextConsole *s, int ch)
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->y -= s->esc_params[0];
if (s->y < 0) {
s->y = 0;
}
set_cursor(s, s->x, s->y - s->esc_params[0]);
break;
case 'B':
/* move cursor down */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->y += s->esc_params[0];
if (s->y >= s->height) {
s->y = s->height - 1;
}
set_cursor(s, s->x, s->y + s->esc_params[0]);
break;
case 'C':
/* move cursor right */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->x += s->esc_params[0];
if (s->x >= s->width) {
s->x = s->width - 1;
}
set_cursor(s, s->x + s->esc_params[0], s->y);
break;
case 'D':
/* move cursor left */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->x -= s->esc_params[0];
if (s->x < 0) {
s->x = 0;
}
set_cursor(s, s->x - s->esc_params[0], s->y);
break;
case 'G':
/* move cursor to column */
s->x = s->esc_params[0] - 1;
if (s->x < 0) {
s->x = 0;
}
set_cursor(s, s->esc_params[0] - 1, s->y);
break;
case 'f':
case 'H':
/* move cursor to row, column */
s->x = s->esc_params[1] - 1;
if (s->x < 0) {
s->x = 0;
}
s->y = s->esc_params[0] - 1;
if (s->y < 0) {
s->y = 0;
}
set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1);
break;
case 'J':
switch (s->esc_params[0]) {
+6
View File
@@ -285,6 +285,12 @@ int cpu_exec(CPUArchState *env)
}
#endif
#if defined(TARGET_I386)
#if !defined(CONFIG_USER_ONLY)
if (interrupt_request & CPU_INTERRUPT_POLL) {
env->interrupt_request &= ~CPU_INTERRUPT_POLL;
apic_poll_irq(env->apic_state);
}
#endif
if (interrupt_request & CPU_INTERRUPT_INIT) {
svm_check_intercept(env, SVM_EXIT_INIT);
do_cpu_init(env);
+1
View File
@@ -33,6 +33,7 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
void qemu_sglist_destroy(QEMUSGList *qsg)
{
g_free(qsg->sg);
memset(qsg, 0, sizeof(*qsg));
}
typedef struct {
+15
View File
@@ -55,6 +55,21 @@ try ...
... then use "bus=ehci.0" to assign your usb devices to that bus.
xhci controller support
-----------------------
There also is xhci host controller support available. It got alot
less testing than ehci and there are a bunch of known limitations, so
ehci may work better for you. On the other hand the xhci hardware
design is much more virtualization-friendly, thus xhci emulation uses
less ressources (especially cpu). If you wanna give xhci a try
use this to add the host controller ...
qemu -device nec-usb-xhci,id=xhci
... then use "bus=xhci.0" when assigning usb devices.
More USB tips & tricks
======================
+2
View File
@@ -96,6 +96,8 @@ void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
int page_unprotect(target_ulong address, uintptr_t pc, void *puc);
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access);
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access);
#if !defined(CONFIG_USER_ONLY)
/* cputlb.c */
void tlb_flush_page(CPUArchState *env, target_ulong addr);
+19 -1
View File
@@ -1075,6 +1075,23 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
return tb;
}
/*
* invalidate all TBs which intersect with the target physical pages
* starting in range [start;end[. NOTE: start and end may refer to
* different physical pages. 'is_cpu_write_access' should be true if called
* from a real cpu write access: the virtual CPU will exit the current
* TB if code is modified inside this TB.
*/
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access)
{
while (start < end) {
tb_invalidate_phys_page_range(start, end, is_cpu_write_access);
start &= TARGET_PAGE_MASK;
start += TARGET_PAGE_SIZE;
}
}
/* invalidate all TBs which intersect with the target physical page
starting in range [start;end[. NOTE: start and end must refer to
the same physical page. 'is_cpu_write_access' should be true if called
@@ -1475,7 +1492,8 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr)
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
{
tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc));
tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
(pc & ~TARGET_PAGE_MASK));
}
#endif
#endif /* TARGET_HAS_ICE */
+3 -2
View File
@@ -345,6 +345,9 @@ static void piix4_reset(void *opaque)
pci_conf[0x5a] = 0;
pci_conf[0x5b] = 0;
pci_conf[0x40] = 0x01; /* PM io base read only bit */
pci_conf[0x80] = 0;
if (s->kvm_enabled) {
/* Mark SMM as already inited (until KVM supports SMM). */
pci_conf[0x5B] = 0x02;
@@ -384,8 +387,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
pci_conf[0x09] = 0x00;
pci_conf[0x3d] = 0x01; // interrupt pin 1
pci_conf[0x40] = 0x01; /* PM io base read only bit */
/* APM */
apm_init(&s->apm, apm_ctrl_changed, s);
+22 -5
View File
@@ -16,6 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>
*/
#include "qemu-thread.h"
#include "apic_internal.h"
#include "apic.h"
#include "ioapic.h"
@@ -369,11 +370,10 @@ static void apic_update_irq(APICCommonState *s)
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
return;
}
if (apic_irq_pending(s) > 0) {
if (!qemu_cpu_is_self(s->cpu_env)) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL);
} else if (apic_irq_pending(s) > 0) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
} else if (apic_accept_pic_intr(&s->busdev.qdev) &&
pic_get_output(isa_pic)) {
apic_deliver_pic_intr(&s->busdev.qdev, 1);
}
}
@@ -543,6 +543,15 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
}
static bool apic_check_pic(APICCommonState *s)
{
if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) {
return false;
}
apic_deliver_pic_intr(&s->busdev.qdev, 1);
return true;
}
int apic_get_interrupt(DeviceState *d)
{
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
@@ -568,7 +577,12 @@ int apic_get_interrupt(DeviceState *d)
reset_bit(s->irr, intno);
set_bit(s->isr, intno);
apic_sync_vapic(s, SYNC_TO_VAPIC);
/* re-inject if there is still a pending PIC interrupt */
apic_check_pic(s);
apic_update_irq(s);
return intno;
}
@@ -808,8 +822,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
int n = index - 0x32;
s->lvt[n] = val;
if (n == APIC_LVT_TIMER)
if (n == APIC_LVT_TIMER) {
apic_timer_update(s, qemu_get_clock_ns(vm_clock));
} else if (n == APIC_LVT_LINT0 && apic_check_pic(s)) {
apic_update_irq(s);
}
}
break;
case 0x38:
+1
View File
@@ -20,6 +20,7 @@ void apic_init_reset(DeviceState *s);
void apic_sipi(DeviceState *s);
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
TPRAccess access);
void apic_poll_irq(DeviceState *d);
/* pc.c */
int cpu_is_bsp(CPUX86State *env);
+3 -1
View File
@@ -289,7 +289,9 @@ static int apic_init_common(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->io_memory);
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK) {
/* Note: We need at least 1M to map the VAPIC option ROM */
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
ram_size >= 1024 * 1024) {
vapic = sysbus_create_simple("kvmvapic", -1, NULL);
}
s->vapic = vapic;
-1
View File
@@ -141,7 +141,6 @@ void apic_report_irq_delivered(int delivered);
bool apic_next_timer(APICCommonState *s, int64_t current_time);
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr);
void apic_poll_irq(DeviceState *d);
void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
TPRAccess access);
+1
View File
@@ -955,6 +955,7 @@ static TypeInfo arm_gic_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(gic_state),
.class_init = arm_gic_class_init,
.class_size = sizeof(SysBusDeviceClass),
};
static void arm_gic_register_types(void)
+6 -5
View File
@@ -410,7 +410,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
if ((old_fmt != new_fmt) || (old_freq != new_freq)) {
d->shift = (new_fmt & 1) + (new_fmt >> 1);
ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n",
ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n",
i,
new_freq,
1 << (new_fmt & 1),
@@ -578,7 +578,7 @@ IO_WRITE_PROTO (es1370_writel)
d++;
case ES1370_REG_DAC1_SCOUNT:
d->scount = (val & 0xffff) | (d->scount & ~0xffff);
ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n",
ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
d - &s->chan[0], val >> 16, (val & 0xffff));
break;
@@ -588,7 +588,7 @@ IO_WRITE_PROTO (es1370_writel)
d++;
case ES1370_REG_DAC1_FRAMEADR:
d->frame_addr = val;
ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val);
ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val);
break;
case ES1370_REG_PHANTOM_FRAMECNT:
@@ -605,7 +605,7 @@ IO_WRITE_PROTO (es1370_writel)
case ES1370_REG_DAC1_FRAMECNT:
d->frame_cnt = val;
d->leftover = 0;
ldebug ("chan %d frame count %d, buffer size %d\n",
ldebug ("chan %td frame count %d, buffer size %d\n",
d - &s->chan[0], val >> 16, val & 0xffff);
break;
@@ -745,9 +745,10 @@ IO_READ_PROTO (es1370_readl)
{
uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;
uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;
if (curr > size)
if (curr > size) {
dolog ("read framecnt curr %d, size %d %d\n", curr, size,
curr > size);
}
}
#endif
break;
+12 -6
View File
@@ -159,6 +159,10 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
drv->sect = sect;
}
if (drv->bs == NULL || !bdrv_is_inserted(drv->bs)) {
ret = 2;
}
return ret;
}
@@ -179,12 +183,14 @@ static void fd_revalidate(FDrive *drv)
FDriveRate rate;
FLOPPY_DPRINTF("revalidate\n");
if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
if (drv->bs != NULL) {
ro = bdrv_is_read_only(drv->bs);
bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
&last_sect, drv->drive, &drive, &rate);
if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
FLOPPY_DPRINTF("User defined disk (%d %d %d)",
if (!bdrv_is_inserted(drv->bs)) {
FLOPPY_DPRINTF("No disk in drive\n");
} else if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
FLOPPY_DPRINTF("User defined disk (%d %d %d)\n",
nb_heads - 1, max_track, last_sect);
} else {
FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
@@ -201,7 +207,7 @@ static void fd_revalidate(FDrive *drv)
drv->drive = drive;
drv->media_rate = rate;
} else {
FLOPPY_DPRINTF("No disk in drive\n");
FLOPPY_DPRINTF("No drive connected\n");
drv->last_sect = 0;
drv->max_track = 0;
drv->flags &= ~FDISK_DBL_SIDES;
@@ -709,7 +715,7 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
FDrive *cur_drv;
/* A seek clears the disk change line (if a disk is inserted) */
cur_drv = get_cur_drv(fdctrl);
if (cur_drv->max_track) {
if (cur_drv->bs != NULL && bdrv_is_inserted(cur_drv->bs)) {
cur_drv->media_changed = 0;
}
}
@@ -1878,7 +1884,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl)
}
fd_init(drive);
fd_revalidate(drive);
fdctrl_change_cb(drive, 0);
if (drive->bs) {
bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
}
-1
View File
@@ -225,7 +225,6 @@ static int pci_i82378_init(PCIDevice *dev)
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
memory_region_set_coalescing(&s->mem);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
/* Make I/O address read only */
+39 -9
View File
@@ -462,7 +462,7 @@ static void ahci_check_cmd_bh(void *opaque)
static void ahci_init_d2h(AHCIDevice *ad)
{
uint8_t init_fis[0x20];
uint8_t init_fis[20];
IDEState *ide_state = &ad->port.ifs[0];
memset(init_fis, 0, sizeof(init_fis));
@@ -619,7 +619,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
d2h_fis[11] = cmd_fis[11];
d2h_fis[12] = cmd_fis[12];
d2h_fis[13] = cmd_fis[13];
for (i = 14; i < 0x20; i++) {
for (i = 14; i < 20; i++) {
d2h_fis[i] = 0;
}
@@ -634,7 +634,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
}
}
static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist)
static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
{
AHCICmdHdr *cmd = ad->cur_cmd;
uint32_t opts = le32_to_cpu(cmd->opts);
@@ -645,6 +645,10 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist)
uint8_t *prdt;
int i;
int r = 0;
int sum = 0;
int off_idx = -1;
int off_pos = -1;
int tbl_entry_size;
if (!sglist_alloc_hint) {
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
@@ -666,9 +670,30 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist)
/* Get entries in the PRDT, init a qemu sglist accordingly */
if (sglist_alloc_hint > 0) {
AHCI_SG *tbl = (AHCI_SG *)prdt;
qemu_sglist_init(sglist, sglist_alloc_hint);
sum = 0;
for (i = 0; i < sglist_alloc_hint; i++) {
/* flags_size is zero-based */
tbl_entry_size = (le32_to_cpu(tbl[i].flags_size) + 1);
if (offset <= (sum + tbl_entry_size)) {
off_idx = i;
off_pos = offset - sum;
break;
}
sum += tbl_entry_size;
}
if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) {
DPRINTF(ad->port_no, "%s: Incorrect offset! "
"off_idx: %d, off_pos: %d\n",
__func__, off_idx, off_pos);
r = -1;
goto out;
}
qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx));
qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
for (i = off_idx + 1; i < sglist_alloc_hint; i++) {
/* flags_size is zero-based */
qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr),
le32_to_cpu(tbl[i].flags_size) + 1);
@@ -741,7 +766,7 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
ncq_tfs->lba, ncq_tfs->lba + ncq_tfs->sector_count - 2,
s->dev[port].port.ifs[0].nb_sectors - 1);
ahci_populate_sglist(&s->dev[port], &ncq_tfs->sglist);
ahci_populate_sglist(&s->dev[port], &ncq_tfs->sglist, 0);
ncq_tfs->tag = tag;
switch(ncq_fis->command) {
@@ -964,7 +989,7 @@ static int ahci_start_transfer(IDEDMA *dma)
goto out;
}
if (!ahci_populate_sglist(ad, &s->sg)) {
if (!ahci_populate_sglist(ad, &s->sg, 0)) {
has_sglist = 1;
}
@@ -1009,6 +1034,7 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s,
DPRINTF(ad->port_no, "\n");
ad->dma_cb = dma_cb;
ad->dma_status |= BM_STATUS_DMAING;
s->io_buffer_offset = 0;
dma_cb(s, 0);
}
@@ -1017,7 +1043,7 @@ static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write)
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
IDEState *s = &ad->port.ifs[0];
ahci_populate_sglist(ad, &s->sg);
ahci_populate_sglist(ad, &s->sg, 0);
s->io_buffer_size = s->sg.size;
DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
@@ -1031,7 +1057,7 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
uint8_t *p = s->io_buffer + s->io_buffer_index;
int l = s->io_buffer_size - s->io_buffer_index;
if (ahci_populate_sglist(ad, &s->sg)) {
if (ahci_populate_sglist(ad, &s->sg, s->io_buffer_offset)) {
return 0;
}
@@ -1041,9 +1067,13 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
dma_buf_write(p, l, &s->sg);
}
/* free sglist that was created in ahci_populate_sglist() */
qemu_sglist_destroy(&s->sg);
/* update number of transferred bytes */
ad->cur_cmd->status = cpu_to_le32(le32_to_cpu(ad->cur_cmd->status) + l);
s->io_buffer_index += l;
s->io_buffer_offset += l;
DPRINTF(ad->port_no, "len=%#x\n", l);
+10 -2
View File
@@ -84,6 +84,14 @@ static const VMStateDescription vmstate_ahci = {
.unmigratable = 1,
};
static void pci_ich9_reset(void *opaque)
{
struct AHCIPCIState *d = opaque;
msi_reset(&d->card);
ahci_reset(opaque);
}
static int pci_ich9_ahci_init(PCIDevice *dev)
{
struct AHCIPCIState *d;
@@ -102,7 +110,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
/* XXX Software should program this register */
d->card.config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */
qemu_register_reset(ahci_reset, d);
qemu_register_reset(pci_ich9_reset, d);
msi_init(dev, 0x50, 1, true, false);
d->ahci.irq = d->card.irq[0];
@@ -133,7 +141,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
d = DO_UPCAST(struct AHCIPCIState, card, dev);
msi_uninit(dev);
qemu_unregister_reset(ahci_reset, d);
qemu_unregister_reset(pci_ich9_reset, d);
ahci_uninit(&d->ahci);
return 0;
+1
View File
@@ -389,6 +389,7 @@ struct IDEState {
struct iovec iov;
QEMUIOVector qiov;
/* ATA DMA state */
int io_buffer_offset;
int io_buffer_size;
QEMUSGList sg;
/* PIO transfer handling */
+3
View File
@@ -1107,6 +1107,9 @@ static void intel_hda_reset(DeviceState *dev)
DeviceState *qdev;
HDACodecDevice *cdev;
if (d->msi) {
msi_reset(&d->pci);
}
intel_hda_regs_reset(d);
d->wall_base_ns = qemu_get_clock_ns(vm_clock);
+4 -20
View File
@@ -351,6 +351,10 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
{
int i, guest_curr_max;
if (!ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
return;
}
guest_curr_max = s->peers[posn].nb_eventfds;
for (i = 0; i < guest_curr_max; i++) {
@@ -363,22 +367,6 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
s->peers[posn].nb_eventfds = 0;
}
static void setup_ioeventfds(IVShmemState *s) {
int i, j;
for (i = 0; i <= s->max_peer; i++) {
for (j = 0; j < s->peers[i].nb_eventfds; j++) {
memory_region_add_eventfd(&s->ivshmem_mmio,
DOORBELL,
4,
true,
(i << 16) | j,
s->peers[i].eventfds[j]);
}
}
}
/* this function increase the dynamic storage need to store data about other
* guests */
static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
@@ -685,10 +673,6 @@ static int pci_ivshmem_init(PCIDevice *dev)
memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s,
"ivshmem-mmio", IVSHMEM_REG_BAR_SIZE);
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
setup_ioeventfds(s);
}
/* region for registers*/
pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
&s->ivshmem_mmio);
+1 -1
View File
@@ -29,7 +29,7 @@ void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
int i;
memset(kapic, 0, sizeof(kapic));
memset(kapic, 0, sizeof(*kapic));
kvm_apic_set_reg(kapic, 0x2, s->id << 24);
kvm_apic_set_reg(kapic, 0x8, s->tpr);
kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
+72 -9
View File
@@ -23,31 +23,71 @@
* THE SOFTWARE.
*/
#include "qemu-timer.h"
#include "sysemu.h"
#include "hw/i8254.h"
#include "hw/i8254_internal.h"
#include "kvm.h"
#define KVM_PIT_REINJECT_BIT 0
#define CALIBRATION_ROUNDS 3
typedef struct KVMPITState {
PITCommonState pit;
LostTickPolicy lost_tick_policy;
bool vm_stopped;
int64_t kernel_clock_offset;
} KVMPITState;
static void kvm_pit_get(PITCommonState *s)
static int64_t abs64(int64_t v)
{
return v < 0 ? -v : v;
}
static void kvm_pit_update_clock_offset(KVMPITState *s)
{
int64_t offset, clock_offset;
struct timespec ts;
int i;
/*
* Measure the delta between CLOCK_MONOTONIC, the base used for
* kvm_pit_channel_state::count_load_time, and vm_clock. Take the
* minimum of several samples to filter out scheduling noise.
*/
clock_offset = INT64_MAX;
for (i = 0; i < CALIBRATION_ROUNDS; i++) {
offset = qemu_get_clock_ns(vm_clock);
clock_gettime(CLOCK_MONOTONIC, &ts);
offset -= ts.tv_nsec;
offset -= (int64_t)ts.tv_sec * 1000000000;
if (abs64(offset) < abs64(clock_offset)) {
clock_offset = offset;
}
}
s->kernel_clock_offset = clock_offset;
}
static void kvm_pit_get(PITCommonState *pit)
{
KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
struct kvm_pit_state2 kpit;
struct kvm_pit_channel_state *kchan;
struct PITChannelState *sc;
int i, ret;
/* No need to re-read the state if VM is stopped. */
if (s->vm_stopped) {
return;
}
if (kvm_has_pit_state2()) {
ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit);
if (ret < 0) {
fprintf(stderr, "KVM_GET_PIT2 failed: %s\n", strerror(ret));
abort();
}
s->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
pit->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
} else {
/*
* kvm_pit_state2 is superset of kvm_pit_state struct,
@@ -61,7 +101,7 @@ static void kvm_pit_get(PITCommonState *s)
}
for (i = 0; i < 3; i++) {
kchan = &kpit.channels[i];
sc = &s->channels[i];
sc = &pit->channels[i];
sc->count = kchan->count;
sc->latched_count = kchan->latched_count;
sc->count_latched = kchan->count_latched;
@@ -74,25 +114,31 @@ static void kvm_pit_get(PITCommonState *s)
sc->mode = kchan->mode;
sc->bcd = kchan->bcd;
sc->gate = kchan->gate;
sc->count_load_time = kchan->count_load_time;
sc->count_load_time = kchan->count_load_time + s->kernel_clock_offset;
}
sc = &s->channels[0];
sc = &pit->channels[0];
sc->next_transition_time =
pit_get_next_transition_time(sc, sc->count_load_time);
}
static void kvm_pit_put(PITCommonState *s)
static void kvm_pit_put(PITCommonState *pit)
{
KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
struct kvm_pit_state2 kpit;
struct kvm_pit_channel_state *kchan;
struct PITChannelState *sc;
int i, ret;
kpit.flags = s->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
/* The offset keeps changing as long as the VM is stopped. */
if (s->vm_stopped) {
kvm_pit_update_clock_offset(s);
}
kpit.flags = pit->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
for (i = 0; i < 3; i++) {
kchan = &kpit.channels[i];
sc = &s->channels[i];
sc = &pit->channels[i];
kchan->count = sc->count;
kchan->latched_count = sc->latched_count;
kchan->count_latched = sc->count_latched;
@@ -105,7 +151,7 @@ static void kvm_pit_put(PITCommonState *s)
kchan->mode = sc->mode;
kchan->bcd = sc->bcd;
kchan->gate = sc->gate;
kchan->count_load_time = sc->count_load_time;
kchan->count_load_time = sc->count_load_time - s->kernel_clock_offset;
}
ret = kvm_vm_ioctl(kvm_state,
@@ -173,6 +219,21 @@ static void kvm_pit_irq_control(void *opaque, int n, int enable)
kvm_pit_put(pit);
}
static void kvm_pit_vm_state_change(void *opaque, int running,
RunState state)
{
KVMPITState *s = opaque;
if (running) {
kvm_pit_update_clock_offset(s);
s->vm_stopped = false;
} else {
kvm_pit_update_clock_offset(s);
kvm_pit_get(&s->pit);
s->vm_stopped = true;
}
}
static int kvm_pit_initfn(PITCommonState *pit)
{
KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
@@ -215,6 +276,8 @@ static int kvm_pit_initfn(PITCommonState *pit)
qdev_init_gpio_in(&pit->dev.qdev, kvm_pit_irq_control, 1);
qemu_add_vm_change_state_handler(kvm_pit_vm_state_change, s);
return 0;
}
+1 -1
View File
@@ -103,7 +103,7 @@ ssize_t read_targphys(const char *name,
/* return the size or -1 if error */
int load_image_targphys(const char *filename,
target_phys_addr_t addr, int max_sz)
target_phys_addr_t addr, uint64_t max_sz)
{
int size;
+2 -1
View File
@@ -4,7 +4,8 @@
/* loader.c */
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
int load_image_targphys(const char *filename, target_phys_addr_t,
uint64_t max_sz);
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
+11 -2
View File
@@ -282,6 +282,15 @@ static void msix_free_irq_entries(PCIDevice *dev)
}
}
static void msix_clear_all_vectors(PCIDevice *dev)
{
int vector;
for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
msix_clr_pending(dev, vector);
}
}
/* Clean up resources for the device. */
int msix_uninit(PCIDevice *dev, MemoryRegion *bar)
{
@@ -322,7 +331,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
return;
}
msix_free_irq_entries(dev);
msix_clear_all_vectors(dev);
qemu_get_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
qemu_get_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
msix_update_function_masked(dev);
@@ -372,7 +381,7 @@ void msix_reset(PCIDevice *dev)
{
if (!(dev->cap_present & QEMU_PCI_CAP_MSIX))
return;
msix_free_irq_entries(dev);
msix_clear_all_vectors(dev);
dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE);
+9 -3
View File
@@ -202,10 +202,16 @@ int load_multiboot(void *fw_cfg,
uint32_t mh_bss_end_addr = ldl_p(header+i+24);
mh_load_addr = ldl_p(header+i+16);
uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
uint32_t mb_load_size = mh_load_end_addr - mh_load_addr;
uint32_t mb_load_size = 0;
mh_entry_addr = ldl_p(header+i+28);
mb_kernel_size = mh_bss_end_addr - mh_load_addr;
if (mh_load_end_addr) {
mb_kernel_size = mh_bss_end_addr - mh_load_addr;
mb_load_size = mh_load_end_addr - mh_load_addr;
} else {
mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
mb_load_size = mb_kernel_size;
}
/* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
uint32_t mh_mode_type = ldl_p(header+i+32);
+32 -24
View File
@@ -47,6 +47,7 @@
#include "ui/qemu-spice.h"
#include "memory.h"
#include "exec-memory.h"
#include "arch_init.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
@@ -343,32 +344,37 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
/* various important CMOS locations needed by PC/Bochs bios */
/* memory size */
val = 640; /* base memory in K */
/* base memory (first MiB) */
val = MIN(ram_size / 1024, 640);
rtc_set_memory(s, 0x15, val);
rtc_set_memory(s, 0x16, val >> 8);
val = (ram_size / 1024) - 1024;
/* extended memory (next 64MiB) */
if (ram_size > 1024 * 1024) {
val = (ram_size - 1024 * 1024) / 1024;
} else {
val = 0;
}
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x17, val);
rtc_set_memory(s, 0x18, val >> 8);
rtc_set_memory(s, 0x30, val);
rtc_set_memory(s, 0x31, val >> 8);
if (above_4g_mem_size) {
rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16);
rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24);
rtc_set_memory(s, 0x5d, (uint64_t)above_4g_mem_size >> 32);
}
if (ram_size > (16 * 1024 * 1024))
val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
else
/* memory between 16MiB and 4GiB */
if (ram_size > 16 * 1024 * 1024) {
val = (ram_size - 16 * 1024 * 1024) / 65536;
} else {
val = 0;
}
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x34, val);
rtc_set_memory(s, 0x35, val >> 8);
/* memory above 4GiB */
val = above_4g_mem_size / 65536;
rtc_set_memory(s, 0x5b, val);
rtc_set_memory(s, 0x5c, val >> 8);
rtc_set_memory(s, 0x5d, val >> 16);
/* set the number of CPU */
rtc_set_memory(s, 0x5f, smp_cpus - 1);
@@ -382,7 +388,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
if (floppy) {
fdc_get_bs(fd, floppy);
for (i = 0; i < 2; i++) {
if (fd[i] && bdrv_is_inserted(fd[i])) {
if (fd[i]) {
bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
&last_sect, FDRIVE_DRV_NONE,
&fd_type[i], &rate);
@@ -1097,7 +1103,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
qemu_irq pit_alt_irq = NULL;
qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042, *port92, *vmmouse, *pit;
ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
qemu_irq *cpu_exit_irq;
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@@ -1126,16 +1132,18 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
qemu_register_boot_set(pc_boot_set, *rtc_state);
if (kvm_irqchip_in_kernel()) {
pit = kvm_pit_init(isa_bus, 0x40);
} else {
pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
if (!xen_enabled()) {
if (kvm_irqchip_in_kernel()) {
pit = kvm_pit_init(isa_bus, 0x40);
} else {
pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
}
if (hpet) {
/* connect PIT to output control line of the HPET */
qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
}
pcspk_init(isa_bus, pit);
}
if (hpet) {
/* connect PIT to output control line of the HPET */
qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
}
pcspk_init(isa_bus, pit);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
-1
View File
@@ -1527,7 +1527,6 @@ static int pci_unplug_device(DeviceState *qdev)
qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
return -1;
}
object_unparent(OBJECT(dev));
return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
PCI_HOTPLUG_DISABLED);
}
+3 -1
View File
@@ -52,7 +52,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
{
PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
int err;
int err, ret;
pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
err = pci_bridge_initfn(dev);
if (err) {
@@ -86,6 +86,8 @@ slotid_error:
shpc_cleanup(dev, &bridge_dev->bar);
shpc_error:
memory_region_destroy(&bridge_dev->bar);
ret = pci_bridge_exitfn(dev);
assert(!ret);
bridge_error:
return err;
}
+20 -7
View File
@@ -20,6 +20,7 @@
#include "qdev.h"
#include "monitor.h"
#include "qmp-commands.h"
#include "arch_init.h"
/*
* Aliases were a bad idea from the start. Let's keep them
@@ -29,16 +30,18 @@ typedef struct QDevAlias
{
const char *typename;
const char *alias;
uint32_t arch_mask;
} QDevAlias;
static const QDevAlias qdev_alias_table[] = {
{ "virtio-blk-pci", "virtio-blk" },
{ "virtio-net-pci", "virtio-net" },
{ "virtio-serial-pci", "virtio-serial" },
{ "virtio-balloon-pci", "virtio-balloon" },
{ "virtio-blk-s390", "virtio-blk" },
{ "virtio-net-s390", "virtio-net" },
{ "virtio-serial-s390", "virtio-serial" },
{ "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-balloon-pci", "virtio-balloon",
QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
{ "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
{ "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
{ "lsi53c895a", "lsi" },
{ "ich9-ahci", "ahci" },
{ }
@@ -50,6 +53,11 @@ static const char *qdev_class_get_alias(DeviceClass *dc)
int i;
for (i = 0; qdev_alias_table[i].typename; i++) {
if (qdev_alias_table[i].arch_mask &&
!(qdev_alias_table[i].arch_mask & arch_type)) {
continue;
}
if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
return qdev_alias_table[i].alias;
}
@@ -110,6 +118,11 @@ static const char *find_typename_by_alias(const char *alias)
int i;
for (i = 0; qdev_alias_table[i].alias; i++) {
if (qdev_alias_table[i].arch_mask &&
!(qdev_alias_table[i].arch_mask & arch_type)) {
continue;
}
if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
return qdev_alias_table[i].typename;
}
+5 -1
View File
@@ -753,10 +753,12 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
}
mac->a[i] = strtol(str+pos, &p, 16);
}
g_free(str);
return;
inval:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
PropertyInfo qdev_prop_macaddr = {
@@ -825,7 +827,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
unsigned int slot, fn, n;
Error *local_err = NULL;
char *str = (char *)"";
char *str;
if (dev->state != DEV_STATE_CREATED) {
error_set(errp, QERR_PERMISSION_DENIED);
@@ -848,10 +850,12 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
goto invalid;
}
*ptr = slot << 3 | fn;
g_free(str);
return;
invalid:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
+3 -3
View File
@@ -240,7 +240,6 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
object_unparent(OBJECT(dev));
qdev_free(dev);
return 0;
}
@@ -255,9 +254,10 @@ int qdev_simple_unplug_cb(DeviceState *dev)
way is somewhat unclean, and best avoided. */
void qdev_init_nofail(DeviceState *dev)
{
const char *typename = object_get_typename(OBJECT(dev));
if (qdev_init(dev) < 0) {
error_report("Initialization of device %s failed",
object_get_typename(OBJECT(dev)));
error_report("Initialization of device %s failed", typename);
exit(1);
}
}
+13 -11
View File
@@ -781,6 +781,13 @@ static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high)
#endif
}
/* Workaround for buggy guest driver such as linux who allocates rx
* rings after the receiver were enabled. */
static bool rtl8139_cp_rx_valid(RTL8139State *s)
{
return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0);
}
static int rtl8139_can_receive(VLANClientState *nc)
{
RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque;
@@ -791,18 +798,15 @@ static int rtl8139_can_receive(VLANClientState *nc)
return 1;
if (!rtl8139_receiver_enabled(s))
return 1;
/* network/host communication happens only in normal mode */
if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal)
return 0;
if (rtl8139_cp_receiver_enabled(s)) {
if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) {
/* ??? Flow control not implemented in c+ mode.
This is a hack to work around slirp deficiencies anyway. */
return 1;
} else {
avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr,
s->RxBufferSize);
return (avail == 0 || avail >= 1514);
return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow));
}
}
@@ -836,12 +840,6 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
return -1;
}
/* check whether we are in normal mode */
if ((s->Cfg9346 & Chip9346_op_mask) != Cfg9346_Normal) {
DPRINTF("not in normal op mode\n");
return -1;
}
/* XXX: check this */
if (s->RxConfig & AcceptAllPhys) {
/* promiscuous: receive all */
@@ -946,6 +944,10 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
if (rtl8139_cp_receiver_enabled(s))
{
if (!rtl8139_cp_rx_valid(s)) {
return size;
}
DPRINTF("in C+ Rx mode ================\n");
/* begin C+ receiver mode */
+6 -4
View File
@@ -163,8 +163,7 @@ static int s390_virtio_blk_init(VirtIOS390Device *dev)
{
VirtIODevice *vdev;
vdev = virtio_blk_init((DeviceState *)dev, &dev->block,
&dev->block_serial);
vdev = virtio_blk_init((DeviceState *)dev, &dev->blk);
if (!vdev) {
return -1;
}
@@ -400,8 +399,11 @@ static TypeInfo s390_virtio_net = {
};
static Property s390_virtio_blk_properties[] = {
DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
#ifdef __linux__
DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
#endif
DEFINE_PROP_END_OF_LIST(),
};
+2 -2
View File
@@ -17,6 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "virtio-blk.h"
#include "virtio-net.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
@@ -64,8 +65,7 @@ struct VirtIOS390Device {
ram_addr_t feat_offs;
uint8_t feat_len;
VirtIODevice *vdev;
BlockConf block;
char *block_serial;
VirtIOBlkConf blk;
NICConf nic;
uint32_t host_features;
virtio_serial_conf serial;
+1 -1
View File
@@ -1561,7 +1561,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
return 0;
}
const VMStateInfo vmstate_info_scsi_requests = {
static const VMStateInfo vmstate_info_scsi_requests = {
.name = "scsi-requests",
.get = get_scsi_requests,
.put = put_scsi_requests,
+33 -23
View File
@@ -67,7 +67,6 @@
#define KERNEL_LOAD_ADDR 0x00404000
#define CMDLINE_ADDR 0x003ff000
#define INITRD_LOAD_ADDR 0x00300000
#define PROM_SIZE_MAX (4 * 1024 * 1024)
#define PROM_VADDR 0x000ffd00000ULL
#define APB_SPECIAL_BASE 0x1fe00000000ULL
@@ -181,14 +180,18 @@ static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
return 0;
}
static unsigned long sun4u_load_kernel(const char *kernel_filename,
const char *initrd_filename,
ram_addr_t RAM_size, long *initrd_size)
static uint64_t sun4u_load_kernel(const char *kernel_filename,
const char *initrd_filename,
ram_addr_t RAM_size, uint64_t *initrd_size,
uint64_t *initrd_addr, uint64_t *kernel_addr,
uint64_t *kernel_entry)
{
int linux_boot;
unsigned int i;
long kernel_size;
uint8_t *ptr;
uint64_t kernel_top;
linux_boot = (kernel_filename != NULL);
@@ -201,29 +204,34 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
#else
bswap_needed = 0;
#endif
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
if (kernel_size < 0) {
*kernel_addr = KERNEL_LOAD_ADDR;
*kernel_entry = KERNEL_LOAD_ADDR;
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
TARGET_PAGE_SIZE);
if (kernel_size < 0)
}
if (kernel_size < 0) {
kernel_size = load_image_targphys(kernel_filename,
KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR);
}
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
/* load initrd above kernel */
*initrd_size = 0;
if (initrd_filename) {
*initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
*initrd_size = load_image_targphys(initrd_filename,
INITRD_LOAD_ADDR,
RAM_size - INITRD_LOAD_ADDR);
if (*initrd_size < 0) {
*initrd_addr,
RAM_size - *initrd_addr);
if ((int)*initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
@@ -231,9 +239,9 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
}
if (*initrd_size > 0) {
for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
ptr = rom_ptr(*kernel_addr + i);
if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
stl_p(ptr + 24, INITRD_LOAD_ADDR + KERNEL_LOAD_ADDR - 0x4000);
stl_p(ptr + 24, *initrd_addr + *kernel_addr);
stl_p(ptr + 28, *initrd_size);
break;
}
@@ -788,7 +796,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
CPUSPARCState *env;
M48t59State *nvram;
unsigned int i;
long initrd_size, kernel_size;
uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
PCIBus *pci_bus, *pci_bus2, *pci_bus3;
ISABus *isa_bus;
qemu_irq *ivec_irqs, *pbm_irqs;
@@ -845,13 +853,15 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
initrd_size = 0;
initrd_addr = 0;
kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
ram_size, &initrd_size);
ram_size, &initrd_size, &initrd_addr,
&kernel_addr, &kernel_entry);
sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
KERNEL_LOAD_ADDR, kernel_size,
kernel_addr, kernel_size,
kernel_cmdline,
INITRD_LOAD_ADDR, initrd_size,
initrd_addr, initrd_size,
/* XXX: need an option to load a NVRAM image */
0,
graphic_width, graphic_height, graphic_depth,
@@ -861,8 +871,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
if (kernel_cmdline) {
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
strlen(kernel_cmdline) + 1);
@@ -872,8 +882,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
}
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
+13
View File
@@ -27,10 +27,23 @@ static struct BusInfo usb_bus_info = {
static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
static int usb_device_post_load(void *opaque, int version_id)
{
USBDevice *dev = opaque;
if (dev->state == USB_STATE_NOTATTACHED) {
dev->attached = 0;
} else {
dev->attached = 1;
}
return 0;
}
const VMStateDescription vmstate_usb_device = {
.name = "USBDevice",
.version_id = 1,
.minimum_version_id = 1,
.post_load = usb_device_post_load,
.fields = (VMStateField []) {
VMSTATE_UINT8(addr, USBDevice),
VMSTATE_INT32(state, USBDevice),
+36 -11
View File
@@ -348,6 +348,7 @@ struct EHCIQueue {
QTAILQ_ENTRY(EHCIQueue) next;
uint32_t seen;
uint64_t ts;
int revalidate;
/* cached data from guest - needs to be flushed
* when guest removes an entry (doorbell, handshake sequence)
@@ -695,7 +696,18 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
return NULL;
}
static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
static void ehci_queues_tag_unused_async(EHCIState *ehci)
{
EHCIQueue *q;
QTAILQ_FOREACH(q, &ehci->aqueues, next) {
if (!q->seen) {
q->revalidate = 1;
}
}
}
static void ehci_queues_rip_unused(EHCIState *ehci, int async)
{
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
@@ -706,7 +718,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
q->ts = ehci->last_run_ns;
continue;
}
if (!flush && ehci->last_run_ns < q->ts + 250000000) {
if (ehci->last_run_ns < q->ts + 250000000) {
/* allow 0.25 sec idle */
continue;
}
@@ -1064,6 +1076,12 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
/* Do any register specific pre-write processing here. */
switch(addr) {
case USBCMD:
if (val & USBCMD_HCRESET) {
ehci_reset(s);
val = s->usbcmd;
break;
}
if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
SET_LAST_RUN_CLOCK(s);
@@ -1077,10 +1095,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
ehci_set_usbsts(s, USBSTS_HALT);
}
if (val & USBCMD_HCRESET) {
ehci_reset(s);
val = s->usbcmd;
}
/* not supporting dynamic frame list size at the moment */
if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
@@ -1451,7 +1465,7 @@ static int ehci_process_itd(EHCIState *ehci,
dev = ehci_find_device(ehci, devaddr);
ep = usb_ep_get(dev, pid, endp);
if (ep->type == USB_ENDPOINT_XFER_ISOC) {
if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) {
usb_packet_setup(&ehci->ipacket, pid, ep);
usb_packet_map(&ehci->ipacket, &ehci->isgl);
ret = usb_handle_packet(dev, &ehci->ipacket);
@@ -1519,7 +1533,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
ehci_set_usbsts(ehci, USBSTS_REC);
}
ehci_queues_rip_unused(ehci, async, 0);
ehci_queues_rip_unused(ehci, async);
/* Find the head of the list (4.9.1.1) */
for(i = 0; i < MAX_QH; i++) {
@@ -1603,6 +1617,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
{
uint32_t entry;
EHCIQueue *q;
EHCIqh qh;
entry = ehci_get_fetch_addr(ehci, async);
q = ehci_find_queue_by_qh(ehci, entry, async);
@@ -1620,7 +1635,16 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
}
get_dwords(ehci, NLPTR_GET(q->qhaddr),
(uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
(uint32_t *) &qh, sizeof(EHCIqh) >> 2);
if (q->revalidate && (q->qh.epchar != qh.epchar ||
q->qh.epcap != qh.epcap ||
q->qh.current_qtd != qh.current_qtd)) {
ehci_free_queue(q, async);
q = ehci_alloc_queue(ehci, async);
q->seen++;
}
q->qh = qh;
q->revalidate = 0;
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
if (q->async == EHCI_ASYNC_INFLIGHT) {
@@ -2045,7 +2069,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
*/
if (ehci->usbcmd & USBCMD_IAAD) {
/* Remove all unseen qhs from the async qhs queue */
ehci_queues_rip_unused(ehci, async, 1);
ehci_queues_tag_unused_async(ehci);
DPRINTF("ASYNC: doorbell request acknowledged\n");
ehci->usbcmd &= ~USBCMD_IAAD;
ehci_set_interrupt(ehci, USBSTS_IAA);
@@ -2100,7 +2124,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
ehci_set_fetch_addr(ehci, async,entry);
ehci_set_state(ehci, async, EST_FETCHENTRY);
ehci_advance_state(ehci, async);
ehci_queues_rip_unused(ehci, async, 0);
ehci_queues_rip_unused(ehci, async);
break;
default:
@@ -2300,6 +2324,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
QTAILQ_INIT(&s->aqueues);
QTAILQ_INIT(&s->pqueues);
usb_packet_init(&s->ipacket);
qemu_register_reset(ehci_reset, s);
+2 -2
View File
@@ -288,10 +288,10 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
static void uhci_async_cancel_all(UHCIState *s)
{
UHCIQueue *queue;
UHCIQueue *queue, *nq;
UHCIAsync *curr, *n;
QTAILQ_FOREACH(queue, &s->queues, next) {
QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) {
QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
uhci_async_unlink(curr);
uhci_async_cancel(curr);
+2
View File
@@ -1031,6 +1031,8 @@ static int usbredir_handle_status(USBRedirDevice *dev,
case usb_redir_inval:
WARNING("got invalid param error from usb-host?\n");
return USB_RET_NAK;
case usb_redir_babble:
return USB_RET_BABBLE;
case usb_redir_ioerror:
case usb_redir_timeout:
default:
+6 -1
View File
@@ -2357,10 +2357,15 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space,
void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
{
#ifdef CONFIG_BOCHS_VBE
/* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
* so use an alias to avoid double-mapping the same region.
*/
memory_region_init_alias(&s->vram_vbe, "vram.vbe",
&s->vram, 0, memory_region_size(&s->vram));
/* XXX: use optimized standard vga accesses */
memory_region_add_subregion(system_memory,
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
&s->vram);
&s->vram_vbe);
s->vbe_mapped = 1;
#endif
}
+1
View File
@@ -105,6 +105,7 @@ typedef struct VGACommonState {
MemoryRegion *legacy_address_space;
uint8_t *vram_ptr;
MemoryRegion vram;
MemoryRegion vram_vbe;
uint32_t vram_size;
uint32_t latch;
MemoryRegion *chain4_alias;
+5 -1
View File
@@ -211,11 +211,15 @@ static void virtio_balloon_save(QEMUFile *f, void *opaque)
static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOBalloon *s = opaque;
int ret;
if (version_id != 1)
return -EINVAL;
virtio_load(&s->vdev, f);
ret = virtio_load(&s->vdev, f);
if (ret) {
return ret;
}
s->num_pages = qemu_get_be32(f);
s->actual = qemu_get_be32(f);
+64 -45
View File
@@ -29,7 +29,7 @@ typedef struct VirtIOBlock
void *rq;
QEMUBH *bh;
BlockConf *conf;
char *serial;
VirtIOBlkConf *blk;
unsigned short sector_mask;
DeviceState *qdev;
} VirtIOBlock;
@@ -145,19 +145,13 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
return req;
}
#ifdef __linux__
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
struct sg_io_hdr hdr;
#ifdef __linux__
int ret;
int status;
int i;
if ((req->dev->vdev.guest_features & (1 << VIRTIO_BLK_F_SCSI)) == 0) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
g_free(req);
return;
}
#endif
int status = VIRTIO_BLK_S_OK;
/*
* We require at least one output segment each for the virtio_blk_outhdr
@@ -172,21 +166,27 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
return;
}
/*
* No support for bidirection commands yet.
*/
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
g_free(req);
return;
}
/*
* The scsi inhdr is placed in the second-to-last input segment, just
* before the regular inhdr.
*/
req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
if (!req->dev->blk->scsi) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
/*
* No support for bidirection commands yet.
*/
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
#ifdef __linux__
struct sg_io_hdr hdr;
memset(&hdr, 0, sizeof(struct sg_io_hdr));
hdr.interface_id = 'S';
hdr.cmd_len = req->elem.out_sg[1].iov_len;
@@ -230,12 +230,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
if (ret) {
status = VIRTIO_BLK_S_UNSUPP;
hdr.status = ret;
hdr.resid = hdr.dxfer_len;
} else if (hdr.status) {
status = VIRTIO_BLK_S_IOERR;
} else {
status = VIRTIO_BLK_S_OK;
goto fail;
}
/*
@@ -258,14 +253,17 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
virtio_blk_req_complete(req, status);
g_free(req);
}
return;
#else
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
abort();
#endif
fail:
/* Just put anything nonzero so that the ioctl fails in the guest. */
stl_p(&req->scsi->errors, 255);
virtio_blk_req_complete(req, status);
g_free(req);
}
#endif /* __linux__ */
typedef struct MultiReqBuffer {
BlockRequest blkreq[32];
@@ -394,7 +392,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
* terminated by '\0' only when shorter than buffer.
*/
strncpy(req->elem.in_sg[0].iov_base,
s->serial ? s->serial : "",
s->blk->serial ? s->blk->serial : "",
MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
g_free(req);
@@ -494,7 +492,22 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
blkcfg.heads = heads;
blkcfg.sectors = secs & ~s->sector_mask;
/*
* We must ensure that the block device capacity is a multiple of
* the logical block size. If that is not the case, lets use
* sector_mask to adopt the geometry to have a correct picture.
* For those devices where the capacity is ok for the given geometry
* we dont touch the sector value of the geometry, since some devices
* (like s390 dasd) need a specific value. Here the capacity is already
* cyls*heads*secs*blk_size and the sector value is not block size
* divided by 512 - instead it is the amount of blk_size blocks
* per track (cylinder).
*/
if (bdrv_getlength(s->bs) / heads / secs % blk_size) {
blkcfg.sectors = secs & ~s->sector_mask;
} else {
blkcfg.sectors = secs;
}
blkcfg.size_max = 0;
blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
blkcfg.alignment_offset = 0;
@@ -509,6 +522,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
features |= (1 << VIRTIO_BLK_F_GEOMETRY);
features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
features |= (1 << VIRTIO_BLK_F_SCSI);
if (bdrv_enable_write_cache(s->bs))
features |= (1 << VIRTIO_BLK_F_WCACHE);
@@ -537,11 +551,16 @@ static void virtio_blk_save(QEMUFile *f, void *opaque)
static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOBlock *s = opaque;
int ret;
if (version_id != 2)
return -EINVAL;
virtio_load(&s->vdev, f);
ret = virtio_load(&s->vdev, f);
if (ret) {
return ret;
}
while (qemu_get_sbyte(f)) {
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
@@ -568,28 +587,27 @@ static const BlockDevOps virtio_block_ops = {
.resize_cb = virtio_blk_resize,
};
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
char **serial)
VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
{
VirtIOBlock *s;
int cylinders, heads, secs;
static int virtio_blk_id;
DriveInfo *dinfo;
if (!conf->bs) {
if (!blk->conf.bs) {
error_report("drive property not set");
return NULL;
}
if (!bdrv_is_inserted(conf->bs)) {
if (!bdrv_is_inserted(blk->conf.bs)) {
error_report("Device needs media, but drive is empty");
return NULL;
}
if (!*serial) {
if (!blk->serial) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(conf->bs);
dinfo = drive_get_by_blockdev(blk->conf.bs);
if (*dinfo->serial) {
*serial = strdup(dinfo->serial);
blk->serial = strdup(dinfo->serial);
}
}
@@ -600,9 +618,9 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
s->vdev.get_config = virtio_blk_update_config;
s->vdev.get_features = virtio_blk_get_features;
s->vdev.reset = virtio_blk_reset;
s->bs = conf->bs;
s->conf = conf;
s->serial = *serial;
s->bs = blk->conf.bs;
s->conf = &blk->conf;
s->blk = blk;
s->rq = NULL;
s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
@@ -614,10 +632,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s);
bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
bdrv_set_buffer_alignment(s->bs, conf->logical_block_size);
bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
bdrv_iostatus_enable(s->bs);
add_boot_device_path(conf->bootindex, dev, "/disk@0,0");
add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
return &s->vdev;
}
@@ -626,5 +644,6 @@ void virtio_blk_exit(VirtIODevice *vdev)
{
VirtIOBlock *s = to_virtio_blk(vdev);
unregister_savevm(s->qdev, "virtio-blk", s);
blockdev_mark_auto_del(s->bs);
virtio_cleanup(vdev);
}
+8 -6
View File
@@ -97,12 +97,14 @@ struct virtio_scsi_inhdr
uint32_t residual;
};
#ifdef __linux__
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
#else
struct VirtIOBlkConf
{
BlockConf conf;
char *serial;
uint32_t scsi;
};
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
#endif
#endif
+5 -1
View File
@@ -891,11 +891,15 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIONet *n = opaque;
int i;
int ret;
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
return -EINVAL;
virtio_load(&n->vdev, f);
ret = virtio_load(&n->vdev, f);
if (ret) {
return ret;
}
qemu_get_buffer(f, n->mac, ETH_ALEN);
n->tx_waiting = qemu_get_be32(f);
+9 -6
View File
@@ -130,6 +130,7 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
if (ret) {
return ret;
}
msix_unuse_all_vectors(&proxy->pci_dev);
msix_load(&proxy->pci_dev, f);
if (msix_present(&proxy->pci_dev)) {
qemu_get_be16s(f, &proxy->vdev->config_vector);
@@ -278,6 +279,7 @@ void virtio_pci_reset(DeviceState *d)
virtio_pci_stop_ioeventfd(proxy);
virtio_reset(proxy->vdev);
msix_reset(&proxy->pci_dev);
msix_unuse_all_vectors(&proxy->pci_dev);
proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
@@ -491,7 +493,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
virtio_config_writel(proxy->vdev, addr, val);
}
const MemoryRegionPortio virtio_portio[] = {
static const MemoryRegionPortio virtio_portio[] = {
{ 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
{ 0, 0x10000, 2, .write = virtio_pci_config_writew, },
{ 0, 0x10000, 4, .write = virtio_pci_config_writel, },
@@ -697,8 +699,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
proxy->class_code != PCI_CLASS_STORAGE_OTHER)
proxy->class_code = PCI_CLASS_STORAGE_SCSI;
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block,
&proxy->block_serial);
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->blk);
if (!vdev) {
return -1;
}
@@ -726,7 +727,6 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
virtio_pci_stop_ioeventfd(proxy);
virtio_blk_exit(proxy->vdev);
blockdev_mark_auto_del(proxy->block.bs);
return virtio_exit_pci(pci_dev);
}
@@ -814,8 +814,11 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
static Property virtio_blk_properties[] = {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
#ifdef __linux__
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
#endif
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
+2 -2
View File
@@ -15,6 +15,7 @@
#ifndef QEMU_VIRTIO_PCI_H
#define QEMU_VIRTIO_PCI_H
#include "virtio-blk.h"
#include "virtio-net.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
@@ -32,8 +33,7 @@ typedef struct {
uint32_t flags;
uint32_t class_code;
uint32_t nvectors;
BlockConf block;
char *block_serial;
VirtIOBlkConf blk;
NICConf nic;
uint32_t host_features;
#ifdef CONFIG_LINUX
+6 -1
View File
@@ -564,7 +564,12 @@ static void virtio_scsi_save(QEMUFile *f, void *opaque)
static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOSCSI *s = opaque;
virtio_load(&s->vdev, f);
int ret;
ret = virtio_load(&s->vdev, f);
if (ret) {
return ret;
}
return 0;
}
+5 -1
View File
@@ -637,13 +637,17 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
VirtIOSerialPort *port;
uint32_t max_nr_ports, nr_active_ports, ports_map;
unsigned int i;
int ret;
if (version_id > 3) {
return -EINVAL;
}
/* The virtio device */
virtio_load(&s->vdev, f);
ret = virtio_load(&s->vdev, f);
if (ret) {
return ret;
}
if (version_id < 2) {
return 0;
+2 -2
View File
@@ -191,8 +191,8 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
void *opaque);
/* Base devices. */
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
char **serial);
typedef struct VirtIOBlkConf VirtIOBlkConf;
VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk);
struct virtio_net_conf;
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
struct virtio_net_conf *net);
+1 -1
View File
@@ -148,6 +148,6 @@ static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom,
}
#endif
void destroy_hvm_domain(void);
void destroy_hvm_domain(bool reboot);
#endif /* QEMU_HW_XEN_COMMON_H */
+41 -15
View File
@@ -48,7 +48,6 @@
/* ------------------------------------------------------------- */
static int syncwrite = 0;
static int batch_maps = 0;
static int max_requests = 32;
@@ -67,6 +66,7 @@ struct ioreq {
QEMUIOVector v;
int presync;
int postsync;
uint8_t mapped;
/* grant mapping */
uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST];
@@ -154,7 +154,7 @@ static void ioreq_finish(struct ioreq *ioreq)
blkdev->requests_finished++;
}
static void ioreq_release(struct ioreq *ioreq)
static void ioreq_release(struct ioreq *ioreq, bool finish)
{
struct XenBlkDev *blkdev = ioreq->blkdev;
@@ -162,7 +162,11 @@ static void ioreq_release(struct ioreq *ioreq)
memset(ioreq, 0, sizeof(*ioreq));
ioreq->blkdev = blkdev;
QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list);
blkdev->requests_finished--;
if (finish) {
blkdev->requests_finished--;
} else {
blkdev->requests_inflight--;
}
}
/*
@@ -189,15 +193,10 @@ static int ioreq_parse(struct ioreq *ioreq)
ioreq->presync = 1;
return 0;
}
if (!syncwrite) {
ioreq->presync = ioreq->postsync = 1;
}
ioreq->presync = ioreq->postsync = 1;
/* fall through */
case BLKIF_OP_WRITE:
ioreq->prot = PROT_READ; /* from memory */
if (syncwrite) {
ioreq->postsync = 1;
}
break;
default:
xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
@@ -248,7 +247,7 @@ static void ioreq_unmap(struct ioreq *ioreq)
XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
int i;
if (ioreq->v.niov == 0) {
if (ioreq->v.niov == 0 || ioreq->mapped == 0) {
return;
}
if (batch_maps) {
@@ -274,6 +273,7 @@ static void ioreq_unmap(struct ioreq *ioreq)
ioreq->page[i] = NULL;
}
}
ioreq->mapped = 0;
}
static int ioreq_map(struct ioreq *ioreq)
@@ -281,7 +281,7 @@ static int ioreq_map(struct ioreq *ioreq)
XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
int i;
if (ioreq->v.niov == 0) {
if (ioreq->v.niov == 0 || ioreq->mapped == 1) {
return 0;
}
if (batch_maps) {
@@ -313,9 +313,12 @@ static int ioreq_map(struct ioreq *ioreq)
ioreq->blkdev->cnt_map++;
}
}
ioreq->mapped = 1;
return 0;
}
static int ioreq_runio_qemu_aio(struct ioreq *ioreq);
static void qemu_aio_complete(void *opaque, int ret)
{
struct ioreq *ioreq = opaque;
@@ -327,11 +330,19 @@ static void qemu_aio_complete(void *opaque, int ret)
}
ioreq->aio_inflight--;
if (ioreq->presync) {
ioreq->presync = 0;
ioreq_runio_qemu_aio(ioreq);
return;
}
if (ioreq->aio_inflight > 0) {
return;
}
if (ioreq->postsync) {
bdrv_flush(ioreq->blkdev->bs);
ioreq->postsync = 0;
ioreq->aio_inflight++;
bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
return;
}
ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
@@ -351,7 +362,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
ioreq->aio_inflight++;
if (ioreq->presync) {
bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
return 0;
}
switch (ioreq->req.operation) {
@@ -449,7 +461,7 @@ static void blk_send_response_all(struct XenBlkDev *blkdev)
while (!QLIST_EMPTY(&blkdev->finished)) {
ioreq = QLIST_FIRST(&blkdev->finished);
send_notify += blk_send_response_one(ioreq);
ioreq_release(ioreq);
ioreq_release(ioreq, true);
}
if (send_notify) {
xen_be_send_notify(&blkdev->xendev);
@@ -505,7 +517,7 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
if (blk_send_response_one(ioreq)) {
xen_be_send_notify(&blkdev->xendev);
}
ioreq_release(ioreq);
ioreq_release(ioreq, false);
continue;
}
@@ -525,6 +537,15 @@ static void blk_bh(void *opaque)
blk_handle_requests(blkdev);
}
/*
* We need to account for the grant allocations requiring contiguous
* chunks; the worst case number would be
* max_req * max_seg + (max_req - 1) * (max_seg - 1) + 1,
* but in order to keep things simple just use
* 2 * max_req * max_seg.
*/
#define MAX_GRANTS(max_req, max_seg) (2 * (max_req) * (max_seg))
static void blk_alloc(struct XenDevice *xendev)
{
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
@@ -536,6 +557,11 @@ static void blk_alloc(struct XenDevice *xendev)
if (xen_mode != XEN_EMULATE) {
batch_maps = 1;
}
if (xc_gnttab_set_max_grants(xendev->gnttabdev,
MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) {
xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n",
strerror(errno));
}
}
static int blk_init(struct XenDevice *xendev)
+1 -1
View File
@@ -87,7 +87,7 @@ static void unplug_nic(PCIBus *b, PCIDevice *d)
{
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET) {
qdev_unplug(&(d->qdev), NULL);
qdev_free(&d->qdev);
}
}
+1
View File
@@ -77,6 +77,7 @@ int qemu_set_fd_handler2(int fd,
ioh->fd_write = fd_write;
ioh->opaque = opaque;
ioh->deleted = 0;
qemu_notify_event();
}
return 0;
}
+142 -88
View File
@@ -27,6 +27,11 @@
typedef struct JSONParserContext
{
Error *err;
struct {
QObject **buf;
size_t pos;
size_t count;
} tokens;
} JSONParserContext;
#define BUG_ON(cond) assert(!(cond))
@@ -40,7 +45,7 @@ typedef struct JSONParserContext
* 4) deal with premature EOI
*/
static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap);
static QObject *parse_value(JSONParserContext *ctxt, va_list *ap);
/**
* Token manipulators
@@ -270,27 +275,111 @@ out:
return NULL;
}
static QObject *parser_context_pop_token(JSONParserContext *ctxt)
{
QObject *token;
g_assert(ctxt->tokens.pos < ctxt->tokens.count);
token = ctxt->tokens.buf[ctxt->tokens.pos];
ctxt->tokens.pos++;
return token;
}
/* Note: parser_context_{peek|pop}_token do not increment the
* token object's refcount. In both cases the references will continue
* to be tracked and cleaned up in parser_context_free(), so do not
* attempt to free the token object.
*/
static QObject *parser_context_peek_token(JSONParserContext *ctxt)
{
QObject *token;
g_assert(ctxt->tokens.pos < ctxt->tokens.count);
token = ctxt->tokens.buf[ctxt->tokens.pos];
return token;
}
static JSONParserContext parser_context_save(JSONParserContext *ctxt)
{
JSONParserContext saved_ctxt = {0};
saved_ctxt.tokens.pos = ctxt->tokens.pos;
saved_ctxt.tokens.count = ctxt->tokens.count;
saved_ctxt.tokens.buf = ctxt->tokens.buf;
return saved_ctxt;
}
static void parser_context_restore(JSONParserContext *ctxt,
JSONParserContext saved_ctxt)
{
ctxt->tokens.pos = saved_ctxt.tokens.pos;
ctxt->tokens.count = saved_ctxt.tokens.count;
ctxt->tokens.buf = saved_ctxt.tokens.buf;
}
static void tokens_append_from_iter(QObject *obj, void *opaque)
{
JSONParserContext *ctxt = opaque;
g_assert(ctxt->tokens.pos < ctxt->tokens.count);
ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
qobject_incref(obj);
}
static JSONParserContext *parser_context_new(QList *tokens)
{
JSONParserContext *ctxt;
size_t count;
if (!tokens) {
return NULL;
}
count = qlist_size(tokens);
if (count == 0) {
return NULL;
}
ctxt = g_malloc0(sizeof(JSONParserContext));
ctxt->tokens.pos = 0;
ctxt->tokens.count = count;
ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
qlist_iter(tokens, tokens_append_from_iter, ctxt);
ctxt->tokens.pos = 0;
return ctxt;
}
/* to support error propagation, ctxt->err must be freed separately */
static void parser_context_free(JSONParserContext *ctxt)
{
int i;
if (ctxt) {
for (i = 0; i < ctxt->tokens.count; i++) {
qobject_decref(ctxt->tokens.buf[i]);
}
g_free(ctxt->tokens.buf);
g_free(ctxt);
}
}
/**
* Parsing rules
*/
static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_list *ap)
static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
{
QObject *key = NULL, *token = NULL, *value, *peek;
QList *working = qlist_copy(*tokens);
JSONParserContext saved_ctxt = parser_context_save(ctxt);
peek = qlist_peek(working);
peek = parser_context_peek_token(ctxt);
if (peek == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
key = parse_value(ctxt, &working, ap);
key = parse_value(ctxt, ap);
if (!key || qobject_type(key) != QTYPE_QSTRING) {
parse_error(ctxt, peek, "key is not a string in object");
goto out;
}
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -301,7 +390,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
goto out;
}
value = parse_value(ctxt, &working, ap);
value = parse_value(ctxt, ap);
if (value == NULL) {
parse_error(ctxt, token, "Missing value in dict");
goto out;
@@ -309,28 +398,24 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value);
qobject_decref(token);
qobject_decref(key);
QDECREF(*tokens);
*tokens = working;
return 0;
out:
qobject_decref(token);
parser_context_restore(ctxt, saved_ctxt);
qobject_decref(key);
QDECREF(working);
return -1;
}
static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *ap)
static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
{
QDict *dict = NULL;
QObject *token, *peek;
QList *working = qlist_copy(*tokens);
JSONParserContext saved_ctxt = parser_context_save(ctxt);
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -338,23 +423,22 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a
if (!token_is_operator(token, '{')) {
goto out;
}
qobject_decref(token);
token = NULL;
dict = qdict_new();
peek = qlist_peek(working);
peek = parser_context_peek_token(ctxt);
if (peek == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
if (!token_is_operator(peek, '}')) {
if (parse_pair(ctxt, dict, &working, ap) == -1) {
if (parse_pair(ctxt, dict, ap) == -1) {
goto out;
}
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -365,59 +449,52 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a
parse_error(ctxt, token, "expected separator in dict");
goto out;
}
qobject_decref(token);
token = NULL;
if (parse_pair(ctxt, dict, &working, ap) == -1) {
if (parse_pair(ctxt, dict, ap) == -1) {
goto out;
}
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
}
qobject_decref(token);
token = NULL;
} else {
token = qlist_pop(working);
qobject_decref(token);
token = parser_context_pop_token(ctxt);
token = NULL;
}
QDECREF(*tokens);
*tokens = working;
return QOBJECT(dict);
out:
qobject_decref(token);
QDECREF(working);
parser_context_restore(ctxt, saved_ctxt);
QDECREF(dict);
return NULL;
}
static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap)
static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
{
QList *list = NULL;
QObject *token, *peek;
QList *working = qlist_copy(*tokens);
JSONParserContext saved_ctxt = parser_context_save(ctxt);
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
if (!token_is_operator(token, '[')) {
token = NULL;
goto out;
}
qobject_decref(token);
token = NULL;
list = qlist_new();
peek = qlist_peek(working);
peek = parser_context_peek_token(ctxt);
if (peek == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -426,7 +503,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
if (!token_is_operator(peek, ']')) {
QObject *obj;
obj = parse_value(ctxt, &working, ap);
obj = parse_value(ctxt, ap);
if (obj == NULL) {
parse_error(ctxt, token, "expecting value");
goto out;
@@ -434,7 +511,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
qlist_append_obj(list, obj);
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -446,10 +523,9 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
goto out;
}
qobject_decref(token);
token = NULL;
obj = parse_value(ctxt, &working, ap);
obj = parse_value(ctxt, ap);
if (obj == NULL) {
parse_error(ctxt, token, "expecting value");
goto out;
@@ -457,39 +533,33 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
qlist_append_obj(list, obj);
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
}
qobject_decref(token);
token = NULL;
} else {
token = qlist_pop(working);
qobject_decref(token);
token = parser_context_pop_token(ctxt);
token = NULL;
}
QDECREF(*tokens);
*tokens = working;
return QOBJECT(list);
out:
qobject_decref(token);
QDECREF(working);
parser_context_restore(ctxt, saved_ctxt);
QDECREF(list);
return NULL;
}
static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens)
static QObject *parse_keyword(JSONParserContext *ctxt)
{
QObject *token, *ret;
QList *working = qlist_copy(*tokens);
JSONParserContext saved_ctxt = parser_context_save(ctxt);
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -507,29 +577,24 @@ static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens)
goto out;
}
qobject_decref(token);
QDECREF(*tokens);
*tokens = working;
return ret;
out:
qobject_decref(token);
QDECREF(working);
parser_context_restore(ctxt, saved_ctxt);
return NULL;
}
static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *ap)
static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
{
QObject *token = NULL, *obj;
QList *working = qlist_copy(*tokens);
JSONParserContext saved_ctxt = parser_context_save(ctxt);
if (ap == NULL) {
goto out;
}
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -553,25 +618,20 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a
goto out;
}
qobject_decref(token);
QDECREF(*tokens);
*tokens = working;
return obj;
out:
qobject_decref(token);
QDECREF(working);
parser_context_restore(ctxt, saved_ctxt);
return NULL;
}
static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens)
static QObject *parse_literal(JSONParserContext *ctxt)
{
QObject *token, *obj;
QList *working = qlist_copy(*tokens);
JSONParserContext saved_ctxt = parser_context_save(ctxt);
token = qlist_pop(working);
token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -591,35 +651,30 @@ static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens)
goto out;
}
qobject_decref(token);
QDECREF(*tokens);
*tokens = working;
return obj;
out:
qobject_decref(token);
QDECREF(working);
parser_context_restore(ctxt, saved_ctxt);
return NULL;
}
static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap)
static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
{
QObject *obj;
obj = parse_object(ctxt, tokens, ap);
obj = parse_object(ctxt, ap);
if (obj == NULL) {
obj = parse_array(ctxt, tokens, ap);
obj = parse_array(ctxt, ap);
}
if (obj == NULL) {
obj = parse_escape(ctxt, tokens, ap);
obj = parse_escape(ctxt, ap);
}
if (obj == NULL) {
obj = parse_keyword(ctxt, tokens);
obj = parse_keyword(ctxt);
}
if (obj == NULL) {
obj = parse_literal(ctxt, tokens);
obj = parse_literal(ctxt);
}
return obj;
@@ -632,19 +687,18 @@ QObject *json_parser_parse(QList *tokens, va_list *ap)
QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
{
JSONParserContext ctxt = {};
QList *working;
JSONParserContext *ctxt = parser_context_new(tokens);
QObject *result;
if (!tokens) {
if (!ctxt) {
return NULL;
}
working = qlist_copy(tokens);
result = parse_value(&ctxt, &working, ap);
QDECREF(working);
result = parse_value(ctxt, ap);
error_propagate(errp, ctxt.err);
error_propagate(errp, ctxt->err);
parser_context_free(ctxt);
return result;
}
+5 -1
View File
@@ -573,6 +573,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
page_dump(stdout);
printf("\n");
#endif
tb_invalidate_phys_range(start, start + len, 0);
mmap_unlock();
return start;
fail:
@@ -675,8 +676,10 @@ int target_munmap(abi_ulong start, abi_ulong len)
}
}
if (ret == 0)
if (ret == 0) {
page_set_flags(start, start + len, 0);
tb_invalidate_phys_range(start, start + len, 0);
}
mmap_unlock();
return ret;
}
@@ -754,6 +757,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
page_set_flags(old_addr, old_addr + old_size, 0);
page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
}
tb_invalidate_phys_range(new_addr, new_addr + new_size, 0);
mmap_unlock();
return new_addr;
}
+2 -2
View File
@@ -2794,7 +2794,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
return -TARGET_EFAULT;
host_mb = malloc(msgsz+sizeof(long));
host_mb = g_malloc(msgsz+sizeof(long));
ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
if (ret > 0) {
@@ -2809,11 +2809,11 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
}
target_mb->mtype = tswapal(host_mb->mtype);
free(host_mb);
end:
if (target_mb)
unlock_user_struct(target_mb, msgp, 1);
g_free(host_mb);
return ret;
}
+1 -1
View File
@@ -426,7 +426,7 @@ static void memory_region_iorange_write(IORange *iorange,
if (mrp) {
mrp->write(mr->opaque, offset, data);
} else if (width == 2) {
mrp = find_portio(mr, offset - mrio->offset, 1, false);
mrp = find_portio(mr, offset - mrio->offset, 1, true);
assert(mrp);
mrp->write(mr->opaque, offset, data & 0xff);
mrp->write(mr->opaque, offset + 1, data >> 8);
+3 -1
View File
@@ -4501,13 +4501,13 @@ static void monitor_control_event(void *opaque, int event)
switch (event) {
case CHR_EVENT_OPENED:
mon->mc->command_mode = 0;
json_message_parser_init(&mon->mc->parser, handle_qmp_command);
data = get_qmp_greeting();
monitor_json_emitter(mon, data);
qobject_decref(data);
break;
case CHR_EVENT_CLOSED:
json_message_parser_destroy(&mon->mc->parser);
json_message_parser_init(&mon->mc->parser, handle_qmp_command);
break;
}
}
@@ -4605,6 +4605,8 @@ void monitor_init(CharDriverState *chr, int flags)
qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
monitor_control_event, mon);
qemu_chr_fe_set_echo(chr, true);
json_message_parser_init(&mon->mc->parser, handle_qmp_command);
} else {
qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
monitor_event, mon);
+24 -2
View File
@@ -26,6 +26,7 @@
#include "config-host.h"
#ifndef _WIN32
#include <pwd.h>
#include <sys/wait.h>
#endif
#include "net.h"
@@ -487,8 +488,27 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
static int instance;
char smb_conf[128];
char smb_cmdline[128];
struct passwd *passwd;
FILE *f;
passwd = getpwuid(geteuid());
if (!passwd) {
error_report("failed to retrieve user name");
return -1;
}
if (access(CONFIG_SMBD_COMMAND, F_OK)) {
error_report("could not find '%s', please install it",
CONFIG_SMBD_COMMAND);
return -1;
}
if (access(exported_dir, R_OK | X_OK)) {
error_report("error accessing shared directory '%s': %s",
exported_dir, strerror(errno));
return -1;
}
snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
(long)getpid(), instance++);
if (mkdir(s->smb_dir, 0700) < 0) {
@@ -517,14 +537,16 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
"[qemu]\n"
"path=%s\n"
"read only=no\n"
"guest ok=yes\n",
"guest ok=yes\n"
"force user=%s\n",
s->smb_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
exported_dir
exported_dir,
passwd->pw_name
);
fclose(f);
+7 -1
View File
@@ -57,7 +57,13 @@ int setenv(const char *name, const char *value, int overwrite)
static BOOL WINAPI qemu_ctrl_handler(DWORD type)
{
exit(STATUS_CONTROL_C_EXIT);
qemu_system_shutdown_request();
/* Windows 7 kills application when the function returns.
Sleep here to give QEMU a try for closing.
Sleep period is 10000ms because Windows kills the program
after 10 seconds anyway. */
Sleep(10000);
return TRUE;
}
+1 -1
View File
@@ -12,7 +12,7 @@
1275-1994 (referred to as Open Firmware) compliant firmware.
The included images for PowerPC (for 32 and 64 bit PPC CPUs),
Sparc32 and Sparc64 are built from OpenBIOS SVN revision
1056.
1060.
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
Binary file not shown.
Binary file not shown.
Binary file not shown.
+37 -22
View File
@@ -126,16 +126,19 @@
# @guest-shutdown:
#
# Initiate guest-activated shutdown. Note: this is an asynchronous
# shutdown request, with no guaruntee of successful shutdown. Errors
# will be logged to guest's syslog.
# shutdown request, with no guarantee of successful shutdown.
#
# @mode: #optional "halt", "powerdown" (default), or "reboot"
#
# Returns: Nothing on success
# This command does NOT return a response on success. Success condition
# is indicated by the VM exiting with a zero exit status or, when
# running with --no-shutdown, by issuing the query-status QMP command
# to confirm the VM status is "shutdown".
#
# Since: 0.15.0
##
{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' } }
{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' },
'success-response': 'no' }
##
# @guest-file-open:
@@ -359,17 +362,21 @@
# For the best results it's strongly recommended to have the pm-utils
# package installed in the guest.
#
# Returns: nothing on success
# This command does NOT return a response on success. There is a high chance
# the command succeeded if the VM exits with a zero exit status or, when
# running with --no-shutdown, by issuing the query-status QMP command to
# to confirm the VM status is "shutdown". However, the VM could also exit
# (or set its status to "shutdown") due to other reasons.
#
# The following errors may be returned:
# If suspend to disk is not supported, Unsupported
#
# Notes: o This is an asynchronous request. There's no guarantee a response
# will be sent
# o It's strongly recommended to issue the guest-sync command before
# sending commands when the guest resumes
# Notes: It's strongly recommended to issue the guest-sync command before
# sending commands when the guest resumes
#
# Since: 1.1
##
{ 'command': 'guest-suspend-disk' }
{ 'command': 'guest-suspend-disk', 'success-response': 'no' }
##
# @guest-suspend-ram
@@ -387,17 +394,21 @@
# command. Thus, it's *required* to query QEMU for the presence of the
# 'system_wakeup' command before issuing guest-suspend-ram.
#
# Returns: nothing on success
# This command does NOT return a response on success. There are two options
# to check for success:
# 1. Wait for the SUSPEND QMP event from QEMU
# 2. Issue the query-status QMP command to confirm the VM status is
# "suspended"
#
# The following errors may be returned:
# If suspend to ram is not supported, Unsupported
#
# Notes: o This is an asynchronous request. There's no guarantee a response
# will be sent
# o It's strongly recommended to issue the guest-sync command before
# sending commands when the guest resumes
# Notes: It's strongly recommended to issue the guest-sync command before
# sending commands when the guest resumes
#
# Since: 1.1
##
{ 'command': 'guest-suspend-ram' }
{ 'command': 'guest-suspend-ram', 'success-response': 'no' }
##
# @guest-suspend-hybrid
@@ -410,17 +421,21 @@
# command. Thus, it's *required* to query QEMU for the presence of the
# 'system_wakeup' command before issuing guest-suspend-hybrid.
#
# Returns: nothing on success
# This command does NOT return a response on success. There are two options
# to check for success:
# 1. Wait for the SUSPEND QMP event from QEMU
# 2. Issue the query-status QMP command to confirm the VM status is
# "suspended"
#
# The following errors may be returned:
# If hybrid suspend is not supported, Unsupported
#
# Notes: o This is an asynchronous request. There's no guarantee a response
# will be sent
# o It's strongly recommended to issue the guest-sync command before
# sending commands when the guest resumes
# Notes: It's strongly recommended to issue the guest-sync command before
# sending commands when the guest resumes
#
# Since: 1.1
##
{ 'command': 'guest-suspend-hybrid' }
{ 'command': 'guest-suspend-hybrid', 'success-response': 'no' }
##
# @GuestIpAddressType:
+9 -1
View File
@@ -25,16 +25,24 @@ typedef enum QmpCommandType
QCT_NORMAL,
} QmpCommandType;
typedef enum QmpCommandOptions
{
QCO_NO_OPTIONS = 0x0,
QCO_NO_SUCCESS_RESP = 0x1,
} QmpCommandOptions;
typedef struct QmpCommand
{
const char *name;
QmpCommandType type;
QmpCommandFunc *fn;
QmpCommandOptions options;
QTAILQ_ENTRY(QmpCommand) node;
bool enabled;
} QmpCommand;
void qmp_register_command(const char *name, QmpCommandFunc *fn);
void qmp_register_command(const char *name, QmpCommandFunc *fn,
QmpCommandOptions options);
QmpCommand *qmp_find_command(const char *name);
QObject *qmp_dispatch(QObject *request);
void qmp_disable_command(const char *name);
+6 -2
View File
@@ -94,8 +94,12 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
switch (cmd->type) {
case QCT_NORMAL:
cmd->fn(args, &ret, errp);
if (!error_is_set(errp) && ret == NULL) {
ret = QOBJECT(qdict_new());
if (!error_is_set(errp)) {
if (cmd->options & QCO_NO_SUCCESS_RESP) {
g_assert(!ret);
} else if (!ret) {
ret = QOBJECT(qdict_new());
}
}
break;
}
+3 -1
View File
@@ -17,7 +17,8 @@
static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
QTAILQ_HEAD_INITIALIZER(qmp_commands);
void qmp_register_command(const char *name, QmpCommandFunc *fn)
void qmp_register_command(const char *name, QmpCommandFunc *fn,
QmpCommandOptions options)
{
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
@@ -25,6 +26,7 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn)
cmd->type = QCT_NORMAL;
cmd->fn = fn;
cmd->enabled = true;
cmd->options = options;
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
}
+31 -25
View File
@@ -104,16 +104,9 @@ static void quit_handler(int sig)
}
#ifndef _WIN32
/* reap _all_ terminated children */
static void child_handler(int sig)
{
int status;
while (waitpid(-1, &status, WNOHANG) > 0) /* NOTHING */;
}
static gboolean register_signal_handlers(void)
{
struct sigaction sigact, sigact_chld;
struct sigaction sigact;
int ret;
memset(&sigact, 0, sizeof(struct sigaction));
@@ -130,15 +123,24 @@ static gboolean register_signal_handlers(void)
return false;
}
memset(&sigact_chld, 0, sizeof(struct sigaction));
sigact_chld.sa_handler = child_handler;
sigact_chld.sa_flags = SA_NOCLDSTOP;
ret = sigaction(SIGCHLD, &sigact_chld, NULL);
if (ret == -1) {
g_error("error configuring signal handler: %s", strerror(errno));
return true;
}
/* TODO: use this in place of all post-fork() fclose(std*) callers */
void reopen_fd_to_null(int fd)
{
int nullfd;
nullfd = open("/dev/null", O_RDWR);
if (nullfd < 0) {
return;
}
return true;
dup2(nullfd, fd);
if (nullfd != fd) {
close(nullfd);
}
}
#endif
@@ -167,7 +169,7 @@ static void usage(const char *cmd)
" -h, --help display this help and exit\n"
"\n"
"Report bugs to <mdroth@linux.vnet.ibm.com>\n"
, cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
, cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
QGA_STATEDIR_DEFAULT);
}
@@ -246,6 +248,9 @@ static bool ga_open_pidfile(const char *pidfile)
pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) {
g_critical("Cannot lock pid file, %s", strerror(errno));
if (pidfd != -1) {
close(pidfd);
}
return false;
}
@@ -428,13 +433,15 @@ static void become_daemon(const char *pidfile)
goto fail;
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
reopen_fd_to_null(STDIN_FILENO);
reopen_fd_to_null(STDOUT_FILENO);
reopen_fd_to_null(STDERR_FILENO);
return;
fail:
unlink(pidfile);
if (pidfile) {
unlink(pidfile);
}
g_critical("failed to daemonize");
exit(EXIT_FAILURE);
#endif
@@ -488,8 +495,6 @@ static void process_command(GAState *s, QDict *req)
g_warning("error sending response: %s", strerror(ret));
}
qobject_decref(rsp);
} else {
g_warning("error getting response");
}
}
@@ -729,7 +734,7 @@ int main(int argc, char **argv)
log_level = G_LOG_LEVEL_MASK;
break;
case 'V':
printf("QEMU Guest Agent %s\n", QGA_VERSION);
printf("QEMU Guest Agent %s\n", QEMU_VERSION);
return 0;
case 'd':
daemonize = 1;
@@ -836,12 +841,13 @@ int main(int argc, char **argv)
become_daemon(pid_filepath);
}
if (log_filepath) {
s->log_file = fopen(log_filepath, "a");
if (!s->log_file) {
FILE *log_file = fopen(log_filepath, "a");
if (!log_file) {
g_critical("unable to open specified log file: %s",
strerror(errno));
goto out_bad;
}
s->log_file = log_file;
}
}
+51
View File
@@ -4,6 +4,16 @@ usage: qemu-img command [command options]
@c man end
@end example
@c man begin DESCRIPTION
qemu-img allows you to create, convert and modify images offline. It can handle
all image formats supported by QEMU.
@b{Warning:} Never use qemu-img to modify images in use by a running virtual
machine or any other process; this may destroy the image. Also, be aware that
querying an image that is being modified by another process may encounter
inconsistent state.
@c man end
@c man begin OPTIONS
The following commands are supported:
@@ -159,6 +169,24 @@ It can be used without an accessible old backing file, i.e. you can use it to
fix an image whose backing file has already been moved/renamed.
@end table
You can use @code{rebase} to perform a ``diff'' operation on two
disk images. This can be useful when you have copied or cloned
a guest, and you want to get back to a thin image on top of a
template or base image.
Say that @code{base.img} has been cloned as @code{modified.img} by
copying it, and that the @code{modified.img} guest has run so there
are now some changes compared to @code{base.img}. To construct a thin
image called @code{diff.qcow2} that contains just the differences, do:
@example
qemu-img create -f qcow2 -b modified.img diff.qcow2
qemu-img rebase -b base.img diff.qcow2
@end example
At this point, @code{modified.img} can be discarded, since
@code{base.img + diff.qcow2} contains the same information.
@item resize @var{filename} [+ | -]@var{size}
Change the disk image as if it had been created with @var{size}.
@@ -214,6 +242,29 @@ to grow.
@end table
@item qed
Image format with support for backing files and compact image files (when your
filesystem or transport medium does not support holes). Good performance due
to less metadata than the more featureful qcow2 format, especially with
cache=writethrough or cache=directsync. Consider using qcow2 which will soon
have a similar optimization and is most actively developed.
Supported options:
@table @code
@item backing_file
File name of a base image (see @option{create} subcommand).
@item backing_fmt
Image file format of backing file (optional). Useful if the format cannot be
autodetected because it has no header, like some vhd/vpc files.
@item cluster_size
Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller
cluster sizes can improve the image file size whereas larger cluster sizes
generally provide better performance.
@item table_size
Changes the number of clusters per L1/L2 table (must be power-of-2 between 1
and 16). There is normally no need to change this value but this option can be
used for performance benchmarking.
@end table
@item qcow
Old QEMU image format. Left for compatibility.
+3 -10
View File
@@ -112,14 +112,10 @@ static int64_t qemu_next_alarm_deadline(void)
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
{
int64_t nearest_delta_ns;
if (!rt_clock->active_timers &&
!vm_clock->active_timers &&
!host_clock->active_timers) {
return;
int64_t nearest_delta_ns = qemu_next_alarm_deadline();
if (nearest_delta_ns < INT64_MAX) {
t->rearm(t, nearest_delta_ns);
}
nearest_delta_ns = qemu_next_alarm_deadline();
t->rearm(t, nearest_delta_ns);
}
/* TODO: MIN_TIMER_REARM_NS should be optimized */
@@ -763,11 +759,8 @@ int init_timer_alarm(void)
goto fail;
}
/* first event is at time 0 */
atexit(quit_timers);
t->pending = true;
alarm_timer = t;
return 0;
fail:
+86 -108
View File
@@ -14,12 +14,22 @@
#include <glib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include "qga/guest-agent-core.h"
#include "qga-qmp-commands.h"
#include "qerror.h"
#include "qemu-queue.h"
#include "host-utils.h"
#ifndef CONFIG_HAS_ENVIRON
#ifdef __APPLE__
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
#endif
#if defined(__linux__)
#include <mntent.h>
#include <linux/fs.h>
@@ -27,36 +37,17 @@
#include <arpa/inet.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/wait.h>
#if defined(__linux__) && defined(FIFREEZE)
#define CONFIG_FSFREEZE
#endif
#endif
#if defined(__linux__)
/* TODO: use this in place of all post-fork() fclose(std*) callers */
static void reopen_fd_to_null(int fd)
{
int nullfd;
nullfd = open("/dev/null", O_RDWR);
if (nullfd < 0) {
return;
}
dup2(nullfd, fd);
if (nullfd != fd) {
close(nullfd);
}
}
#endif /* defined(__linux__) */
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
{
int ret;
const char *shutdown_flag;
pid_t rpid, pid;
int status;
slog("guest-shutdown called, mode: %s", mode);
if (!has_mode || strcmp(mode, "powerdown") == 0) {
@@ -71,23 +62,30 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
return;
}
ret = fork();
if (ret == 0) {
pid = fork();
if (pid == 0) {
/* child, start the shutdown */
setsid();
fclose(stdin);
fclose(stdout);
fclose(stderr);
reopen_fd_to_null(0);
reopen_fd_to_null(1);
reopen_fd_to_null(2);
ret = execl("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
"hypervisor initiated shutdown", (char*)NULL);
if (ret) {
slog("guest-shutdown failed: %s", strerror(errno));
}
exit(!!ret);
} else if (ret < 0) {
error_set(err, QERR_UNDEFINED_ERROR);
execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
"hypervisor initiated shutdown", (char*)NULL, environ);
_exit(EXIT_FAILURE);
} else if (pid < 0) {
goto exit_err;
}
do {
rpid = waitpid(pid, &status, 0);
} while (rpid == -1 && errno == EINTR);
if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
return;
}
exit_err:
error_set(err, QERR_UNDEFINED_ERROR);
}
typedef struct GuestFileHandle {
@@ -347,7 +345,7 @@ static int guest_fsfreeze_build_mount_list(GuestFsfreezeMountList *mounts)
{
struct mntent *ment;
GuestFsfreezeMount *mount;
char const *mtab = MOUNTED;
char const *mtab = "/proc/self/mounts";
FILE *fp;
fp = setmntent(mtab, "r");
@@ -531,117 +529,88 @@ static void guest_fsfreeze_cleanup(void)
#define SUSPEND_SUPPORTED 0
#define SUSPEND_NOT_SUPPORTED 1
/**
* This function forks twice and the information about the mode support
* status is passed to the qemu-ga process via a pipe.
*
* This approach allows us to keep the way we reap terminated children
* in qemu-ga quite simple.
*/
static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
const char *sysfile_str, Error **err)
{
pid_t pid;
ssize_t ret;
char *pmutils_path;
int status, pipefds[2];
if (pipe(pipefds) < 0) {
error_set(err, QERR_UNDEFINED_ERROR);
return;
}
pid_t pid, rpid;
int status;
pmutils_path = g_find_program_in_path(pmutils_bin);
pid = fork();
if (!pid) {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &act, NULL);
char buf[32]; /* hopefully big enough */
ssize_t ret;
int fd;
setsid();
close(pipefds[0]);
reopen_fd_to_null(0);
reopen_fd_to_null(1);
reopen_fd_to_null(2);
pid = fork();
if (!pid) {
int fd;
char buf[32]; /* hopefully big enough */
if (pmutils_path) {
execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
}
if (pmutils_path) {
execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
}
/*
* If we get here either pm-utils is not installed or execle() has
* failed. Let's try the manual method if the caller wants it.
*/
if (!sysfile_str) {
_exit(SUSPEND_NOT_SUPPORTED);
}
fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
if (fd < 0) {
_exit(SUSPEND_NOT_SUPPORTED);
}
ret = read(fd, buf, sizeof(buf)-1);
if (ret <= 0) {
_exit(SUSPEND_NOT_SUPPORTED);
}
buf[ret] = '\0';
if (strstr(buf, sysfile_str)) {
_exit(SUSPEND_SUPPORTED);
}
/*
* If we get here either pm-utils is not installed or execle() has
* failed. Let's try the manual method if the caller wants it.
*/
if (!sysfile_str) {
_exit(SUSPEND_NOT_SUPPORTED);
}
if (pid > 0) {
wait(&status);
} else {
status = SUSPEND_NOT_SUPPORTED;
fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
if (fd < 0) {
_exit(SUSPEND_NOT_SUPPORTED);
}
ret = write(pipefds[1], &status, sizeof(status));
if (ret != sizeof(status)) {
_exit(EXIT_FAILURE);
ret = read(fd, buf, sizeof(buf)-1);
if (ret <= 0) {
_exit(SUSPEND_NOT_SUPPORTED);
}
buf[ret] = '\0';
if (strstr(buf, sysfile_str)) {
_exit(SUSPEND_SUPPORTED);
}
_exit(EXIT_SUCCESS);
_exit(SUSPEND_NOT_SUPPORTED);
}
close(pipefds[1]);
g_free(pmutils_path);
if (pid < 0) {
error_set(err, QERR_UNDEFINED_ERROR);
goto out;
goto undef_err;
}
ret = read(pipefds[0], &status, sizeof(status));
if (ret == sizeof(status) && WIFEXITED(status) &&
WEXITSTATUS(status) == SUSPEND_SUPPORTED) {
goto out;
do {
rpid = waitpid(pid, &status, 0);
} while (rpid == -1 && errno == EINTR);
if (rpid == pid && WIFEXITED(status)) {
switch (WEXITSTATUS(status)) {
case SUSPEND_SUPPORTED:
return;
case SUSPEND_NOT_SUPPORTED:
error_set(err, QERR_UNSUPPORTED);
return;
default:
goto undef_err;
}
}
error_set(err, QERR_UNSUPPORTED);
out:
close(pipefds[0]);
undef_err:
error_set(err, QERR_UNDEFINED_ERROR);
}
static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
Error **err)
{
pid_t pid;
char *pmutils_path;
pid_t rpid, pid;
int status;
pmutils_path = g_find_program_in_path(pmutils_bin);
@@ -683,9 +652,18 @@ static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
g_free(pmutils_path);
if (pid < 0) {
error_set(err, QERR_UNDEFINED_ERROR);
goto exit_err;
}
do {
rpid = waitpid(pid, &status, 0);
} while (rpid == -1 && errno == EINTR);
if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
return;
}
exit_err:
error_set(err, QERR_UNDEFINED_ERROR);
}
void qmp_guest_suspend_disk(Error **err)
+1 -1
View File
@@ -52,7 +52,7 @@ struct GuestAgentInfo *qmp_guest_info(Error **err)
GuestAgentCommandInfoList *cmd_info_list;
char **cmd_list_head, **cmd_list;
info->version = g_strdup(QGA_VERSION);
info->version = g_strdup(QEMU_VERSION);
cmd_list_head = cmd_list = qmp_get_command_list();
if (*cmd_list_head == NULL) {
+4 -1
View File
@@ -13,7 +13,6 @@
#include "qapi/qmp-core.h"
#include "qemu-common.h"
#define QGA_VERSION "1.0"
#define QGA_READ_COUNT_DEFAULT 4096
typedef struct GAState GAState;
@@ -35,3 +34,7 @@ void ga_set_response_delimited(GAState *s);
bool ga_is_frozen(GAState *s);
void ga_set_frozen(GAState *s);
void ga_unset_frozen(GAState *s);
#ifndef _WIN32
void reopen_fd_to_null(int fd);
#endif
+13
View File
@@ -124,6 +124,19 @@ int qlist_empty(const QList *qlist)
return QTAILQ_EMPTY(&qlist->head);
}
static void qlist_size_iter(QObject *obj, void *opaque)
{
size_t *count = opaque;
(*count)++;
}
size_t qlist_size(const QList *qlist)
{
size_t count = 0;
qlist_iter(qlist, qlist_size_iter, &count);
return count;
}
/**
* qobject_to_qlist(): Convert a QObject into a QList
*/
+1
View File
@@ -49,6 +49,7 @@ void qlist_iter(const QList *qlist,
QObject *qlist_pop(QList *qlist);
QObject *qlist_peek(QList *qlist);
int qlist_empty(const QList *qlist);
size_t qlist_size(const QList *qlist);
QList *qobject_to_qlist(const QObject *obj);
static inline const QListEntry *qlist_first(const QList *qlist)
+2 -3
View File
@@ -347,8 +347,6 @@ static void object_deinit(Object *obj, TypeImpl *type)
if (type_has_parent(type)) {
object_deinit(obj, type_get_parent(type));
}
object_unparent(obj);
}
void object_finalize(void *data)
@@ -385,8 +383,9 @@ Object *object_new(const char *typename)
void object_delete(Object *obj)
{
object_unparent(obj);
g_assert(obj->ref == 1);
object_unref(obj);
g_assert(obj->ref == 0);
g_free(obj);
}
+3
View File
@@ -337,6 +337,9 @@ static void readline_completion(ReadLineState *rs)
}
readline_show_prompt(rs);
}
for (i = 0; i < rs->nb_completions; i++) {
g_free(rs->completions[i]);
}
}
/* return true if command handled */
Loaded 100 of 137 files, more files were not shown because too many files have changed in this diff. Show more