Compare commits

...
156 Commits
Author SHA1 Message Date
Michael Roth adba377ea7 Update VERSION for 1.7.2 release
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-21 17:42:15 -05:00
Dr. David Alan Gilbert 8fde73e138 Allow mismatched virtio config-len
Commit 'virtio: validate config_len on load' restricted config_len
loaded from the wire to match the config_len that the device had.

Unfortunately, there are cases where this isn't true, the one
we found it on was the wce addition in virtio-blk.

Allow mismatched config-lengths:
   *) If the version on the wire is shorter then fine
   *) If the version on the wire is longer, load what we have space
      for and skip the rest.

(This is mst@redhat.com's rework of what I originally posted)

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 2f5732e964)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Le Tan 14d9fb02c2 pci: assign devfn to pci_dev before calling pci_device_iommu_address_space()
In function do_pci_register_device() in file hw/pci/pci.c, move the assignment
of pci_dev->devfn to the position before the call to
pci_device_iommu_address_space(pci_dev) which will use the value of
pci_dev->devfn.

Fixes: 9eda7d373e
    pci: Introduce helper to retrieve a PCI device's DMA address space

Cc: qemu-stable@nongnu.org
Signed-off-by: Le Tan <tamlokveer@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit efc8188e93)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Andreas Färber 53e4895c98 hw: Fix qemu_allocate_irqs() leaks
Replace qemu_allocate_irqs(foo, bar, 1)[0]
with qemu_allocate_irq(foo, bar, 0).

This avoids leaking the dereferenced qemu_irq *.

Cc: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andreas Färber <afaerber@suse.de>
[PC Changes:
 * Applied change to instance in sh4/sh7750.c
]
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Kirill Batuzov <batuzovk@ispras.ru>
[AF: Fix IRQ index in sh4/sh7750.c]
Cc: qemu-stable@nongnu.org
Signed-off-by: Andreas Färber <afaerber@suse.de>

(cherry picked from commit f3c7d0389f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Andreas Färber bb485bf2e8 sdhci: Fix misuse of qemu_free_irqs()
It does a g_free() on the pointer, so don't pass a local &foo reference.

Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit 127a4e1a51)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Markus Armbruster 02835d5744 vnc: Fix tight_detect_smooth_image() for lossless case
VncTight member uint8_t quality is either (uint8_t)-1 for lossless or
less than 10 for lossy.

tight_detect_smooth_image() first promotes it to int, then compares
with -1.  Always unequal, so we always execute the lossy code.  Reads
beyond tight_conf[] and returns crap when quality is actually
lossless.

Compare to (uint8_t)-1 instead, like we do elsewhere.

Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 2e7bcdb99a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Michael Roth 41ee91810e qapi: zero-initialize all QMP command parameters
In general QMP command parameter values are specified by consumers of the
QMP/HMP interface, but in the case of optional parameters these values may
be left uninitialized.

It is considered a bug for code to make use of optional parameters that have
not been flagged as being present by the marshalling code (via corresponding
has_<parameter> parameter), however our marshalling code will still pass
these uninitialized values on to the corresponding QMP function (to then
be ignored). Some compilers (clang in particular) consider this unsafe
however, and generate warnings as a result. As reported by Peter Maydell:

  This is something clang's -fsanitize=undefined spotted. The
  code generated by qapi-commands.py in qmp-marshal.c for
  qmp_marshal_* functions where there are some optional
  arguments looks like this:

      bool has_force = false;
      bool force;

      mi = qmp_input_visitor_new_strict(QOBJECT(args));
      v = qmp_input_get_visitor(mi);
      visit_type_str(v, &device, "device", errp);
      visit_start_optional(v, &has_force, "force", errp);
      if (has_force) {
          visit_type_bool(v, &force, "force", errp);
      }
      visit_end_optional(v, errp);
      qmp_input_visitor_cleanup(mi);

      if (error_is_set(errp)) {
          goto out;
      }
      qmp_eject(device, has_force, force, errp);

  In the case where has_force is false, we never initialize
  force, but then we use it by passing it to qmp_eject.
  I imagine we don't then actually use the value, but clang
  complains in particular for 'bool' variables because the value
  that ends up being loaded from memory for 'force' is not either
  0 or 1 (being uninitialized stack contents).

Fix this by initializing all QMP command parameters to {0} in the
marshalling code prior to passing them on to the QMP functions.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit fc13d93726)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Hani Benhabiles 0c60b74a0c nbd: Shutdown socket before closing.
This forces finishing data sending to client before closing the socket like in
exports listing or replying with NBD_REP_ERR_UNSUP cases.

Signed-off-by: Hani Benhabiles <kroosec@gmail.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 27e5eae457)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:02 -05:00
Hani Benhabiles 25351f6a9a nbd: Close socket on negotiation failure.
Otherwise, the nbd client may hang waiting for the server response.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 36af599417)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Hani Benhabiles cf392d2c7c nbd: Don't validate from and len in NBD_CMD_DISC.
These values aren't used in this case.

Currently, the from field in the request sent by the nbd kernel module leading
to a false error message when ending the connection with the client.

$ qemu-nbd some.img -v
// After nbd-client -d /dev/nbd0
nbd.c:nbd_trip():L1031: From: 18446744073709551104, Len: 0, Size: 20971520,
Offset: 0
nbd.c:nbd_trip():L1032: requested operation past EOF--bad client?
nbd.c:nbd_receive_request():L638: read failed

Signed-off-by: Hani Benhabiles <kroosec@gmail.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 8c5d1abbb7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Hani Benhabiles 3c3d8c6d19 nbd: Don't export a block device with no medium.
The device is exported with erroneous values and can't be read.

Before the patch:
$ sudo nbd-client localhost -p 10809 /dev/nbd0 -name floppy0
Negotiation: ..size = 17592186044415MB
bs=1024, sz=18446744073709547520 bytes

$ sudo mount /dev/nbd0 /mnt/tmp/
mount: block device /dev/nbd0 is write-protected, mounting read-only
mount: /dev/nbd0: can't read superblock

After the patch:
(qemu) nbd_server_add ide0-hd0
(qemu) nbd_server_add floppy0
Device 'floppy0' has no medium

Signed-off-by: Hani Benhabiles <kroosec@gmail.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 60fe4fac22)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Alexander Graf 62c754e67c virtio-serial: don't migrate the config space
The device configuration is set at realize time and never changes. It
should not be migrated as it is done today. For the sake of compatibility,
let's just skip them at load time.

Signed-off-by: Alexander Graf <agraf@suse.de>
[ added missing casts to uint16_t *,
  added From, SoB and commit message,
  Greg Kurz <gkurz@linux.vnet.ibm.com> ]
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

(cherry picked from commit e38e943a1f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Cédric Le Goater 0fd14a5564 virtio-net: byteswap virtio-net header
TCP connectivity fails when the guest has a different endianness.
The packets are silently dropped on the host by the tap backend
when they are read from user space because the endianness of the
virtio-net header is in the wrong order. These lines may appear
in the guest console:

[  454.709327] skbuff: bad partial csum: csum=8704/4096 len=74
[  455.702554] skbuff: bad partial csum: csum=8704/4096 len=74

The issue that got first spotted with a ppc64le PowerKVM guest,
but it also exists for the less common case of a x86_64 guest run
by a big-endian ppc64 TCG hypervisor.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
[ Ported from PowerKVM,
  Greg Kurz <gkurz@linux.vnet.ibm.com> ]
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

(cherry picked from commit 032a74a1c0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Eduardo Habkost 7a3cd5ab40 target-i386: Filter FEAT_7_0_EBX TCG features too
The TCG_7_0_EBX_FEATURES macro was defined but never used (it even had a
typo that was never noticed). Make the existing TCG feature filtering
code use it.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit d0a70f46fa)

Conflicts:
	target-i386/cpu.c

*fixed simple context mismatch

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Peter Maydell 8a93721d04 coroutine-win32.c: Add noinline attribute to work around gcc bug
A gcc codegen bug in x86_64-w64-mingw32-gcc (GCC) 4.6.3 means that
non-debug builds of QEMU for Windows tend to assert when using
coroutines. Work around this by marking qemu_coroutine_switch
as noinline.

If we allow gcc to inline qemu_coroutine_switch into
coroutine_trampoline, then it hoists the code to get the
address of the TLS variable "current" out of the while() loop.
This is an invalid transformation because the SwitchToFiber()
call may be called when running thread A but return in thread B,
and so we might be in a different thread context each time
round the loop. This can happen quite often.  Typically.
a coroutine is started when a VCPU thread does bdrv_aio_readv:

     VCPU thread

     main VCPU thread coroutine      I/O coroutine
        bdrv_aio_readv ----->
                                     start I/O operation
                                       thread_pool_submit_co
                       <------------ yields
        back to emulation

Then I/O finishes and the thread-pool.c event notifier triggers in
the I/O thread.  event_notifier_ready calls thread_pool_co_cb, and
the I/O coroutine now restarts *in another thread*:

     iothread

     main iothread coroutine         I/O coroutine (formerly in VCPU thread)
        event_notifier_ready
          thread_pool_co_cb ----->   current = I/O coroutine;
                                     call AIO callback

But on Win32, because of the bug, the "current" being set here the
current coroutine of the VCPU thread, not the iothread.

noinline is a good-enough workaround, and quite unlikely to break in
the future.

(Thanks to Paolo Bonzini for assistance in diagnosing the problem
and providing the detailed example/ascii art quoted above.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1403535303-14939-1-git-send-email-peter.maydell@linaro.org
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
(cherry picked from commit ff4873cb8c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Alexander Graf b47506f55c KVM: Fix GSI number space limit
KVM tells us the number of GSIs it can handle inside the kernel. That value is
basically KVM_MAX_IRQ_ROUTES. However when we try to set the GSI mapping table,
it checks for

    r = -EINVAL;
    if (routing.nr >= KVM_MAX_IRQ_ROUTES)
        goto out;

erroring out even when we're only using all of the GSIs. To make sure we never
hit that limit, let's reduce the number of GSIs we get from KVM by one.

Cc: qemu-stable@nongnu.org
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 00008418aa)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Hani Benhabiles f0c609dede usb: Fix usb-bt-dongle initialization.
Due to an incomplete initialization, adding a usb-bt-dongle device through HMP
or QMP will cause a segmentation fault.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit c340a284f3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Michael S. Tsirkin 79bd7781dd vhost: fix resource leak in error handling
vhost_verify_ring_mappings leaks mappings on error.
Fix this up.

Cc: qemu-stable@nongnu.org
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

(cherry picked from commit 8617343faa)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Ulrich Obergfell 36afdba00a scsi-disk: fix bug in scsi_block_new_request() introduced by commit 137745c
This patch fixes a bug in scsi_block_new_request() that was introduced
by commit 137745c5c6. If the host cache
is used - i.e. if BDRV_O_NOCACHE is _not_ set - the 'break' statement
needs to be executed to 'fall back' to SG_IO.

Cc: qemu-stable@nongnu.org
Signed-off-by: Ulrich Obergfell <uobergfe@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 2fe5a9f73b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:01 -05:00
Michael R. Hines 63bf1e0ea5 rdma: bug fixes
1. Fix small memory leak in parsing inet address from command line in data_init()
2. Fix ibv_post_send() return value check and pass error code back up correctly.
3. Fix rdma_destroy_qp() segfault after failure to connect to destination.

Reported-by: frank.yangjie@gmail.com
Reported-by: dgilbert@redhat.com
Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit e325b49a32)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:00 -05:00
Gonglei 23dbc56d22 qga: Fix handle fd leak in acquire_privilege()
token should be closed in all conditions.
So move CloseHandle(token) to "out" branch.

Signed-off-by: Wang Rui <moon.wangrui@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
(cherry picked from commit 374044f08f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-15 19:28:00 -05:00
Stefan Hajnoczi 4041945624 aio: fix qemu_bh_schedule() bh->ctx race condition
qemu_bh_schedule() is supposed to be thread-safe at least the first time
it is called.  Unfortunately this is not quite true:

  bh->scheduled = 1;
  aio_notify(bh->ctx);

Since another thread may run the BH callback once it has been scheduled,
there is a race condition if the callback frees the BH before
aio_notify(bh->ctx) has a chance to run.

Reported-by: Stefan Priebe <s.priebe@profihost.ag>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Stefan Priebe <s.priebe@profihost.ag>
(cherry picked from commit 924fe1293c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:30 -05:00
Cornelia Huck 5019106862 s390x/css: handle emw correctly for tsch
We should not try to store the emw portion of the irb if extended
measurements are not applicable. In particular, we should not surprise
the guest by storing a larger irb if it did not enable extended
measurements.

Cc: qemu-stable@nongnu.org
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit f068d320de)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:30 -05:00
Peter Maydell f784615221 target-arm: Fix errors in writes to generic timer control registers
The code for handling writes to the generic timer control registers
had several bugs:
 * ISTATUS (bit 2) is read-only but we forced it to zero on any write
 * the check for "was IMASK (bit 1) toggled?" incorrectly used '&' where
   it should be '^'
 * the handling of IMASK was inverted: we should set the IRQ if
   ISTATUS is set and IMASK is clear, not if both are set

The combination of these bugs meant that when running a Linux guest
that uses the generic timers we would fairly quickly end up either
forgetting that the timer output should be asserted, or failing to
set the IRQ when the timer was unmasked. The result is that the guest
never gets any more timer interrupts.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401803208-1281-1-git-send-email-peter.maydell@linaro.org
Cc: qemu-stable@nongnu.org
(cherry picked from commit d3afacc726)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:30 -05:00
Richard Henderson e34feec264 tcg-i386: Fix win64 qemu store
The first non-register argument isn't placed at offset 0.

Cc: qemu-stable@nongnu.org
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
(cherry picked from commit 0b91966730)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:30 -05:00
Peter Maydell ccb08f53d5 linux-user: Don't overrun guest buffer in sched_getaffinity
If the guest's "long" type is smaller than the host's, then
our sched_getaffinity wrapper needs to round the buffer size
up to a multiple of the host sizeof(long). This means that when
we copy the data back from the host buffer to the guest's
buffer there might be more than we can fit. Rather than
overflowing the guest's buffer, handle this case by returning
EINVAL or ignoring the unused extra space, as appropriate.

Note that only guests using the syscall interface directly might
run into this bug -- the glibc wrappers around it will always
use a buffer whose size is a multiple of 8 regardless of guest
architecture.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
(cherry picked from commit be3bd286bc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:30 -05:00
Markus Armbruster cb34d1e9e9 qemu-img: Plug memory leak in convert command
Introduced in commit 661a0f7.  Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit bb9cd2ee99)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster df9c108acd block/sheepdog: Plug memory leak in sd_snapshot_create()
Has always been leaky.  Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 2df5fee2db)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster d3cd48a85f block/vvfat: Plug memory leak in read_directory()
Has always been leaky.  Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit b122c3b6d0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster 501da9369c block/vvfat: Plug memory leak in check_directory_consistency()
On error path.  Introduced in commit a046433a.  Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 6262bbd363)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster 7267e51b32 block/qapi: Plug memory leak in dump_qobject() case QTYPE_QERROR
Introduced in commit a8d8ecb.  Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit f25391c2a6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster d1775fe94a blockdev: Plug memory leak in drive_init()
bs_opts is leaked on all paths from its qdev_new() that don't got
through blockdev_init().  Add the missing QDECREF(), and zap bs_opts
after blockdev_init(), so the new QDECREF() does nothing when we go
through blockdev_init().

Leak introduced in commit f298d07.  Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 3cb0e25c4b)

Conflicts:
	blockdev.c

*fixed trivial context mismatch due to blockdev_init signature change

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster d2b987479a blockdev: Plug memory leak in blockdev_init()
blockdev_init() leaks bs_opts when qemu_opts_create() fails, i.e. when
the ID is bad.  Missed in commit ec9c10d.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 6376f95223)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Stefan Weil c2fb0f2870 cputlb: Fix regression with TCG interpreter (bug 1310324)
Commit 0f842f8a24 replaced GETPC_EXT() which
was derived from GETPC() by GETRA_EXT() without fixing cputlb.c. A later
patch replaced GETRA_EXT() by GETRA() in exec/softmmu_template.h which
is included in cputlb.c.

The TCG interpreter failed because the values returned by GETRA() were no
longer explicitly set to 0. The redefinition of GETRA() introduced here
fixes this.

In addition, GETPC_ADJ which is also used in exec/softmmu_template.h is
set to 0. Both changes reduce the compiled code size for cputlb.c by more
than 100 bytes, so the normal TCG without interpreter also profits from
the reduced code size and slightly faster code.

Cc: qemu-stable@nongnu.org
Reported-by: Giovanni Mascellani <gio@debian.org>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 7e4e88656c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Max Filippov 26b51027f9 target-xtensa: fix cross-page jumps/calls at the end of TB
Use tb->pc instead of dc->pc to check for cross-page jumps.
When TB translation stops at the page boundary dc->pc points to the next
page allowing chaining to TBs in it, which is wrong.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
(cherry picked from commit 433d33c555)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Markus Armbruster 44564f8226 virtio-scsi: Plug memory leak on virtio_scsi_push_event() error path
Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 91e7fcca47)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:29 -05:00
Kevin Wolf 2f1eb049df qcow1: Stricter backing file length check
Like qcow2 since commit 6d33e8e7, error out on invalid lengths instead
of silently truncating them to 1023.

Also don't rely on bdrv_pread() catching integer overflows that make len
negative, but use unsigned variables in the first place.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
(cherry picked from commit d66e5cee00)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf b53d8665a2 qcow1: Validate image size (CVE-2014-0223)
A huge image size could cause s->l1_size to overflow. Make sure that
images never require a L1 table larger than what fits in s->l1_size.

This cannot only cause unbounded allocations, but also the allocation of
a too small L1 table, resulting in out-of-bounds array accesses (both
reads and writes).

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 46485de0cb)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf 8b17eb6e6c qcow1: Validate L2 table size (CVE-2014-0222)
Too large L2 table sizes cause unbounded allocations. Images actually
created by qemu-img only have 512 byte or 4k L2 tables.

To keep things consistent with cluster sizes, allow ranges between 512
bytes and 64k (in fact, down to 1 entry = 8 bytes is technically
working, but L2 table sizes smaller than a cluster don't make a lot of
sense).

This also means that the number of bytes on the virtual disk that are
described by the same L2 table is limited to at most 8k * 64k or 2^29,
preventively avoiding any integer overflows.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
(cherry picked from commit 42eb58179b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf e6c55cf7c2 qcow1: Check maximum cluster size
Huge values for header.cluster_bits cause unbounded allocations (e.g.
for s->cluster_cache) and crash qemu this way. Less huge values may
survive those allocations, but can cause integer overflows later on.

The only cluster sizes that qemu can create are 4k (for standalone
images) and 512 (for images with backing files), so we can limit it
to 64k.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
(cherry picked from commit 7159a45b2b)

Conflicts:
	block/qcow.c
	tests/qemu-iotests/group

*removed mismatch due to error msgs from upstream's b6d5066d
*removed context from upstream block tests

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf 41819e90af qcow1: Make padding in the header explicit
We were relying on all compilers inserting the same padding in the
header struct that is used for the on-disk format. Let's not do that.
Mark the struct as packed and insert an explicit padding field for
compatibility.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
(cherry picked from commit ea54feff58)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf 97a0e27e71 parallels: Sanity check for s->tracks (CVE-2014-0142)
This avoids a possible division by zero.

Convert s->tracks to unsigned as well because it feels better than
surviving just because the results of calculations with s->tracks are
converted to unsigned anyway.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 9302e863aa)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf 750336bc90 parallels: Fix catalog size integer overflow (CVE-2014-0143)
The first test case would cause a huge memory allocation, leading to a
qemu abort; the second one to a too small malloc() for the catalog
(smaller than s->catalog_size), which causes a read-only out-of-bounds
array access and on big endian hosts an endianess conversion for an
undefined memory area.

The sample image used here is not an original Parallels image. It was
created using an hexeditor on the basis of the struct that qemu uses.
Good enough for trying to crash the driver, but not for ensuring
compatibility.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit afbcc40bee)

Conflicts:
	tests/qemu-iotests/group

*fixed mismatches in group file

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf cfa8008cc0 qcow2: Check maximum L1 size in qcow2_snapshot_load_tmp() (CVE-2014-0143)
This avoids an unbounded allocation.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 6a83f8b5be)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:31:28 -05:00
Kevin Wolf d99c4e2d85 qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145)
For the L1 table to loaded for an internal snapshot, the code allocated
only enough memory to hold the currently active L1 table. If the
snapshot's L1 table is actually larger than the current one, this leads
to a buffer overflow.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit c05e4667be)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:14 -05:00
Kevin Wolf 641c3ec442 qcow2: Fix copy_sectors() with VM state
bs->total_sectors is not the highest possible sector number that could
be involved in a copy on write operation: VM state is after the end of
the virtual disk. This resulted in wrong values for the number of
sectors to be copied (n).

The code that checks for the end of the image isn't required any more
because the code hasn't been calling the block layer's bdrv_read() for a
long time; instead, it directly calls qcow2_readv(), which doesn't error
out on VM state sector numbers.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 6b7d4c5558)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:14 -05:00
Kevin Wolf c2c52728f5 qcow2: Fix NULL dereference in qcow2_open() error path (CVE-2014-0146)
The qcow2 code assumes that s->snapshots is non-NULL if s->nb_snapshots
!= 0. By having the initialisation of both fields separated in
qcow2_open(), any error occuring in between would cause the error path
to dereference NULL in qcow2_free_snapshots() if the image had any
snapshots.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 11b128f406)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:14 -05:00
Kevin Wolf 759d38652a block: Limit request size (CVE-2014-0143)
Limiting the size of a single request to INT_MAX not only fixes a
direct integer overflow in bdrv_check_request() (which would only
trigger bad behaviour with ridiculously huge images, as in close to
2^64 bytes), but can also prevent overflows in all block drivers.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 8f4754ede5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi b6f7fbdd1d dmg: prevent chunk buffer overflow (CVE-2014-0145)
Both compressed and uncompressed I/O is buffered.  dmg_open() calculates
the maximum buffer size needed from the metadata in the image file.

There is currently a buffer overflow since ->lengths[] is accounted
against the maximum compressed buffer size but actually uses the
uncompressed buffer:

  switch (s->types[chunk]) {
  case 1: /* copy */
      ret = bdrv_pread(bs->file, s->offsets[chunk],
                       s->uncompressed_chunk, s->lengths[chunk]);

We must account against the maximum uncompressed buffer size for type=1
chunks.

This patch fixes the maximum buffer size calculation to take into
account the chunk type.  It is critical that we update the correct
maximum since there are two buffers ->compressed_chunk and
->uncompressed_chunk.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit f0dce23475)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi d400b5dc4a dmg: use uint64_t consistently for sectors and lengths
The DMG metadata is stored as uint64_t, so use the same type for
sector_num.  int was a particularly poor choice since it is only 32-bit
and would truncate large values.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 686d7148ec)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi 758c4840c6 dmg: sanitize chunk length and sectorcount (CVE-2014-0145)
Chunk length and sectorcount are used for decompression buffers as well
as the bdrv_pread() count argument.  Ensure that they have reasonable
values so neither memory allocation nor conversion from uint64_t to int
will cause problems.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit c165f77580)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi 4b50bd7357 dmg: use appropriate types when reading chunks
Use the right types instead of signed int:

  size_t new_size;

  This is a byte count for g_realloc() that is calculated from uint32_t
  and size_t values.

  uint32_t chunk_count;

  Use the same type as s->n_chunks, which is used together with
  chunk_count.

This patch is a cleanup and does not fix bugs.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit eb71803b04)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi 4ee5b9c8cb dmg: drop broken bdrv_pread() loop
It is not necessary to check errno for EINTR and the block layer does
not produce short reads.  Therefore we can drop the loop that attempts
to read a compressed chunk.

The loop is buggy because it incorrectly adds the transferred bytes
twice:

  do {
      ret = bdrv_pread(...);
      i += ret;
  } while (ret >= 0 && ret + i < s->lengths[chunk]);

Luckily we can drop the loop completely and perform a single
bdrv_pread().

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit b404bf8542)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi ad08cae75c dmg: prevent out-of-bounds array access on terminator
When a terminator is reached the base for offsets and sectors is stored.
The following records that are processed will use this base value.

If the first record we encounter is a terminator, then calculating the
base values would result in out-of-bounds array accesses.  Don't do
that.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 73ed27ec28)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Stefan Hajnoczi dedf4a5f79 dmg: coding style and indentation cleanup
Clean up the mix of tabs and spaces, as well as the coding style
violations in block/dmg.c.  There are no semantic changes since this
patch simply reformats the code.

This patch is necessary before we can make meaningful changes to this
file, due to the inconsistent formatting and confusing indentation.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 2c1885adcf)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Kevin Wolf 3c6347ce8c qcow2: Fix new L1 table size check (CVE-2014-0143)
The size in bytes is assigned to an int later, so check that instead of
the number of entries.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit cab60de930)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Kevin Wolf e1c8770f56 qcow2: Protect against some integer overflows in bdrv_check
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 0abe740f1d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Kevin Wolf c874837475 qcow2: Fix types in qcow2_alloc_clusters and alloc_clusters_noref
In order to avoid integer overflows.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit bb572aefbd)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Kevin Wolf 610ab7bd3d qcow2: Check new refcount table size on growth
If the size becomes larger than what qcow2_open() would accept, fail the
growing operation.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 2b5d5953ee)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:13 -05:00
Kevin Wolf 7a6088c870 qcow2: Avoid integer overflow in get_refcount (CVE-2014-0143)
This ensures that the checks catch all invalid cluster indexes
instead of returning the refcount of a wrong cluster.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit db8a31d11d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf ffa3ab0217 qcow2: Don't rely on free_cluster_index in alloc_refcount_block() (CVE-2014-0147)
free_cluster_index is only correct if update_refcount() was called from
an allocation function, and even there it's brittle because it's used to
protect unfinished allocations which still have a refcount of 0 - if it
moves in the wrong place, the unfinished allocation can be corrupted.

