Compare commits

...

84 Commits

Author SHA1 Message Date
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
74 changed files with 970 additions and 504 deletions

View File

@@ -1 +1 @@
1.0.92
1.1.0

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

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);
}

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] = {

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

37
block.c
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)

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 {
@@ -104,11 +108,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
@@ -161,12 +181,12 @@ iscsi_readv_writev_bh_cb(void *p)
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);
@@ -179,7 +199,7 @@ iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
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;
}
@@ -204,12 +224,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);
@@ -219,18 +236,44 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
acb->canceled = 0;
/* 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,12 +285,12 @@ 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);
@@ -258,7 +301,7 @@ iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
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;
}
@@ -277,8 +320,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;
@@ -303,16 +348,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;
}
@@ -490,6 +563,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 +668,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;

View File

@@ -762,7 +762,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 +807,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;
}
/*

View File

@@ -919,7 +919,8 @@ int qcow2_update_header(BlockDriverState *bs)
ret = sizeof(*header);
break;
default:
return -EINVAL;
ret = -EINVAL;
goto fail;
}
buf += ret;

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) {
@@ -495,7 +495,7 @@ static int connect_to_sdog(const char *addr, const char *port)
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 +510,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 +554,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 +566,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 +590,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 +602,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 +792,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 +801,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 +888,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 +909,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 +988,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 +996,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 +1046,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 +1054,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 +1090,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 +1109,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 +1122,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 +1151,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 +1166,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 +1189,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 +1249,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 +1284,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 +1293,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 +1306,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 +1401,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 +1413,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 +1485,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 +1628,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 +1747,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 +1755,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 +1763,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 +1773,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 +1793,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 +1811,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 +1828,6 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
closesocket(fd);
if (ret) {
ret = -ENOENT;
goto out;
}
@@ -1861,6 +1880,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 +1908,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 +1946,10 @@ out:
g_free(vdi_inuse);
if (ret < 0) {
return ret;
}
return found;
}
@@ -1940,8 +1965,7 @@ 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) {
@@ -1965,7 +1989,6 @@ 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;
}

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);

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);

19
configure vendored
View File

@@ -2831,6 +2831,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
@@ -3342,6 +3357,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)

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
======================

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);

17
exec.c
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

View File

@@ -299,6 +299,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
if (pc->no_hotplug) {
slot_free = false;
} else {
object_unparent(OBJECT(dev));
qdev_free(qdev);
}
}

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;

View File

@@ -179,12 +179,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 +203,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 +711,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 +1880,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);
}

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;

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,

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);

25
hw/pc.c
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
@@ -382,7 +383,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 +1098,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 +1127,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]) {

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);
}

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)

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(),
};

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;

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,

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);

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
}

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;

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);

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,20 +145,12 @@ 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;
int ret;
int status;
int status = VIRTIO_BLK_S_OK;
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;
}
/*
* We require at least one output segment each for the virtio_blk_outhdr
* and the SCSI command block.
@@ -172,21 +164,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 +228,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 +251,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
virtio_blk_req_complete(req, status);
g_free(req);
}
#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 +389,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);
@@ -509,6 +504,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 +533,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 +569,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 +600,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 +614,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 +626,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);
}

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

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);

View File

@@ -491,7 +491,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 +697,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 +725,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 +812,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),

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

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;
}

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;

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);

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 */

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;
}

View File

@@ -87,7 +87,10 @@ 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);
/* Until qdev_free includes a call to object_unparent, we call it here
*/
object_unparent(&d->qdev.parent_obj);
qdev_free(&d->qdev);
}
}

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;
}

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.

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:

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);

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;
}

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);
}

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);
}
@@ -428,9 +430,9 @@ 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:
@@ -488,8 +490,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 +729,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 +836,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;
}
}

View File