So not using it any more seems to be a good idea. Instead, use the
first requested cluster to do the calculations. Return -EAGAIN if
unfinished allocations could become invalid and let the caller restart
its search for some free clusters.

The context of creating a snapsnot is one situation where
update_refcount() is called outside of a cluster allocation. For this
case, the change fixes a buffer overflow if a cluster is referenced in
an L2 table that cannot be represented by an existing refcount block.
(new_table[refcount_table_index] was out of bounds)

[Bump the qemu-iotests 026 refblock_alloc.write leak count from 10 to
11.
--Stefan]

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit b106ad9185)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf aeba41549d qcow2: Zero-initialise first cluster for new images
Strictly speaking, this is only required for has_zero_init() == false,
but it's easy enough to just do a cluster-aligned write that is padded
with zeros after the header.

This fixes that after 'qemu-img create' header extensions are attempted
to be parsed that are really just random leftover data.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit f8413b3c23)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Hu Tao 2f59c95f16 qcow2: fix offset overflow in qcow2_alloc_clusters_at()
When cluster size is big enough it can lead to an offset overflow
in qcow2_alloc_clusters_at(). This patch fixes it.

The allocation is stopped each time at L2 table boundary
(see handle_alloc()), so the possible maximum bytes could be

  2^(cluster_bits - 3 + cluster_bits)

cluster_bits - 3 is used to compute the number of entry by L2
and the additional cluster_bits is to take into account each
clusters referenced by the L2 entries.

so int is safe for cluster_bits<=17, unsafe otherwise.

Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 33304ec9fa)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf 5ba151f4dc qcow2: Fix backing file name length check
len could become negative and would pass the check then. Nothing bad
happened because bdrv_pread() happens to return an error for negative
length values, but make variables for sizes unsigned anyway.

This patch also changes the behaviour to error out on invalid lengths
instead of silently truncating it to 1023.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 6d33e8e7dc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf cd598d4161 qcow2: Validate active L1 table offset and size (CVE-2014-0144)
This avoids an unbounded allocation.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 2d51c32c4b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf 04bc6981ca qcow2: Validate snapshot table offset/size (CVE-2014-0144)
This avoid unbounded memory allocation and fixes a potential buffer
overflow on 32 bit hosts.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit ce48f2f441)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf 818ce8487e qcow2: Validate refcount table offset
The end of the refcount table must not exceed INT64_MAX so that integer
overflows are avoided.

Also check for misaligned refcount table. Such images are invalid and
probably the result of data corruption. Error out to avoid further
corruption.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 8c7de28305)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf f6027f805b qcow2: Check refcount table size (CVE-2014-0144)
Limit the in-memory reference count table size to 8 MB, it's enough in
practice. This fixes an unbounded allocation as well as a buffer
overflow in qcow2_refcount_init().

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 5dab2faddc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf 6f6db0c7af qcow2: Check backing_file_offset (CVE-2014-0144)
Header, header extension and the backing file name must all be stored in
the first cluster. Setting the backing file to a much higher value
allowed header extensions to become much bigger than we want them to be
(unbounded allocation).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit a1b3955c94)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Kevin Wolf 665f3ad58f qcow2: Check header_length (CVE-2014-0144)
This fixes an unbounded allocation for s->unknown_header_fields.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 24342f2cae)

Conflicts:
	tests/qemu-iotests/group

*fixed context mismatches in group file

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:12 -05:00
Fam Zheng 4854971ac1 curl: check data size before memcpy to local buffer. (CVE-2014-0144)
curl_read_cb is callback function for libcurl when data arrives. The
data size passed in here is not guaranteed to be within the range of
request we submitted, so we may overflow the guest IO buffer. Check the
real size we have before memcpy to buffer to avoid overflow.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 6d4b9e55fc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Jeff Cody 1786c4225d vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148)
Other variables (e.g. sectors_per_block) are calculated using these
variables, and if not range-checked illegal values could be obtained
causing infinite loops and other potential issues when calculating
BAT entries.

The 1.00 VHDX spec requires BlockSize to be min 1MB, max 256MB.
LogicalSectorSize is required to be either 512 or 4096 bytes.

Reported-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 1d7678dec4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Jeff Cody 37173f54b7 vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144)
The maximum blocks_in_image is 0xffffffff / 4, which also limits the
maximum disk_size for a VDI image to 1024TB.  Note that this is the maximum
size that QEMU will currently support with this driver, not necessarily the
maximum size allowed by the image format.

This also fixes an incorrect error message, a bug introduced by commit
5b7aa9b56d (Reported by Stefan Weil)

Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 63fa06dc97)

Conflicts:
	block/vdi.c

*modified to retain 1.7's usage of logout() over error_setg()

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf 76d1eddbe5 vpc: Validate block size (CVE-2014-0142)
This fixes some cases of division by zero crashes.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 5e71dfad76)

Conflicts:
	tests/qemu-iotests/group

*fixed context mismatches in group file

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Jeff Cody b2390c7008 vpc/vhd: add bounds check for max_table_entries and block_size (CVE-2014-0144)
This adds checks to make sure that max_table_entries and block_size
are in sane ranges.  Memory is allocated based on max_table_entries,
and block_size is used to calculate indices into that allocated
memory, so if these values are incorrect that can lead to potential
unbounded memory allocation, or invalid memory accesses.

Also, the allocation of the pagetable is changed from g_malloc0()
to qemu_blockalign().

Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 97f1c45c6f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf 6ee0d5fdc7 bochs: Fix bitmap offset calculation
32 bit truncation could let us access the wrong offset in the image.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit a9ba36a45d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf b0a7517c24 bochs: Check extent_size header field (CVE-2014-0142)
This fixes two possible division by zero crashes: In bochs_open() and in
seek_to_sector().

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 8e53abbc20)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf 6b94cfeca8 bochs: Check catalog_size header field (CVE-2014-0143)
It should neither become negative nor allow unbounded memory
allocations. This fixes aborts in g_malloc() and an s->catalog_bitmap
buffer overflow on big endian hosts.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit e3737b820b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf 0e748624bd bochs: Use unsigned variables for offsets and sizes (CVE-2014-0147)
Gets us rid of integer overflows resulting in negative sizes which
aren't correctly checked.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 246f65838d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf bb8b201815 bochs: Unify header structs and make them QEMU_PACKED
This is an on-disk structure, so offsets must be accurate.

Before this patch, sizeof(bochs) != sizeof(header_v1), which makes the
memcpy() between both invalid. We're lucky enough that the destination
buffer happened to be the larger one, and the memcpy size to be taken
from the smaller one, so we didn't get a buffer overflow in practice.

This patch unifies the both structures, eliminating the need to do a
memcpy in the first place. The common fields are extracted to the top
level of the struct and the actually differing part gets a union of the
two versions.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 3dd8a6763b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Kevin Wolf ae9b5df877 qemu-iotests: Support for bochs format
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 24f3078a04)

Conflicts:
	tests/qemu-iotests/group

*fix context mismatches in group file

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:11 -05:00
Stefan Hajnoczi dbd3e4a75c block/cloop: fix offsets[] size off-by-one
cloop stores the number of compressed blocks in the n_blocks header
field.  The file actually contains n_blocks + 1 offsets, where the extra
offset is the end-of-file offset.

The following line in cloop_read_block() results in an out-of-bounds
offsets[] access:

    uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];

This patch allocates and loads the extra offset so that
cloop_read_block() works correctly when the last block is accessed.

Notice that we must free s->offsets[] unconditionally now since there is
always an end-of-file offset.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 42d43d35d9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:10 -05:00
Stefan Hajnoczi 0fda3e2d63 block/cloop: refuse images with bogus offsets (CVE-2014-0144)
The offsets[] array allows efficient seeking and tells us the maximum
compressed data size.  If the offsets are bogus the maximum compressed
data size will be unrealistic.

This could cause g_malloc() to abort and bogus offsets mean the image is
broken anyway.  Therefore we should refuse such images.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit f56b9bc3ae)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:10 -05:00
Stefan Hajnoczi 7dcffbb2bf block/cloop: refuse images with huge offsets arrays (CVE-2014-0144)
Limit offsets_size to 512 MB so that:

1. g_malloc() does not abort due to an unreasonable size argument.

2. offsets_size does not overflow the bdrv_pread() int size argument.

This limit imposes a maximum image size of 16 TB at 256 KB block size.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 7b103b36d6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:10 -05:00
Stefan Hajnoczi d723971b5d block/cloop: prevent offsets_size integer overflow (CVE-2014-0143)
The following integer overflow in offsets_size can lead to out-of-bounds
memory stores when n_blocks has a huge value:

    uint32_t n_blocks, offsets_size;
    [...]
    ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
    [...]
    s->n_blocks = be32_to_cpu(s->n_blocks);

    /* read offsets */
    offsets_size = s->n_blocks * sizeof(uint64_t);
    s->offsets = g_malloc(offsets_size);

    [...]

    for(i=0;i<s->n_blocks;i++) {
        s->offsets[i] = be64_to_cpu(s->offsets[i]);

offsets_size can be smaller than n_blocks due to integer overflow.
Therefore s->offsets[] is too small when the for loop byteswaps offsets.

This patch refuses to open files if offsets_size would overflow.

Note that changing the type of offsets_size is not a fix since 32-bit
hosts still only have 32-bit size_t.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 509a41bab5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:10 -05:00
Stefan Hajnoczi 1f6bda9301 block/cloop: validate block_size header field (CVE-2014-0144)
Avoid unbounded s->uncompressed_block memory allocation by checking that
the block_size header field has a reasonable value.  Also enforce the
assumption that the value is a non-zero multiple of 512.

These constraints conform to cloop 2.639's code so we accept existing
image files.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit d65f97a82c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:10 -05:00
Stefan Hajnoczi 46c5cacbb4 qemu-iotests: add cloop input validation tests
Add a cloop format-specific test case.  Later patches add tests for
input validation to the script.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 05560fcebb)

Conflicts:
	tests/qemu-iotests/group

*fixed context mismatches in group file

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:10 -05:00
Stefan Hajnoczi 95139b786a qemu-iotests: add ./check -cloop support
Add the cloop block driver to qemu-iotests.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 47f73da0a7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-03 16:18:03 -05:00
Peter Lieven 69b7aacc01 migration: catch unknown flags in ram_load
if a saved vm has unknown flags in the memory data qemu
currently simply ignores this flag and continues which
yields in an unpredictable result.

This patch catches all unknown flags and aborts the
loading of the vm. Additionally error reports are thrown
if the migration aborts abnormally.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit db80facefa)

Conflicts:
	arch_init.c

*removed unecessary context from 4798fe55

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-01 11:11:36 -05:00
ChenLiang 3102b1a221 migration: remove duplicate code
version_id is checked twice in the ram_load.

Signed-off-by: ChenLiang <chenliang88@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 21a246a43b)

*prereq for db80fac backport
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-01 11:07:12 -05:00
Michael S. Tsirkin 84321ba2b6 virtio: allow mapping up to max queue size
It's a loop from i < num_sg  and the array is VIRTQUEUE_MAX_SIZE - so
it's OK if the value read is VIRTQUEUE_MAX_SIZE.

Not a big problem in practice as people don't use
such big queues, but it's inelegant.

Reported-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 9372514080)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-01 11:03:24 -05:00
Michael S. Tsirkin 9fbc298a47 pci-assign: limit # of msix vectors
KVM only supports MSIX table size up to 256 vectors,
but some assigned devices support more vectors,
at the moment attempts to assign them fail with EINVAL.

Tweak the MSIX capability exposed to guest to limit table size
to a supported value.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Gonglei <arei.gonglei@huawei.com>
Cc: qemu-stable@nongnu.org
Acked-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 639973a474)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-07-01 10:57:03 -05:00
Alexey Kardashevskiy 74dd27cecb spapr_pci: Fix number of returned vectors in ibm, change-msi
Current guest kernels try allocating as many vectors as the quota is.
For example, in the case of virtio-net (which has just 3 vectors)
the guest requests 4 vectors (that is the quota in the test) and
the existing ibm,change-msi handler returns 4. But before it returns,
it calls msix_set_message() in a loop and corrupts memory behind
the end of msix_table.

This limits the number of vectors returned by ibm,change-msi to
the maximum supported by the actual device.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Cc: qemu-stable@nongnu.org
[agraf: squash in bugfix from aik]
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit b26696b519)

*s/error_report/fprintf/ to reflect v1.7.x error reporting style

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-29 15:58:43 -05:00
Peter Maydell b6760b6203 linux-user/elfload.c: Fix A64 code which was incorrectly acting like A32
The ARM target-specific code in elfload.c was incorrectly allowing
the 64-bit ARM target to use most of the existing 32-bit definitions:
most noticably this meant that our HWCAP bits passed to the guest
were wrong, and register handling when dumping core was totally
broken. Fix this by properly separating the 64 and 32 bit code,
since they have more differences than similarities.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
(cherry picked from commit 24e76ff06b)

Conflicts:
	linux-user/elfload.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 15:43:30 -05:00
Peter Maydell 64b210d4d5 linux-user/elfload.c: Update ARM HWCAP bits
The kernel has added support for a number of new ARM HWCAP bits;
add them to QEMU, including support for setting them where we have
a corresponding CPU feature bit.

We were also incorrectly setting the VFPv3D16 HWCAP -- this means
"only 16 D registers", not "supports 16-bit floating point format";
since QEMU always has 32 D registers for VFPv3, we can just remove
the line that incorrectly set this bit.

The kernel does not set the HWCAP_FPA even if it is providing FPA
emulation via nwfpe, so don't set this bit in QEMU either.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
(cherry picked from commit 2468265465)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 15:42:08 -05:00
Peter Maydell f6de3526a0 linux-user/elfload.c: Fix incorrect ARM HWCAP bits
The ELF HWCAP bits for ARM features THUMBEE, NEON, VFPv3 and VFPv3D16 are
all off by one compared to the kernel definitions. Fix this discrepancy
and add in the missing CRUNCH bit which was the cause of the off-by-one
error. (We don't emulate any of the CPUs which have that weird hardware,
so it's otherwise uninteresting to us.)

Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
(cherry picked from commit 43ce393ee5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 15:41:56 -05:00
Edgar E. Iglesias 7c56952183 target-arm: Make vbar_write 64bit friendly on 32bit hosts
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1398926097-28097-2-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit fed3ffb9f1)

Conflicts:
	target-arm/helper.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 15:39:34 -05:00
Paolo Bonzini 3c1162e471 target-i386: fix set of registers zeroed on reset
BND0-3, BNDCFGU, BNDCFGS, BNDSTATUS were not zeroed on reset, but they
should be (Intel Instruction Set Extensions Programming Reference
319433-015, pages 9-4 and 9-6).  Same for YMM.

XCR0 should be reset to 1.

TSC and TSC_RESET were zeroed already by the memset, remove the explicit
assignments.

Cc: Andreas Faerber <afaerber@suse.de>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 05e7e819d7)

Conflicts:
	target-i386/cpu.c
	target-i386/cpu.h

*removed dependency on 79e9ebeb

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:57:46 -05:00
Michael S. Tsirkin 73d8965bcc stellaris_enet: block migration
Incoming migration with stellaris_enet is unsafe.
It's being reworked, but for now, simply block it
since noone is using it anyway.
Block outgoing migration for good measure.

CVE-2013-4532

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:36:01 -05:00
Michael S. Tsirkin 2003205fd2 virtio: validate config_len on load
Malformed input can have config_len in migration stream
exceed the array size allocated on destination, the
result will be heap overflow.

To fix, that config_len matches on both sides.

CVE-2014-0182

Reported-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>

--

v2: use %ix and %zx to print config_len values
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit a890a2f913)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:31:48 -05:00
Peter Maydell 7abee6c988 savevm: Ignore minimum_version_id_old if there is no load_state_old
At the moment we require vmstate definitions to set minimum_version_id_old
to the same value as minimum_version_id if they do not provide a
load_state_old handler. Since the load_state_old functionality is
required only for a handful of devices that need to retain migration
compatibility with a pre-vmstate implementation, this means the bulk
of devices have pointless boilerplate. Relax the definition so that
minimum_version_id_old is ignored if there is no load_state_old handler.

Note that under the old scheme we would segfault if the vmstate
specified a minimum_version_id_old that was less than minimum_version_id
but did not provide a load_state_old function, and the incoming state
specified a version number between minimum_version_id_old and
minimum_version_id. Under the new scheme this will just result in
our failing the migration.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 767adce2d9)

Conflicts:
	vmstate.c

*removed dependency on b6fcfa59 (Move VMState code to vmstate.c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:26:28 -05:00
Michael S. Tsirkin c4bd2e4cb0 usb: sanity check setup_index+setup_len in post_load
CVE-2013-4541

s->setup_len and s->setup_index are fed into usb_packet_copy as
size/offset into s->data_buf, it's possible for invalid state to exploit
this to load arbitrary data.

setup_len and setup_index should be checked to make sure
they are not negative.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 9f8e9895c5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:22:06 -05:00
Michael S. Tsirkin 0776525e77 vmstate: s/VMSTATE_INT32_LE/VMSTATE_INT32_POSITIVE_LE/
As the macro verifies the value is positive, rename it
to make the function clearer.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 3476436a44)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:21:46 -05:00
Michael S. Tsirkin a7fcb4c5e0 virtio-scsi: fix buffer overrun on invalid state load
CVE-2013-4542

hw/scsi/scsi-bus.c invokes load_request.

 virtio_scsi_load_request does:
    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));

this probably can make elem invalid, for example,
make in_num or out_num huge, then:

    virtio_scsi_parse_req(s, vs->cmd_vqs[n], req);

will do:

    if (req->elem.out_num > 1) {
        qemu_sgl_init_external(req, &req->elem.out_sg[1],
                               &req->elem.out_addr[1],
                               req->elem.out_num - 1);
    } else {
        qemu_sgl_init_external(req, &req->elem.in_sg[1],
                               &req->elem.in_addr[1],
                               req->elem.in_num - 1);
    }

and this will access out of array bounds.

Note: this adds security checks within assert calls since
SCSIBusInfo's load_request cannot fail.
For now simply disable builds with NDEBUG - there seems
to be little value in supporting these.

Cc: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 3c3ce98142)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:21:30 -05:00
Michael S. Tsirkin 8d948a000d zaurus: fix buffer overrun on invalid state load
CVE-2013-4540

Within scoop_gpio_handler_update, if prev_level has a high bit set, then
we get bit > 16 and that causes a buffer overrun.

Since prev_level comes from wire indirectly, this can
happen on invalid state load.

Similarly for gpio_level and gpio_dir.

To fix, limit to 16 bit.

Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 52f91c3723)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:21:17 -05:00
Michael S. Tsirkin c75e43b871 tsc210x: fix buffer overrun on invalid state load
CVE-2013-4539

s->precision, nextprecision, function and nextfunction
come from wire and are used
as idx into resolution[] in TSC_CUT_RESOLUTION.

Validate after load to avoid buffer overrun.

Cc: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 5193be3be3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:21:02 -05:00
Michael S. Tsirkin af443645c3 ssd0323: fix buffer overun on invalid state load
CVE-2013-4538

s->cmd_len used as index in ssd0323_transfer() to store 32-bit field.
Possible this field might then be supplied by guest to overwrite a
return addr somewhere. Same for row/col fields, which are indicies into
framebuffer array.

To fix validate after load.

Additionally, validate that the row/col_start/end are within bounds;
otherwise the guest can provoke an overrun by either setting the _end
field so large that the row++ increments just walk off the end of the
array, or by setting the _start value to something bogus and then
letting the "we hit end of row" logic reset row to row_start.

For completeness, validate mode as well.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit ead7a57df3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:20:52 -05:00
Michael S. Tsirkin 45edb0ca7a ssi-sd: fix buffer overrun on invalid state load
CVE-2013-4537

s->arglen is taken from wire and used as idx
in ssi_sd_transfer().

Validate it before access.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit a9c380db3b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:19:48 -05:00
Michael S. Tsirkin d92a7683e8 pxa2xx: avoid buffer overrun on incoming migration
CVE-2013-4533

s->rx_level is read from the wire and used to determine how many bytes
to subsequently read into s->rx_fifo[]. If s->rx_level exceeds the
length of s->rx_fifo[] the buffer can be overrun with arbitrary data
from the wire.

Fix this by validating rx_level against the size of s->rx_fifo.

Cc: Don Koch <dkoch@verizon.com>
Reported-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Don Koch <dkoch@verizon.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit caa881abe0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:19:05 -05:00
Michael S. Tsirkin 68801b7be1 virtio: validate num_sg when mapping
CVE-2013-4535
CVE-2013-4536

Both virtio-block and virtio-serial read,
VirtQueueElements are read in as buffers, and passed to
virtqueue_map_sg(), where num_sg is taken from the wire and can force
writes to indicies beyond VIRTQUEUE_MAX_SIZE.

To fix, validate num_sg.

Reported-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Cc: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 36cf2a3713)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:18:51 -05:00
Michael Roth 609f5bf6fe openpic: avoid buffer overrun on incoming migration
CVE-2013-4534

opp->nb_cpus is read from the wire and used to determine how many
IRQDest elements to read into opp->dst[]. If the value exceeds the
length of opp->dst[], MAX_CPU, opp->dst[] can be overrun with arbitrary
data from the wire.

Fix this by failing migration if the value read from the wire exceeds
MAX_CPU.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 73d963c0a7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:18:27 -05:00
Michael Roth 8f0e369a52 virtio: avoid buffer overrun on incoming migration
CVE-2013-6399

vdev->queue_sel is read from the wire, and later used in the
emulation code as an index into vdev->vq[]. If the value of
vdev->queue_sel exceeds the length of vdev->vq[], currently
allocated to be VIRTIO_PCI_QUEUE_MAX elements, subsequent PIO
operations such as VIRTIO_PCI_QUEUE_PFN can be used to overrun
the buffer with arbitrary data originating from the source.

Fix this by failing migration if the value from the wire exceeds
VIRTIO_PCI_QUEUE_MAX.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 4b53c2c72c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:16:13 -05:00
Michael S. Tsirkin 630ebeffb4 vmstate: fix buffer overflow in target-arm/machine.c
CVE-2013-4531

cpreg_vmstate_indexes is a VARRAY_INT32. A negative value for
cpreg_vmstate_array_len will cause a buffer overflow.

VMSTATE_INT32_LE was supposed to protect against this
but doesn't because it doesn't validate that input is
non-negative.

Fix this macro to valide the value appropriately.

The only other user of VMSTATE_INT32_LE doesn't
ever use negative numbers so it doesn't care.

Reported-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit d2ef4b61fe)

Conflicts:
	vmstate.c

*removed dependency on b6fcfa59 (Move VMState code to vmstate.c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:15:02 -05:00
Dr. David Alan Gilbert a2b4e846b3 Fix vmstate_info_int32_le comparison/assign
Fix comparison of vmstate_info_int32_le so that it succeeds if loaded
value is (l)ess than or (e)qual

When the comparison succeeds, assign the value loaded
  This is a change in behaviour but I think the original intent, since
  the idea is to check if the version/size of the thing you're loading is
  less than some limit, but you might well want to do something based on
  the actual version/size in the file

Fix up comment and name text

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 24a370ef23)

Conflicts:
	vmstate.c

*removed dependency on b6fcfa59 (Move VMState code to vmstate.c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:12:33 -05:00
Michael S. Tsirkin f217f379a8 pl022: fix buffer overun on invalid state load
CVE-2013-4530

pl022.c did not bounds check tx_fifo_head and
rx_fifo_head after loading them from file and
before they are used to dereference array.

Reported-by: Michael S. Tsirkin <mst@redhat.com
Reported-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit d8d0a0bc7e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:02:16 -05:00
Michael S. Tsirkin e83444f71e hw/pci/pcie_aer.c: fix buffer overruns on invalid state load
4) CVE-2013-4529
hw/pci/pcie_aer.c    pcie aer log can overrun the buffer if log_num is
                     too large

There are two issues in this file:
1. log_max from remote can be larger than on local
then buffer will overrun with data coming from state file.
2. log_num can be larger then we get data corruption
again with an overflow but not adversary controlled.

Fix both issues.

Reported-by: Anthony Liguori <anthony@codemonkey.ws>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 5f691ff91d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:01:51 -05:00
Michael S. Tsirkin d8aba740f2 hpet: fix buffer overrun on invalid state load
CVE-2013-4527 hw/timer/hpet.c buffer overrun

hpet is a VARRAY with a uint8 size but static array of 32

To fix, make sure num_timers is valid using VMSTATE_VALID hook.

Reported-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 3f1c49e213)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:01:11 -05:00
Michael S. Tsirkin d34e6f7960 ahci: fix buffer overrun on invalid state load
CVE-2013-4526

Within hw/ide/ahci.c, VARRAY refers to ports which is also loaded.  So
we use the old version of ports to read the array but then allow any
value for ports.  This can cause the code to overflow.

There's no reason to migrate ports - it never changes.
So just make sure it matches.

Reported-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit ae2158ad6c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:00:54 -05:00
Michael S. Tsirkin 5544b7e419 virtio: out-of-bounds buffer write on invalid state load
CVE-2013-4151 QEMU 1.0 out-of-bounds buffer write in
virtio_load@hw/virtio/virtio.c

So we have this code since way back when:

    num = qemu_get_be32(f);

    for (i = 0; i < num; i++) {
        vdev->vq[i].vring.num = qemu_get_be32(f);

array of vqs has size VIRTIO_PCI_QUEUE_MAX, so
on invalid input this will write beyond end of buffer.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit cc45995294)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 14:00:35 -05:00
Michael S. Tsirkin 7b6444a2e4 virtio-net: out-of-bounds buffer write on load
CVE-2013-4149 QEMU 1.3.0 out-of-bounds buffer write in
virtio_net_load()@hw/net/virtio-net.c

>         } else if (n->mac_table.in_use) {
>             uint8_t *buf = g_malloc0(n->mac_table.in_use);

We are allocating buffer of size n->mac_table.in_use

>             qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);

and read to the n->mac_table.in_use size buffer n->mac_table.in_use *
ETH_ALEN bytes, corrupting memory.

If adversary controls state then memory written there is controlled
by adversary.

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 98f93ddd84)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 13:59:56 -05:00
Michael S. Tsirkin 2b15f410bd virtio-net: out-of-bounds buffer write on invalid state load
CVE-2013-4150 QEMU 1.5.0 out-of-bounds buffer write in
virtio_net_load()@hw/net/virtio-net.c

This code is in hw/net/virtio-net.c:

    if (n->max_queues > 1) {
        if (n->max_queues != qemu_get_be16(f)) {
            error_report("virtio-net: different max_queues ");
            return -1;
        }

        n->curr_queues = qemu_get_be16(f);
        for (i = 1; i < n->curr_queues; i++) {
            n->vqs[i].tx_waiting = qemu_get_be32(f);
        }
    }

Number of vqs is max_queues, so if we get invalid input here,
for example if max_queues = 2, curr_queues = 3, we get
write beyond end of the buffer, with data that comes from
wire.

This might be used to corrupt qemu memory in hard to predict ways.
Since we have lots of function pointers around, RCE might be possible.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit eea750a562)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 13:59:50 -05:00
Michael S. Tsirkin 95f118fa82 virtio-net: fix buffer overflow on invalid state load
CVE-2013-4148 QEMU 1.0 integer conversion in
virtio_net_load()@hw/net/virtio-net.c

Deals with loading a corrupted savevm image.

>         n->mac_table.in_use = qemu_get_be32(f);

in_use is int so it can get negative when assigned 32bit unsigned value.

>         /* MAC_TABLE_ENTRIES may be different from the saved image */
>         if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {

passing this check ^^^

>             qemu_get_buffer(f, n->mac_table.macs,
>                             n->mac_table.in_use * ETH_ALEN);

with good in_use value, "n->mac_table.in_use * ETH_ALEN" can get
positive and bigger than mac_table.macs. For example 0x81000000
satisfies this condition when ETH_ALEN is 6.

Fix it by making the value unsigned.
For consistency, change first_multi as well.

Note: all call sites were audited to confirm that
making them unsigned didn't cause any issues:
it turns out we actually never do math on them,
so it's easy to validate because both values are
always <= MAC_TABLE_ENTRIES.

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 71f7fe48e1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 13:57:15 -05:00
Michael S. Tsirkin 29e2bbef19 vmstate: add VMSTATE_VALIDATE
Validate state using VMS_ARRAY with num = 0 and VMS_MUST_EXIST

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 4082f0889b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 13:55:15 -05:00
Michael S. Tsirkin a075a3a27e vmstate: add VMS_MUST_EXIST
Can be used to verify a required field exists or validate
state in some other way.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 5bf81c8d63)

Conflicts:
	vmstate.c

*removed dependency on b6fcfa59 (Move VMState code to vmstate.c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 13:53:45 -05:00
Michael S. Tsirkin 25062a7521 vmstate: reduce code duplication
move size offset and number of elements math out
to functions, to reduce code duplication.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 35fc1f7189)

Conflicts:
	vmstate.c

*removed dependency on b6fcfa59 (Move VMState code to vmstate.c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-26 13:48:59 -05:00
Dmitry Fleytman f93614c936 vmxnet3: validate queues configuration read on migration
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-5-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit f12d048a52)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 17:13:49 -05:00
Dmitry Fleytman 709cc04345 vmxnet3: validate interrupt indices read on migration
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-4-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 3c99afc779)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 17:13:33 -05:00
Dmitry Fleytman ed995c6c2f vmxnet3: validate queues configuration coming from guest
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-3-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 9878d173f5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 17:13:22 -05:00
Dmitry Fleytman 6bbbb937aa vmxnet3: validate interrupt indices coming from guest
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-2-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 8c6c047899)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 17:13:08 -05:00
Michael S. Tsirkin 636fa8aec3 acpi: fix tables for no-hpet configuration
acpi build tried to add offset of hpet table to rsdt even when hpet was
disabled.  If no tables follow hpet, this could lead to a malformed
rsdt.

Fix it up.

To avoid such errors in the future, rearrange code slightly to make it
clear that acpi_add_table stores the offset of the following table - not
of the previous one.

Reported-by: TeLeMan <geleman@gmail.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 9ac1c4c07e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 17:10:19 -05:00
Michael Tokarev 1a6ea31052 po/Makefile: fix $SRC_PATH reference
The rule for messages.po appears to be slightly wrong.
Move the `cd' command within parens.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Tested-by: Stefan Weil <sw@weilnetz.de>
(cherry picked from commit b920cad669)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 17:09:33 -05:00
David Hildenbrand 012d778c07 s390x: empty function stubs in preparation for __KVM_HAVE_GUEST_DEBUG
This patch creates empty function stubs (used by the gdbserver) in preparation
for the hw debugging support by kvm on s390, which will enable the
__KVM_HAVE_GUEST_DEBUG define in the linux headers and require these methods on
the qemu side.

Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit 8c0124490b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 16:43:05 -05:00
Thomas Huth dd8f80b83c s390x/helper: Added format control bit to MMU translation
With the EDAT-1 facility, the MMU translation can stop at the
segment table already, pointing to a 1 MB block. And while we're
at it, move the page table entry handling to a separate function,
too, as suggested by Alexander Graf.

Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit c4400206d4)

Conflicts:
	target-s390x/helper.c

*removed unecessary context

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 16:39:52 -05:00
Kevin Wolf b1a86eb532 block: Use BDRV_O_NO_BACKING where appropriate
If you open an image temporarily just because you want to check its size
or get it flushed, there's no real reason to open the whole backing file
chain.

This is a backport of c9fbb99d41 to
qemu 1.7.1.

The backport was done to fix a bug where QEMU 1.7.1 would crash or freeze
when the user take around 80 consecutives snapshots in a row.

git bisect would lead to commit: ba2ab2f2ca
and it was clear that BDRV_NO_BACKING was missing.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 16:33:46 -05:00
Benoît Canet 792a40384f block: Prevent coroutine stack overflow when recursing in bdrv_open_backing_file.
In 1.7.1 qcow2_create2 reopen the file for flushing without the BDRV_O_NO_BACKING
flags.

As a consequence the code would recursively open the whole backing chain.

These three stack arrays would pile up through the recursion and lead to a coroutine
stack overflow.

Convert these array to malloced buffers in order to streamline the coroutine
footprint.

Symptoms where freezes or segfaults on production machines while taking QMP externals
snapshots. The overflow disturbed coroutine switching.

Signed-off-by: Benoit Canet <benoit.canet@gmail.com>

*note: backport of upstream's 1ba4b6a

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 16:28:44 -05:00
Peter Crosthwaite 0655eeed18 arm: translate.c: Fix smlald Instruction
The smlald (and probably smlsld) instruction was doing incorrect sign
extensions of the operands amongst 64bit result calculation. The
instruction psuedo-code is:

 operand2 = if m_swap then ROR(R[m],16) else R[m];
 product1 = SInt(R[n]<15:0>) * SInt(operand2<15:0>);
 product2 = SInt(R[n]<31:16>) * SInt(operand2<31:16>);
 result = product1 + product2 + SInt(R[dHi]:R[dLo]);
 R[dHi] = result<63:32>;
 R[dLo] = result<31:0>;

The result calculation should be done in 64 bit arithmetic, and hence
product1 and product2 should be sign extended to 64b before calculation.

The current implementation was adding product1 and product2 together
then sign-extending the intermediate result leading to false negatives.

E.G. if product1 = product2 = 0x4000000, their sum = 0x80000000, which
will be incorrectly interpreted as -ve on sign extension.

We fix by doing the 64b extensions on both product1 and product2 before
any addition/subtraction happens.

We also fix where we were possibly incorrectly setting the Q saturation
flag for SMLSLD, which the ARM ARM specifically says is not set.

Reported-by: Christina Smith <christina.smith@xilinx.com>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 2cddb6f5a15be4ab8d2160f3499d128ae93d304d.1397704570.git.peter.crosthwaite@xilinx.com
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 33bbd75a7c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 16:08:05 -05:00
Hannes Reinecke 5cfd43b79d megasas: Implement LD_LIST_QUERY
Newer firmware implement a LD_LIST_QUERY command, and due to a driver
issue no drives might be detected if this command isn't supported.
So add emulation for this command, too.

Cc: qemu-stable@nongnu.org
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 34bb4d02e0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 16:02:25 -05:00
Benoît Canet c5dae2f4c5 ide: Correct improper smart self test counter reset in ide core.
The SMART self test counter was incorrectly being reset to zero,
not 1. This had the effect that on every 21st SMART EXECUTE OFFLINE:
 * We would write off the beginning of a dynamically allocated buffer
 * We forgot the SMART history
Fix this.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Message-id: 1397336390-24664-1-git-send-email-benoit.canet@irqsave.net
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Cc: qemu-stable@nongnu.org
Acked-by: Kevin Wolf <kwolf@redhat.com>
[PMM: tweaked commit message as per suggestions from Markus]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

(cherry picked from commit 940973ae0b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:56:17 -05:00
Max Reitz 3239a20294 block-commit: speed is an optional parameter
As speed is an optional parameter for the QMP block-commit command, it
should be set to 0 if not given (as it is undefined if has_speed is
false), that is, the speed should not be limited.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 5450466394)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:39:13 -05:00
Kevin Wolf a8b7e73901 qcow2: Flush metadata during read-only reopen
If lazy refcounts are enabled for a backing file, committing to this
backing file may leave it in a dirty state even if the commit succeeds.
The reason is that the bdrv_flush() call in bdrv_commit() doesn't flush
refcount updates with lazy refcounts enabled, and qcow2_reopen_prepare()
doesn't take care to flush metadata.

In order to fix this, this patch also fixes qcow2_mark_clean(), which
contains another ineffective bdrv_flush() call beause lazy refcounts are
disabled only afterwards. All existing callers of qcow2_mark_clean()
either don't modify refcounts or already flush manually, so that this
fixes only a latent, but not yet actually triggerable bug.

Another instance of the same problem is live snapshots. Again, a real
corruption is prevented by an explicit flush for non-read-only images in
external_snapshot_prepare(), but images using lazy refcounts stay dirty.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 4c2e5f8f46)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:34:50 -05:00
Peter Maydell 38a55f3070 hw/net/stellaris_enet: Correct handling of packet padding
The PADEN bit in the transmit control register enables padding of short
data packets out to the required minimum length. However a typo here
meant we were adjusting tx_fifo_len rather than tx_frame_len, so the
padding didn't actually happen. Fix this bug.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 7fd5f064d1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:33:46 -05:00
Peter Maydell 7d09facec7 hw/net/stellaris_enet: Restructure tx_fifo code to avoid buffer overrun
The current tx_fifo code has a corner case where the guest can overrun
the fifo buffer: if automatic CRCs are disabled we allow the guest to write
the CRC word even if there isn't actually space for it in the FIFO.
The datasheet is unclear about exactly how the hardware deals with this
situation; the most plausible answer seems to be that the CRC word is
just lost.

Implement this fix by separating the "can we stuff another word in the
FIFO" logic from the "should we transmit the packet now" check. This
also moves us closer to the real hardware, which has a number of ways
it can be configured to trigger sending the packet, some of which we
don't implement.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 5c10495ab1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:33:30 -05:00
Stefan Fritsch 11088abadf virtio-net: Do not filter VLANs without F_CTRL_VLAN
If VIRTIO_NET_F_CTRL_VLAN is not negotiated, do not filter out all
VLAN-tagged packets but send them to the guest.

This fixes VLANs with OpenBSD guests (and probably NetBSD, too, because
the OpenBSD driver started as a port from NetBSD).

Signed-off-by: Stefan Fritsch <sf@sfritsch.de>
Signed-off-by: Amos Kong <akong@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 0b1eaa8803)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:28:50 -05:00
Stefan Hajnoczi 0fd56fb844 mirror: fix early wake from sleep due to aio
The mirror blockjob coroutine rate-limits itself by sleeping.  The
coroutine also performs I/O asynchronously so it's important that the
aio callback doesn't wake the coroutine early as that breaks
rate-limiting.

Reported-by: Joaquim Barrera <jbarrera@ac.upc.edu>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 7b770c720b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:26:29 -05:00
Paolo Bonzini 8211eeb7d2 mirror: fix throttling delay calculation
The throttling delay calculation was using an inaccurate sector count to
calculate the time to sleep.  This broke rate-limiting for the block
mirror job.

Move the delay calculation into mirror_iteration() where we know how
many sectors were transferred.  This lets us calculate an accurate delay
time.

Reported-by: Joaquim Barrera <jbarrera@ac.upc.edu>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit cc8c9d6c6f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:26:23 -05:00
Stefan Weil 0414abe04f configure: Don't use __int128_t for clang versions before 3.2
Those versions don't fully support __int128_t.

Cc: qemu-stable@nongnu.org
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit a00f66ab9b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:24:19 -05:00
Stefan Weil 151be4f61f tests: Fix 'make test' for i686 hosts (build regression)
'make test' is broken at least since commit
baacf04799. Several source files were moved
to util/, and some of them there split, so add the missing prefix and new
files to fix the compiler and linker errors.

There remain more issues, but these changes allow running the test on a
Linux i686 host.

Cc: qemu-stable@nongnu.org
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 6d4adef48d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:23:31 -05:00
Stefan Hajnoczi a290aeebc4 tap: avoid deadlocking rx
The net subsystem has a control flow mechanism so peer NetClientStates
can tell each other to stop sending packets.  This is used to stop
monitoring the tap file descriptor for incoming packets if the guest rx
ring has no spare buffers.

There is a corner case when tap_can_send() is true at the beginning of
an event loop iteration but becomes false before the tap_send() fd
handler is invoked.

tap_send() will read the packet from the tap file descriptor and attempt
to send it.  The net queue will hold on to the packet and return 0,
indicating that further I/O is not possible.  tap then stops monitoring
the file descriptor for reads.

This is unlike the normal case where tap_can_send() is the same before
and during the event loop iteration.  The event loop would simply not
monitor the file descriptor if tap_can_send() returns true.  Upon next
iteration it would check tap_can_send() again and begin monitoring if we
can send.

The deadlock happens because tap_send() explicitly disabled read_poll.
This is done with the expectation that the peer will call
qemu_net_queue_flush().  But hw/net/virtio-net.c does not monitor
vm_running transitions and issue the flush.  Hence we're left with a
broken tap device.

Cc: qemu-stable@nongnu.org
Reported-by: Neil Skrypuch <neil@tembosocial.com>
Tested-by: Neil Skrypuch <neil@tembosocial.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 68e5ec6400)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:17:15 -05:00
Stefan Hajnoczi 7e42cd6f35 qom: Avoid leaking str and bool properties on failure
When object_property_add_str() and object_property_add_bool() fail, they
leak their internal StringProperty and BoolProperty structs.  Remember
to free the structs on error.

Luckily this is a low-impact memory leak since most QOM properties are
static qdev properties that will never take the error case.
object_property_add() only fails if the property name is already in use.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit a01aedc8d3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:11:17 -05:00
Fam Zheng 4f577e9e69 scsi: Change scsi sense buf size to 252
Current buffer size fails the assersion check in like

    hw/scsi/scsi-bus.c:1655:    assert(req->sense_len <= sizeof(req->sense));

when backend (block/iscsi.c) returns more data then 96.

Exercise the core dump path by booting an Gentoo ISO with scsi-generic
device backed with iscsi (built with libiscsi 1.7.0):

    x86_64-softmmu/qemu-system-x86_64 \
    -drive file=iscsi://localhost:3260/iqn.foobar/0,if=none,id=drive-disk \
    -device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x6 \
    -device scsi-generic,drive=drive-disk,bus=scsi1.0,id=iscsi-disk \
    -boot d \
    -cdrom gentoo.iso

    qemu-system-x86_64: hw/scsi/scsi-bus.c:1655: scsi_req_complete:
    Assertion `req->sense_len <= sizeof(req->sense)' failed.

According to SPC-4, section 4.5.2.1, 252 is the limit of sense data. So
increase the value to fix it.

Also remove duplicated define for the macro.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit c5f52875b9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 15:05:09 -05:00
Richard Henderson 6be38ee9e7 target-i386: Fix ucomis and comis memory access
We were loading 16 bytes for both single and double-precision
scalar comparisons.

Reported-by: Alexander Bluhm <bluhm@openbsd.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
(cherry picked from commit cb48da7f81)

Conflicts:
	target-i386/translate.c

*removed dependency on 323d1876

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 11:45:00 -05:00
Richard Henderson 2e191f8e54 target-i386: Fix CC_OP_CLR vs PF
Parity should be set for a zero result.

Cc: qemu-stable@nongnu.org
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
(cherry picked from commit d2fe51bda8)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 11:25:09 -05:00
Thomas Huth 91ae1d30ec s390x/virtio-hcall: Add range check for hypervisor call
The handler for diag 500 did not check whether the requested function
was in the supported range, so illegal values could crash QEMU in the
worst case.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
CC: qemu-stable@nongnu.org
(cherry picked from commit f2c55d1735)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 11:11:45 -05:00
Peter Lieven 0a77a92d74 block/iscsi: fix deadlock on scsi check condition
the retry logic was broken because the complete status
of the task structure was not reset. this resulted in
an infinite loop retrying the command over and over.

CC: qemu-stable@nongnu.org
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 837c390137)

Conflicts:
	block/iscsi.c

*only modified retry clauses present before 063c3378

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 11:08:29 -05:00
Markus Armbruster 8b8dd2c4b5 scsi-bus: Fix transfer length for VERIFY with BYTCHK=11b
The transfer length depends on field BYTCHK, which is encoded in byte
1, bits 1..2.  However, the guard for for case BYTCHK=11b doesn't
work, and we get case 01b instead.  Fix it.

Note that since emulated scsi-hd fails the command outright, it takes
SCSI passthrough of a device that actually implements VERIFY with
BYTCHK=11b to make the bug bite.

Screwed up in commit d12ad44.  Spotted by Coverity.

Cc: qemu-stable@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 7ef8cf9a08)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-25 11:00:29 -05:00
Gal Hammer 248de52cf8 char: restore read callback on a reattached (hotplug) chardev
Fix a bug that was introduced in commit 386a5a1e. A removal of a device
set the chr handlers to NULL. However when the device is plugged back,
its read callback is not restored so data can't be transferred from the
host to the guest (e.g. via the virtio-serial port).

https://bugzilla.redhat.com/show_bug.cgi?id=1027181

Signed-off-by: Gal Hammer <ghammer@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit ac1b84dd1e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-20 08:19:49 -05:00
132 changed files with 2643 additions and 693 deletions

No files matched your search