@@ -159,6 +159,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}.

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)

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) {

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

View File

@@ -291,14 +291,24 @@ out:
return ret
def option_value_matches(opt, val, cmd):
if opt in cmd and cmd[opt] == val:
return True
return False
def gen_registry(commands):
registry=""
push_indent()
for cmd in commands:
options = 'QCO_NO_OPTIONS'
if option_value_matches('success-response', 'no', cmd):
options = 'QCO_NO_SUCCESS_RESP'
registry += mcgen('''
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
''',
name=cmd['command'], c_name=c_fun(cmd['command']))
name=cmd['command'], c_name=c_fun(cmd['command']),
opts=options)
pop_indent()
ret = mcgen('''
static void qmp_init_marshal(void)

View File

@@ -34,18 +34,14 @@
#define _IP_H_
#ifdef HOST_WORDS_BIGENDIAN
# ifndef NTOHL
# define NTOHL(d)
# endif
# ifndef NTOHS
# define NTOHS(d)
# endif
# ifndef HTONL
# define HTONL(d)
# endif
# ifndef HTONS
# define HTONS(d)
# endif
# undef NTOHL
# undef NTOHS
# undef HTONL
# undef HTONS
# define NTOHL(d)
# define NTOHS(d)
# define HTONL(d)
# define HTONS(d)
#else
# ifndef NTOHL
# define NTOHL(d) ((d) = ntohl((d)))

View File

@@ -79,20 +79,23 @@ struct tcphdr {
#define TCPOPT_EOL 0
#define TCPOPT_NOP 1
#define TCPOPT_MAXSEG 2
#define TCPOLEN_MAXSEG 4
#define TCPOPT_WINDOW 3
#define TCPOLEN_WINDOW 3
#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
#define TCPOLEN_SACK_PERMITTED 2
#define TCPOPT_SACK 5 /* Experimental */
#define TCPOPT_TIMESTAMP 8
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
#define TCPOPT_TSTAMP_HDR \
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
#endif
#ifndef TCPOLEN_MAXSEG
#define TCPOLEN_MAXSEG 4
#define TCPOLEN_WINDOW 3
#define TCPOLEN_SACK_PERMITTED 2
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
#endif
/*
* Default maximum segment size for TCP.
* With an IP MSS of 576, this is 536,

View File

@@ -47,6 +47,7 @@ static const u_char tcp_outflags[TCP_NSTATES] = {
};
#undef MAX_TCPOPTLEN
#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
/*

View File

@@ -238,6 +238,8 @@ typedef struct x86_def_t {
/* Store the results of Centaur's CPUID instructions */
uint32_t ext4_features;
uint32_t xlevel2;
/* The feature bits on CPUID[EAX=7,ECX=0].EBX */
uint32_t cpuid_7_0_ebx_features;
} x86_def_t;
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -521,6 +523,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
x86_cpu_def->ext_features = ecx;
x86_cpu_def->features = edx;
if (kvm_enabled() && x86_cpu_def->level >= 7) {
x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
} else {
x86_cpu_def->cpuid_7_0_ebx_features = 0;
}
host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
x86_cpu_def->xlevel = eax;
@@ -1185,6 +1193,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
env->cpuid_kvm_features = def->kvm_features;
env->cpuid_svm_features = def->svm_features;
env->cpuid_ext4_features = def->ext4_features;
env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features;
env->cpuid_xlevel2 = def->xlevel2;
object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
"tsc-frequency", &error);
@@ -1451,13 +1460,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = 0;
break;
case 7:
if (kvm_enabled()) {
KVMState *s = env->kvm_state;
*eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX);
*ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX);
*ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX);
*edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX);
/* Structured Extended Feature Flags Enumeration Leaf */
if (count == 0) {
*eax = 0; /* Maximum ECX value for sub-leaves */
*ebx = env->cpuid_7_0_ebx; /* Feature flags */
*ecx = 0; /* Reserved */
*edx = 0; /* Reserved */
} else {
*eax = 0;
*ebx = 0;

View File

@@ -741,6 +741,8 @@ typedef struct CPUX86State {
/* Store the results of Centaur's CPUID instructions */
uint32_t cpuid_xlevel2;
uint32_t cpuid_ext4_features;
/* Flags from CPUID[EAX=7,ECX=0].EBX */
uint32_t cpuid_7_0_ebx;
/* MTRRs */
uint64_t mtrr_fixed[11];

View File

@@ -743,7 +743,7 @@ static void dec_bit(DisasContext *dc)
unsigned int op;
int mem_index = cpu_mmu_index(dc->env);
op = dc->ir & ((1 << 8) - 1);
op = dc->ir & ((1 << 9) - 1);
switch (op) {
case 0x21:
/* src. */
@@ -825,6 +825,16 @@ static void dec_bit(DisasContext *dc)
gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
}
break;
case 0x1e0:
/* swapb */
LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
break;
case 0x1e1:
/*swaph */
LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
break;
default:
cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
dc->pc, op, dc->rd, dc->ra, dc->rb);

View File

@@ -6099,7 +6099,7 @@ static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
tcg_gen_nor_i32(t0, t0, t1);
tcg_gen_nand_i32(t0, t0, t1);
tcg_temp_free_i32(t1);
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
@@ -6123,11 +6123,11 @@ static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
tcg_gen_or_i32(t0, t0, t1);
tcg_gen_and_i32(t0, t0, t1);
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
tcg_gen_or_i32(t0, t0, t1);
tcg_gen_and_i32(t0, t0, t1);
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
tcg_gen_nor_i32(t0, t0, t1);
tcg_gen_nand_i32(t0, t0, t1);
tcg_temp_free_i32(t1);
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);

View File

@@ -24,7 +24,11 @@
static uint8_t *tb_ret_addr;
#ifdef _CALL_DARWIN
#if defined _CALL_DARWIN || defined __APPLE__
#define TCG_TARGET_CALL_DARWIN
#endif
#ifdef TCG_TARGET_CALL_DARWIN
#define LINKAGE_AREA_SIZE 24
#define LR_OFFSET 8
#elif defined _CALL_AIX
@@ -99,7 +103,7 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R29,
TCG_REG_R30,
TCG_REG_R31,
#ifdef _CALL_DARWIN
#ifdef TCG_TARGET_CALL_DARWIN
TCG_REG_R2,
#endif
TCG_REG_R3,
@@ -110,7 +114,7 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R8,
TCG_REG_R9,
TCG_REG_R10,
#ifndef _CALL_DARWIN
#ifndef TCG_TARGET_CALL_DARWIN
TCG_REG_R11,
#endif
TCG_REG_R12,
@@ -140,7 +144,7 @@ static const int tcg_target_call_oarg_regs[2] = {
};
static const int tcg_target_callee_save_regs[] = {
#ifdef _CALL_DARWIN
#ifdef TCG_TARGET_CALL_DARWIN
TCG_REG_R11,
TCG_REG_R13,
#endif
@@ -1965,7 +1969,7 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_R0) |
#ifdef _CALL_DARWIN
#ifdef TCG_TARGET_CALL_DARWIN
(1 << TCG_REG_R2) |
#endif
(1 << TCG_REG_R3) |
@@ -1983,7 +1987,7 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
#ifndef _CALL_DARWIN
#ifndef TCG_TARGET_CALL_DARWIN
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
#endif
#ifdef _CALL_SYSV

View File

@@ -18,8 +18,8 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
# All QTests for now are POSIX-only, but the dependencies are
# really in libqtest, not in the testcases themselves.
check-qtest-i386-y = tests/rtc-test$(EXESUF)
check-qtest-i386-y = tests/fdc-test$(EXESUF)
check-qtest-i386-y += tests/rtc-test$(EXESUF)
check-qtest-x86_64-y = $(check-qtest-i386-y)
check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
@@ -68,7 +68,7 @@ tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marsh
tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o
tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
# QTest rules

View File

@@ -63,6 +63,12 @@ char test_image[] = "/tmp/qtest.XXXXXX";
#define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
#define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
static uint8_t base = 0x70;
enum {
CMOS_FLOPPY = 0x10,
};
static void floppy_send(uint8_t byte)
{
uint8_t msr;
@@ -108,16 +114,59 @@ static void send_step_pulse(void)
cyl = (cyl + 1) % 4;
}
static uint8_t cmos_read(uint8_t reg)
{
outb(base + 0, reg);
return inb(base + 1);
}
static void test_cmos(void)
{
uint8_t cmos;
cmos = cmos_read(CMOS_FLOPPY);
g_assert(cmos == 0x40);
}
static void test_no_media_on_start(void)
{
uint8_t dir;
/* Media changed bit must be set all time after start if there is
* no media in drive. */
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
send_step_pulse();
send_step_pulse();
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
}
static void test_media_change(void)
{
uint8_t dir;
/* Media changed bit must be up-to-date after step pulse. Do two SEEKs
* because we may already happen to be on the right cylinder initially. */
send_step_pulse();
/* Insert media in drive. DSKCHK should not be reset until a step pulse
* is sent. */
qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
"'target': '%s' }}", test_image);
qmp(""); /* ignore event (FIXME open -> open transition?!) */
qmp(""); /* ignore event */
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
send_step_pulse();
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_clear(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_clear(dir, DSKCHG);
/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
* reset the bit. */
@@ -134,24 +183,6 @@ static void test_media_change(void)
assert_bit_set(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
/* And then insert it again. DSKCHK should not be reset until a step pulse
* is sent. */
qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
"'target': '%s' }}", test_image);
qmp(""); /* ignore event (FIXME open -> open transition?!) */
qmp(""); /* ignore event */
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
send_step_pulse();
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_clear(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_clear(dir, DSKCHG);
}
int main(int argc, char **argv)
@@ -177,12 +208,12 @@ int main(int argc, char **argv)
/* Run the tests */
g_test_init(&argc, &argv, NULL);
cmdline = g_strdup_printf("-vnc none "
"-drive file=%s,if=floppy,cache=writeback ",
test_image);
cmdline = g_strdup_printf("-vnc none ");
qtest_start(cmdline);
qtest_irq_intercept_in(global_qtest, "ioapic");
qtest_add_func("/fdc/cmos", test_cmos);
qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start);
qtest_add_func("/fdc/media_change", test_media_change);
ret = g_test_run();

View File

@@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
_supported_fmt generic
_supported_fmt qcow2
_supported_proto generic
_supported_os Linux

View File

@@ -602,9 +602,9 @@ escc_kbd_command(int val) "Command %d"
escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
# block/iscsi.c
iscsi_aio_write10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
iscsi_aio_write16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
iscsi_aio_read10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
# hw/esp.c

View File

@@ -879,7 +879,8 @@ int main (int argc, const char * argv[]) {
!strcmp(opt, "-vnc") ||
!strcmp(opt, "-nographic") ||
!strcmp(opt, "-version") ||
!strcmp(opt, "-curses")) {
!strcmp(opt, "-curses") ||
!strcmp(opt, "-qtest")) {
return qemu_main(gArgc, gArgv, *_NSGetEnviron());
}
}

View File

@@ -2849,6 +2849,10 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires)
{
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
if (!vs) {
return -EINVAL;
}
vs->expires = expires;
return 0;
}

View File

@@ -603,6 +603,10 @@ void xen_vcpu_init(void)
qemu_register_reset(xen_reset_vcpu, first_cpu);
xen_reset_vcpu(first_cpu);
}
/* if rtc_clock is left to default (host_clock), disable it */
if (rtc_clock == host_clock) {
qemu_clock_enable(rtc_clock, false);
}
}
/* get the ioreq packets from share mem */
@@ -856,7 +860,7 @@ static void cpu_handle_ioreq(void *opaque)
"data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
req->state, req->data_is_ptr, req->addr,
req->data, req->count, req->size);
destroy_hvm_domain();
destroy_hvm_domain(false);
return;
}
@@ -870,10 +874,11 @@ static void cpu_handle_ioreq(void *opaque)
*/
if (runstate_is_running()) {
if (qemu_shutdown_requested_get()) {
destroy_hvm_domain();
destroy_hvm_domain(false);
}
if (qemu_reset_requested_get()) {
qemu_system_reset(VMRESET_REPORT);
destroy_hvm_domain(true);
}
}
@@ -1159,7 +1164,7 @@ int xen_hvm_init(void)
return 0;
}
void destroy_hvm_domain(void)
void destroy_hvm_domain(bool reboot)
{
XenXC xc_handle;
int sts;
@@ -1168,12 +1173,15 @@ void destroy_hvm_domain(void)
if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
fprintf(stderr, "Cannot acquire xenctrl handle\n");
} else {
sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff);
sts = xc_domain_shutdown(xc_handle, xen_domid,
reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
if (sts != 0) {
fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, "
"sts %d, %s\n", sts, strerror(errno));
fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
"sts %d, %s\n", reboot ? "reboot" : "poweroff",
sts, strerror(errno));
} else {
fprintf(stderr, "Issued domain %d poweroff\n", xen_domid);
fprintf(stderr, "Issued domain %d %s\n", xen_domid,
reboot ? "reboot" : "poweroff");
}
xc_interface_close(xc_handle);
}