+1 -1
View File
@@ -1 +1 @@
1.7.1
1.7.2
+46 -46
View File
@@ -857,64 +857,60 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
{
ram_addr_t addr;
int flags, ret = 0;
int error;
static uint64_t seq_iter;
seq_iter++;
if (version_id < 4 || version_id > 4) {
if (version_id != 4) {
return -EINVAL;
}
do {
while (!ret) {
addr = qemu_get_be64(f);
flags = addr & ~TARGET_PAGE_MASK;
addr &= TARGET_PAGE_MASK;
if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
if (version_id == 4) {
/* Synchronize RAM block list */
char id[256];
ram_addr_t length;
ram_addr_t total_ram_bytes = addr;
/* Synchronize RAM block list */
char id[256];
ram_addr_t length;
ram_addr_t total_ram_bytes = addr;
while (total_ram_bytes) {
RAMBlock *block;
uint8_t len;
while (total_ram_bytes) {
RAMBlock *block;
uint8_t len;
len = qemu_get_byte(f);
qemu_get_buffer(f, (uint8_t *)id, len);
id[len] = 0;
length = qemu_get_be64(f);
len = qemu_get_byte(f);
qemu_get_buffer(f, (uint8_t *)id, len);
id[len] = 0;
length = qemu_get_be64(f);
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id))) {
if (block->length != length) {
fprintf(stderr,
"Length mismatch: %s: " RAM_ADDR_FMT
" in != " RAM_ADDR_FMT "\n", id, length,
block->length);
ret = -EINVAL;
goto done;
}
break;
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id))) {
if (block->length != length) {
fprintf(stderr,
"Length mismatch: %s: " RAM_ADDR_FMT
" in != " RAM_ADDR_FMT "\n", id, length,
block->length);
ret = -EINVAL;
}
break;
}
if (!block) {
fprintf(stderr, "Unknown ramblock \"%s\", cannot "
"accept migration\n", id);
ret = -EINVAL;
goto done;
}
total_ram_bytes -= length;
}
}
}
if (flags & RAM_SAVE_FLAG_COMPRESS) {
if (!block) {
fprintf(stderr, "Unknown ramblock \"%s\", cannot "
"accept migration\n", id);
ret = -EINVAL;
}
if (ret) {
break;
}
total_ram_bytes -= length;
}
} else if (flags & RAM_SAVE_FLAG_COMPRESS) {
void *host;
uint8_t ch;
@@ -941,20 +937,24 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
}
if (load_xbzrle(f, addr, host) < 0) {
error_report("Failed to decompress XBZRLE page at "
RAM_ADDR_FMT, addr);
ret = -EINVAL;
goto done;
break;
}
} else if (flags & RAM_SAVE_FLAG_HOOK) {
ram_control_load_hook(f, flags);
} else if (flags & RAM_SAVE_FLAG_EOS) {
/* normal exit */
break;
} else {
error_report("Unknown migration flags: %#x", flags);
ret = -EINVAL;
break;
}
error = qemu_file_get_error(f);
if (error) {
ret = error;
goto done;
}
} while (!(flags & RAM_SAVE_FLAG_EOS));
ret = qemu_file_get_error(f);
}
done:
DPRINTF("Completed load of VM with exit code %d seq iteration "
"%" PRIu64 "\n", ret, seq_iter);
return ret;
+10 -4
View File
@@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
void qemu_bh_schedule(QEMUBH *bh)
{
AioContext *ctx;
if (bh->scheduled)
return;
ctx = bh->ctx;
bh->idle = 0;
/* Make sure that idle & any writes needed by the callback are done
* before the locations are read in the aio_bh_poll.
/* Make sure that:
* 1. idle & any writes needed by the callback are done before the
* locations are read in the aio_bh_poll.
* 2. ctx is loaded before scheduled is set and the callback has a chance
* to execute.
*/
smp_wmb();
smp_mb();
bh->scheduled = 1;
aio_notify(bh->ctx);
aio_notify(ctx);
}
+25 -15
View File
@@ -966,14 +966,14 @@ fail:
*/
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
{
char backing_filename[PATH_MAX];
int back_flags, ret;
char *backing_filename = g_malloc0(PATH_MAX);
int back_flags, ret = 0;
BlockDriver *back_drv = NULL;
Error *local_err = NULL;
if (bs->backing_hd != NULL) {
QDECREF(options);
return 0;
goto free_exit;
}
/* NULL means an empty set of options */
@@ -986,10 +986,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
backing_filename[0] = '\0';
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
QDECREF(options);
return 0;
goto free_exit;
} else {
bdrv_get_full_backing_filename(bs, backing_filename,
sizeof(backing_filename));
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
}
bs->backing_hd = bdrv_new("");
@@ -1012,11 +1011,14 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
error_setg(errp, "Could not open backing file: %s",
error_get_pretty(local_err));
error_free(local_err);
return ret;
goto free_exit;
}
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
bs->backing_hd->file->filename);
return 0;
ret = 0;
free_exit:
g_free(backing_filename);
return ret;
}
/*
@@ -1032,7 +1034,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
{
int ret;
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
char tmp_filename[PATH_MAX + 1];
char *backing_filename = NULL;
char *tmp_filename = g_malloc0(PATH_MAX + 1);
BlockDriverState *file = NULL;
QDict *file_options = NULL;
const char *drvname;
@@ -1052,7 +1055,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
int64_t total_size;
BlockDriver *bdrv_qcow2;
QEMUOptionParameter *create_options;
char backing_filename[PATH_MAX];
backing_filename = g_malloc0(PATH_MAX);
if (qdict_size(options) != 0) {
error_setg(errp, "Can't use snapshot=on with driver-specific options");
@@ -1064,9 +1067,9 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
/* if snapshot, we create a temporary backing file and open it
instead of opening 'filename' directly */
/* if there is a backing file, use it */
bs1 = bdrv_new("");
ret = bdrv_open(bs1, filename, NULL, 0, drv, &local_err);
ret = bdrv_open(bs1, filename, NULL, BDRV_O_NO_BACKING, drv,
&local_err);
if (ret < 0) {
bdrv_unref(bs1);
goto fail;
@@ -1075,7 +1078,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
bdrv_unref(bs1);
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not get temporary filename");
goto fail;
@@ -1083,8 +1086,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
/* Real path is meaningless for protocols */
if (path_has_protocol(filename)) {
snprintf(backing_filename, sizeof(backing_filename),
"%s", filename);
snprintf(backing_filename, PATH_MAX, "%s", filename);
} else if (!realpath(filename, backing_filename)) {
ret = -errno;
error_setg_errno(errp, errno, "Could not resolve path '%s'", filename);
@@ -1206,6 +1208,8 @@ fail:
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
}
g_free(tmp_filename);
g_free(backing_filename);
return ret;
close_and_fail:
@@ -1214,6 +1218,8 @@ close_and_fail:
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
}
g_free(tmp_filename);
g_free(backing_filename);
return ret;
}
@@ -2271,6 +2277,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
return -EIO;
}
return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE);
}
+57 -52
View File
@@ -38,57 +38,42 @@
// not allocated: 0xffffffff
// always little-endian
struct bochs_header_v1 {
char magic[32]; // "Bochs Virtual HD Image"
char type[16]; // "Redolog"
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
uint32_t version;
uint32_t header; // size of header
union {
struct {
uint32_t catalog; // num of entries
uint32_t bitmap; // bitmap size
uint32_t extent; // extent size
uint64_t disk; // disk size
char padding[HEADER_SIZE - 64 - 8 - 20];
} redolog;
char padding[HEADER_SIZE - 64 - 8];
} extra;
};
// always little-endian
struct bochs_header {
char magic[32]; // "Bochs Virtual HD Image"
char type[16]; // "Redolog"
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
char magic[32]; /* "Bochs Virtual HD Image" */
char type[16]; /* "Redolog" */
char subtype[16]; /* "Undoable" / "Volatile" / "Growing" */
uint32_t version;
uint32_t header; // size of header
uint32_t header; /* size of header */
uint32_t catalog; /* num of entries */
uint32_t bitmap; /* bitmap size */
uint32_t extent; /* extent size */
union {
struct {
uint32_t catalog; // num of entries
uint32_t bitmap; // bitmap size
uint32_t extent; // extent size
uint32_t reserved; // for ???
uint64_t disk; // disk size
char padding[HEADER_SIZE - 64 - 8 - 24];
} redolog;
char padding[HEADER_SIZE - 64 - 8];
struct {
uint32_t reserved; /* for ??? */
uint64_t disk; /* disk size */
char padding[HEADER_SIZE - 64 - 20 - 12];
} QEMU_PACKED redolog;
struct {
uint64_t disk; /* disk size */
char padding[HEADER_SIZE - 64 - 20 - 8];
} QEMU_PACKED redolog_v1;
char padding[HEADER_SIZE - 64 - 20];
} extra;
};
} QEMU_PACKED;
typedef struct BDRVBochsState {
CoMutex lock;
uint32_t *catalog_bitmap;
int catalog_size;
uint32_t catalog_size;
int data_offset;
uint32_t data_offset;
int bitmap_blocks;
int extent_blocks;
int extent_size;
uint32_t bitmap_blocks;
uint32_t extent_blocks;
uint32_t extent_size;
} BDRVBochsState;
static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -112,9 +97,8 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVBochsState *s = bs->opaque;
int i;
uint32_t i;
struct bochs_header bochs;
struct bochs_header_v1 header_v1;
int ret;
bs->read_only = 1; // no write support yet
@@ -133,13 +117,19 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
}
if (le32_to_cpu(bochs.version) == HEADER_V1) {
memcpy(&header_v1, &bochs, sizeof(bochs));
bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
bs->total_sectors = le64_to_cpu(bochs.extra.redolog_v1.disk) / 512;
} else {
bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
}
/* Limit to 1M entries to avoid unbounded allocation. This is what is
* needed for the largest image that bximage can create (~8 TB). */
s->catalog_size = le32_to_cpu(bochs.catalog);
if (s->catalog_size > 0x100000) {
error_setg(errp, "Catalog size is too large");
return -EFBIG;
}
s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
s->catalog_bitmap = g_malloc(s->catalog_size * 4);
ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
@@ -153,10 +143,24 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
s->bitmap_blocks = 1 + (le32_to_cpu(bochs.bitmap) - 1) / 512;
s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
s->extent_size = le32_to_cpu(bochs.extent);
if (s->extent_size == 0) {
error_setg(errp, "Extent size may not be zero");
return -EINVAL;
} else if (s->extent_size > 0x800000) {
error_setg(errp, "Extent size %" PRIu32 " is too large",
s->extent_size);
return -EINVAL;
}
if (s->catalog_size < bs->total_sectors / s->extent_size) {
error_setg(errp, "Catalog size is too small for this disk size");
ret = -EINVAL;
goto fail;
}
qemu_co_mutex_init(&s->lock);
return 0;
@@ -169,8 +173,8 @@ fail:
static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
{
BDRVBochsState *s = bs->opaque;
int64_t offset = sector_num * 512;
int64_t extent_index, extent_offset, bitmap_offset;
uint64_t offset = sector_num * 512;
uint64_t extent_index, extent_offset, bitmap_offset;
char bitmap_entry;
// seek to sector
@@ -181,8 +185,9 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
return -1; /* not allocated */
}
bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
(s->extent_blocks + s->bitmap_blocks));
bitmap_offset = s->data_offset +
(512 * (uint64_t) s->catalog_bitmap[extent_index] *
(s->extent_blocks + s->bitmap_blocks));
/* read in bitmap for current extent */
if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
+71 -10
View File
@@ -26,6 +26,9 @@
#include "qemu/module.h"
#include <zlib.h>
/* Maximum compressed block size */
#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
typedef struct BDRVCloopState {
CoMutex lock;
uint32_t block_size;
@@ -68,6 +71,26 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
s->block_size = be32_to_cpu(s->block_size);
if (s->block_size % 512) {
error_setg(errp, "block_size %u must be a multiple of 512",
s->block_size);
return -EINVAL;
}
if (s->block_size == 0) {
error_setg(errp, "block_size cannot be zero");
return -EINVAL;
}
/* cloop's create_compressed_fs.c warns about block sizes beyond 256 KB but
* we can accept more. Prevent ridiculous values like 4 GB - 1 since we
* need a buffer this big.
*/
if (s->block_size > MAX_BLOCK_SIZE) {
error_setg(errp, "block_size %u must be %u MB or less",
s->block_size,
MAX_BLOCK_SIZE / (1024 * 1024));
return -EINVAL;
}
ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
if (ret < 0) {
@@ -76,7 +99,23 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
s->n_blocks = be32_to_cpu(s->n_blocks);
/* read offsets */
offsets_size = s->n_blocks * sizeof(uint64_t);
if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
/* Prevent integer overflow */
error_setg(errp, "n_blocks %u must be %zu or less",
s->n_blocks,
(UINT32_MAX - 1) / sizeof(uint64_t));
return -EINVAL;
}
offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
if (offsets_size > 512 * 1024 * 1024) {
/* Prevent ridiculous offsets_size which causes memory allocation to
* fail or overflows bdrv_pread() size. In practice the 512 MB
* offsets[] limit supports 16 TB images at 256 KB block size.
*/
error_setg(errp, "image requires too many offsets, "
"try increasing block size");
return -EINVAL;
}
s->offsets = g_malloc(offsets_size);
ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
@@ -84,13 +123,37 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
for(i=0;i<s->n_blocks;i++) {
for (i = 0; i < s->n_blocks + 1; i++) {
uint64_t size;
s->offsets[i] = be64_to_cpu(s->offsets[i]);
if (i > 0) {
uint32_t size = s->offsets[i] - s->offsets[i - 1];
if (size > max_compressed_block_size) {
max_compressed_block_size = size;
}
if (i == 0) {
continue;
}
if (s->offsets[i] < s->offsets[i - 1]) {
error_setg(errp, "offsets not monotonically increasing at "
"index %u, image file is corrupt", i);
ret = -EINVAL;
goto fail;
}
size = s->offsets[i] - s->offsets[i - 1];
/* Compressed blocks should be smaller than the uncompressed block size
* but maybe compression performed poorly so the compressed block is
* actually bigger. Clamp down on unrealistic values to prevent
* ridiculous s->compressed_block allocation.
*/
if (size > 2 * MAX_BLOCK_SIZE) {
error_setg(errp, "invalid compressed block size at index %u, "
"image file is corrupt", i);
ret = -EINVAL;
goto fail;
}
if (size > max_compressed_block_size) {
max_compressed_block_size = size;
}
}
@@ -180,9 +243,7 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
static void cloop_close(BlockDriverState *bs)
{
BDRVCloopState *s = bs->opaque;
if (s->n_blocks > 0) {
g_free(s->offsets);
}
g_free(s->offsets);
g_free(s->compressed_block);
g_free(s->uncompressed_block);
inflateEnd(&s->zstream);
+5
View File
@@ -157,6 +157,11 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
if (!s || !s->orig_buf)
goto read_end;
if (s->buf_off >= s->buf_len) {
/* buffer full, read nothing */
return 0;
}
realsize = MIN(realsize, s->buf_len - s->buf_off);
memcpy(s->orig_buf + s->buf_off, ptr, realsize);
s->buf_off += realsize;
+163 -106
View File
@@ -27,6 +27,14 @@
#include "qemu/module.h"
#include <zlib.h>
enum {
/* Limit chunk sizes to prevent unreasonable amounts of memory being used
* or truncating when converting to 32-bit types
*/
DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */
DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
};
typedef struct BDRVDMGState {
CoMutex lock;
/* each chunk contains a certain number of sectors,
@@ -92,13 +100,44 @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
return 0;
}
/* Increase max chunk sizes, if necessary. This function is used to calculate
* the buffer sizes needed for compressed/uncompressed chunk I/O.
*/
static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
uint32_t *max_compressed_size,
uint32_t *max_sectors_per_chunk)
{
uint32_t compressed_size = 0;
uint32_t uncompressed_sectors = 0;
switch (s->types[chunk]) {
case 0x80000005: /* zlib compressed */
compressed_size = s->lengths[chunk];
uncompressed_sectors = s->sectorcounts[chunk];
break;
case 1: /* copy */
uncompressed_sectors = (s->lengths[chunk] + 511) / 512;
break;
case 2: /* zero */
uncompressed_sectors = s->sectorcounts[chunk];
break;
}
if (compressed_size > *max_compressed_size) {
*max_compressed_size = compressed_size;
}
if (uncompressed_sectors > *max_sectors_per_chunk) {
*max_sectors_per_chunk = uncompressed_sectors;
}
}
static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVDMGState *s = bs->opaque;
uint64_t info_begin,info_end,last_in_offset,last_out_offset;
uint64_t info_begin, info_end, last_in_offset, last_out_offset;
uint32_t count, tmp;
uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
uint32_t max_compressed_size = 1, max_sectors_per_chunk = 1, i;
int64_t offset;
int ret;
@@ -160,37 +199,40 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
if (type == 0x6d697368 && count >= 244) {
int new_size, chunk_count;
if (type == 0x6d697368 && count >= 244) {
size_t new_size;
uint32_t chunk_count;
offset += 4;
offset += 200;
chunk_count = (count-204)/40;
new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
s->types = g_realloc(s->types, new_size/2);
s->offsets = g_realloc(s->offsets, new_size);
s->lengths = g_realloc(s->lengths, new_size);
s->sectors = g_realloc(s->sectors, new_size);
s->sectorcounts = g_realloc(s->sectorcounts, new_size);
chunk_count = (count - 204) / 40;
new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
s->types = g_realloc(s->types, new_size / 2);
s->offsets = g_realloc(s->offsets, new_size);
s->lengths = g_realloc(s->lengths, new_size);
s->sectors = g_realloc(s->sectors, new_size);
s->sectorcounts = g_realloc(s->sectorcounts, new_size);
for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) {
ret = read_uint32(bs, offset, &s->types[i]);
if (ret < 0) {
goto fail;
}
offset += 4;
if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
if(s->types[i]==0xffffffff) {
last_in_offset = s->offsets[i-1]+s->lengths[i-1];
last_out_offset = s->sectors[i-1]+s->sectorcounts[i-1];
}
chunk_count--;
i--;
offset += 36;
continue;
}
offset += 4;
offset += 4;
if (s->types[i] != 0x80000005 && s->types[i] != 1 &&
s->types[i] != 2) {
if (s->types[i] == 0xffffffff && i > 0) {
last_in_offset = s->offsets[i - 1] + s->lengths[i - 1];
last_out_offset = s->sectors[i - 1] +
s->sectorcounts[i - 1];
}
chunk_count--;
i--;
offset += 36;
continue;
}
offset += 4;
ret = read_uint64(bs, offset, &s->sectors[i]);
if (ret < 0) {
@@ -205,6 +247,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
}
offset += 8;
if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
error_report("sector count %" PRIu64 " for chunk %u is "
"larger than max (%u)",
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
ret = -EINVAL;
goto fail;
}
ret = read_uint64(bs, offset, &s->offsets[i]);
if (ret < 0) {
goto fail;
@@ -218,19 +268,25 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
}
offset += 8;
if(s->lengths[i]>max_compressed_size)
max_compressed_size = s->lengths[i];
if(s->sectorcounts[i]>max_sectors_per_chunk)
max_sectors_per_chunk = s->sectorcounts[i];
}
s->n_chunks+=chunk_count;
}
if (s->lengths[i] > DMG_LENGTHS_MAX) {
error_report("length %" PRIu64 " for chunk %u is larger "
"than max (%u)",
s->lengths[i], i, DMG_LENGTHS_MAX);
ret = -EINVAL;
goto fail;
}
update_max_chunk_size(s, i, &max_compressed_size,
&max_sectors_per_chunk);
}
s->n_chunks += chunk_count;
}
}
/* initialize zlib engine */
s->compressed_chunk = g_malloc(max_compressed_size+1);
s->uncompressed_chunk = g_malloc(512*max_sectors_per_chunk);
if(inflateInit(&s->zstream) != Z_OK) {
s->compressed_chunk = g_malloc(max_compressed_size + 1);
s->uncompressed_chunk = g_malloc(512 * max_sectors_per_chunk);
if (inflateInit(&s->zstream) != Z_OK) {
ret = -EINVAL;
goto fail;
}
@@ -252,83 +308,82 @@ fail:
}
static inline int is_sector_in_chunk(BDRVDMGState* s,
uint32_t chunk_num,int sector_num)
uint32_t chunk_num, uint64_t sector_num)
{
if(chunk_num>=s->n_chunks || s->sectors[chunk_num]>sector_num ||
s->sectors[chunk_num]+s->sectorcounts[chunk_num]<=sector_num)
return 0;
else
return -1;
if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num ||
s->sectors[chunk_num] + s->sectorcounts[chunk_num] <= sector_num) {
return 0;
} else {
return -1;
}
}
static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
{
/* binary search */
uint32_t chunk1=0,chunk2=s->n_chunks,chunk3;
while(chunk1!=chunk2) {
chunk3 = (chunk1+chunk2)/2;
if(s->sectors[chunk3]>sector_num)
chunk2 = chunk3;
else if(s->sectors[chunk3]+s->sectorcounts[chunk3]>sector_num)
return chunk3;
else
chunk1 = chunk3;
uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
while (chunk1 != chunk2) {
chunk3 = (chunk1 + chunk2) / 2;
if (s->sectors[chunk3] > sector_num) {
chunk2 = chunk3;
} else if (s->sectors[chunk3] + s->sectorcounts[chunk3] > sector_num) {
return chunk3;
} else {
chunk1 = chunk3;
}
}
return s->n_chunks; /* error */
}
static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num)
static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
{
BDRVDMGState *s = bs->opaque;
if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
int ret;
uint32_t chunk = search_chunk(s,sector_num);
if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) {
int ret;
uint32_t chunk = search_chunk(s, sector_num);
if(chunk>=s->n_chunks)
return -1;
if (chunk >= s->n_chunks) {
return -1;
}
s->current_chunk = s->n_chunks;
switch(s->types[chunk]) {
case 0x80000005: { /* zlib compressed */
int i;
s->current_chunk = s->n_chunks;
switch (s->types[chunk]) {
case 0x80000005: { /* zlib compressed */
/* we need to buffer, because only the chunk as whole can be
* inflated. */
ret = bdrv_pread(bs->file, s->offsets[chunk],
s->compressed_chunk, s->lengths[chunk]);
if (ret != s->lengths[chunk]) {
return -1;
}
/* we need to buffer, because only the chunk as whole can be
* inflated. */
i=0;
do {
ret = bdrv_pread(bs->file, s->offsets[chunk] + i,
s->compressed_chunk+i, s->lengths[chunk]-i);
if(ret<0 && errno==EINTR)
ret=0;
i+=ret;
} while(ret>=0 && ret+i<s->lengths[chunk]);
if (ret != s->lengths[chunk])
return -1;
s->zstream.next_in = s->compressed_chunk;
s->zstream.avail_in = s->lengths[chunk];
s->zstream.next_out = s->uncompressed_chunk;
s->zstream.avail_out = 512*s->sectorcounts[chunk];
ret = inflateReset(&s->zstream);
if(ret != Z_OK)
return -1;
ret = inflate(&s->zstream, Z_FINISH);
if(ret != Z_STREAM_END || s->zstream.total_out != 512*s->sectorcounts[chunk])
return -1;
break; }
case 1: /* copy */
ret = bdrv_pread(bs->file, s->offsets[chunk],
s->zstream.next_in = s->compressed_chunk;
s->zstream.avail_in = s->lengths[chunk];
s->zstream.next_out = s->uncompressed_chunk;
s->zstream.avail_out = 512 * s->sectorcounts[chunk];
ret = inflateReset(&s->zstream);
if (ret != Z_OK) {
return -1;
}
ret = inflate(&s->zstream, Z_FINISH);
if (ret != Z_STREAM_END ||
s->zstream.total_out != 512 * s->sectorcounts[chunk]) {
return -1;
}
break; }
case 1: /* copy */
ret = bdrv_pread(bs->file, s->offsets[chunk],
s->uncompressed_chunk, s->lengths[chunk]);
if (ret != s->lengths[chunk])
return -1;
break;
case 2: /* zero */
memset(s->uncompressed_chunk, 0, 512*s->sectorcounts[chunk]);
break;
}
s->current_chunk = chunk;
if (ret != s->lengths[chunk]) {
return -1;
}
break;
case 2: /* zero */
memset(s->uncompressed_chunk, 0, 512 * s->sectorcounts[chunk]);
break;
}
s->current_chunk = chunk;
}
return 0;
}
@@ -339,12 +394,14 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
BDRVDMGState *s = bs->opaque;
int i;
for(i=0;i<nb_sectors;i++) {
uint32_t sector_offset_in_chunk;
if(dmg_read_chunk(bs, sector_num+i) != 0)
return -1;
sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk];
memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512);
for (i = 0; i < nb_sectors; i++) {
uint32_t sector_offset_in_chunk;
if (dmg_read_chunk(bs, sector_num + i) != 0) {
return -1;
}
sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk];
memcpy(buf + i * 512,
s->uncompressed_chunk + sector_offset_in_chunk * 512, 512);
}
return 0;
}
@@ -376,12 +433,12 @@ static void dmg_close(BlockDriverState *bs)
}
static BlockDriver bdrv_dmg = {
.format_name = "dmg",
.instance_size = sizeof(BDRVDMGState),
.bdrv_probe = dmg_probe,
.bdrv_open = dmg_open,
.bdrv_read = dmg_co_read,
.bdrv_close = dmg_close,
.format_name = "dmg",
.instance_size = sizeof(BDRVDMGState),
.bdrv_probe = dmg_probe,
.bdrv_open = dmg_open,
.bdrv_read = dmg_co_read,
.bdrv_close = dmg_close,
};
static void bdrv_dmg_init(void)
+4 -1
View File
@@ -143,12 +143,13 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi));
iTask->do_retry = 1;
goto out;
}
if (status != SCSI_STATUS_GOOD) {
error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi));
error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
}
out:
@@ -868,6 +869,7 @@ retry:
scsi_free_scsi_task(iTask.task);
iTask.task = NULL;
}
iTask.complete = 0;
goto retry;
}
@@ -964,6 +966,7 @@ retry:
}
if (iTask.do_retry) {
iTask.complete = 0;
goto retry;
}
+23 -14
View File
@@ -95,7 +95,14 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
}
g_slice_free(MirrorOp, op);
qemu_coroutine_enter(s->common.co, NULL);
/* Enter coroutine when it is not sleeping. The coroutine sleeps to
* rate-limit itself. The coroutine will eventually resume since there is
* a sleep timeout so don't wake it early.
*/
if (s->common.busy) {
qemu_coroutine_enter(s->common.co, NULL);
}
}
static void mirror_write_complete(void *opaque, int ret)
@@ -136,11 +143,12 @@ static void mirror_read_complete(void *opaque, int ret)
mirror_write_complete, op);
}
static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
{
BlockDriverState *source = s->common.bs;
int nb_sectors, sectors_per_chunk, nb_chunks;
int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
uint64_t delay_ns;
MirrorOp *op;
s->sector_num = hbitmap_iter_next(&s->hbi);
@@ -227,7 +235,12 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
nb_chunks += added_chunks;
next_sector += added_sectors;
next_chunk += added_chunks;
} while (next_sector < end);
if (!s->synced && s->common.speed) {
delay_ns = ratelimit_calculate_delay(&s->limit, added_sectors);
} else {
delay_ns = 0;
}
} while (delay_ns == 0 && next_sector < end);
/* Allocate a MirrorOp that is used as an AIO callback. */
op = g_slice_new(MirrorOp);
@@ -263,6 +276,7 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
trace_mirror_one_iteration(s, sector_num, nb_sectors);
bdrv_aio_readv(source, sector_num, &op->qiov, nb_sectors,
mirror_read_complete, op);
return delay_ns;
}
static void mirror_free_init(MirrorBlockJob *s)
@@ -358,7 +372,7 @@ static void coroutine_fn mirror_run(void *opaque)
bdrv_dirty_iter_init(bs, &s->hbi);
last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
for (;;) {
uint64_t delay_ns;
uint64_t delay_ns = 0;
int64_t cnt;
bool should_complete;
@@ -382,8 +396,10 @@ static void coroutine_fn mirror_run(void *opaque)
qemu_coroutine_yield();
continue;
} else if (cnt != 0) {
mirror_iteration(s);
continue;
delay_ns = mirror_iteration(s);
if (delay_ns == 0) {
continue;
}
}
}
@@ -428,17 +444,10 @@ static void coroutine_fn mirror_run(void *opaque)
}
ret = 0;
trace_mirror_before_sleep(s, cnt, s->synced);
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
if (!s->synced) {
/* Publish progress */
s->common.offset = (end - cnt) * BDRV_SECTOR_SIZE;
if (s->common.speed) {
delay_ns = ratelimit_calculate_delay(&s->limit, sectors_per_chunk);
} else {
delay_ns = 0;
}
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
if (block_job_is_cancelled(&s->common)) {
break;
+12 -2
View File
@@ -49,9 +49,9 @@ typedef struct BDRVParallelsState {
CoMutex lock;
uint32_t *catalog_bitmap;
int catalog_size;
unsigned int catalog_size;
int tracks;
unsigned int tracks;
} BDRVParallelsState;
static int parallels_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -92,8 +92,18 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
bs->total_sectors = le32_to_cpu(ph.nb_sectors);
s->tracks = le32_to_cpu(ph.tracks);
if (s->tracks == 0) {
error_setg(errp, "Invalid image: Zero sectors per track");
ret = -EINVAL;
goto fail;
}
s->catalog_size = le32_to_cpu(ph.catalog_entries);
if (s->catalog_size > INT_MAX / 4) {
error_setg(errp, "Catalog too large");
ret = -EFBIG;
goto fail;
}
s->catalog_bitmap = g_malloc(s->catalog_size * 4);
ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4);
+1
View File
@@ -471,6 +471,7 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
case QTYPE_QERROR: {
QString *value = qerror_human((QError *)obj);
func_fprintf(f, "%s", qstring_get_str(value));
QDECREF(value);
break;
}
case QTYPE_NONE:
+37 -6
View File
@@ -48,9 +48,10 @@ typedef struct QCowHeader {
uint64_t size; /* in bytes */
uint8_t cluster_bits;
uint8_t l2_bits;
uint16_t padding;
uint32_t crypt_method;
uint64_t l1_table_offset;
} QCowHeader;
} QEMU_PACKED QCowHeader;
#define L2_CACHE_SIZE 16
@@ -60,7 +61,7 @@ typedef struct BDRVQcowState {
int cluster_sectors;
int l2_bits;
int l2_size;
int l1_size;
unsigned int l1_size;
uint64_t cluster_offset_mask;
uint64_t l1_table_offset;
uint64_t *l1_table;
@@ -96,7 +97,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVQcowState *s = bs->opaque;
int len, i, shift, ret;
unsigned int len, i, shift;
int ret;
QCowHeader header;
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
@@ -125,10 +127,25 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
if (header.size <= 1 || header.cluster_bits < 9) {
if (header.size <= 1) {
error_setg(errp, "Image size is too small (must be at least 2 bytes)");
ret = -EINVAL;
goto fail;
}
if (header.cluster_bits < 9 || header.cluster_bits > 16) {
error_setg(errp, "Cluster size must be between 512 and 64k");
ret = -EINVAL;
goto fail;
}
/* l2_bits specifies number of entries; storing a uint64_t in each entry,
* so bytes = num_entries << 3. */
if (header.l2_bits < 9 - 3 || header.l2_bits > 16 - 3) {
error_setg(errp, "L2 table size must be between 512 and 64k");
ret = -EINVAL;
goto fail;
}
if (header.crypt_method > QCOW_CRYPT_AES) {
ret = -EINVAL;
goto fail;
@@ -147,7 +164,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
/* read the level 1 table */
shift = s->cluster_bits + s->l2_bits;
s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
if (header.size > UINT64_MAX - (1LL << shift)) {
error_setg(errp, "Image too large");
ret = -EINVAL;
goto fail;
} else {
uint64_t l1_size = (header.size + (1LL << shift) - 1) >> shift;
if (l1_size > INT_MAX / sizeof(uint64_t)) {
error_setg(errp, "Image too large");
ret = -EINVAL;
goto fail;
}
s->l1_size = l1_size;
}
s->l1_table_offset = header.l1_table_offset;
s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
@@ -171,7 +200,9 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
if (len > 1023) {
len = 1023;
error_setg(errp, "Backing file name too long");
ret = -EINVAL;
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
bs->backing_file, len);
+1 -10
View File
@@ -55,7 +55,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
}
}
if (new_l1_size > INT_MAX) {
if (new_l1_size > INT_MAX / sizeof(uint64_t)) {
return -EFBIG;
}
@@ -359,15 +359,6 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
struct iovec iov;
int n, ret;
/*
* If this is the last cluster and it is only partially used, we must only
* copy until the end of the image, or bdrv_check_request will fail for the
* bdrv_read/write calls below.
*/
if (start_sect + n_end > bs->total_sectors) {
n_end = bs->total_sectors - start_sect;
}
n = n_end - n_start;
if (n <= 0) {
return 0;
+68 -53
View File
@@ -28,7 +28,7 @@
#include "qemu/range.h"
#include "qapi/qmp/types.h"
static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size);
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size);
static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length,
int addend, enum qcow2_discard_type type);
@@ -40,8 +40,10 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
int qcow2_refcount_init(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
int ret, refcount_table_size2, i;
unsigned int refcount_table_size2, i;
int ret;
assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t));
refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
s->refcount_table = g_malloc(refcount_table_size2);
if (s->refcount_table_size > 0) {
@@ -87,7 +89,7 @@ static int load_refcount_block(BlockDriverState *bs,
static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
{
BDRVQcowState *s = bs->opaque;
int refcount_table_index, block_index;
uint64_t refcount_table_index, block_index;
int64_t refcount_block_offset;
int ret;
uint16_t *refcount_block;
@@ -191,10 +193,11 @@ static int alloc_refcount_block(BlockDriverState *bs,
* they can describe them themselves.
*
* - We need to consider that at this point we are inside update_refcounts
* and doing the initial refcount increase. This means that some clusters
* have already been allocated by the caller, but their refcount isn't
* accurate yet. free_cluster_index tells us where this allocation ends
* as long as we don't overwrite it by freeing clusters.
* and potentially doing an initial refcount increase. This means that
* some clusters have already been allocated by the caller, but their
* refcount isn't accurate yet. If we allocate clusters for metadata, we
* need to return -EAGAIN to signal the caller that it needs to restart
* the search for free clusters.
*
* - alloc_clusters_noref and qcow2_free_clusters may load a different
* refcount block into the cache
@@ -279,7 +282,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
}
s->refcount_table[refcount_table_index] = new_block;
return 0;
/* The new refcount block may be where the caller intended to put its
* data, so let it restart the search. */
return -EAGAIN;
}
ret = qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block);
@@ -302,8 +308,11 @@ static int alloc_refcount_block(BlockDriverState *bs,
/* Calculate the number of refcount blocks needed so far */
uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
uint64_t blocks_used = (s->free_cluster_index +
refcount_block_clusters - 1) / refcount_block_clusters;
uint64_t blocks_used = DIV_ROUND_UP(cluster_index, refcount_block_clusters);
if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {
return -EFBIG;
}
/* And now we need at least one block more for the new metadata */
uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);
@@ -336,8 +345,6 @@ static int alloc_refcount_block(BlockDriverState *bs,
uint16_t *new_blocks = g_malloc0(blocks_clusters * s->cluster_size);
uint64_t *new_table = g_malloc0(table_size * sizeof(uint64_t));
assert(meta_offset >= (s->free_cluster_index * s->cluster_size));
/* Fill the new refcount table */
memcpy(new_table, s->refcount_table,
s->refcount_table_size * sizeof(uint64_t));
@@ -400,18 +407,19 @@ static int alloc_refcount_block(BlockDriverState *bs,
s->refcount_table_size = table_size;
s->refcount_table_offset = table_offset;
/* Free old table. Remember, we must not change free_cluster_index */
uint64_t old_free_cluster_index = s->free_cluster_index;
/* Free old table. */
qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t),
QCOW2_DISCARD_OTHER);
s->free_cluster_index = old_free_cluster_index;
ret = load_refcount_block(bs, new_block, (void**) refcount_block);
if (ret < 0) {
return ret;
}
return 0;
/* If we were trying to do the initial refcount update for some cluster
* allocation, we might have used the same clusters to store newly
* allocated metadata. Make the caller search some new space. */
return -EAGAIN;
fail_table:
g_free(new_table);
@@ -626,15 +634,16 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
/* return < 0 if error */
static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size)
{
BDRVQcowState *s = bs->opaque;
int i, nb_clusters, refcount;
uint64_t i, nb_clusters;
int refcount;
nb_clusters = size_to_clusters(s, size);
retry:
for(i = 0; i < nb_clusters; i++) {
int64_t next_cluster_index = s->free_cluster_index++;
uint64_t next_cluster_index = s->free_cluster_index++;
refcount = get_refcount(bs, next_cluster_index);
if (refcount < 0) {
@@ -651,18 +660,21 @@ retry:
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
}
int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
{
int64_t offset;
int ret;
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
offset = alloc_clusters_noref(bs, size);
if (offset < 0) {
return offset;
}
do {
offset = alloc_clusters_noref(bs, size);
if (offset < 0) {
return offset;
}
ret = update_refcount(bs, offset, size, 1, QCOW2_DISCARD_NEVER);
} while (ret == -EAGAIN);
ret = update_refcount(bs, offset, size, 1, QCOW2_DISCARD_NEVER);
if (ret < 0) {
return ret;
}
@@ -675,33 +687,36 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
{
BDRVQcowState *s = bs->opaque;
uint64_t cluster_index;
uint64_t old_free_cluster_index;
int i, refcount, ret;
uint64_t i;
int refcount, ret;
/* Check how many clusters there are free */
cluster_index = offset >> s->cluster_bits;
for(i = 0; i < nb_clusters; i++) {
refcount = get_refcount(bs, cluster_index++);
if (refcount < 0) {
return refcount;
} else if (refcount != 0) {
break;
}
assert(nb_clusters >= 0);
if (nb_clusters == 0) {
return 0;
}
/* And then allocate them */
old_free_cluster_index = s->free_cluster_index;
s->free_cluster_index = cluster_index + i;
do {
/* Check how many clusters there are free */
cluster_index = offset >> s->cluster_bits;
for(i = 0; i < nb_clusters; i++) {
refcount = get_refcount(bs, cluster_index++);
if (refcount < 0) {
return refcount;
} else if (refcount != 0) {
break;
}
}
/* And then allocate them */
ret = update_refcount(bs, offset, i << s->cluster_bits, 1,
QCOW2_DISCARD_NEVER);
} while (ret == -EAGAIN);
ret = update_refcount(bs, offset, i << s->cluster_bits, 1,
QCOW2_DISCARD_NEVER);
if (ret < 0) {
return ret;
}
s->free_cluster_index = old_free_cluster_index;
return i;
}
@@ -1004,8 +1019,7 @@ static void inc_refcounts(BlockDriverState *bs,
int64_t offset, int64_t size)
{
BDRVQcowState *s = bs->opaque;
int64_t start, last, cluster_offset;
int k;
uint64_t start, last, cluster_offset, k;
if (size <= 0)
return;
@@ -1015,11 +1029,7 @@ static void inc_refcounts(BlockDriverState *bs,
for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size) {
k = cluster_offset >> s->cluster_bits;
if (k < 0) {
fprintf(stderr, "ERROR: invalid cluster offset=0x%" PRIx64 "\n",
cluster_offset);
res->corruptions++;
} else if (k >= refcount_table_size) {
if (k >= refcount_table_size) {
fprintf(stderr, "Warning: cluster offset=0x%" PRIx64 " is after "
"the end of the image file, can't properly check refcounts.\n",
cluster_offset);
@@ -1460,14 +1470,19 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix)
{
BDRVQcowState *s = bs->opaque;
int64_t size, i, highest_cluster;
int nb_clusters, refcount1, refcount2;
int64_t size, i, highest_cluster, nb_clusters;
int refcount1, refcount2;
QCowSnapshot *sn;
uint16_t *refcount_table;
int ret;
size = bdrv_getlength(bs->file);
nb_clusters = size_to_clusters(s, size);
if (nb_clusters > INT_MAX) {
res->check_errors++;
return -EFBIG;
}
refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t));
res->bfi.total_clusters =
+9 -26
View File
@@ -26,31 +26,6 @@
#include "block/block_int.h"
#include "block/qcow2.h"
typedef struct QEMU_PACKED QCowSnapshotHeader {
/* header is 8 byte aligned */
uint64_t l1_table_offset;
uint32_t l1_size;
uint16_t id_str_size;
uint16_t name_size;
uint32_t date_sec;
uint32_t date_nsec;
uint64_t vm_clock_nsec;
uint32_t vm_state_size;
uint32_t extra_data_size; /* for extension */
/* extra data follows */
/* id_str follows */
/* name follows */
} QCowSnapshotHeader;
typedef struct QEMU_PACKED QCowSnapshotExtraData {
uint64_t vm_state_size_large;
uint64_t disk_size;
} QCowSnapshotExtraData;
void qcow2_free_snapshots(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
@@ -357,6 +332,10 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
uint64_t *l1_table = NULL;
int64_t l1_table_offset;
if (s->nb_snapshots >= QCOW_MAX_SNAPSHOTS) {
return -EFBIG;
}
memset(sn, 0, sizeof(*sn));
/* Generate an ID if it wasn't passed */
@@ -694,7 +673,11 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
sn = &s->snapshots[snapshot_index];
/* Allocate and read in the snapshot's L1 table */
new_l1_bytes = s->l1_size * sizeof(uint64_t);
if (sn->l1_size > QCOW_MAX_L1_SIZE) {
error_report("Snapshot L1 table too large");
return -EFBIG;
}
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
+158 -40
View File
@@ -269,12 +269,15 @@ static int qcow2_mark_clean(BlockDriverState *bs)
BDRVQcowState *s = bs->opaque;
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
int ret = bdrv_flush(bs);
int ret;
s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
ret = bdrv_flush(bs);
if (ret < 0) {
return ret;
}
s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
return qcow2_update_header(bs);
}
return 0;
@@ -329,6 +332,32 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
return ret;
}
static int validate_table_offset(BlockDriverState *bs, uint64_t offset,
uint64_t entries, size_t entry_len)
{
BDRVQcowState *s = bs->opaque;
uint64_t size;
/* Use signed INT64_MAX as the maximum even for uint64_t header fields,
* because values will be passed to qemu functions taking int64_t. */
if (entries > INT64_MAX / entry_len) {
return -EINVAL;
}
size = entries * entry_len;
if (INT64_MAX - size < offset) {
return -EINVAL;
}
/* Tables must be cluster aligned */
if (offset & (s->cluster_size - 1)) {
return -EINVAL;
}
return 0;
}
static QemuOptsList qcow2_runtime_opts = {
.name = "qcow2",
.head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head),
@@ -419,7 +448,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVQcowState *s = bs->opaque;
int len, i, ret = 0;
unsigned int len, i;
int ret = 0;
QCowHeader header;
QemuOpts *opts;
Error *local_err = NULL;
@@ -460,6 +490,18 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
s->qcow_version = header.version;
/* Initialise cluster size */
if (header.cluster_bits < MIN_CLUSTER_BITS ||
header.cluster_bits > MAX_CLUSTER_BITS) {
error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
ret = -EINVAL;
goto fail;
}
s->cluster_bits = header.cluster_bits;
s->cluster_size = 1 << s->cluster_bits;
s->cluster_sectors = 1 << (s->cluster_bits - 9);
/* Initialise version 3 header fields */
if (header.version == 2) {
header.incompatible_features = 0;
@@ -473,6 +515,18 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
be64_to_cpus(&header.autoclear_features);
be32_to_cpus(&header.refcount_order);
be32_to_cpus(&header.header_length);
if (header.header_length < 104) {
error_setg(errp, "qcow2 header too short");
ret = -EINVAL;
goto fail;
}
}
if (header.header_length > s->cluster_size) {
error_setg(errp, "qcow2 header exceeds cluster size");
ret = -EINVAL;
goto fail;
}
if (header.header_length > sizeof(header)) {
@@ -487,6 +541,12 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
}
if (header.backing_file_offset > s->cluster_size) {
error_setg(errp, "Invalid backing file offset");
ret = -EINVAL;
goto fail;
}
if (header.backing_file_offset) {
ext_end = header.backing_file_offset;
} else {
@@ -529,12 +589,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
s->refcount_order = header.refcount_order;
if (header.cluster_bits < MIN_CLUSTER_BITS ||
header.cluster_bits > MAX_CLUSTER_BITS) {
error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
ret = -EINVAL;
goto fail;
}
if (header.crypt_method > QCOW_CRYPT_AES) {
error_setg(errp, "Unsupported encryption method: %i",
header.crypt_method);
@@ -545,23 +599,52 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
if (s->crypt_method_header) {
bs->encrypted = 1;
}
s->cluster_bits = header.cluster_bits;
s->cluster_size = 1 << s->cluster_bits;
s->cluster_sectors = 1 << (s->cluster_bits - 9);
s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
s->l2_size = 1 << s->l2_bits;
bs->total_sectors = header.size / 512;
s->csize_shift = (62 - (s->cluster_bits - 8));
s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
s->refcount_table_offset = header.refcount_table_offset;
s->refcount_table_size =
header.refcount_table_clusters << (s->cluster_bits - 3);
s->snapshots_offset = header.snapshots_offset;
s->nb_snapshots = header.nb_snapshots;
if (header.refcount_table_clusters > qcow2_max_refcount_clusters(s)) {
error_setg(errp, "Reference count table too large");
ret = -EINVAL;
goto fail;
}
ret = validate_table_offset(bs, s->refcount_table_offset,
s->refcount_table_size, sizeof(uint64_t));
if (ret < 0) {
error_setg(errp, "Invalid reference count table offset");
goto fail;
}
/* Snapshot table offset/length */
if (header.nb_snapshots > QCOW_MAX_SNAPSHOTS) {
error_setg(errp, "Too many snapshots");
ret = -EINVAL;
goto fail;
}
ret = validate_table_offset(bs, header.snapshots_offset,
header.nb_snapshots,
sizeof(QCowSnapshotHeader));
if (ret < 0) {
error_setg(errp, "Invalid snapshot table offset");
goto fail;
}
/* read the level 1 table */
if (header.l1_size > QCOW_MAX_L1_SIZE) {
error_setg(errp, "Active L1 table too large");
ret = -EFBIG;
goto fail;
}
s->l1_size = header.l1_size;
l1_vm_state_index = size_to_l1(s, header.size);
@@ -579,7 +662,16 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
ret = -EINVAL;
goto fail;
}
ret = validate_table_offset(bs, header.l1_table_offset,
header.l1_size, sizeof(uint64_t));
if (ret < 0) {
error_setg(errp, "Invalid L1 table offset");
goto fail;
}
s->l1_table_offset = header.l1_table_offset;
if (s->l1_size > 0) {
s->l1_table = g_malloc0(
align_offset(s->l1_size * sizeof(uint64_t), 512));
@@ -625,8 +717,10 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
if (len > 1023) {
len = 1023;
if (len > MIN(1023, s->cluster_size - header.backing_file_offset)) {
error_setg(errp, "Backing file name too long");
ret = -EINVAL;
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
bs->backing_file, len);
@@ -637,6 +731,10 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
bs->backing_file[len] = '\0';
}
/* Internal snapshots */
s->snapshots_offset = header.snapshots_offset;
s->nb_snapshots = header.nb_snapshots;
ret = qcow2_read_snapshots(bs);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read snapshots");
@@ -792,11 +890,25 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
return 0;
}
/* We have nothing to do for QCOW2 reopen, stubs just return
* success */
/* We have no actual commit/abort logic for qcow2, but we need to write out any
* unwritten data if we reopen read-only. */
static int qcow2_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
int ret;
if ((state->flags & BDRV_O_RDWR) == 0) {
ret = bdrv_flush(state->bs);
if (ret < 0) {
return ret;
}
ret = qcow2_mark_clean(state->bs);
if (ret < 0) {
return ret;
}
}
return 0;
}
@@ -1471,8 +1583,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
* size for any qcow2 image.
*/
BlockDriverState* bs;
QCowHeader header;
uint8_t* refcount_table;
QCowHeader *header;
uint64_t* refcount_table;
Error *local_err = NULL;
int ret;
@@ -1489,38 +1601,43 @@ static int qcow2_create2(const char *filename, int64_t total_size,
}
/* Write the header */
memset(&header, 0, sizeof(header));
header.magic = cpu_to_be32(QCOW_MAGIC);
header.version = cpu_to_be32(version);
header.cluster_bits = cpu_to_be32(cluster_bits);
header.size = cpu_to_be64(0);
header.l1_table_offset = cpu_to_be64(0);
header.l1_size = cpu_to_be32(0);
header.refcount_table_offset = cpu_to_be64(cluster_size);
header.refcount_table_clusters = cpu_to_be32(1);
header.refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT);
header.header_length = cpu_to_be32(sizeof(header));
QEMU_BUILD_BUG_ON((1 << MIN_CLUSTER_BITS) < sizeof(*header));
header = g_malloc0(cluster_size);
*header = (QCowHeader) {
.magic = cpu_to_be32(QCOW_MAGIC),
.version = cpu_to_be32(version),
.cluster_bits = cpu_to_be32(cluster_bits),
.size = cpu_to_be64(0),
.l1_table_offset = cpu_to_be64(0),
.l1_size = cpu_to_be32(0),
.refcount_table_offset = cpu_to_be64(cluster_size),
.refcount_table_clusters = cpu_to_be32(1),
.refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT),
.header_length = cpu_to_be32(sizeof(*header)),
};
if (flags & BLOCK_FLAG_ENCRYPT) {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
header->crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
} else {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
}
if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) {
header.compatible_features |=
header->compatible_features |=
cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS);
}
ret = bdrv_pwrite(bs, 0, &header, sizeof(header));
ret = bdrv_pwrite(bs, 0, header, cluster_size);
g_free(header);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not write qcow2 header");
goto out;
}
/* Write an empty refcount table */
refcount_table = g_malloc0(cluster_size);
ret = bdrv_pwrite(bs, cluster_size, refcount_table, cluster_size);
/* Write a refcount table with one refcount block */
refcount_table = g_malloc0(2 * cluster_size);
refcount_table[0] = cpu_to_be64(2 * cluster_size);
ret = bdrv_pwrite(bs, cluster_size, refcount_table, 2 * cluster_size);
g_free(refcount_table);
if (ret < 0) {
@@ -1544,7 +1661,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
goto out;
}
ret = qcow2_alloc_clusters(bs, 2 * cluster_size);
ret = qcow2_alloc_clusters(bs, 3 * cluster_size);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not allocate clusters for qcow2 "
"header and refcount table");
@@ -1588,7 +1705,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
ret = bdrv_open(bs, filename, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB, drv, &local_err);
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING,
drv, &local_err);
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
goto out;
+44 -4
View File
@@ -38,6 +38,15 @@
#define QCOW_CRYPT_AES 1
#define QCOW_MAX_CRYPT_CLUSTERS 32
#define QCOW_MAX_SNAPSHOTS 65536
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
#define QCOW_MAX_REFTABLE_SIZE 0x800000
/* 32 MB L1 table is enough for 2 PB images at 64k cluster size
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
#define QCOW_MAX_L1_SIZE 0x2000000
/* indicate that the refcount of the referenced cluster is exactly one. */
#define QCOW_OFLAG_COPIED (1ULL << 63)
@@ -97,6 +106,32 @@ typedef struct QCowHeader {
uint32_t header_length;
} QEMU_PACKED QCowHeader;
typedef struct QEMU_PACKED QCowSnapshotHeader {
/* header is 8 byte aligned */
uint64_t l1_table_offset;
uint32_t l1_size;
uint16_t id_str_size;
uint16_t name_size;
uint32_t date_sec;
uint32_t date_nsec;
uint64_t vm_clock_nsec;
uint32_t vm_state_size;
uint32_t extra_data_size; /* for extension */
/* extra data follows */
/* id_str follows */
/* name follows */
} QCowSnapshotHeader;
typedef struct QEMU_PACKED QCowSnapshotExtraData {
uint64_t vm_state_size_large;
uint64_t disk_size;
} QCowSnapshotExtraData;
typedef struct QCowSnapshot {
uint64_t l1_table_offset;
uint32_t l1_size;
@@ -191,8 +226,8 @@ typedef struct BDRVQcowState {
uint64_t *refcount_table;
uint64_t refcount_table_offset;
uint32_t refcount_table_size;
int64_t free_cluster_index;
int64_t free_byte_offset;
uint64_t free_cluster_index;
uint64_t free_byte_offset;
CoMutex lock;
@@ -202,7 +237,7 @@ typedef struct BDRVQcowState {
AES_KEY aes_decrypt_key;
uint64_t snapshots_offset;
int snapshots_size;
int nb_snapshots;
unsigned int nb_snapshots;
QCowSnapshot *snapshots;
int flags;
@@ -383,6 +418,11 @@ static inline int64_t qcow2_vm_state_offset(BDRVQcowState *s)
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
}
static inline uint64_t qcow2_max_refcount_clusters(BDRVQcowState *s)
{
return QCOW_MAX_REFTABLE_SIZE >> s->cluster_bits;
}
static inline int qcow2_get_cluster_type(uint64_t l2_entry)
{
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
@@ -431,7 +471,7 @@ void qcow2_refcount_close(BlockDriverState *bs);
int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
int addend, enum qcow2_discard_type type);
int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size);
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
int nb_clusters);
int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
+2 -2
View File
@@ -2082,6 +2082,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
/* we don't need to update entire object */
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
inode = g_malloc(datalen);
/* refresh inode. */
fd = connect_to_sdog(s);
@@ -2105,8 +2106,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
goto cleanup;
}
inode = (SheepdogInode *)g_malloc(datalen);
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
s->inode.nr_copies, datalen, 0, s->cache_flags);
@@ -2120,6 +2119,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
s->inode.name, s->inode.snap_id, s->inode.vdi_id);
cleanup:
g_free(inode);
closesocket(fd);
return ret;
}
+29 -2
View File
@@ -120,6 +120,11 @@ typedef unsigned char uuid_t[16];
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
/* max blocks in image is (0xffffffff / 4) */
#define VDI_BLOCKS_IN_IMAGE_MAX 0x3fffffff
#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
(uint64_t)DEFAULT_CLUSTER_SIZE)
#if !defined(CONFIG_UUID)
static inline void uuid_generate(uuid_t out)
{
@@ -384,6 +389,13 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
vdi_header_print(&header);
#endif
if (header.disk_size > VDI_DISK_SIZE_MAX) {
logout("disk size is 0x%" PRIx64 ", max supported is 0x%" PRIx64,
header.disk_size, VDI_DISK_SIZE_MAX);
ret = -ENOTSUP;
goto fail;
}
if (header.disk_size % SECTOR_SIZE != 0) {
/* 'VBoxManage convertfromraw' can create images with odd disk sizes.
We accept them but round the disk size to the next multiple of
@@ -416,7 +428,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
logout("unsupported sector size %u B\n", header.sector_size);
ret = -ENOTSUP;
goto fail;
} else if (header.block_size != 1 * MiB) {
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
logout("unsupported block size %u B\n", header.block_size);
ret = -ENOTSUP;
goto fail;
@@ -433,6 +445,11 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
logout("parent uuid != 0, unsupported\n");
ret = -ENOTSUP;
goto fail;
} else if (header.blocks_in_image > VDI_BLOCKS_IN_IMAGE_MAX) {
logout("too many blocks %u, max is %u)",
header.blocks_in_image, VDI_BLOCKS_IN_IMAGE_MAX);
ret = -ENOTSUP;
goto fail;
}
bs->total_sectors = header.disk_size / SECTOR_SIZE;
@@ -681,11 +698,20 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
options++;
}
if (bytes > VDI_DISK_SIZE_MAX) {
result = -ENOTSUP;
logout("image size (size is 0x%" PRIx64
", max supported is 0x%" PRIx64 ")",
bytes, VDI_DISK_SIZE_MAX);
goto exit;
}
fd = qemu_open(filename,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (fd < 0) {
return -errno;
result = -errno;
goto exit;
}
/* We need enough blocks to store the given disk size,
@@ -746,6 +772,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
result = -errno;
}
exit:
return result;
}
+10 -2
View File
@@ -785,12 +785,20 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
le32_to_cpus(&s->logical_sector_size);
le32_to_cpus(&s->physical_sector_size);
if (s->logical_sector_size == 0 || s->params.block_size == 0) {
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
ret = -EINVAL;
goto exit;
}
/* both block_size and sector_size are guaranteed powers of 2 */
/* only 2 supported sector sizes */
if (s->logical_sector_size != 512 && s->logical_sector_size != 4096) {
ret = -EINVAL;
goto exit;
}
/* Both block_size and sector_size are guaranteed powers of 2, below.
Due to range checks above, s->sectors_per_block can never be < 256 */
s->sectors_per_block = s->params.block_size / s->logical_sector_size;
s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
(uint64_t)s->logical_sector_size /
+1 -1
View File
@@ -1689,7 +1689,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
}
if (backing_file) {
BlockDriverState *bs = bdrv_new("");
ret = bdrv_open(bs, backing_file, NULL, 0, NULL, errp);
ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp);
if (ret != 0) {
bdrv_unref(bs);
return ret;
+28 -4
View File
@@ -45,6 +45,8 @@ enum vhd_type {
// Seconds since Jan 1, 2000 0:00:00 (UTC)
#define VHD_TIMESTAMP_BASE 946684800
#define VHD_MAX_SECTORS (65535LL * 255 * 255)
// always big-endian
typedef struct vhd_footer {
char creator[8]; // "conectix"
@@ -164,6 +166,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
VHDDynDiskHeader *dyndisk_header;
uint8_t buf[HEADER_SIZE];
uint32_t checksum;
uint64_t computed_size;
int disk_type = VHD_DYNAMIC;
int ret;
@@ -221,7 +224,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Allow a maximum disk size of approximately 2 TB */
if (bs->total_sectors >= 65535LL * 255 * 255) {
if (bs->total_sectors >= VHD_MAX_SECTORS) {
ret = -EFBIG;
goto fail;
}
@@ -241,10 +244,31 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
}
s->block_size = be32_to_cpu(dyndisk_header->block_size);
if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) {
error_setg(errp, "Invalid block size %" PRIu32, s->block_size);
ret = -EINVAL;
goto fail;
}
s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
s->pagetable = g_malloc(s->max_table_entries * 4);
if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) {
ret = -EINVAL;
goto fail;
}
if (s->max_table_entries > (VHD_MAX_SECTORS * 512) / s->block_size) {
ret = -EINVAL;
goto fail;
}
computed_size = (uint64_t) s->max_table_entries * s->block_size;
if (computed_size < bs->total_sectors * 512) {
ret = -EINVAL;
goto fail;
}
s->pagetable = qemu_blockalign(bs, s->max_table_entries * 4);
s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
@@ -297,7 +321,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
return 0;
fail:
g_free(s->pagetable);
qemu_vfree(s->pagetable);
#ifdef CACHE
g_free(s->pageentry_u8);
#endif
@@ -819,7 +843,7 @@ static int vpc_has_zero_init(BlockDriverState *bs)
static void vpc_close(BlockDriverState *bs)
{
BDRVVPCState *s = bs->opaque;
g_free(s->pagetable);
qemu_vfree(s->pagetable);
#ifdef CACHE
g_free(s->pageentry_u8);
#endif
+4 -2
View File
@@ -788,7 +788,9 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
s->current_mapping->path=buffer;
s->current_mapping->read_only =
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
}
} else {
g_free(buffer);
}
}
closedir(dir);
@@ -1866,7 +1868,7 @@ static int check_directory_consistency(BDRVVVFATState *s,
if (s->used_clusters[cluster_num] & USED_ANY) {
fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
return 0;
goto fail;
}
s->used_clusters[cluster_num] = USED_DIRECTORY;
+7 -2
View File
@@ -27,8 +27,9 @@ static void nbd_accept(void *opaque)
socklen_t addr_len = sizeof(addr);
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
if (fd >= 0) {
nbd_client_new(NULL, fd, nbd_client_put);
if (fd >= 0 && !nbd_client_new(NULL, fd, nbd_client_put)) {
shutdown(fd, 2);
close(fd);
}
}
@@ -91,6 +92,10 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
}
if (!bdrv_is_inserted(bs)) {
error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
return;
}
if (!has_writable) {
writable = false;
+9 -2
View File
@@ -334,7 +334,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
if (error_is_set(&error)) {
error_propagate(errp, error);
return NULL;
goto err_no_opts;
}
qemu_opts_absorb_qdict(opts, bs_opts, &error);
@@ -535,8 +535,9 @@ err:
QTAILQ_REMOVE(&drives, dinfo, next);
g_free(dinfo);
early_err:
QDECREF(bs_opts);
qemu_opts_del(opts);
err_no_opts:
QDECREF(bs_opts);
return NULL;
}
@@ -867,6 +868,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
/* Actual block device init: Functionality shared with blockdev-add */
dinfo = blockdev_init(bs_opts, type, &local_err);
bs_opts = NULL;
if (dinfo == NULL) {
if (error_is_set(&local_err)) {
qerror_report_err(local_err);
@@ -903,6 +905,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
fail:
qemu_opts_del(legacy_opts);
QDECREF(bs_opts);
return dinfo;
}
@@ -1786,6 +1789,10 @@ void qmp_block_commit(const char *device,
*/
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
if (!has_speed) {
speed = 0;
}
/* drain all i/o before commits */
bdrv_drain_all();
Vendored
+5
View File
@@ -3520,6 +3520,11 @@ fi
int128=no
cat > $TMPC << EOF
#if defined(__clang_major__) && defined(__clang_minor__)
# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2))
# error __int128_t does not work in CLANG before 3.2
# endif
#endif
__int128_t a;
__uint128_t b;
int main (void) {
+11 -2
View File
@@ -36,8 +36,17 @@ typedef struct
static __thread CoroutineWin32 leader;
static __thread Coroutine *current;
CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
CoroutineAction action)
/* This function is marked noinline to prevent GCC from inlining it
* into coroutine_trampoline(). If we allow it to do that then it
* hoists the code to get the address of the TLS variable "current"
* out of the while() loop. This is an invalid transformation because
* the SwitchToFiber() call may be called when running thread A but
* return in thread B, and so we might be in a different thread
* context each time round the loop.
*/
CoroutineAction __attribute__((noinline))
qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
CoroutineAction action)
{
CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
+4 -2
View File
@@ -344,8 +344,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
}
#define MMUSUFFIX _cmmu
#undef GETPC
#define GETPC() ((uintptr_t)0)
#undef GETPC_ADJ
#define GETPC_ADJ 0
#undef GETRA
#define GETRA() ((uintptr_t)0)
#define SOFTMMU_CODE_ACCESS
#define SHIFT 0
+5 -7
View File
@@ -139,7 +139,6 @@ static const VMStateDescription vmstate_kbd = {
.name = "pckbd",
.version_id = 3,
.minimum_version_id = 3,
.minimum_version_id_old = 3,
.fields = (VMStateField []) {
VMSTATE_UINT8(write_cmd, KBDState),
VMSTATE_UINT8(status, KBDState),
@@ -168,12 +167,13 @@ You can see that there are several version fields:
- minimum_version_id: the minimum version_id that VMState is able to understand
for that device.
- minimum_version_id_old: For devices that were not able to port to vmstate, we can
assign a function that knows how to read this old state.
assign a function that knows how to read this old state. This field is
ignored if there is no load_state_old handler.
So, VMState is able to read versions from minimum_version_id to
version_id. And the function load_state_old() is able to load state
from minimum_version_id_old to minimum_version_id. This function is
deprecated and will be removed when no more users are left.
version_id. And the function load_state_old() (if present) is able to
load state from minimum_version_id_old to minimum_version_id. This
function is deprecated and will be removed when no more users are left.
=== Massaging functions ===
@@ -255,7 +255,6 @@ const VMStateDescription vmstate_ide_drive_pio_state = {
.name = "ide_drive/pio_state",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.pre_save = ide_drive_pio_pre_save,
.post_load = ide_drive_pio_post_load,
.fields = (VMStateField []) {
@@ -275,7 +274,6 @@ const VMStateDescription vmstate_ide_drive = {
.name = "ide_drive",
.version_id = 3,
.minimum_version_id = 0,
.minimum_version_id_old = 0,
.post_load = ide_drive_post_load,
.fields = (VMStateField []) {
.... several fields ....
+7 -7
View File
@@ -172,7 +172,7 @@ static void omap_timer_clk_update(void *opaque, int line, int on)
static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
{
omap_clk_adduser(timer->clk,
qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
qemu_allocate_irq(omap_timer_clk_update, timer, 0));
timer->rate = omap_clk_getrate(timer->clk);
}
@@ -2094,7 +2094,7 @@ static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
"omap-mpuio", 0x800);
memory_region_add_subregion(memory, base, &s->iomem);
omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
omap_clk_adduser(clk, qemu_allocate_irq(omap_mpuio_onoff, s, 0));
return s;
}
@@ -2397,7 +2397,7 @@ static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
"omap-pwl", 0x800);
memory_region_add_subregion(system_memory, base, &s->iomem);
omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
omap_clk_adduser(clk, qemu_allocate_irq(omap_pwl_clk_update, s, 0));
return s;
}
@@ -3481,8 +3481,8 @@ static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
{
s->codec = slave;
slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
slave->rx_swallow = qemu_allocate_irq(omap_mcbsp_i2s_swallow, s, 0);
slave->tx_start = qemu_allocate_irq(omap_mcbsp_i2s_start, s, 0);
}
/* LED Pulse Generators */
@@ -3630,7 +3630,7 @@ static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
memory_region_init_io(&s->iomem, NULL, &omap_lpg_ops, s, "omap-lpg", 0x800);
memory_region_add_subregion(system_memory, base, &s->iomem);
omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
omap_clk_adduser(clk, qemu_allocate_irq(omap_lpg_clk_update, s, 0));
return s;
}
@@ -3844,7 +3844,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
s->sdram_size = sdram_size;
s->sram_size = OMAP15XX_SRAM_SIZE;
s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
/* Clocks */
omap_clk_init(s);
+1 -1
View File
@@ -2260,7 +2260,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
s->sdram_size = sdram_size;
s->sram_size = OMAP242X_SRAM_SIZE;
s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
/* Clocks */
omap_clk_init(s);
+8 -4
View File
@@ -742,7 +742,7 @@ static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
{
PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
int i;
int i, v;
s->enable = qemu_get_be32(f);
@@ -756,7 +756,11 @@ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_8s(f, &s->ssrsa);
qemu_get_8s(f, &s->ssacd);
s->rx_level = qemu_get_byte(f);
v = qemu_get_byte(f);
if (v < 0 || v > ARRAY_SIZE(s->rx_fifo)) {
return -EINVAL;
}
s->rx_level = v;
s->rx_start = 0;
for (i = 0; i < s->rx_level; i ++)
s->rx_fifo[i] = qemu_get_byte(f);
@@ -2053,7 +2057,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
s->reset = qemu_allocate_irq(pxa2xx_reset, s, 0);
/* SDRAM & Internal Memory Storage */
memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size);
@@ -2184,7 +2188,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
s->reset = qemu_allocate_irq(pxa2xx_reset, s, 0);
/* SDRAM & Internal Memory Storage */
memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size);
+2 -2
View File
@@ -743,7 +743,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
spitz_wm8750_addr(wm, 0, 0);
qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
qemu_allocate_irq(spitz_wm8750_addr, wm, 0));
/* .. and to the sound interface. */
cpu->i2s->opaque = wm;
cpu->i2s->codec_out = wm8750_dac_dat;
@@ -849,7 +849,7 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
* wouldn't guarantee that a guest ever exits the loop.
*/
spitz_hsync = 0;
lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
lcd_hsync = qemu_allocate_irq(spitz_lcd_hsync_handler, cpu, 0);
pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
+1 -1
View File
@@ -359,7 +359,7 @@ static void z2_init(QEMUMachineInitArgs *args)
wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
qemu_allocate_irq(z2_lcd_cs, z2_lcd, 0));
z2_binfo.kernel_filename = kernel_filename;
z2_binfo.kernel_cmdline = kernel_cmdline;
+6 -10
View File
@@ -670,6 +670,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
uint32_t max_nr_ports, nr_active_ports, ports_map;
unsigned int i;
int ret;
uint32_t tmp;
if (version_id > 3) {
return -EINVAL;
@@ -685,17 +686,12 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
/* The config space */
qemu_get_be16s(f, &s->config.cols);
qemu_get_be16s(f, &s->config.rows);
qemu_get_be32s(f, &max_nr_ports);
tswap32s(&max_nr_ports);
if (max_nr_ports > tswap32(s->config.max_nr_ports)) {
/* Source could have had more ports than us. Fail migration. */
return -EINVAL;
}
/* Unused */
qemu_get_be16s(f, (uint16_t *) &tmp);
qemu_get_be16s(f, (uint16_t *) &tmp);
qemu_get_be32s(f, &tmp);
max_nr_ports = tswap32(s->config.max_nr_ports);
for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
qemu_get_be32s(f, &ports_map);
+2 -2
View File
@@ -102,7 +102,7 @@ qemu_irq qemu_irq_invert(qemu_irq irq)
{
/* The default state for IRQs is low, so raise the output now. */
qemu_irq_raise(irq);
return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
return qemu_allocate_irq(qemu_notirq, irq, 0);
}
static void qemu_splitirq(void *opaque, int line, int level)
@@ -117,7 +117,7 @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
qemu_irq *s = g_malloc0(2 * sizeof(qemu_irq));
s[0] = irq1;
s[1] = irq2;
return qemu_allocate_irqs(qemu_splitirq, s, 1)[0];
return qemu_allocate_irq(qemu_splitirq, s, 0);
}
static void proxy_irq_handler(void *opaque, int n, int level)
+24
View File
@@ -312,18 +312,42 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
return -EINVAL;
s->cmd_len = qemu_get_be32(f);
if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
return -EINVAL;
}
s->cmd = qemu_get_be32(f);
for (i = 0; i < 8; i++)
s->cmd_data[i] = qemu_get_be32(f);
s->row = qemu_get_be32(f);
if (s->row < 0 || s->row >= 80) {
return -EINVAL;
}
s->row_start = qemu_get_be32(f);
if (s->row_start < 0 || s->row_start >= 80) {
return -EINVAL;
}
s->row_end = qemu_get_be32(f);
if (s->row_end < 0 || s->row_end >= 80) {
return -EINVAL;
}
s->col = qemu_get_be32(f);
if (s->col < 0 || s->col >= 64) {
return -EINVAL;
}
s->col_start = qemu_get_be32(f);
if (s->col_start < 0 || s->col_start >= 64) {
return -EINVAL;
}
s->col_end = qemu_get_be32(f);
if (s->col_end < 0 || s->col_end >= 64) {
return -EINVAL;
}
s->redraw = qemu_get_be32(f);
s->remap = qemu_get_be32(f);
s->mode = qemu_get_be32(f);
if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
return -EINVAL;
}
qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
ss->cs = qemu_get_be32(f);
+2 -2
View File
@@ -1660,7 +1660,7 @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs,
}
omap_dma_setcaps(s);
omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
omap_clk_adduser(s->clk, qemu_allocate_irq(omap_dma_clk_update, s, 0));
omap_dma_reset(s->dma);
omap_dma_clk_update(s, 0, 1);
@@ -2082,7 +2082,7 @@ struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs,
s->intr_update = omap_dma_interrupts_4_update;
omap_dma_setcaps(s);
omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
omap_clk_adduser(s->clk, qemu_allocate_irq(omap_dma_clk_update, s, 0));
omap_dma_reset(s->dma);
omap_dma_clk_update(s, 0, !!s->dma->freq);
+10
View File
@@ -203,6 +203,15 @@ static bool is_version_0 (void *opaque, int version_id)
return version_id == 0;
}
static bool vmstate_scoop_validate(void *opaque, int version_id)
{
ScoopInfo *s = opaque;
return !(s->prev_level & 0xffff0000) &&
!(s->gpio_level & 0xffff0000) &&
!(s->gpio_dir & 0xffff0000);
}
static const VMStateDescription vmstate_scoop_regs = {
.name = "scoop",
.version_id = 1,
@@ -215,6 +224,7 @@ static const VMStateDescription vmstate_scoop_regs = {
VMSTATE_UINT32(gpio_level, ScoopInfo),
VMSTATE_UINT32(gpio_dir, ScoopInfo),
VMSTATE_UINT32(prev_level, ScoopInfo),
VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
VMSTATE_UINT16(mcr, ScoopInfo),
VMSTATE_UINT16(cdr, ScoopInfo),
VMSTATE_UINT16(ccr, ScoopInfo),
+4 -3
View File
@@ -1075,15 +1075,16 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
/* ACPI tables pointed to by RSDT */
acpi_add_table(table_offsets, tables->table_data);
build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
acpi_add_table(table_offsets, tables->table_data);
acpi_add_table(table_offsets, tables->table_data);
build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
guest_info);
acpi_add_table(table_offsets, tables->table_data);
build_madt(tables->table_data, tables->linker, &cpu, guest_info);
acpi_add_table(table_offsets, tables->table_data);
build_madt(tables->table_data, tables->linker, &cpu, guest_info);
if (misc.has_hpet) {
acpi_add_table(table_offsets, tables->table_data);
build_hpet(tables->table_data, tables->linker);
}
if (guest_info->numa_nodes) {
+6 -6
View File
@@ -1257,6 +1257,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
if (pos != 0 && kvm_device_msix_supported(kvm_state)) {
int bar_nr;
uint32_t msix_table_entry;
uint16_t msix_max;
if (!check_irqchip_in_kernel()) {
return -ENOTSUP;
@@ -1268,9 +1269,10 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
}
pci_dev->msix_cap = pos;
pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS,
pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
PCI_MSIX_FLAGS_QSIZE);
msix_max = (pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
PCI_MSIX_FLAGS_QSIZE) + 1;
msix_max = MIN(msix_max, KVM_MAX_MSIX_PER_DEV);
pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS, msix_max - 1);
/* Only enable and function mask bits are writable */
pci_set_word(pci_dev->wmask + pos + PCI_MSIX_FLAGS,
@@ -1280,9 +1282,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
bar_nr = msix_table_entry & PCI_MSIX_FLAGS_BIRMASK;
msix_table_entry &= ~PCI_MSIX_FLAGS_BIRMASK;
dev->msix_table_addr = pci_region[bar_nr].base_addr + msix_table_entry;
dev->msix_max = pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS);
dev->msix_max &= PCI_MSIX_FLAGS_QSIZE;
dev->msix_max += 1;
dev->msix_max = msix_max;
}
/* Minimal PM support, nothing writable, device appears to NAK changes */
+1 -1
View File
@@ -1290,7 +1290,7 @@ const VMStateDescription vmstate_ahci = {
VMSTATE_UINT32(control_regs.impl, AHCIState),
VMSTATE_UINT32(control_regs.version, AHCIState),
VMSTATE_UINT32(idp_index, AHCIState),
VMSTATE_INT32(ports, AHCIState),
VMSTATE_INT32_EQUAL(ports, AHCIState),
VMSTATE_END_OF_LIST()
},
};
+1 -1
View File
@@ -1601,7 +1601,7 @@ static bool cmd_smart(IDEState *s, uint8_t cmd)
case 2: /* extended self test */
s->smart_selftest_count++;
if (s->smart_selftest_count > 21) {
s->smart_selftest_count = 0;
s->smart_selftest_count = 1;
}
n = 2 + (s->smart_selftest_count - 1) * 24;
s->smart_selftest_data[n] = s->sector;
+1 -1
View File
@@ -594,7 +594,7 @@ static void microdrive_realize(DeviceState *dev, Error **errp)
{
MicroDriveState *md = MICRODRIVE(dev);
ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
ide_init2(&md->bus, qemu_allocate_irq(md_set_irq, md, 0));
}
static void microdrive_init(Object *obj)
+12
View File
@@ -1070,9 +1070,21 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
s->enabled = qemu_get_byte(f);
s->host_mode = qemu_get_byte(f);
s->function = qemu_get_byte(f);
if (s->function < 0 || s->function >= ARRAY_SIZE(mode_regs)) {
return -EINVAL;
}
s->nextfunction = qemu_get_byte(f);
if (s->nextfunction < 0 || s->nextfunction >= ARRAY_SIZE(mode_regs)) {
return -EINVAL;
}
s->precision = qemu_get_byte(f);
if (s->precision < 0 || s->precision >= ARRAY_SIZE(resolution)) {
return -EINVAL;
}
s->nextprecision = qemu_get_byte(f);
if (s->nextprecision < 0 || s->nextprecision >= ARRAY_SIZE(resolution)) {
return -EINVAL;
}
s->filter = qemu_get_byte(f);
s->pin_func = qemu_get_byte(f);
s->ref = qemu_get_byte(f);
+14 -2
View File
@@ -41,6 +41,7 @@
#include "hw/sysbus.h"
#include "hw/pci/msi.h"
#include "qemu/bitops.h"
#include "qapi/qmp/qerror.h"
//#define DEBUG_OPENPIC
@@ -1416,7 +1417,7 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
{
OpenPICState *opp = (OpenPICState *)opaque;
unsigned int i;
unsigned int i, nb_cpus;
if (version_id != 1) {
return -EINVAL;
@@ -1428,7 +1429,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
qemu_get_be32s(f, &opp->spve);
qemu_get_be32s(f, &opp->tfrr);
qemu_get_be32s(f, &opp->nb_cpus);
qemu_get_be32s(f, &nb_cpus);
if (opp->nb_cpus != nb_cpus) {
return -EINVAL;
}
assert(nb_cpus > 0 && nb_cpus <= MAX_CPU);
for (i = 0; i < opp->nb_cpus; i++) {
qemu_get_sbe32s(f, &opp->dst[i].ctpr);
@@ -1567,6 +1572,13 @@ static void openpic_realize(DeviceState *dev, Error **errp)
{NULL}
};
if (opp->nb_cpus > MAX_CPU) {
error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
(uint64_t)0, (uint64_t)MAX_CPU);
return;
}
switch (opp->model) {
case OPENPIC_MODEL_FSL_MPIC_20:
default:
+3 -3
View File
@@ -135,9 +135,9 @@ CBus *cbus_init(qemu_irq dat)
CBusPriv *s = (CBusPriv *) g_malloc0(sizeof(*s));
s->dat_out = dat;
s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0];
s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0];
s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0];
s->cbus.clk = qemu_allocate_irq(cbus_clk, s, 0);
s->cbus.dat = qemu_allocate_irq(cbus_dat, s, 0);
s->cbus.sel = qemu_allocate_irq(cbus_sel, s, 0);
s->sel = 1;
s->clk = 0;
+17 -6
View File
@@ -8,6 +8,7 @@
*/
#include "hw/sysbus.h"
#include "net/net.h"
#include "migration/migration.h"
#include <zlib.h>
//#define DEBUG_STELLARIS_ENET 1
@@ -75,6 +76,7 @@ typedef struct {
NICConf conf;
qemu_irq irq;
MemoryRegion mmio;
Error *migration_blocker;
} stellaris_enet_state;
static void stellaris_enet_update(stellaris_enet_state *s)
@@ -252,17 +254,19 @@ static void stellaris_enet_write(void *opaque, hwaddr offset,
s->tx_fifo[s->tx_fifo_len++] = value >> 24;
}
} else {
s->tx_fifo[s->tx_fifo_len++] = value;
s->tx_fifo[s->tx_fifo_len++] = value >> 8;
s->tx_fifo[s->tx_fifo_len++] = value >> 16;
s->tx_fifo[s->tx_fifo_len++] = value >> 24;
if (s->tx_fifo_len + 4 <= ARRAY_SIZE(s->tx_fifo)) {
s->tx_fifo[s->tx_fifo_len++] = value;
s->tx_fifo[s->tx_fifo_len++] = value >> 8;
s->tx_fifo[s->tx_fifo_len++] = value >> 16;
s->tx_fifo[s->tx_fifo_len++] = value >> 24;
}
if (s->tx_fifo_len >= s->tx_frame_len) {
/* We don't implement explicit CRC, so just chop it off. */
if ((s->tctl & SE_TCTL_CRC) == 0)
s->tx_frame_len -= 4;
if ((s->tctl & SE_TCTL_PADEN) && s->tx_frame_len < 60) {
memset(&s->tx_fifo[s->tx_frame_len], 0, 60 - s->tx_frame_len);
s->tx_fifo_len = 60;
s->tx_frame_len = 60;
}
qemu_send_packet(qemu_get_queue(s->nic), s->tx_fifo,
s->tx_frame_len);
@@ -359,7 +363,7 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id)
stellaris_enet_state *s = (stellaris_enet_state *)opaque;
int i;
if (version_id != 1)
if (1)
return -EINVAL;
s->ris = qemu_get_be32(f);
@@ -420,6 +424,10 @@ static int stellaris_enet_init(SysBusDevice *sbd)
stellaris_enet_reset(s);
register_savevm(dev, "stellaris_enet", -1, 1,
stellaris_enet_save, stellaris_enet_load, s);
error_setg(&s->migration_blocker,
"stellaris_enet does not support migration");
migrate_add_blocker(s->migration_blocker);
return 0;
}
@@ -427,6 +435,9 @@ static void stellaris_enet_unrealize(DeviceState *dev, Error **errp)
{
stellaris_enet_state *s = STELLARIS_ENET(dev);
migrate_del_blocker(s->migration_blocker);
error_free(s->migration_blocker);
unregister_savevm(DEVICE(s), "stellaris_enet", s);
memory_region_destroy(&s->mmio);
+39 -4
View File
@@ -515,6 +515,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
}
vhost_net_ack_features(tap_get_vhost_net(nc->peer), features);
}
if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) {
memset(n->vlans, 0, MAX_VLAN >> 3);
} else {
memset(n->vlans, 0xff, MAX_VLAN >> 3);
}
}
static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
@@ -837,6 +843,14 @@ static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
return 1;
}
static void virtio_net_hdr_swap(struct virtio_net_hdr *hdr)
{
tswap16s(&hdr->hdr_len);
tswap16s(&hdr->gso_size);
tswap16s(&hdr->csum_start);
tswap16s(&hdr->csum_offset);
}
/* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so
* it never finds out that the packets don't have valid checksums. This
* causes dhclient to get upset. Fedora's carried a patch for ages to
@@ -872,6 +886,7 @@ static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
void *wbuf = (void *)buf;
work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
size - n->host_hdr_len);
virtio_net_hdr_swap(wbuf);
iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
} else {
struct virtio_net_hdr hdr = {
@@ -1080,6 +1095,14 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
exit(1);
}
if (n->has_vnet_hdr) {
if (out_sg[0].iov_len < n->guest_hdr_len) {
error_report("virtio-net header incorrect");
exit(1);
}
virtio_net_hdr_swap((void *) out_sg[0].iov_base);
}
/*
* If host wants to see the guest header as is, we can
* pass it on unchanged. Otherwise, copy just the parts
@@ -1336,10 +1359,17 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
qemu_get_buffer(f, n->mac_table.macs,
n->mac_table.in_use * ETH_ALEN);
} else if (n->mac_table.in_use) {
uint8_t *buf = g_malloc0(n->mac_table.in_use);
qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
g_free(buf);
} else {
int64_t i;
/* Overflow detected - can happen if source has a larger MAC table.
* We simply set overflow flag so there's no need to maintain the
* table of addresses, discard them all.
* Note: 64 bit math to avoid integer overflow.
*/
for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) {
qemu_get_byte(f);
}
n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
n->mac_table.in_use = 0;
}
@@ -1381,6 +1411,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
}
n->curr_queues = qemu_get_be16(f);
if (n->curr_queues > n->max_queues) {
error_report("virtio-net: curr_queues %x > max_queues %x",
n->curr_queues, n->max_queues);
return -1;
}
for (i = 1; i < n->curr_queues; i++) {
n->vqs[i].tx_waiting = qemu_get_be32(f);
}
+55 -3
View File
@@ -52,6 +52,9 @@
#define VMXNET3_DEVICE_VERSION 0x1
#define VMXNET3_DEVICE_REVISION 0x1
/* Number of interrupt vectors for non-MSIx modes */
#define VMXNET3_MAX_NMSIX_INTRS (1)
/* Macros for rings descriptors access */
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
@@ -1305,6 +1308,51 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
}
static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
{
int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
if (idx >= max_ints) {
hw_error("Bad interrupt index: %d\n", idx);
}
}
static void vmxnet3_validate_interrupts(VMXNET3State *s)
{
int i;
VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
for (i = 0; i < s->txq_num; i++) {
int idx = s->txq_descr[i].intr_idx;
VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
}
for (i = 0; i < s->rxq_num; i++) {
int idx = s->rxq_descr[i].intr_idx;
VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
}
}
static void vmxnet3_validate_queues(VMXNET3State *s)
{
/*
* txq_num and rxq_num are total number of queues
* configured by guest. These numbers must not
* exceed corresponding maximal values.
*/
if (s->txq_num > VMXNET3_DEVICE_MAX_TX_QUEUES) {
hw_error("Bad TX queues number: %d\n", s->txq_num);
}
if (s->rxq_num > VMXNET3_DEVICE_MAX_RX_QUEUES) {
hw_error("Bad RX queues number: %d\n", s->rxq_num);
}
}
static void vmxnet3_activate_device(VMXNET3State *s)
{
int i;
@@ -1351,7 +1399,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
vmxnet3_validate_queues(s);
qdescr_table_pa =
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
@@ -1447,6 +1495,8 @@ static void vmxnet3_activate_device(VMXNET3State *s)
sizeof(s->rxq_descr[i].rxq_stats));
}
vmxnet3_validate_interrupts(s);
/* Make sure everything is in place before device activation */
smp_wmb();
@@ -2007,7 +2057,6 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
}
}
#define VMXNET3_MSI_NUM_VECTORS (1)
#define VMXNET3_MSI_OFFSET (0x50)
#define VMXNET3_USE_64BIT (true)
#define VMXNET3_PER_VECTOR_MASK (false)
@@ -2018,7 +2067,7 @@ vmxnet3_init_msi(VMXNET3State *s)
PCIDevice *d = PCI_DEVICE(s);
int res;
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MSI_NUM_VECTORS,
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MAX_NMSIX_INTRS,
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
if (0 > res) {
VMW_WRPRN("Failed to initialize MSI, error %d", res);
@@ -2344,6 +2393,9 @@ static int vmxnet3_post_load(void *opaque, int version_id)
}
}
vmxnet3_validate_queues(s);
vmxnet3_validate_interrupts(s);
return 0;
}
+3 -3
View File
@@ -474,7 +474,7 @@ const VMStateDescription vmstate_pci_device = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_INT32_LE(version_id, PCIDevice),
VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
vmstate_info_pci_config,
PCI_CONFIG_SPACE_SIZE),
@@ -491,7 +491,7 @@ const VMStateDescription vmstate_pcie_device = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_INT32_LE(version_id, PCIDevice),
VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
vmstate_info_pci_config,
PCIE_CONFIG_SPACE_SIZE),
@@ -820,6 +820,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
}
pci_dev->bus = bus;
pci_dev->devfn = devfn;
dma_as = pci_device_iommu_address_space(pci_dev);
memory_region_init_alias(&pci_dev->bus_master_enable_region,
@@ -829,7 +830,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
name);
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
+9 -1
View File
@@ -795,6 +795,13 @@ static const VMStateDescription vmstate_pcie_aer_err = {
}
};
static bool pcie_aer_state_log_num_valid(void *opaque, int version_id)
{
PCIEAERLog *s = opaque;
return s->log_num <= s->log_max;
}
const VMStateDescription vmstate_pcie_aer_log = {
.name = "PCIE_AER_ERROR_LOG",
.version_id = 1,
@@ -802,7 +809,8 @@ const VMStateDescription vmstate_pcie_aer_log = {
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT16(log_num, PCIEAERLog),
VMSTATE_UINT16(log_max, PCIEAERLog),
VMSTATE_UINT16_EQUAL(log_max, PCIEAERLog),
VMSTATE_VALIDATE("log_num <= log_max", pcie_aer_state_log_num_valid),
VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
vmstate_pcie_aer_err, PCIEAERErr),
VMSTATE_END_OF_LIST()
+1 -1
View File
@@ -195,7 +195,7 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
memory_region_add_subregion(&s->container_mem, 0x0c000000,
&s->common_iomem);
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
s->slot.irq = qemu_allocate_irq(pxa2xx_pcmcia_set_irq, s, 0);
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
(Object **)&s->card, NULL);
+16
View File
@@ -342,6 +342,22 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
/* There is no cached config, allocate MSIs */
if (!phb->msi_table[ndev].nvec) {
int max_irqs = 0;
if (ret_intr_type == RTAS_TYPE_MSI) {
max_irqs = msi_nr_vectors_allocated(pdev);
} else if (ret_intr_type == RTAS_TYPE_MSIX) {
max_irqs = pdev->msix_entries_nr;
}
if (!max_irqs) {
fprintf(stderr,
"Requested interrupt type %d is not enabled for device#%d\n",
ret_intr_type, ndev);
rtas_st(rets, 0, -1); /* Hardware error */
return;
}
if (req_num > max_irqs) {
req_num = max_irqs;
}
irq = spapr_allocate_irq_block(req_num, false,
ret_intr_type == RTAS_TYPE_MSI);
if (irq < 0) {
+20 -4
View File
@@ -722,9 +722,11 @@ out:
return ret;
}
static void copy_irb_to_guest(IRB *dest, const IRB *src)
static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
{
int i;
uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
uint16_t actl = src->scsw.ctrl & SCSW_CTRL_MASK_ACTL;
copy_scsw_to_guest(&dest->scsw, &src->scsw);
@@ -734,8 +736,22 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src)
for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
dest->ecw[i] = cpu_to_be32(src->ecw[i]);
}
for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
dest->emw[i] = cpu_to_be32(src->emw[i]);
/* extended measurements enabled? */
if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
!(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
!(pmcw->chars & PMCW_CHARS_MASK_XMWME)) {
return;
}
/* extended measurements pending? */
if (!(stctl & SCSW_STCTL_STATUS_PEND)) {
return;
}
if ((stctl & SCSW_STCTL_PRIMARY) ||
(stctl == SCSW_STCTL_SECONDARY) ||
((stctl & SCSW_STCTL_INTERMEDIATE) && (actl & SCSW_ACTL_SUSP))) {
for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
dest->emw[i] = cpu_to_be32(src->emw[i]);
}
}
}
@@ -781,7 +797,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
}
}
/* Store the irb to the guest. */
copy_irb_to_guest(target_irb, &irb);
copy_irb_to_guest(target_irb, &irb, p);
/* Clear conditions on subchannel, if applicable. */
if (stctl & SCSW_STCTL_STATUS_PEND) {
+7 -4
View File
@@ -26,11 +26,14 @@ void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn)
int s390_virtio_hypercall(CPUS390XState *env)
{
s390_virtio_fn fn = s390_diag500_table[env->regs[1]];
s390_virtio_fn fn;
if (!fn) {
return -EINVAL;
if (env->regs[1] < MAX_DIAG_SUBCODES) {
fn = s390_diag500_table[env->regs[1]];
if (fn) {
return fn(&env->regs[2]);
}
}
return fn(&env->regs[2]);
return -EINVAL;
}
+17
View File
@@ -1101,6 +1101,21 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
return MFI_STAT_OK;
}
static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
{
uint16_t flags;
/* mbox0 contains flags */
flags = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
trace_megasas_dcmd_ld_list_query(cmd->index, flags);
if (flags == MR_LD_QUERY_TYPE_ALL ||
flags == MR_LD_QUERY_TYPE_EXPOSED_TO_HOST) {
return megasas_dcmd_ld_get_list(s, cmd);
}
return MFI_STAT_OK;
}
static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
MegasasCmd *cmd)
{
@@ -1404,6 +1419,8 @@ static const struct dcmd_cmd_tbl_t {
megasas_dcmd_dummy },
{ MFI_DCMD_LD_GET_LIST, "LD_GET_LIST",
megasas_dcmd_ld_get_list},
{ MFI_DCMD_LD_LIST_QUERY, "LD_LIST_QUERY",
megasas_dcmd_ld_list_query },
{ MFI_DCMD_LD_GET_INFO, "LD_GET_INFO",
megasas_dcmd_ld_get_info },
{ MFI_DCMD_LD_GET_PROP, "LD_GET_PROP",
+9
View File
@@ -164,6 +164,7 @@ typedef enum {
MFI_DCMD_PD_BLINK = 0x02070100,
MFI_DCMD_PD_UNBLINK = 0x02070200,
MFI_DCMD_LD_GET_LIST = 0x03010000,
MFI_DCMD_LD_LIST_QUERY = 0x03010100,
MFI_DCMD_LD_GET_INFO = 0x03020000,
MFI_DCMD_LD_GET_PROP = 0x03030000,
MFI_DCMD_LD_SET_PROP = 0x03040000,
@@ -411,6 +412,14 @@ typedef enum {
MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, /*query for system drives */
} mfi_pd_query_type;
typedef enum {
MR_LD_QUERY_TYPE_ALL = 0,
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST = 1,
MR_LD_QUERY_TYPE_USED_TGT_IDS = 2,
MR_LD_QUERY_TYPE_CLUSTER_ACCESS = 3,
MR_LD_QUERY_TYPE_CLUSTER_LOCALE = 4,
} mfi_ld_query_type;
/*
* Other propertities and definitions
*/
+1 -1
View File
@@ -909,7 +909,7 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case VERIFY_16:
if ((buf[1] & 2) == 0) {
cmd->xfer = 0;
} else if ((buf[1] & 4) == 1) {
} else if ((buf[1] & 4) != 0) {
cmd->xfer = 1;
}
cmd->xfer *= dev->blocksize;
+1 -1
View File
@@ -2372,7 +2372,7 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
* ones (such as WRITE SAME or EXTENDED COPY, etc.). So, without
* O_DIRECT everything must go through SG_IO.
*/
if (bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE) {
if (!(bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE)) {
break;
}
-2
View File
@@ -37,8 +37,6 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
#include <scsi/sg.h>
#include "block/scsi.h"
#define SCSI_SENSE_BUF_SIZE 96
#define SG_ERR_DRIVER_TIMEOUT 0x06
#define SG_ERR_DRIVER_SENSE 0x08
-1
View File
@@ -60,7 +60,6 @@
#define VSCSI_MAX_SECTORS 4096
#define VSCSI_REQ_LIMIT 24
#define SCSI_SENSE_BUF_SIZE 96
#define SRP_RSP_SENSE_DATA_LEN 18
typedef union vscsi_crq {
+11 -1
View File
@@ -147,6 +147,15 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
qemu_get_be32s(f, &n);
assert(n < vs->conf.num_queues);
qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
/* TODO: add a way for SCSIBusInfo's load_request to fail,
* and fail migration instead of asserting here.
* When we do, we might be able to re-enable NDEBUG below.
*/
#ifdef NDEBUG
#error building with NDEBUG is not supported
#endif
assert(req->elem.in_num <= ARRAY_SIZE(req->elem.in_sg));
assert(req->elem.out_num <= ARRAY_SIZE(req->elem.out_sg));
virtio_scsi_parse_req(s, vs->cmd_vqs[n], req);
scsi_req_ref(sreq);
@@ -487,7 +496,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
uint32_t event, uint32_t reason)
{
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
VirtIOSCSIReq *req = virtio_scsi_pop_req(s, vs->event_vq);
VirtIOSCSIReq *req;
VirtIOSCSIEvent *evt;
VirtIODevice *vdev = VIRTIO_DEVICE(s);
int in_size;
@@ -496,6 +505,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
return;
}
req = virtio_scsi_pop_req(s, vs->event_vq);
if (!req) {
s->events_dropped = true;
return;
+1 -1
View File
@@ -625,7 +625,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
exit(1);
}
s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0];
s->cdet = qemu_allocate_irq(omap_mmc_cover_cb, s, 0);
sd_set_cb(s->card, NULL, s->cdet);
return s;
+4 -4
View File
@@ -1169,8 +1169,8 @@ static void sdhci_initfn(Object *obj)
if (s->card == NULL) {
exit(1);
}
s->eject_cb = qemu_allocate_irqs(sdhci_insert_eject_cb, s, 1)[0];
s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0];
s->eject_cb = qemu_allocate_irq(sdhci_insert_eject_cb, s, 0);
s->ro_cb = qemu_allocate_irq(sdhci_card_readonly_cb, s, 0);
sd_set_cb(s->card, s->ro_cb, s->eject_cb);
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
@@ -1185,8 +1185,8 @@ static void sdhci_uninitfn(Object *obj)
timer_free(s->insert_timer);
timer_del(s->transfer_timer);
timer_free(s->transfer_timer);
qemu_free_irqs(&s->eject_cb);
qemu_free_irqs(&s->ro_cb);
qemu_free_irq(s->eject_cb);
qemu_free_irq(s->ro_cb);
if (s->fifo_buffer) {
g_free(s->fifo_buffer);
+9
View File
@@ -230,8 +230,17 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
for (i = 0; i < 5; i++)
s->response[i] = qemu_get_be32(f);
s->arglen = qemu_get_be32(f);
if (s->mode == SSI_SD_CMDARG &&
(s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
return -EINVAL;
}
s->response_pos = qemu_get_be32(f);
s->stopping = qemu_get_be32(f);
if (s->mode == SSI_SD_RESPONSE &&
(s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
(!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
return -EINVAL;
}
ss->cs = qemu_get_be32(f);
+1 -2
View File
@@ -838,6 +838,5 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
qemu_irq sh7750_irl(SH7750State *s)
{
sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
1)[0];
return qemu_allocate_irq(sh_intc_set_irl, sh_intc_source(&s->intc, IRL), 0);
}
+14
View File
@@ -240,11 +240,25 @@ static const MemoryRegionOps pl022_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static int pl022_post_load(void *opaque, int version_id)
{
PL022State *s = opaque;
if (s->tx_fifo_head < 0 ||
s->tx_fifo_head >= ARRAY_SIZE(s->tx_fifo) ||
s->rx_fifo_head < 0 ||
s->rx_fifo_head >= ARRAY_SIZE(s->rx_fifo)) {
return -1;
}
return 0;
}
static const VMStateDescription vmstate_pl022 = {
.name = "pl022_ssp",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.post_load = pl022_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(cr0, PL022State),
VMSTATE_UINT32(cr1, PL022State),
+13
View File
@@ -227,6 +227,18 @@ static int hpet_pre_load(void *opaque)
return 0;
}
static bool hpet_validate_num_timers(void *opaque, int version_id)
{
HPETState *s = opaque;
if (s->num_timers < HPET_MIN_TIMERS) {
return false;
} else if (s->num_timers > HPET_MAX_TIMERS) {
return false;
}
return true;
}
static int hpet_post_load(void *opaque, int version_id)
{
HPETState *s = opaque;
@@ -295,6 +307,7 @@ static const VMStateDescription vmstate_hpet = {
VMSTATE_UINT64(isr, HPETState),
VMSTATE_UINT64(hpet_counter, HPETState),
VMSTATE_UINT8_V(num_timers, HPETState, 2),
VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST()
+2 -2
View File
@@ -227,7 +227,7 @@ static void omap_gp_timer_clk_update(void *opaque, int line, int on)
static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
{
omap_clk_adduser(timer->clk,
qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
qemu_allocate_irq(omap_gp_timer_clk_update, timer, 0));
timer->rate = omap_clk_getrate(timer->clk);
}
@@ -476,7 +476,7 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
s->clk = fclk;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_tick, s);
s->match = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_match, s);
s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
s->in = qemu_allocate_irq(omap_gp_timer_input, s, 0);
omap_gp_timer_reset(s);
omap_gp_timer_clk_setup(s);
+3 -1
View File
@@ -47,7 +47,9 @@ static int usb_device_post_load(void *opaque, int version_id)
} else {
dev->attached = 1;
}
if (dev->setup_index >= sizeof(dev->data_buf) ||
if (dev->setup_index < 0 ||
dev->setup_len < 0 ||
dev->setup_index >= sizeof(dev->data_buf) ||
dev->setup_len >= sizeof(dev->data_buf)) {
return -EINVAL;
}
+16 -8
View File
@@ -19,6 +19,7 @@
*/
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "hw/usb.h"
#include "hw/usb/desc.h"
#include "sysemu/bt.h"
@@ -506,6 +507,14 @@ static int usb_bt_initfn(USBDevice *dev)
usb_desc_create_serial(dev);
usb_desc_init(dev);
s->dev.opaque = s;
if (!s->hci) {
s->hci = bt_new_hci(qemu_find_bt_vlan(0));
}
s->hci->opaque = s;
s->hci->evt_recv = usb_bt_out_hci_packet_event;
s->hci->acl_recv = usb_bt_out_hci_packet_acl;
usb_bt_handle_reset(&s->dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, USB_EVT_EP);
return 0;
@@ -516,6 +525,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
USBDevice *dev;
struct USBBtState *s;
HCIInfo *hci;
const char *name = "usb-bt-dongle";
if (*cmdline) {
hci = hci_init(cmdline);
@@ -525,19 +535,17 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
if (!hci)
return NULL;
dev = usb_create_simple(bus, "usb-bt-dongle");
dev = usb_create(bus, name);
if (!dev) {
error_report("Failed to create USB device '%s'", name);
return NULL;
}
s = DO_UPCAST(struct USBBtState, dev, dev);
s->dev.opaque = s;
s->hci = hci;
s->hci->opaque = s;
s->hci->evt_recv = usb_bt_out_hci_packet_event;
s->hci->acl_recv = usb_bt_out_hci_packet_acl;
usb_bt_handle_reset(&s->dev);
if (qdev_init(&dev->qdev) < 0) {
error_report("Failed to initialize USB device '%s'", name);
return NULL;
}
return dev;
}
+6 -4
View File
@@ -309,7 +309,9 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
uint64_t size)
{
int i;
for (i = 0; i < dev->nvqs; ++i) {
int r = 0;
for (i = 0; !r && i < dev->nvqs; ++i) {
struct vhost_virtqueue *vq = dev->vqs + i;
hwaddr l;
void *p;
@@ -321,15 +323,15 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
p = cpu_physical_memory_map(vq->ring_phys, &l, 1);
if (!p || l != vq->ring_size) {
fprintf(stderr, "Unable to map ring buffer for ring %d\n", i);
return -ENOMEM;
r = -ENOMEM;
}
if (p != vq->ring) {
fprintf(stderr, "Ring buffer relocated for ring %d\n", i);
return -EBUSY;
r = -EBUSY;
}
cpu_physical_memory_unmap(p, l, 0, 0);
}
return 0;
return r;
}
static struct vhost_memory_region *vhost_dev_find_reg(struct vhost_dev *dev,
+30 -3
View File
@@ -427,6 +427,12 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
unsigned int i;
hwaddr len;
if (num_sg > VIRTQUEUE_MAX_SIZE) {
error_report("virtio: map attempt out of bounds: %zd > %d",
num_sg, VIRTQUEUE_MAX_SIZE);
exit(1);
}
for (i = 0; i < num_sg; i++) {
len = sg[i].iov_len;
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
@@ -888,7 +894,9 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
int num, i, ret;
int i, ret;
int32_t config_len;
uint32_t num;
uint32_t features;
uint32_t supported_features;
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -903,6 +911,9 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
qemu_get_8s(f, &vdev->status);
qemu_get_8s(f, &vdev->isr);
qemu_get_be16s(f, &vdev->queue_sel);
if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {
return -1;
}
qemu_get_be32s(f, &features);
if (virtio_set_features(vdev, features) < 0) {
@@ -911,11 +922,27 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
features, supported_features);
return -1;
}
vdev->config_len = qemu_get_be32(f);
qemu_get_buffer(f, vdev->config, vdev->config_len);
config_len = qemu_get_be32(f);
/*
* There are cases where the incoming config can be bigger or smaller
* than what we have; so load what we have space for, and skip
* any excess that's in the stream.
*/
qemu_get_buffer(f, vdev->config, MIN(config_len, vdev->config_len));
while (config_len > vdev->config_len) {
qemu_get_byte(f);
config_len--;
}
num = qemu_get_be32(f);
if (num > VIRTIO_PCI_QUEUE_MAX) {
error_report("Invalid number of PCI queues: 0x%x", num);
return -1;
}
for (i = 0; i < num; i++) {
vdev->vq[i].vring.num = qemu_get_be32(f);
if (k->has_variable_vring_alignment) {
+1 -1
View File
@@ -31,7 +31,7 @@ typedef struct SCSISense {
uint8_t ascq;
} SCSISense;
#define SCSI_SENSE_BUF_SIZE 96
#define SCSI_SENSE_BUF_SIZE 252
struct SCSICommand {
uint8_t buf[SCSI_CMD_BUF_SIZE];
+2 -2
View File
@@ -176,8 +176,8 @@ typedef struct VirtIONet {
uint8_t nobcast;
uint8_t vhost_started;
struct {
int in_use;
int first_multi;
uint32_t in_use;
uint32_t first_multi;
uint8_t multi_overflow;
uint8_t uni_overflow;
uint8_t *macs;
+10 -1
View File
@@ -100,6 +100,7 @@ enum VMStateFlags {
VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */
VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/
VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/
VMS_MUST_EXIST = 0x1000, /* Field must exist in input */
};
typedef struct {
@@ -203,6 +204,14 @@ extern const VMStateInfo vmstate_info_bitmap;
.offset = vmstate_offset_value(_state, _field, _type), \
}
/* Validate state using a boolean predicate. */
#define VMSTATE_VALIDATE(_name, _test) { \
.name = (_name), \
.field_exists = (_test), \
.flags = VMS_ARRAY | VMS_MUST_EXIST, \
.num = 0, /* 0 elements: no data, only run _test */ \
}
#define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \
.name = (stringify(_field)), \
.version_id = (_version), \
@@ -582,7 +591,7 @@ extern const VMStateInfo vmstate_info_bitmap;
#define VMSTATE_UINT64_EQUAL(_f, _s) \
VMSTATE_UINT64_EQUAL_V(_f, _s, 0)
#define VMSTATE_INT32_LE(_f, _s) \
#define VMSTATE_INT32_POSITIVE_LE(_f, _s) \
VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
#define VMSTATE_UINT8_TEST(_f, _s, _t) \
+1 -1
View File
@@ -965,7 +965,7 @@ void kvm_init_irq_routing(KVMState *s)
{
int gsi_count, i;
gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING);
gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING) - 1;
if (gsi_count > 0) {
unsigned int gsi_bits, i;
+98 -17
View File
@@ -267,17 +267,15 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
#ifdef TARGET_ARM
#ifndef TARGET_AARCH64
/* 32 bit ARM definitions */
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ((x) == ELF_MACHINE)
#define ELF_ARCH ELF_MACHINE
#ifdef TARGET_AARCH64
#define ELF_CLASS ELFCLASS64
#else
#define ELF_CLASS ELFCLASS32
#endif
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
@@ -285,10 +283,6 @@ static inline void init_thread(struct target_pt_regs *regs,
abi_long stack = infop->start_stack;
memset(regs, 0, sizeof(*regs));
#ifdef TARGET_AARCH64
regs->pc = infop->entry & ~0x3ULL;
regs->sp = stack;
#else
regs->ARM_cpsr = 0x10;
if (infop->entry & 1)
regs->ARM_cpsr |= CPSR_T;
@@ -302,7 +296,6 @@ static inline void init_thread(struct target_pt_regs *regs,
/* For uClinux PIC binaries. */
/* XXX: Linux does this only on ARM with no MMU (do we care ?) */
regs->ARM_r10 = infop->start_data;
#endif
}
#define ELF_NREG 18
@@ -346,10 +339,18 @@ enum
ARM_HWCAP_ARM_EDSP = 1 << 7,
ARM_HWCAP_ARM_JAVA = 1 << 8,
ARM_HWCAP_ARM_IWMMXT = 1 << 9,
ARM_HWCAP_ARM_THUMBEE = 1 << 10,
ARM_HWCAP_ARM_NEON = 1 << 11,
ARM_HWCAP_ARM_VFPv3 = 1 << 12,
ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
ARM_HWCAP_ARM_CRUNCH = 1 << 10,
ARM_HWCAP_ARM_THUMBEE = 1 << 11,
ARM_HWCAP_ARM_NEON = 1 << 12,
ARM_HWCAP_ARM_VFPv3 = 1 << 13,
ARM_HWCAP_ARM_VFPv3D16 = 1 << 14,
ARM_HWCAP_ARM_TLS = 1 << 15,
ARM_HWCAP_ARM_VFPv4 = 1 << 16,
ARM_HWCAP_ARM_IDIVA = 1 << 17,
ARM_HWCAP_ARM_IDIVT = 1 << 18,
ARM_HWCAP_ARM_VFPD32 = 1 << 19,
ARM_HWCAP_ARM_LPAE = 1 << 20,
ARM_HWCAP_ARM_EVTSTRM = 1 << 21,
};
#define TARGET_HAS_VALIDATE_GUEST_SPACE
@@ -424,23 +425,103 @@ static uint32_t get_elf_hwcap(void)
hwcaps |= ARM_HWCAP_ARM_HALF;
hwcaps |= ARM_HWCAP_ARM_THUMB;
hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
hwcaps |= ARM_HWCAP_ARM_FPA;
/* probe for the extra features */
#define GET_FEATURE(feat, hwcap) \
do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
/* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
GET_FEATURE(ARM_FEATURE_VFP_FP16, ARM_HWCAP_ARM_VFPv3D16);
GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4);
GET_FEATURE(ARM_FEATURE_ARM_DIV, ARM_HWCAP_ARM_IDIVA);
GET_FEATURE(ARM_FEATURE_THUMB_DIV, ARM_HWCAP_ARM_IDIVT);
/* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c.
* Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of
* ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated
* to our VFP_FP16 feature bit.
*/
GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPD32);
GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
#undef GET_FEATURE
return hwcaps;
}
#endif
#else
/* 64 bit ARM definitions */
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ((x) == ELF_MACHINE)
#define ELF_ARCH ELF_MACHINE
#define ELF_CLASS ELFCLASS64
#define ELF_PLATFORM "aarch64"
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
abi_long stack = infop->start_stack;
memset(regs, 0, sizeof(*regs));
regs->pc = infop->entry & ~0x3ULL;
regs->sp = stack;
}
#define ELF_NREG 34
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
static void elf_core_copy_regs(target_elf_gregset_t *regs,
const CPUARMState *env)
{
int i;
for (i = 0; i < 32; i++) {
(*regs)[i] = tswapreg(env->xregs[i]);
}
(*regs)[32] = tswapreg(env->pc);
(*regs)[33] = tswapreg(pstate_read((CPUARMState *)env));
}
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
enum {
ARM_HWCAP_A64_FP = 1 << 0,
ARM_HWCAP_A64_ASIMD = 1 << 1,
ARM_HWCAP_A64_EVTSTRM = 1 << 2,
ARM_HWCAP_A64_AES = 1 << 3,
ARM_HWCAP_A64_PMULL = 1 << 4,
ARM_HWCAP_A64_SHA1 = 1 << 5,
ARM_HWCAP_A64_SHA2 = 1 << 6,
ARM_HWCAP_A64_CRC32 = 1 << 7,
};
#define ELF_HWCAP get_elf_hwcap()
static uint32_t get_elf_hwcap(void)
{
ARMCPU *cpu = ARM_CPU(thread_cpu);
uint32_t hwcaps = 0;
hwcaps |= ARM_HWCAP_A64_FP;
hwcaps |= ARM_HWCAP_A64_ASIMD;
/* probe for the extra features */
#define GET_FEATURE(feat, hwcap) \
do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
GET_FEATURE(ARM_FEATURE_V8_AES, ARM_HWCAP_A64_PMULL);
#undef GET_FEATURE
return hwcaps;
}
#endif /* not TARGET_AARCH64 */
#endif /* TARGET_ARM */
#ifdef TARGET_UNICORE32
+16
View File
@@ -7479,6 +7479,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
if (!is_error(ret)) {
if (ret > arg2) {
/* More data returned than the caller's buffer will fit.
* This only happens if sizeof(abi_long) < sizeof(long)
* and the caller passed us a buffer holding an odd number
* of abi_longs. If the host kernel is actually using the
* extra 4 bytes then fail EINVAL; otherwise we can just
* ignore them and only copy the interesting part.
*/
int numcpus = sysconf(_SC_NPROCESSORS_CONF);
if (numcpus > arg2 * 8) {
ret = -TARGET_EINVAL;
break;
}
ret = arg2;
}
if (copy_to_user(arg3, mask, ret)) {
goto efault;
}
+10 -10
View File
@@ -1589,13 +1589,11 @@ static int qemu_rdma_post_send_control(RDMAContext *rdma, uint8_t *buf,
}
if (ibv_post_send(rdma->qp, &send_wr, &bad_wr)) {
return -1;
}
ret = ibv_post_send(rdma->qp, &send_wr, &bad_wr);
if (ret < 0) {
if (ret > 0) {
fprintf(stderr, "Failed to use post IB SEND for control!\n");
return ret;
return -ret;
}
ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_SEND_CONTROL, NULL);
@@ -2237,10 +2235,6 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
}
}
if (rdma->qp) {
rdma_destroy_qp(rdma->cm_id);
rdma->qp = NULL;
}
if (rdma->cq) {
ibv_destroy_cq(rdma->cq);
rdma->cq = NULL;
@@ -2258,6 +2252,10 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
rdma->listen_id = NULL;
}
if (rdma->cm_id) {
if (rdma->qp) {
rdma_destroy_qp(rdma->cm_id);
rdma->qp = NULL;
}
rdma_destroy_id(rdma->cm_id);
rdma->cm_id = NULL;
}
@@ -2512,8 +2510,10 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
} else {
ERROR(errp, "bad RDMA migration address '%s'", host_port);
g_free(rdma);
return NULL;
rdma = NULL;
}
qapi_free_InetSocketAddress(addr);
}
return rdma;
+1 -1
View File
@@ -105,7 +105,7 @@ static void process_incoming_migration_co(void *opaque)
ret = qemu_loadvm_state(f);
qemu_fclose(f);
if (ret < 0) {
fprintf(stderr, "load of migration failed\n");
error_report("load of migration failed: %s", strerror(-ret));
exit(EXIT_FAILURE);
}
qemu_announce_self();
+4 -3
View File
@@ -1069,6 +1069,7 @@ static void nbd_trip(void *opaque)
struct nbd_request request;
struct nbd_reply reply;
ssize_t ret;
uint32_t command;
TRACE("Reading request.");
if (client->closing) {
@@ -1091,8 +1092,8 @@ static void nbd_trip(void *opaque)
reply.error = -ret;
goto error_reply;
}
if ((request.from + request.len) > exp->size) {
command = request.type & NBD_CMD_MASK_COMMAND;
if (command != NBD_CMD_DISC && (request.from + request.len) > exp->size) {
LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
", Offset: %" PRIu64 "\n",
request.from, request.len,
@@ -1101,7 +1102,7 @@ static void nbd_trip(void *opaque)
goto invalid_request;
}
switch (request.type & NBD_CMD_MASK_COMMAND) {
switch (command) {
case NBD_CMD_READ:
TRACE("Request type is READ");
+5 -2
View File
@@ -190,7 +190,7 @@ static void tap_send(void *opaque)
TAPState *s = opaque;
int size;
do {
while (qemu_can_send_packet(&s->nc)) {
uint8_t *buf = s->buf;
size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
@@ -206,8 +206,11 @@ static void tap_send(void *opaque)
size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
if (size == 0) {
tap_read_poll(s, false);
break;
} else if (size < 0) {
break;
}
} while (size > 0 && qemu_can_send_packet(&s->nc));
}
}
bool tap_has_ufo(NetClientState *nc)
+2 -2
View File
@@ -37,8 +37,8 @@ install: $(OBJS)
$(call quiet-command, msgfmt -o $@ $<, " GEN $@")
$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c
$(call quiet-command, cd $(SRC_PATH) && \
(xgettext -o - --from-code=UTF-8 --foreign-user \
$(call quiet-command, ( cd $(SRC_PATH) && \
xgettext -o - --from-code=UTF-8 --foreign-user \
--package-name=QEMU --package-version=$(VERSION) \
--msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \
sed -e s/CHARSET/UTF-8/) >$@, " GEN $@")
+15 -2
View File
@@ -213,7 +213,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
s->chr_read = fd_read;
s->chr_event = fd_event;
s->handler_opaque = opaque;
if (s->chr_update_read_handler)
if (fe_open && s->chr_update_read_handler)
s->chr_update_read_handler(s);
if (!s->explicit_fe_open) {
@@ -1136,13 +1136,14 @@ static void pty_chr_state(CharDriverState *chr, int connected)
if (!s->connected) {
s->connected = 1;
qemu_chr_be_generic_open(chr);
}
if (!chr->fd_in_tag) {
chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
pty_chr_read, chr);
}
}
}
static void pty_chr_close(struct CharDriverState *chr)
{
PtyCharDriver *s = chr->opaque;
@@ -2510,6 +2511,17 @@ static void tcp_chr_connect(void *opaque)
qemu_chr_be_generic_open(chr);
}
static void tcp_chr_update_read_handler(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
remove_fd_in_watch(chr);
if (s->chan) {
chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
tcp_chr_read, chr);
}
}
#define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
static void tcp_chr_telnet_init(int fd)
{
@@ -2665,6 +2677,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
chr->get_msgfd = tcp_get_msgfd;
chr->chr_add_client = tcp_chr_add_client;
chr->chr_add_watch = tcp_chr_add_watch;
chr->chr_update_read_handler = tcp_chr_update_read_handler;
/* be isn't opened until we get a connection */
chr->explicit_be_open = true;
+1 -1
View File
@@ -1355,7 +1355,7 @@ static int img_convert(int argc, char **argv)
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
return -1;
goto out;
}
out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
+4 -1
View File
@@ -299,8 +299,11 @@ static void nbd_accept(void *opaque)
return;
}
if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) {
if (nbd_client_new(exp, fd, nbd_client_closed)) {
nb_fds++;
} else {
shutdown(fd, 2);
close(fd);
}
}
+4 -2
View File
@@ -31,7 +31,7 @@
static void acquire_privilege(const char *name, Error **err)
{
HANDLE token;
HANDLE token = NULL;
TOKEN_PRIVILEGES priv;
Error *local_err = NULL;
@@ -57,13 +57,15 @@ static void acquire_privilege(const char *name, Error **err)
goto out;
}
CloseHandle(token);
} else {
error_set(&local_err, QERR_QGA_COMMAND_FAILED,
"failed to open privilege token");
}
out:
if (token) {
CloseHandle(token);
}
if (local_err) {
error_propagate(err, local_err);
}
+12 -2
View File
@@ -1273,6 +1273,7 @@ void object_property_add_str(Object *obj, const char *name,
void (*set)(Object *, const char *, Error **),
Error **errp)
{
Error *local_err = NULL;
StringProperty *prop = g_malloc0(sizeof(*prop));
prop->get = get;
@@ -1282,7 +1283,11 @@ void object_property_add_str(Object *obj, const char *name,
get ? property_get_str : NULL,
set ? property_set_str : NULL,
property_release_str,
prop, errp);
prop, &local_err);
if (local_err) {
error_propagate(errp, local_err);
g_free(prop);
}
}
typedef struct BoolProperty
@@ -1329,6 +1334,7 @@ void object_property_add_bool(Object *obj, const char *name,
void (*set)(Object *, bool, Error **),
Error **errp)
{
Error *local_err = NULL;
BoolProperty *prop = g_malloc0(sizeof(*prop));
prop->get = get;
@@ -1338,7 +1344,11 @@ void object_property_add_bool(Object *obj, const char *name,
get ? property_get_bool : NULL,
set ? property_set_bool : NULL,
property_release_bool,
prop, errp);
prop, &local_err);
if (local_err) {
error_propagate(errp, local_err);
g_free(prop);
}
}
static char *qdev_get_type(Object *obj, Error **errp)
+75 -57
View File
@@ -1111,22 +1111,25 @@ const VMStateInfo vmstate_info_int32_equal = {
.put = put_int32,
};
/* 32 bit int. See that the received value is the less or the same
than the one in the field */
/* 32 bit int. Check that the received value is non-negative
* and less than or equal to the one in the field.
*/
static int get_int32_le(QEMUFile *f, void *pv, size_t size)
{
int32_t *old = pv;
int32_t new;
qemu_get_sbe32s(f, &new);
int32_t *cur = pv;
int32_t loaded;
qemu_get_sbe32s(f, &loaded);
if (*old <= new)
if (loaded >= 0 && loaded <= *cur) {
*cur = loaded;
return 0;
}
return -EINVAL;
}
const VMStateInfo vmstate_info_int32_le = {
.name = "int32 equal",
.name = "int32 le",
.get = get_int32_le,
.put = put_int32,
};
@@ -1673,6 +1676,50 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
static int vmstate_n_elems(void *opaque, VMStateField *field)
{
int n_elems = 1;
if (field->flags & VMS_ARRAY) {
n_elems = field->num;
} else if (field->flags & VMS_VARRAY_INT32) {
n_elems = *(int32_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT32) {
n_elems = *(uint32_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT16) {
n_elems = *(uint16_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT8) {
n_elems = *(uint8_t *)(opaque+field->num_offset);
}
return n_elems;
}
static int vmstate_size(void *opaque, VMStateField *field)
{
int size = field->size;
if (field->flags & VMS_VBUFFER) {
size = *(int32_t *)(opaque+field->size_offset);
if (field->flags & VMS_MULTIPLY) {
size *= field->size;
}
}
return size;
}
static void *vmstate_base_addr(void *opaque, VMStateField *field)
{
void *base_addr = opaque + field->offset;
if (field->flags & VMS_POINTER) {
base_addr = *(void **)base_addr + field->start;
}
return base_addr;
}
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id)
{
@@ -1682,11 +1729,12 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
if (version_id > vmsd->version_id) {
return -EINVAL;
}
if (version_id < vmsd->minimum_version_id_old) {
return -EINVAL;
}
if (version_id < vmsd->minimum_version_id) {
return vmsd->load_state_old(f, opaque, version_id);
if (vmsd->load_state_old &&
version_id >= vmsd->minimum_version_id_old) {
return vmsd->load_state_old(f, opaque, version_id);
}
return -EINVAL;
}
if (vmsd->pre_load) {
int ret = vmsd->pre_load(opaque);
@@ -1698,30 +1746,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
field->field_exists(opaque, version_id)) ||
(!field->field_exists &&
field->version_id <= version_id)) {
void *base_addr = opaque + field->offset;
int i, n_elems = 1;
int size = field->size;
void *base_addr = vmstate_base_addr(opaque, field);
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
if (field->flags & VMS_VBUFFER) {
size = *(int32_t *)(opaque+field->size_offset);
if (field->flags & VMS_MULTIPLY) {
size *= field->size;
}
}
if (field->flags & VMS_ARRAY) {
n_elems = field->num;
} else if (field->flags & VMS_VARRAY_INT32) {
n_elems = *(int32_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT32) {
n_elems = *(uint32_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT16) {
n_elems = *(uint16_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT8) {
n_elems = *(uint8_t *)(opaque+field->num_offset);
}
if (field->flags & VMS_POINTER) {
base_addr = *(void **)base_addr + field->start;
}
for (i = 0; i < n_elems; i++) {
void *addr = base_addr + size * i;
@@ -1738,6 +1766,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
return ret;
}
}
} else if (field->flags & VMS_MUST_EXIST) {
fprintf(stderr, "Input validation failed: %s/%s\n",
vmsd->name, field->name);
return -1;
}
field++;
}
@@ -1762,30 +1794,10 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
while(field->name) {
if (!field->field_exists ||
field->field_exists(opaque, vmsd->version_id)) {
void *base_addr = opaque + field->offset;
int i, n_elems = 1;
int size = field->size;
void *base_addr = vmstate_base_addr(opaque, field);
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
if (field->flags & VMS_VBUFFER) {
size = *(int32_t *)(opaque+field->size_offset);
if (field->flags & VMS_MULTIPLY) {
size *= field->size;
}
}
if (field->flags & VMS_ARRAY) {
n_elems = field->num;
} else if (field->flags & VMS_VARRAY_INT32) {
n_elems = *(int32_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT32) {
n_elems = *(uint32_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT16) {
n_elems = *(uint16_t *)(opaque+field->num_offset);
} else if (field->flags & VMS_VARRAY_UINT8) {
n_elems = *(uint8_t *)(opaque+field->num_offset);
}
if (field->flags & VMS_POINTER) {
base_addr = *(void **)base_addr + field->start;
}
for (i = 0; i < n_elems; i++) {
void *addr = base_addr + size * i;
@@ -1798,6 +1810,12 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
field->info->put(f, addr, size);
}
}
} else {
if (field->flags & VMS_MUST_EXIST) {
fprintf(stderr, "Output state validation failed: %s/%s\n",
vmsd->name, field->name);
assert(!(field->flags & VMS_MUST_EXIST));
}
}
field++;
}
+1 -1
View File
@@ -119,7 +119,7 @@ bool has_%(argname)s = false;
argname=c_var(argname), argtype=c_type(argtype))
else:
ret += mcgen('''
%(argtype)s %(argname)s;
%(argtype)s %(argname)s = {0};
''',
argname=c_var(argname), argtype=c_type(argtype))
+4 -4
View File
@@ -546,7 +546,7 @@ static int pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
static int vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
env->cp15.c12_vbar = value & ~0x1Ful;
env->cp15.c12_vbar = value & ~0x1FULL;
return 0;
}
@@ -859,16 +859,16 @@ static int gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
int timeridx = ri->crm & 1;
uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
env->cp15.c14_timer[timeridx].ctl = value & 3;
env->cp15.c14_timer[timeridx].ctl = deposit64(oldval, 0, 2, value);
if ((oldval ^ value) & 1) {
/* Enable toggled */
gt_recalc_timer(cpu, timeridx);
} else if ((oldval & value) & 2) {
} else if ((oldval ^ value) & 2) {
/* IMASK toggled: don't need to recalculate,
* just set the interrupt line based on ISTATUS
*/
qemu_set_irq(cpu->gt_timer_outputs[timeridx],
(oldval & 4) && (value & 2));
(oldval & 4) && !(value & 2));
}
return 0;
}
+1 -1
View File
@@ -246,7 +246,7 @@ const VMStateDescription vmstate_arm_cpu = {
/* The length-check must come before the arrays to avoid
* incoming data possibly overflowing the array.
*/
VMSTATE_INT32_LE(cpreg_vmstate_array_len, ARMCPU),
VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU),
VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU,
cpreg_vmstate_array_len,
0, vmstate_info_uint64, uint64_t),
+23 -11
View File
@@ -7732,27 +7732,39 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (insn & (1 << 5))
gen_swap_half(tmp2);
gen_smul_dual(tmp, tmp2);
if (insn & (1 << 6)) {
/* This subtraction cannot overflow. */
tcg_gen_sub_i32(tmp, tmp, tmp2);
} else {
/* This addition cannot overflow 32 bits;
* however it may overflow considered as a signed
* operation, in which case we must set the Q flag.
*/
gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
if (insn & (1 << 22)) {
/* smlald, smlsld */
TCGv_i64 tmp64_2;
tmp64 = tcg_temp_new_i64();
tmp64_2 = tcg_temp_new_i64();
tcg_gen_ext_i32_i64(tmp64, tmp);
tcg_gen_ext_i32_i64(tmp64_2, tmp2);
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(tmp2);
if (insn & (1 << 6)) {
tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
} else {
tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
}
tcg_temp_free_i64(tmp64_2);
gen_addq(s, tmp64, rd, rn);
gen_storeq_reg(s, rd, rn, tmp64);
tcg_temp_free_i64(tmp64);
} else {
/* smuad, smusd, smlad, smlsd */
if (insn & (1 << 6)) {
/* This subtraction cannot overflow. */
tcg_gen_sub_i32(tmp, tmp, tmp2);
} else {
/* This addition cannot overflow 32 bits;
* however it may overflow considered as a
* signed operation, in which case we must set
* the Q flag.
*/
gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
if (rd != 15)
{
tmp2 = load_reg(s, rd);
+1 -1
View File
@@ -103,7 +103,7 @@ target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1,
case CC_OP_EFLAGS:
return src1;
case CC_OP_CLR:
return CC_Z;
return CC_Z | CC_P;
case CC_OP_MULB:
return compute_all_mulb(dst, src1);
+4 -1
View File
@@ -539,7 +539,7 @@ typedef struct x86_def_t {
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
#define TCG_SVM_FEATURES 0
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP \
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
/* missing:
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
@@ -2446,6 +2446,8 @@ static void x86_cpu_reset(CPUState *s)
cpu_breakpoint_remove_all(env, BP_CPU);
cpu_watchpoint_remove_all(env, BP_CPU);
env->xcr0 = 1;
#if !defined(CONFIG_USER_ONLY)
/* We hard-wire the BSP to the first CPU. */
if (s->cpu_index == 0) {
@@ -2560,6 +2562,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
if (!kvm_enabled()) {
env->features[FEAT_1_EDX] &= TCG_FEATURES;
env->features[FEAT_1_ECX] &= TCG_EXT_FEATURES;
env->features[FEAT_7_0_EBX] &= TCG_7_0_EBX_FEATURES;
env->features[FEAT_8000_0001_EDX] &= (TCG_EXT2_FEATURES
#ifdef TARGET_X86_64
| CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
+2 -2
View File
@@ -801,6 +801,8 @@ typedef struct CPUX86State {
XMMReg xmm_t0;
MMXReg mmx_t0;
XMMReg ymmh_regs[CPU_NB_REGS];
/* sysenter registers */
uint32_t sysenter_cs;
target_ulong sysenter_esp;
@@ -909,9 +911,7 @@ typedef struct CPUX86State {
uint16_t fpus_vmstate;
uint16_t fptag_vmstate;
uint16_t fpregs_format_vmstate;
uint64_t xstate_bv;
XMMReg ymmh_regs[CPU_NB_REGS];
uint64_t xcr0;
+37 -11
View File
@@ -915,7 +915,7 @@ static void gen_compute_eflags(DisasContext *s)
return;
}
if (s->cc_op == CC_OP_CLR) {
tcg_gen_movi_tl(cpu_cc_src, CC_Z);
tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
set_cc_op(s, CC_OP_EFLAGS);
return;
}
@@ -4565,21 +4565,47 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
if (is_xmm) {
op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
if (mod != 3) {
int sz = 4;
gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
op2_offset = offsetof(CPUX86State,xmm_t0);
if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
b == 0xc2)) {
/* specific case for SSE single instructions */
switch (b) {
case 0x50 ... 0x5a:
case 0x5c ... 0x5f:
case 0xc2:
/* Most sse scalar operations. */
if (b1 == 2) {
/* 32 bit access */
gen_op_ld_T0_A0(OT_LONG + s->mem_index);
tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
} else {
/* 64 bit access */
gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
sz = 2;
} else if (b1 == 3) {
sz = 3;
}
} else {
break;
case 0x2e: /* ucomis[sd] */
case 0x2f: /* comis[sd] */
if (b1 == 0) {
sz = 2;
} else {
sz = 3;
}
break;
}
switch (sz) {
case 2:
/* 32 bit access */
gen_op_ld_T0_A0(OT_LONG + s->mem_index);
tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
break;
case 3:
/* 64 bit access */
gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
break;
default:
/* 128 bit access */
gen_ldo_env_A0(s->mem_index, op2_offset);
break;
}
} else {
rm = (modrm & 7) | REX_B(s);
Loaded 100 of 132 files, more files were not shown because too many files have changed in this diff. Show more