Compare commits

...

65 Commits

Author SHA1 Message Date
Michael Roth dfa83a6bae Update version for 2.3.1 release 2015-08-10 16:09:34 -05:00
Paolo Bonzini 35a616edef qemu-char: handle EINTR for TCP character devices
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 9172f428af)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-10 15:31:16 -05:00
Stefan Hajnoczi 35c30d3efd rtl8139: check TCP Data Offset field (CVE-2015-5165)
The TCP Data Offset field contains the length of the header.  Make sure
it is valid and does not exceed the IP data length.

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 8357946b15)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:34:00 -05:00
Stefan Hajnoczi f4c861fd68 rtl8139: skip offload on short TCP header (CVE-2015-5165)
TCP Large Segment Offload accesses the TCP header in the packet.  If the
packet is too short we must not attempt to access header fields:

  tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
  int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 4240be4563)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:33:54 -05:00
Stefan Hajnoczi b7a197c39e rtl8139: check IP Total Length field (CVE-2015-5165)
The IP Total Length field includes the IP header and data.  Make sure it
is valid and does not exceed the Ethernet payload size.

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit c6296ea88d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:33:48 -05:00
Stefan Hajnoczi 85611098ff rtl8139: check IP Header Length field (CVE-2015-5165)
The IP Header Length field was only checked in the IP checksum case, but
is used in other cases too.

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 03247d43c5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:33:42 -05:00
Stefan Hajnoczi ce4f451bbb rtl8139: skip offload on short Ethernet/IP header (CVE-2015-5165)
Transmit offload features access Ethernet and IP headers the packet.  If
the packet is too short we must not attempt to access header fields:

  int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
  ...
  eth_payload_data = saved_buffer + ETH_HLEN;
  ...
  ip = (ip_header*)eth_payload_data;
  if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit e1c120a9c5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:33:36 -05:00
Stefan Hajnoczi 6722c126f3 rtl8139: drop tautologous if (ip) {...} statement (CVE-2015-5165)
The previous patch stopped using the ip pointer as an indicator that the
IP header is present.  When we reach the if (ip) {...} statement we know
ip is always non-NULL.

Remove the if statement to reduce nesting.

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit d6812d60e7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:33:30 -05:00
Stefan Hajnoczi 8dd45dcd83 rtl8139: avoid nested ifs in IP header parsing (CVE-2015-5165)
Transmit offload needs to parse packet headers.  If header fields have
unexpected values the offload processing is skipped.

The code currently uses nested ifs because there is relatively little
input validation.  The next patches will add missing input validation
and a goto label is more appropriate to avoid deep if statement nesting.

Reported-by: 朱东海(启路) <donghai.zdh@alibaba-inc.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 39b8e7dcaf)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:32:40 -05:00
Aurelien Jarno e750591c8a tcg/mips: fix add2
The add2 code in the tcg_out_addsub2 function doesn't take into account
the case where rl == al == bl. In that case we can't compute the carry
after the addition. As it corresponds to a multiplication by 2, the
carry bit is the bit 31.

While this is a corner case, this prevents x86-64 guests to boot on a
MIPS host.

Cc: qemu-stable@nongnu.org
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit c99d69694a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:30:37 -05:00
Aurelien Jarno f9c0ae2723 tcg/mips: fix TLB loading for BE host with 32-bit guests
For 32-bit guest, we load a 32-bit address from the TLB, so there is no
need to compensate for the low or high part. This fixes 32-bit guests on
big-endian hosts.

Cc: qemu-stable@nongnu.org
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit e72c4fb81d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:30:20 -05:00
Stefano Stabellini c8bd74d1d5 Fix release_drive on unplugged devices (pci_piix3_xen_ide_unplug)
pci_piix3_xen_ide_unplug should completely unhook the unplugged
IDEDevice from the corresponding BlockBackend, otherwise the next call
to release_drive will try to detach the drive again.

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
(cherry picked from commit 6cd387833d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-08-04 12:25:11 -05:00
Kevin Wolf d1557697fd ide: Clear DRQ after handling all expected accesses
This is additional hardening against an end_transfer_func that fails to
clear the DRQ status bit. The bit must be unset as soon as the PIO
transfer has completed, so it's better to do this in a central place
instead of duplicating the code in all commands (and forgetting it in
some).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
(cherry picked from commit cb72cba830)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:19:55 -05:00
Kevin Wolf 86d6fe4cb0 ide/atapi: Fix START STOP UNIT command completion
The command must be completed on all code paths. START STOP UNIT with
pwrcnd set should succeed without doing anything.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
(cherry picked from commit 03441c3a4a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:19:39 -05:00
Kevin Wolf 9634e45e0b ide: Check array bounds before writing to io_buffer (CVE-2015-5154)
If the end_transfer_func of a command is called because enough data has
been read or written for the current PIO transfer, and it fails to
correctly call the command completion functions, the DRQ bit in the
status register and s->end_transfer_func may remain set. This allows the
guest to access further bytes in s->io_buffer beyond s->data_end, and
eventually overflowing the io_buffer.

One case where this currently happens is emulation of the ATAPI command
START STOP UNIT.

This patch fixes the problem by adding explicit array bounds checks
before accessing the buffer instead of relying on end_transfer_func to
function correctly.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
(cherry picked from commit d2ff858545)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:19:29 -05:00
Jeff Cody 0dc545e977 block: qemu-iotests - add check for multiplication overflow in vpc
This checks that VPC is able to successfully fail (without segfault)
on an image file with a max_table_entries that exceeds 0x40000000.

This table entry is within the valid range for VPC (although too large
for this sample image).

Cc: qemu-stable@nongnu.org
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 77c102c26e)
Conflicts:
	tests/qemu-iotests/group

* removed context dependency on iotest not present in 2.3.0 group
  file

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:18:23 -05:00
Jeff Cody 358f0ee234 block: vpc - prevent overflow if max_table_entries >= 0x40000000
When we allocate the pagetable based on max_table_entries, we multiply
the max table entry value by 4 to accomodate a table of 32-bit integers.
However, max_table_entries is a uint32_t, and the VPC driver accepts
ranges for that entry over 0x40000000.  So during this allocation:

s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4);

The size arg overflows, allocating significantly less memory than
expected.

Since qemu_try_blockalign() size argument is size_t, cast the
multiplication correctly to prevent overflow.

The value of "max_table_entries * 4" is used elsewhere in the code as
well, so store the correct value for use in all those cases.

We also check the Max Tables Entries value, to make sure that it is <
SIZE_MAX / 4, so we know the pagetable size will fit in size_t.

Cc: qemu-stable@nongnu.org
Reported-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit b15deac795)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:16:01 -05:00
Paolo Bonzini 961c74a841 scsi: fix buffer overflow in scsi_req_parse_cdb (CVE-2015-5158)
This is a guest-triggerable buffer overflow present in QEMU 2.2.0
and newer.  scsi_cdb_length returns -1 as an error value, but the
caller does not check it.

Luckily, the massive overflow means that QEMU will just SIGSEGV,
making the impact much smaller.

Reported-by: Zhu Donghai (朱东海) <donghai.zdh@alibaba-inc.com>
Fixes: 1894df0281
Reviewed-by: Fam Zheng <famz@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit c170aad8b0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:13:25 -05:00
Alex Williamson 98fe91ed66 vfio/pci: Fix bootindex
bootindex was incorrectly changed to a device Property during the
platform code split, resulting in it no longer working.  Remove it.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: qemu-stable@nongnu.org # v2.3+
(cherry picked from commit 759b484c5d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:12:30 -05:00
Jason Wang 46addaa0b5 virtio-net: unbreak any layout
Commit 032a74a1c0
("virtio-net: byteswap virtio-net header") breaks any layout by
requiring out_sg[0].iov_len >= n->guest_hdr_len. Fixing this by
copying header to temporary buffer if swap is needed, and then use
this buffer as part of out_sg.

Fixes 032a74a1c0
("virtio-net: byteswap virtio-net header")
Cc: qemu-stable@nongnu.org
Cc: clg@fr.ibm.com
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>

(cherry picked from commit feb93f3617)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:10:36 -05:00
Alex Williamson 5a4568717c vfio/pci: Fix RTL8168 NIC quirks
The RTL8168 quirk correctly describes using bit 31 as a signal to
mark a latch/completion, but the code mistakenly uses bit 28.  This
causes the Realtek driver to spin on this register for quite a while,
20k cycles on Windows 7 v7.092 driver.  Then it gets frustrated and
tries to set the bit itself and spins for another 20k cycles.  For
some this still results in a working driver, for others not.  About
the only thing the code really does in its current form is protect
the guest from sneaking in writes to the real hardware MSI-X table.
The fix is obviously to use bit 31 as we document that we should.

The other problem doesn't seem to affect current drivers as nobody
seems to use these window registers for writes to the MSI-X table, but
we need to use the stored data when a write is triggered, not the
value of the current write, which only provides the offset.

Note that only the Windows drivers from Realtek seem to use these
registers, the Microsoft drivers provided with Windows 8.1 do not
access them, nor do Linux in-kernel drivers.

Link: https://bugs.launchpad.net/qemu/+bug/1384892
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: qemu-stable@nongnu.org # v2.1+
(cherry picked from commit 69970fcef9)
Conflicts:
	hw/vfio/pci.c

* removed dependency on 3b643495

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:07:43 -05:00
James Hogan 87740cecc3 mips/kvm: Sign extend registers written to KVM
In case we're running on a 64-bit host, be sure to sign extend the
general purpose registers and hi/lo/pc before writing them to KVM, so as
to take advantage of MIPS32/MIPS64 compatibility.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: kvm@vger.kernel.org
Cc: qemu-stable@nongnu.org
Message-Id: <1429871214-23514-3-git-send-email-james.hogan@imgtec.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 02dae26ac4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:00:11 -05:00
James Hogan 8df2a9acd2 mips/kvm: Fix Big endian 32-bit register access
Fix access to 32-bit registers on big endian targets. The pointer passed
to the kernel must be for the actual 32-bit value, not a temporary
64-bit value, otherwise on big endian systems the kernel will only
interpret the upper half.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: kvm@vger.kernel.org
Cc: qemu-stable@nongnu.org
Message-Id: <1429871214-23514-2-git-send-email-james.hogan@imgtec.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit f8b3e48b2d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 22:00:07 -05:00
Fam Zheng c5c71e87aa block: Initialize local_err in bdrv_append_temp_snapshot
Cc: qemu-stable@nongnu.org
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-id: 1436156684-16526-1-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit c2e0dbbfd7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:56:40 -05:00
马文霜 2060efae47 Fix irq route entries exceeding KVM_MAX_IRQ_ROUTES
Last month, we experienced several guests crash(6cores-8cores), qemu logs
display the following messages:

qemu-system-x86_64: /build/qemu-2.1.2/kvm-all.c:976:
kvm_irqchip_commit_routes: Assertion `ret == 0' failed.

After analysis and verification, we can confirm it's irq-balance
daemon(in guest) leads to the assertion failure. Start a 8 core guest with
two disks, execute the following scripts will reproduce the BUG quickly:

irq_affinity.sh
========================================================================

vda_irq_num=25
vdb_irq_num=27
while [ 1 ]
do
    for irq in {1,2,4,8,10,20,40,80}
        do
            echo $irq > /proc/irq/$vda_irq_num/smp_affinity
            echo $irq > /proc/irq/$vdb_irq_num/smp_affinity
            dd if=/dev/vda of=/dev/zero bs=4K count=100 iflag=direct
            dd if=/dev/vdb of=/dev/zero bs=4K count=100 iflag=direct
        done
done
========================================================================

QEMU setup static irq route entries in kvm_pc_setup_irq_routing(), PIC and
IOAPIC share the first 15 GSI numbers, take up 23 GSI numbers, but take up
38 irq route entries. When change irq smp_affinity in guest, a dynamic route
entry may be setup, the current logic is: if allocate GSI number succeeds,
a new route entry can be added. The available dynamic GSI numbers is
1021(KVM_MAX_IRQ_ROUTES-23), but available irq route entries is only
986(KVM_MAX_IRQ_ROUTES-38), GSI numbers greater than route entries.
irq-balance's behavior will eventually leads to total irq route entries
exceed KVM_MAX_IRQ_ROUTES, ioctl(KVM_SET_GSI_ROUTING) fail and
kvm_irqchip_commit_routes() trigger assertion failure.

This patch fix the BUG.

Signed-off-by: Wenshuang Ma <kevinnma@tencent.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit bdf026317d)
Conflicts:
	kvm-all.c

* remove context dependency on bd2a8884
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:54:31 -05:00
Michael Roth 8d64975c98 target-ppc: fix hugepage support when using memory-backend-file
Current PPC code relies on -mem-path being used in order for
hugepage support to be detected. With the introduction of
MemoryBackendFile we can now handle this via:
  -object memory-file-backend,mem-path=...,id=hugemem0 \
  -numa node,id=mem0,memdev=hugemem0

Management tools like libvirt treat the 2 approaches as
interchangeable in some cases, which can lead to user-visible
regressions even for previously supported guest configurations.

Fix these by also iterating through any configured memory
backends that may be backed by hugepages.

Since the old code assumed hugepages always backed the entirety
of guest memory, play it safe an pick the minimum across the
max pages sizes for all backends, even ones that aren't backed
by hugepages.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit 2d103aae87)
Conflicts:
	target-ppc/kvm.c

*remove context dependency on header includes not in 2.3.0

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:50:55 -05:00
David Gibson 9b4420ad62 spapr_vty: lookup should only return valid VTY objects
If a guest passes the reg property of a valid VIO object that is not a VTY
to either H_GET_TERM_CHAR or H_PUT_TERM_CHAR, QEMU hits a dynamic cast
assertion and aborts.

PAPR+ says "Hypervisor checks the termno parameter for validity against the
Vterm IOA unit addresses assigned to the partition, else return H_Parameter."

This patch adds a type check to ensure vty_lookup() either returns a pointer
to a valid VTY object or NULL.  H_GET_TERM_CHAR and H_PUT_TERM_CHAR will
now return H_PARAMETER to the guest instead of crashing.

The patch has no effect on the reg == 0 hack used to implement the RTAS call
display-character.

Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit 0f888bfadd)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:48:27 -05:00
Christian Borntraeger 99c3468d8f s390x/ipl: Fix boot if no bootindex was specified
commit fa92e218df ("s390x/ipl: avoid sign extension") introduced
a regression:

qemu-system-s390x -drive file=image.qcow,format=qcow2
does not boot, the bios states
"No virtio-blk device found!"

adding bootindex=1 does boot.

The reason is that the uint32_t as return value will not do the right
thing for the return -1 (default without bootindex).
The bios itself, will interpret a 64bit -1 as autodetect (but it will
interpret 32bit -1 as ccw device address ff.ff.ffff)

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: qemu-stable@nongnu.org # v2.3.0
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit 6efd2c2a12)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:47:15 -05:00
Peter Lieven 1c17e8c7d3 block/nfs: limit maximum readahead size to 1MB
a malicious caller could otherwise specify a very
large value via the URI and force libnfs to allocate
a large amount of memory for the readahead buffer.

Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Lieven <pl@kamp.de>
Message-id: 1435317241-25585-1-git-send-email-pl@kamp.de
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 29c838cdc9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:36 -05:00
John Snow ffd060d51f iotests: add QMP event waiting queue
A filter is added to allow callers to request very specific
events to be pulled from the event queue, while leaving undesired
events still in the stream.

This allows us to poll for completion data for multiple asynchronous
events in any arbitrary order.

A new timeout context is added to the qmp pull_event method's
wait parameter to allow tests to fail if they do not complete
within some expected period of time.

Also fixed is a bug in qmp.pull_event where we try to retrieve an event
from an empty list if we attempt to retrieve an event with wait=False
but no events have occurred.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1429314609-29776-19-git-send-email-jsnow@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 7898f74e78)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:08 -05:00
Fam Zheng e4fb4bea37 iotests: Use event_wait in wait_ready
Only poll the specific type of event we are interested in, to avoid
stealing events that should be consumed by someone else.

Suggested-by: John Snow <jsnow@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit d7b2529792)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:08 -05:00
Fam Zheng edc0a65326 qemu-iotests: Add test case for mirror with unmap
This checks that the discard on mirror source that effectively zeroes
data is also reflected by the data of target.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit c615091793)
Conflicts:
	tests/qemu-iotests/group

*remove context dependencies on newer block tests

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:07 -05:00
Fam Zheng c62f6c8f67 qemu-iotests: Make block job methods common
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 866323f39d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:07 -05:00
Fam Zheng 3d8b7aed60 block: Fix dirty bitmap in bdrv_co_discard
Unsetting dirty globally with discard is not very correct. The discard may zero
out sectors (depending on can_write_zeroes_with_unmap), we should replicate
this change to destination side to make sure that the guest sees the same data.

Calling bdrv_reset_dirty also troubles mirror job because the hbitmap iterator
doesn't expect unsetting of bits after current position.

So let's do it the opposite way which fixes both problems: set the dirty bits
if we are to discard it.

Reported-by: wangxiaolong@ucloud.cn
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 508249952c)
Conflicts:
	block/io.c

* applied manually to avoid dependency on 61007b316
* squashed in 6e82e4b bdrv_reset_dirty() is static in
  2.3.0 and becomes unused as of this patch
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:07 -05:00
Fam Zheng 27ed14c4d7 mirror: Do zero write on target if sectors not allocated
If guest discards a source cluster, mirroring with bdrv_aio_readv is overkill.
Some protocols do zero upon discard, where it's best to use
bdrv_aio_write_zeroes, otherwise, bdrv_aio_discard will be enough.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit dcfb3beb51)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:46:07 -05:00
Fam Zheng 6a45a1b8e4 qmp: Add optional bool "unmap" to drive-mirror
If specified as "true", it allows discarding on target sectors where source is
not allocated.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 0fc9f8ea28)

* added to maintain any interdependencies between patches in the
  set. not intended as a new feature for 2.3.1, though it's there
  for anyone interested

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 21:43:36 -05:00
Fam Zheng 6cacd2651a block: Add bdrv_get_block_status_above
Like bdrv_is_allocated_above, this function follows the backing chain until seeing
BDRV_BLOCK_ALLOCATED.  Base is not included.

Reimplement bdrv_is_allocated on top.

[Initialized bdrv_co_get_block_status_above() ret to 0 to silence
mingw64 compiler warning about the unitialized variable.  assert(bs !=
base) prevents that case but I suppose the program could be compiled
with -DNDEBUG.
--Stefan]

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit ba3f0e2545)
Conflicts:
	block/io.c

* applied manually to avoid dependency on 61007b316
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 20:37:30 -05:00
Cornelia Huck e8248a5af1 virtio-ccw: complete handling of guest-initiated resets
For a guest-initiated reset, we need to not only reset the virtio device,
but also reset the VirtioCcwDevice into a clean state. This includes
resetting the indicators, or else a guest will not be able to e.g.
switch from classic interrupts to adapter interrupts.

Split off this routine into a new function virtio_ccw_reset_virtio()
to make the distinction between resetting the virtio-related devices
and the base subchannel device clear.

CC: qemu-stable@nongnu.org
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
(cherry picked from commit fa8b0ca5d1)
Conflicts:
	hw/s390x/virtio-ccw.c

*removed context dependency on 0b352fd

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:50:08 -05:00
Jason Wang 81cb0a5657 vhost: correctly pass error to caller in vhost_dev_enable_notifiers()
We override the error value r in fail_vq, this will cause the caller
can't detect the failure which may cause the caller may disable the
notifiers twice if vhost is failed to start. Fix this by using another
variable to keep track the return value of set_host_notifier().

Fixes b0b3db7955 ("vhost-net: cleanup
host notifiers at last step")

Cc: qemu-stable@nongnu.org
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 16617e36b0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:44:36 -05:00
Laszlo Ersek 6130c46232 hw/core: rebase sysbus_get_fw_dev_path() to g_strdup_printf()
This is done mainly for improving readability, and in preparation for the
next patch, but Markus pointed out another bonus for the string being
returned:

"No arbitrary length limit. Before the patch, it's 39 characters, and the
code breaks catastrophically when qdev_fw_name() is longer: the second
snprintf() is called with its first argument pointing beyond path[], and
its second argument underflowing to a huge size."

Cc: qemu-stable@nongnu.org
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 5ba03e2dd7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:41:25 -05:00
Petr Matousek 49ef542e41 i8254: fix out-of-bounds memory access in pit_ioport_read()
Due converting PIO to the new memory read/write api we no longer provide
separate I/O region lenghts for read and write operations. As a result,
reading from PIT Mode/Command register will end with accessing
pit->channels with invalid index.

Fix this by ignoring read from the Mode/Command register.

This is CVE-2015-3214.

Reported-by: Matt Tait <matttait@google.com>
Fixes: 0505bcdec8
Cc: qemu-stable@nongnu.org
Signed-off-by: Petr Matousek <pmatouse@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d4862a87e3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:40:21 -05:00
Gerd Hoffmann c270245a53 spice-display: fix segfault in qemu_spice_create_update
Although it is pretty unusual the stride for the guest image and the
mirror image maintained by spice-display can be different.  So use
separate variables for them.

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

Cc: qemu-stable@nongnu.org
Reported-by: perrier vincent <clownix@clownix.net>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit c6e484707f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:34:12 -05:00
Alberto Garcia 9272707a1f sdl2: fix crash in handle_windowevent() when restoring the screen size
The Ctrl-Alt-u keyboard shortcut restores the screen to its original
size. In the SDL2 UI this is done by destroying the window and
creating a new one. The old window emits SDL_WINDOWEVENT_HIDDEN when
it's destroyed, but trying to call SDL_GetWindowFromID() from that
event's window ID returns a null pointer. handle_windowevent() assumes
that the pointer is never null so it results in a crash.

Cc: qemu-stable@nongnu.org
Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 08d49df0db)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:33:50 -05:00
Fam Zheng c759f1a078 vmdk: Use vmdk_find_index_in_cluster everywhere
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 90df601f06)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:33:01 -05:00
Fam Zheng 714b54401c vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status
It has the similar issue with b1649fae49. Since the calculation
is repeated for a few times already, introduce a function so it can be
reused.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 61f0ed1d54)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:32:49 -05:00
Max Reitz e7e08380c3 iotests: qcow2 COW with minimal L2 cache size
This adds a test case to test 103 for performing a COW operation in a
qcow2 image using an L2 cache with minimal size (which should be at
least two clusters so the COW can access both source and destination
simultaneously).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit a4291eafc5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:27:34 -05:00
Max Reitz c631ee6520 qcow2: Set MIN_L2_CACHE_SIZE to 2
The L2 cache must cover at least two L2 tables, because during COW two
L2 tables are accessed simultaneously.

Reported-by: Alexander Graf <agraf@suse.de>
Cc: qemu-stable <qemu-stable@nongnu.org>
Signed-off-by: Max Reitz <mreitz@redhat.com>
Tested-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 57e2166959)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:26:34 -05:00
Gerd Hoffmann b153c8d3f3 kbd: add brazil kbd keys to x11 evdev map
This patch adds the two extra brazilian keys to the evdev keymap for
X11.  This patch gets the two keys going with the vnc, gtk and sdl1
UIs.

The SDL2 library complains it doesn't know these keys, so the SDL2
library must be fixed before we can update ui/sdl2-keymap.h

Cc: qemu-stable@nongnu.org
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 33aa30cafc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:25:10 -05:00
Gerd Hoffmann f45048225a kbd: add brazil kbd keys to qemu
The brazilian computer keyboard layout has two extra keys (compared to
the usual 105-key intl ps/2 keyboard).  This patch makes these two keys
known to qemu.

For historic reasons qemu has two ways to specify a key:  A QKeyCode
(name-based) or a number (ps/2 scancode based).  Therefore we have to
update multiple places to make new keys known to qemu:

  (1) The QKeyCode definition in qapi-schema.json
  (2) The QKeyCode <-> number mapping table in ui/input-keymap.c

This patch does just that.  With this patch applied you can send those
two keys to the guest using the send-key monitor command.

Cc: qemu-stable@nongnu.org
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit b771f470f3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:25:03 -05:00
Justin Ossevoort ae0fa48f51 qga/commands-posix: Fix bug in guest-fstrim
The FITRIM ioctl updates the fstrim_range structure it receives. This
way the caller can determine how many bytes were trimmed. The
guest-fstrim logic reuses the same fstrim_range for each filesystem,
effectively limiting each filesystem to trim at most as much as the
previous was able to trim.

If a previous filesystem would have trimmed 0 bytes, than the next
filesystem would report an error 'Invalid argument' because a FITRIM
request with length 0 is not valid.

This change resets the fstrim_range structure for each filesystem.

Signed-off-by: Justin Ossevoort <justin@quarantainenet.nl>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
(cherry picked from commit 73a652a1b0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:24:00 -05:00
Shannon Zhao bb3a1da4d4 hw/acpi/aml-build: Fix memory leak
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
(cherry picked from commit afcf905cff)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:21:41 -05:00
Fam Zheng b48a391cff qemu-iotests: Test unaligned sub-block zero write
Test zero write in byte range 512~1024 for 4k alignment.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1431522721-3266-4-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit ab53c44718)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:18:59 -05:00
Fam Zheng cc883fe42d block: Fix NULL deference for unaligned write if qiov is NULL
For zero write, callers pass in NULL qiov (qemu-io "write -z" or
scsi-disk "write same").

Commit fc3959e466 fixed bdrv_co_write_zeroes which is the common case
for this bug, but it still exists in bdrv_aio_write_zeroes. A simpler
fix would be in bdrv_co_do_pwritev which is the NULL dereference point
and covers both cases.

So don't access it in bdrv_co_do_pwritev in this case, use three aligned
writes.

[Initialize ret to 0 in bdrv_co_do_zero_pwritev() to avoid uninitialized
variable warning with gcc 4.9.2.
--Stefan]

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-id: 1431522721-3266-3-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 9eeb6dd1b2)
Conflicts:
	block/io.c

* moved hunks into corresponding location in block.c due to lack of
  61007b316 in v2.3.0
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 18:15:27 -05:00
Michael Roth 4072585ecf Revert "block: Fix unaligned zero write"
This reverts commit fc3959e466.

From upstream commit d01c07f:
  This reverts commit fc3959e466.

  The core write code already handles the case, so remove this
  duplication.

  Because commit 61007b316 moved the touched code from block.c to
  block/io.c, the change is manually reverted.

  Signed-off-by: Fam Zheng <famz@redhat.com>
  Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
  Reviewed-by: Kevin Wolf <kwolf@redhat.com>

v2.3.0 does not contain 61007b316 so we can revert the change
directly.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-29 17:05:56 -05:00
Petr Matousek 959fad0ff1 fdc: force the fifo access to be in bounds of the allocated buffer
During processing of certain commands such as FD_CMD_READ_ID and
FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could
get out of bounds leading to memory corruption with values coming
from the guest.

Fix this by making sure that the index is always bounded by the
allocated memory.

This is CVE-2015-3456.

Signed-off-by: Petr Matousek <pmatouse@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit e907746266)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:26:06 -05:00
Peter Maydell a4bb522ee5 target-arm: Avoid buffer overrun on UNPREDICTABLE ldrd/strd
A LDRD or STRD where rd is not an even number is UNPREDICTABLE.
We were letting this fall through, which is OK unless rd is 15,
in which case we would attempt to do a load_reg or store_reg
to a nonexistent r16 for the second half of the double-word.
Catch the odd-numbered-rd cases and UNDEF them instead.

To do this we rearrange the structure of the code a little
so we can put the UNDEF catches at the top before we've
allocated TCG temporaries.

Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1431348973-21315-1-git-send-email-peter.maydell@linaro.org
(cherry picked from commit 3960c336ad)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:23:18 -05:00
Jason Wang cf6c213981 virtio-net: fix the upper bound when trying to delete queues
Virtqueue were indexed from zero, so don't delete virtqueue whose
index is n->max_queues * 2 + 1.

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

(cherry picked from commit 27a46dcf50)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:22:35 -05:00
Michal Kazior cf3297868c usb: fix usb-net segfault
The dev->config pointer isn't set until guest
system initializes usb devices (via
usb_desc_set_config). However qemu networking can
go through some motions prior to that, e.g.:

 #0  is_rndis (s=0x555557261970) at hw/usb/dev-network.c:653
 #1  0x000055555585f723 in usbnet_can_receive (nc=0x55555641e820) at hw/usb/dev-network.c:1315
 #2  0x000055555587635e in qemu_can_send_packet (sender=0x5555572660a0) at net/net.c:470
 #3  0x0000555555878e34 in net_hub_port_can_receive (nc=0x5555562d7800) at net/hub.c:101
 #4  0x000055555587635e in qemu_can_send_packet (sender=0x5555562d7980) at net/net.c:470
 #5  0x000055555587dbca in tap_can_send (opaque=0x5555562d7980) at net/tap.c:172

The command to reproduce most reliably was:

 qemu-system-i386 -usb -device usb-net,vlan=0 -net tap,vlan=0

This wasn't strictly a problem with tap. Other
networking endpoints (vde, user) could trigger
this problem as well.

Fixes: https://bugs.launchpad.net/qemu/+bug/1050823
Cc: qemu-stable@nongnu.org
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 278412d0e7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:20:04 -05:00
Kevin Wolf ad9c167fd2 qcow2: Flush pending discards before allocating cluster
Before a freed cluster can be reused, pending discards for this cluster
must be processed.

The original assumption was that this was not a problem because discards
are only cached during discard/write zeroes operations, which are
synchronous so that no concurrent write requests can cause cluster
allocations.

However, the discard/write zeroes operation itself can allocate a new L2
table (and it has to in order to put zero flags there), so make sure we
can cope with the situation.

This fixes https://bugs.launchpad.net/bugs/1349972.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit ecbda7a225)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:19:33 -05:00
Fam Zheng d8e231fce2 vmdk: Fix overflow if l1_size is 0x20000000
Richard Jones caught this bug with afl fuzzer.

In fact, that's the only possible value to overflow (extent->l1_size =
0x20000000) l1_size:

l1_size = extent->l1_size * sizeof(long) => 0x80000000;

g_try_malloc returns NULL because l1_size is interpreted as negative
during type casting from 'int' to 'gsize', which yields a enormous
value. Hence, by coincidence, we get a "not too bad" behavior:

qemu-img: Could not open '/tmp/afl6.img': Could not open
'/tmp/afl6.img': Cannot allocate memory

Values larger than 0x20000000 will be refused by the validation in
vmdk_add_extent.

Values smaller than 0x20000000 will not overflow l1_size.

Cc: qemu-stable@nongnu.org
Reported-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 13c4941cdd)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:19:02 -05:00
Fam Zheng 53cd79c117 vmdk: Fix next_cluster_sector for compressed write
This fixes the bug introduced by commit c6ac36e (vmdk: Optimize cluster
allocation).

Sometimes, write_len could be larger than cluster size, because it
contains both data and marker.  We must advance next_cluster_sector in
this case, otherwise the image gets corrupted.

Cc: qemu-stable@nongnu.org
Reported-by: Antoni Villalonga <qemu-list@friki.cat>
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 5e82a31eb9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:18:27 -05:00
Bogdan Purcareata 3dd15f3e58 nbd/trivial: fix type cast for ioctl
This fixes ioctl behavior on powerpc e6500 platforms with 64bit kernel and 32bit
userspace. The current type cast has no effect there and the value passed to the
kernel is still 0. Probably an issue related to the compiler, since I'm assuming
the same configuration works on a similar setup on x86.

Also ensure consistency with previous type cast in TRACE message.

Signed-off-by: Bogdan Purcareata <bogdan.purcareata@freescale.com>
Message-Id: <1428058914-32050-1-git-send-email-bogdan.purcareata@freescale.com>
Cc: qemu-stable@nongnu.org
[Fix parens as noticed by Michael. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

(cherry picked from commit d064d9f381)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:14:07 -05:00
Ján Tomko 4c59860506 Strip brackets from vnc host
Commit v2.2.0-1530-ge556032 vnc: switch to inet_listen_opts
bypassed the use of inet_parse in inet_listen, making literal
IPv6 addresses enclosed in brackets fail:

qemu-kvm: -vnc [::1]:0: Failed to start VNC server on `(null)': address
resolution failed for [::1]:5900: Name or service not known

Strip the brackets to make it work again.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 274c3b52e1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:13:19 -05:00
Peter Lieven b575af0730 block/iscsi: do not forget to logout from target
We actually were always impolitely dropping the connection and
not cleanly logging out.

CC: qemu-stable@nongnu.org
Signed-off-by: Peter Lieven <pl@kamp.de>
Message-id: 1429193313-4263-2-git-send-email-pl@kamp.de
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 20474e9aa0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 18:08:49 -05:00
Stefan Hajnoczi d3b59789e8 bt-sdp: fix broken uuids power-of-2 calculation
The binary search in sdp_uuid_match() only works when the number of
elements to search is a power of two.

  lo = record->uuid;
  hi = record->uuids;
  while (hi >>= 1)
      if (lo[hi] <= val)
          lo += hi;

  return *lo == val;

I noticed that the record->uuids calculation in
sdp_service_record_build() was suspect:

  record->uuids = 1 << ffs(record->uuids - 1);

Unlike most ffs(val) - 1 users, the expression is ffs(val - 1)!

Actually ffs() is the wrong function to use for power-of-2.  Use
pow2ceil() to achieve the correct effect.  Now the record->uuid[] array
is sized correctly and the binary search in sdp_uuid_match() should
work.

I'm not sure how to run/test this code.

Cc: Andrzej Zaborowski <balrog@zabor.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1427124571-28598-2-git-send-email-stefanha@redhat.com
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 588ef9d411)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-07-28 17:46:44 -05:00
60 changed files with 1076 additions and 492 deletions

View File

@ -1 +1 @@
2.3.0
2.3.1

215
block.c
View File

@ -99,8 +99,6 @@ static QLIST_HEAD(, BlockDriver) bdrv_drivers =
static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors);
static void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors);
/* If non-zero, use only whitelisted block drivers */
static int use_bdrv_whitelist;
@ -1382,7 +1380,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
QemuOpts *opts = NULL;
QDict *snapshot_options;
BlockDriverState *bs_snapshot;
Error *local_err;
Error *local_err = NULL;
int ret;
/* if snapshot, we create a temporary backing file and open it
@ -3118,19 +3116,6 @@ out:
return ret;
}
static inline uint64_t bdrv_get_align(BlockDriverState *bs)
{
/* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
return MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
}
static inline bool bdrv_req_is_aligned(BlockDriverState *bs,
int64_t offset, size_t bytes)
{
int64_t align = bdrv_get_align(bs);
return !(offset & (align - 1) || (bytes & (align - 1)));
}
/*
* Handle a read request in coroutine context
*/
@ -3141,7 +3126,8 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
BlockDriver *drv = bs->drv;
BdrvTrackedRequest req;
uint64_t align = bdrv_get_align(bs);
/* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
uint8_t *head_buf = NULL;
uint8_t *tail_buf = NULL;
QEMUIOVector local_qiov;
@ -3375,6 +3361,94 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
return ret;
}
static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs,
int64_t offset,
unsigned int bytes,
BdrvRequestFlags flags,
BdrvTrackedRequest *req)
{
uint8_t *buf = NULL;
QEMUIOVector local_qiov;
struct iovec iov;
uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
unsigned int head_padding_bytes, tail_padding_bytes;
int ret = 0;
head_padding_bytes = offset & (align - 1);
tail_padding_bytes = align - ((offset + bytes) & (align - 1));
assert(flags & BDRV_REQ_ZERO_WRITE);
if (head_padding_bytes || tail_padding_bytes) {
buf = qemu_blockalign(bs, align);
iov = (struct iovec) {
.iov_base = buf,
.iov_len = align,
};
qemu_iovec_init_external(&local_qiov, &iov, 1);
}
if (head_padding_bytes) {
uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);
/* RMW the unaligned part before head. */
mark_request_serialising(req, align);
wait_serialising_requests(req);
BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_HEAD);
ret = bdrv_aligned_preadv(bs, req, offset & ~(align - 1), align,
align, &local_qiov, 0);
if (ret < 0) {
goto fail;
}
BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
memset(buf + head_padding_bytes, 0, zero_bytes);
ret = bdrv_aligned_pwritev(bs, req, offset & ~(align - 1), align,
&local_qiov,
flags & ~BDRV_REQ_ZERO_WRITE);
if (ret < 0) {
goto fail;
}
offset += zero_bytes;
bytes -= zero_bytes;
}
assert(!bytes || (offset & (align - 1)) == 0);
if (bytes >= align) {
/* Write the aligned part in the middle. */
uint64_t aligned_bytes = bytes & ~(align - 1);
ret = bdrv_aligned_pwritev(bs, req, offset, aligned_bytes,
NULL, flags);
if (ret < 0) {
goto fail;
}
bytes -= aligned_bytes;
offset += aligned_bytes;
}
assert(!bytes || (offset & (align - 1)) == 0);
if (bytes) {
assert(align == tail_padding_bytes + bytes);
/* RMW the unaligned part after tail. */
mark_request_serialising(req, align);
wait_serialising_requests(req);
BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_TAIL);
ret = bdrv_aligned_preadv(bs, req, offset, align,
align, &local_qiov, 0);
if (ret < 0) {
goto fail;
}
BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
memset(buf, 0, bytes);
ret = bdrv_aligned_pwritev(bs, req, offset, align,
&local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
}
fail:
qemu_vfree(buf);
return ret;
}
/*
* Handle a write request in coroutine context
*/
@ -3383,7 +3457,8 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
BdrvRequestFlags flags)
{
BdrvTrackedRequest req;
uint64_t align = bdrv_get_align(bs);
/* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
uint8_t *head_buf = NULL;
uint8_t *tail_buf = NULL;
QEMUIOVector local_qiov;
@ -3414,6 +3489,11 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
*/
tracked_request_begin(&req, bs, offset, bytes, true);
if (!qiov) {
ret = bdrv_co_do_zero_pwritev(bs, offset, bytes, flags, &req);
goto out;
}
if (offset & (align - 1)) {
QEMUIOVector head_qiov;
struct iovec head_iov;
@ -3482,23 +3562,19 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
bytes = ROUND_UP(bytes, align);
}
if (use_local_qiov) {
/* Local buffer may have non-zero data. */
flags &= ~BDRV_REQ_ZERO_WRITE;
}
ret = bdrv_aligned_pwritev(bs, &req, offset, bytes,
use_local_qiov ? &local_qiov : qiov,
flags);
fail:
tracked_request_end(&req);
if (use_local_qiov) {
qemu_iovec_destroy(&local_qiov);
}
qemu_vfree(head_buf);
qemu_vfree(tail_buf);
out:
tracked_request_end(&req);
return ret;
}
@ -3526,32 +3602,14 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
BdrvRequestFlags flags)
{
int ret;
trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);
if (!(bs->open_flags & BDRV_O_UNMAP)) {
flags &= ~BDRV_REQ_MAY_UNMAP;
}
if (bdrv_req_is_aligned(bs, sector_num << BDRV_SECTOR_BITS,
nb_sectors << BDRV_SECTOR_BITS)) {
ret = bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
BDRV_REQ_ZERO_WRITE | flags);
} else {
uint8_t *buf;
QEMUIOVector local_qiov;
size_t bytes = nb_sectors << BDRV_SECTOR_BITS;
buf = qemu_memalign(bdrv_opt_mem_align(bs), bytes);
memset(buf, 0, bytes);
qemu_iovec_init(&local_qiov, 1);
qemu_iovec_add(&local_qiov, buf, bytes);
ret = bdrv_co_do_writev(bs, sector_num, nb_sectors, &local_qiov,
BDRV_REQ_ZERO_WRITE | flags);
qemu_vfree(buf);
}
return ret;
return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
BDRV_REQ_ZERO_WRITE | flags);
}
/**
@ -4142,28 +4200,54 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
return ret;
}
/* Coroutine wrapper for bdrv_get_block_status() */
static void coroutine_fn bdrv_get_block_status_co_entry(void *opaque)
static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
BlockDriverState *base,
int64_t sector_num,
int nb_sectors,
int *pnum)
{
BlockDriverState *p;
int64_t ret = 0;
assert(bs != base);
for (p = bs; p != base; p = p->backing_hd) {
ret = bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum);
if (ret < 0 || ret & BDRV_BLOCK_ALLOCATED) {
break;
}
/* [sector_num, pnum] unallocated on this layer, which could be only
* the first part of [sector_num, nb_sectors]. */
nb_sectors = MIN(nb_sectors, *pnum);
}
return ret;
}
/* Coroutine wrapper for bdrv_get_block_status_above() */
static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque)
{
BdrvCoGetBlockStatusData *data = opaque;
BlockDriverState *bs = data->bs;
data->ret = bdrv_co_get_block_status(bs, data->sector_num, data->nb_sectors,
data->pnum);
data->ret = bdrv_co_get_block_status_above(data->bs, data->base,
data->sector_num,
data->nb_sectors,
data->pnum);
data->done = true;
}
/*
* Synchronous wrapper around bdrv_co_get_block_status().
* Synchronous wrapper around bdrv_co_get_block_status_above().
*
* See bdrv_co_get_block_status() for details.
* See bdrv_co_get_block_status_above() for details.
*/
int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
BlockDriverState *base,
int64_t sector_num,
int nb_sectors, int *pnum)
{
Coroutine *co;
BdrvCoGetBlockStatusData data = {
.bs = bs,
.base = base,
.sector_num = sector_num,
.nb_sectors = nb_sectors,
.pnum = pnum,
@ -4172,11 +4256,11 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
if (qemu_in_coroutine()) {
/* Fast-path if already in coroutine context */
bdrv_get_block_status_co_entry(&data);
bdrv_get_block_status_above_co_entry(&data);
} else {
AioContext *aio_context = bdrv_get_aio_context(bs);
co = qemu_coroutine_create(bdrv_get_block_status_co_entry);
co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry);
qemu_coroutine_enter(co, &data);
while (!data.done) {
aio_poll(aio_context, true);
@ -4185,6 +4269,14 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
return data.ret;
}
int64_t bdrv_get_block_status(BlockDriverState *bs,
int64_t sector_num,
int nb_sectors, int *pnum)
{
return bdrv_get_block_status_above(bs, bs->backing_hd,
sector_num, nb_sectors, pnum);
}
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
@ -5205,8 +5297,6 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
return -EROFS;
}
bdrv_reset_dirty(bs, sector_num, nb_sectors);
/* Do nothing if disabled. */
if (!(bs->open_flags & BDRV_O_UNMAP)) {
return 0;
@ -5216,6 +5306,8 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
return 0;
}
bdrv_set_dirty(bs, sector_num, nb_sectors);
max_discard = MIN_NON_ZERO(bs->bl.max_discard, BDRV_REQUEST_MAX_SECTORS);
while (nb_sectors > 0) {
int ret;
@ -5526,15 +5618,6 @@ static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
}
}
static void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors)
{
BdrvDirtyBitmap *bitmap;
QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
}
}
int64_t bdrv_get_dirty_count(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
{
return hbitmap_count(bitmap->bitmap);

View File

@ -1501,6 +1501,9 @@ out:
if (ret) {
if (iscsi != NULL) {
if (iscsi_is_logged_in(iscsi)) {
iscsi_logout_sync(iscsi);
}
iscsi_destroy_context(iscsi);
}
memset(iscsilun, 0, sizeof(IscsiLun));
@ -1514,6 +1517,9 @@ static void iscsi_close(BlockDriverState *bs)
struct iscsi_context *iscsi = iscsilun->iscsi;
iscsi_detach_aio_context(bs);
if (iscsi_is_logged_in(iscsi)) {
iscsi_logout_sync(iscsi);
}
iscsi_destroy_context(iscsi);
g_free(iscsilun->zeroblock);
g_free(iscsilun->allocationmap);

View File

@ -57,6 +57,7 @@ typedef struct MirrorBlockJob {
int in_flight;
int sectors_in_flight;
int ret;
bool unmap;
} MirrorBlockJob;
typedef struct MirrorOp {
@ -167,6 +168,8 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
uint64_t delay_ns = 0;
MirrorOp *op;
int pnum;
int64_t ret;
s->sector_num = hbitmap_iter_next(&s->hbi);
if (s->sector_num < 0) {
@ -295,8 +298,22 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
s->in_flight++;
s->sectors_in_flight += nb_sectors;
trace_mirror_one_iteration(s, sector_num, nb_sectors);
bdrv_aio_readv(source, sector_num, &op->qiov, nb_sectors,
mirror_read_complete, op);
ret = bdrv_get_block_status_above(source, NULL, sector_num,
nb_sectors, &pnum);
if (ret < 0 || pnum < nb_sectors ||
(ret & BDRV_BLOCK_DATA && !(ret & BDRV_BLOCK_ZERO))) {
bdrv_aio_readv(source, sector_num, &op->qiov, nb_sectors,
mirror_read_complete, op);
} else if (ret & BDRV_BLOCK_ZERO) {
bdrv_aio_write_zeroes(s->target, sector_num, op->nb_sectors,
s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
mirror_write_complete, op);
} else {
assert(!(ret & BDRV_BLOCK_DATA));
bdrv_aio_discard(s->target, sector_num, op->nb_sectors,
mirror_write_complete, op);
}
return delay_ns;
}
@ -660,6 +677,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
int64_t buf_size,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb,
void *opaque, Error **errp,
const BlockJobDriver *driver,
@ -702,6 +720,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
s->base = base;
s->granularity = granularity;
s->buf_size = MAX(buf_size, granularity);
s->unmap = unmap;
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, errp);
if (!s->dirty_bitmap) {
@ -720,6 +739,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, int64_t granularity, int64_t buf_size,
MirrorSyncMode mode, BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb,
void *opaque, Error **errp)
{
@ -730,7 +750,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
base = mode == MIRROR_SYNC_MODE_TOP ? bs->backing_hd : NULL;
mirror_start_job(bs, target, replaces,
speed, granularity, buf_size,
on_source_error, on_target_error, cb, opaque, errp,
on_source_error, on_target_error, unmap, cb, opaque, errp,
&mirror_job_driver, is_none_mode, base);
}
@ -778,7 +798,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
bdrv_ref(base);
mirror_start_job(bs, base, NULL, speed, 0, 0,
on_error, on_error, cb, opaque, &local_err,
on_error, on_error, false, cb, opaque, &local_err,
&commit_active_job_driver, false, base);
if (local_err) {
error_propagate(errp, local_err);

View File

@ -35,6 +35,8 @@
#include "sysemu/sysemu.h"
#include <nfsc/libnfs.h>
#define QEMU_NFS_MAX_READAHEAD_SIZE 1048576
typedef struct NFSClient {
struct nfs_context *context;
struct nfsfh *fh;
@ -327,6 +329,11 @@ static int64_t nfs_client_open(NFSClient *client, const char *filename,
nfs_set_tcp_syncnt(client->context, val);
#ifdef LIBNFS_FEATURE_READAHEAD
} else if (!strcmp(qp->p[i].name, "readahead")) {
if (val > QEMU_NFS_MAX_READAHEAD_SIZE) {
error_report("NFS Warning: Truncating NFS readahead"
" size to %d", QEMU_NFS_MAX_READAHEAD_SIZE);
val = QEMU_NFS_MAX_READAHEAD_SIZE;
}
nfs_set_readahead(client->context, val);
#endif
} else {

View File

@ -833,6 +833,11 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size)
uint64_t i, nb_clusters, refcount;
int ret;
/* We can't allocate clusters if they may still be queued for discard. */
if (s->cache_discards) {
qcow2_process_discards(bs, 0);
}
nb_clusters = size_to_clusters(s, size);
retry:
for(i = 0; i < nb_clusters; i++) {

View File

@ -62,7 +62,8 @@
#define MIN_CLUSTER_BITS 9
#define MAX_CLUSTER_BITS 21
#define MIN_L2_CACHE_SIZE 1 /* cluster */
/* Must be at least 2 to cover COW */
#define MIN_L2_CACHE_SIZE 2 /* clusters */
/* Must be at least 4 to cover all cases of refcount table growth */
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */

View File

@ -451,7 +451,8 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
Error **errp)
{
int ret;
int l1_size, i;
size_t l1_size;
int i;
/* read the L1 table */
l1_size = extent->l1_size * sizeof(uint32_t);
@ -1247,6 +1248,17 @@ static VmdkExtent *find_extent(BDRVVmdkState *s,
return NULL;
}
static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent,
int64_t sector_num)
{
uint64_t index_in_cluster, extent_begin_sector, extent_relative_sector_num;
extent_begin_sector = extent->end_sector - extent->sectors;
extent_relative_sector_num = sector_num - extent_begin_sector;
index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
return index_in_cluster;
}
static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int *pnum)
{
@ -1284,7 +1296,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
break;
}
index_in_cluster = sector_num % extent->cluster_sectors;
index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
n = extent->cluster_sectors - index_in_cluster;
if (n > nb_sectors) {
n = nb_sectors;
@ -1302,6 +1314,8 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
uLongf buf_len;
const uint8_t *write_buf = buf;
int write_len = nb_sectors * 512;
int64_t write_offset;
int64_t write_end_sector;
if (extent->compressed) {
if (!extent->has_marker) {
@ -1320,10 +1334,14 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
write_buf = (uint8_t *)data;
write_len = buf_len + sizeof(VmdkGrainMarker);
}
ret = bdrv_pwrite(extent->file,
cluster_offset + offset_in_cluster,
write_buf,
write_len);
write_offset = cluster_offset + offset_in_cluster,
ret = bdrv_pwrite(extent->file, write_offset, write_buf, write_len);
write_end_sector = DIV_ROUND_UP(write_offset + write_len, BDRV_SECTOR_SIZE);
extent->next_cluster_sector = MAX(extent->next_cluster_sector,
write_end_sector);
if (ret != write_len) {
ret = ret < 0 ? ret : -EIO;
goto out;
@ -1406,7 +1424,6 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
BDRVVmdkState *s = bs->opaque;
int ret;
uint64_t n, index_in_cluster;
uint64_t extent_begin_sector, extent_relative_sector_num;
VmdkExtent *extent = NULL;
uint64_t cluster_offset;
@ -1418,9 +1435,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
ret = get_cluster_offset(bs, extent, NULL,
sector_num << 9, false, &cluster_offset,
0, 0);
extent_begin_sector = extent->end_sector - extent->sectors;
extent_relative_sector_num = sector_num - extent_begin_sector;
index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
n = extent->cluster_sectors - index_in_cluster;
if (n > nb_sectors) {
n = nb_sectors;
@ -1482,7 +1497,6 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
VmdkExtent *extent = NULL;
int ret;
int64_t index_in_cluster, n;
uint64_t extent_begin_sector, extent_relative_sector_num;
uint64_t cluster_offset;
VmdkMetaData m_data;
@ -1498,9 +1512,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
if (!extent) {
return -EIO;
}
extent_begin_sector = extent->end_sector - extent->sectors;
extent_relative_sector_num = sector_num - extent_begin_sector;
index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
n = extent->cluster_sectors - index_in_cluster;
if (n > nb_sectors) {
n = nb_sectors;

View File

@ -168,6 +168,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
uint8_t buf[HEADER_SIZE];
uint32_t checksum;
uint64_t computed_size;
uint64_t pagetable_size;
int disk_type = VHD_DYNAMIC;
int ret;
@ -269,7 +270,17 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4);
if (s->max_table_entries > SIZE_MAX / 4 ||
s->max_table_entries > (int) INT_MAX / 4) {
error_setg(errp, "Max Table Entries too large (%" PRId32 ")",
s->max_table_entries);
ret = -EINVAL;
goto fail;
}
pagetable_size = (uint64_t) s->max_table_entries * 4;
s->pagetable = qemu_try_blockalign(bs->file, pagetable_size);
if (s->pagetable == NULL) {
ret = -ENOMEM;
goto fail;
@ -277,14 +288,13 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
s->max_table_entries * 4);
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable, pagetable_size);
if (ret < 0) {
goto fail;
}
s->free_data_block_offset =
(s->bat_offset + (s->max_table_entries * 4) + 511) & ~511;
ROUND_UP(s->bat_offset + pagetable_size, 512);
for (i = 0; i < s->max_table_entries; i++) {
be32_to_cpus(&s->pagetable[i]);

View File

@ -2461,6 +2461,7 @@ void qmp_drive_mirror(const char *device, const char *target,
bool has_buf_size, int64_t buf_size,
bool has_on_source_error, BlockdevOnError on_source_error,
bool has_on_target_error, BlockdevOnError on_target_error,
bool has_unmap, bool unmap,
Error **errp)
{
BlockBackend *blk;
@ -2492,6 +2493,9 @@ void qmp_drive_mirror(const char *device, const char *target,
if (!has_buf_size) {
buf_size = DEFAULT_MIRROR_BUF_SIZE;
}
if (!has_unmap) {
unmap = true;
}
if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
@ -2631,6 +2635,7 @@ void qmp_drive_mirror(const char *device, const char *target,
has_replaces ? replaces : NULL,
speed, granularity, buf_size, sync,
on_source_error, on_target_error,
unmap,
block_job_cb, bs, &local_err);
if (local_err != NULL) {
bdrv_unref(target_bs);

2
hmp.c
View File

@ -1034,7 +1034,7 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
false, NULL, false, NULL,
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
true, mode, false, 0, false, 0, false, 0,
false, 0, false, 0, &err);
false, 0, false, 0, false, true, &err);
hmp_handle_error(mon, &err);
}

View File

@ -304,6 +304,7 @@ static void aml_free(gpointer data, gpointer user_data)
{
Aml *var = data;
build_free_array(var->buf);
g_free(var);
}
Aml *init_aml_allocator(void)

View File

@ -1512,7 +1512,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
{
FDrive *cur_drv;
uint32_t retval = 0;
int pos;
uint32_t pos;
cur_drv = get_cur_drv(fdctrl);
fdctrl->dsr &= ~FD_DSR_PWRDOWN;
@ -1521,8 +1521,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
return 0;
}
pos = fdctrl->data_pos;
pos %= FD_SECTOR_LEN;
if (fdctrl->msr & FD_MSR_NONDMA) {
pos %= FD_SECTOR_LEN;
if (pos == 0) {
if (fdctrl->data_pos != 0)
if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
@ -1867,10 +1867,13 @@ static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
{
FDrive *cur_drv = get_cur_drv(fdctrl);
uint32_t pos;
if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
pos = fdctrl->data_pos - 1;
pos %= FD_SECTOR_LEN;
if (fdctrl->fifo[pos] & 0x80) {
/* Command parameters done */
if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
if (fdctrl->fifo[pos] & 0x40) {
fdctrl->fifo[0] = fdctrl->fifo[1];
fdctrl->fifo[2] = 0;
fdctrl->fifo[3] = 0;
@ -1970,7 +1973,7 @@ static uint8_t command_to_handler[256];
static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
{
FDrive *cur_drv;
int pos;
uint32_t pos;
/* Reset mode */
if (!(fdctrl->dor & FD_DOR_nRESET)) {
@ -2019,7 +2022,9 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
}
FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
fdctrl->fifo[fdctrl->data_pos++] = value;
pos = fdctrl->data_pos++;
pos %= FD_SECTOR_LEN;
fdctrl->fifo[pos] = value;
if (fdctrl->data_pos == fdctrl->data_len) {
/* We now have all parameters
* and will be able to treat the command

View File

@ -707,7 +707,7 @@ static void sdp_service_record_build(struct sdp_service_record_s *record,
len += sdp_attr_max_size(&def->attributes[record->attributes ++].data,
&record->uuids);
}
record->uuids = 1 << ffs(record->uuids - 1);
record->uuids = pow2ceil(record->uuids);
record->attribute_list =
g_malloc0(record->attributes * sizeof(*record->attribute_list));
record->uuid =

View File

@ -228,6 +228,10 @@ VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
return spapr_vty_get_default(spapr->vio_bus);
}
if (!object_dynamic_cast(OBJECT(sdev), TYPE_VIO_SPAPR_VTY_DEVICE)) {
return NULL;
}
return sdev;
}

View File

@ -281,19 +281,15 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
static char *sysbus_get_fw_dev_path(DeviceState *dev)
{
SysBusDevice *s = SYS_BUS_DEVICE(dev);
char path[40];
int off;
off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
if (s->num_mmio) {
snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
s->mmio[0].addr);
} else if (s->num_pio) {
snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
s->mmio[0].addr);
}
return g_strdup(path);
if (s->num_pio) {
return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
}
return g_strdup(qdev_fw_name(dev));
}
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,

View File

@ -983,6 +983,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
if (pwrcnd) {
/* eject/load only happens for power condition == 0 */
ide_atapi_cmd_ok(s);
return;
}

View File

@ -2021,11 +2021,17 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
}
p = s->data_ptr;
if (p + 2 > s->data_end) {
return;
}
*(uint16_t *)p = le16_to_cpu(val);
p += 2;
s->data_ptr = p;
if (p >= s->data_end)
if (p >= s->data_end) {
s->status &= ~DRQ_STAT;
s->end_transfer_func(s);
}
}
uint32_t ide_data_readw(void *opaque, uint32_t addr)
@ -2042,11 +2048,17 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
}
p = s->data_ptr;
if (p + 2 > s->data_end) {
return 0;
}
ret = cpu_to_le16(*(uint16_t *)p);
p += 2;
s->data_ptr = p;
if (p >= s->data_end)
if (p >= s->data_end) {
s->status &= ~DRQ_STAT;
s->end_transfer_func(s);
}
return ret;
}
@ -2063,11 +2075,17 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
}
p = s->data_ptr;
if (p + 4 > s->data_end) {
return;
}
*(uint32_t *)p = le32_to_cpu(val);
p += 4;
s->data_ptr = p;
if (p >= s->data_end)
if (p >= s->data_end) {
s->status &= ~DRQ_STAT;
s->end_transfer_func(s);
}
}
uint32_t ide_data_readl(void *opaque, uint32_t addr)
@ -2084,11 +2102,17 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
}
p = s->data_ptr;
if (p + 4 > s->data_end) {
return 0;
}
ret = cpu_to_le32(*(uint32_t *)p);
p += 4;
s->data_ptr = p;
if (p >= s->data_end)
if (p >= s->data_end) {
s->status &= ~DRQ_STAT;
s->end_transfer_func(s);
}
return ret;
}

View File

@ -169,6 +169,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
PCIIDEState *pci_ide;
DriveInfo *di;
int i;
IDEDevice *idedev;
pci_ide = PCI_IDE(dev);
@ -181,6 +182,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
blk_detach_dev(blk, ds);
}
pci_ide->bus[di->bus].ifs[di->unit].blk = NULL;
if (!(i % 2)) {
idedev = pci_ide->bus[di->bus].master;
} else {
idedev = pci_ide->bus[di->bus].slave;
}
idedev->conf.blk = NULL;
blk_unref(blk);
}
}

View File

@ -2150,6 +2150,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
{
DPRINTF("+++ C+ mode offloaded task checksum\n");
/* Large enough for Ethernet and IP headers? */
if (saved_size < ETH_HLEN + sizeof(ip_header)) {
goto skip_offload;
}
/* ip packet header */
ip_header *ip = NULL;
int hlen = 0;
@ -2160,223 +2165,235 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
size_t eth_payload_len = 0;
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
if (proto == ETH_P_IP)
if (proto != ETH_P_IP)
{
DPRINTF("+++ C+ mode has IP packet\n");
/* not aligned */
eth_payload_data = saved_buffer + ETH_HLEN;
eth_payload_len = saved_size - ETH_HLEN;
ip = (ip_header*)eth_payload_data;
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
DPRINTF("+++ C+ mode packet has bad IP version %d "
"expected %d\n", IP_HEADER_VERSION(ip),
IP_HEADER_VERSION_4);
ip = NULL;
} else {
hlen = IP_HEADER_LENGTH(ip);
ip_protocol = ip->ip_p;
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
}
goto skip_offload;
}
if (ip)
DPRINTF("+++ C+ mode has IP packet\n");
/* not aligned */
eth_payload_data = saved_buffer + ETH_HLEN;
eth_payload_len = saved_size - ETH_HLEN;
ip = (ip_header*)eth_payload_data;
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
DPRINTF("+++ C+ mode packet has bad IP version %d "
"expected %d\n", IP_HEADER_VERSION(ip),
IP_HEADER_VERSION_4);
goto skip_offload;
}
hlen = IP_HEADER_LENGTH(ip);
if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
goto skip_offload;
}
ip_protocol = ip->ip_p;
ip_data_len = be16_to_cpu(ip->ip_len);
if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
goto skip_offload;
}
ip_data_len -= hlen;
if (txdw0 & CP_TX_IPCS)
{
if (txdw0 & CP_TX_IPCS)
{
DPRINTF("+++ C+ mode need IP checksum\n");
DPRINTF("+++ C+ mode need IP checksum\n");
if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
/* bad packet header len */
/* or packet too short */
}
else
{
ip->ip_sum = 0;
ip->ip_sum = ip_checksum(ip, hlen);
DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
hlen, ip->ip_sum);
}
ip->ip_sum = 0;
ip->ip_sum = ip_checksum(ip, hlen);
DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
hlen, ip->ip_sum);
}
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
{
/* Large enough for the TCP header? */
if (ip_data_len < sizeof(tcp_header)) {
goto skip_offload;
}
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
"frame data %d specified MSS=%d\n", ETH_MTU,
ip_data_len, saved_size - ETH_HLEN, large_send_mss);
int tcp_send_offset = 0;
int send_count = 0;
/* maximum IP header length is 60 bytes */
uint8_t saved_ip_header[60];
/* save IP header template; data area is used in tcp checksum calculation */
memcpy(saved_ip_header, eth_payload_data, hlen);
/* a placeholder for checksum calculation routine in tcp case */
uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
// size_t data_to_checksum_len = eth_payload_len - hlen + 12;
/* pointer to TCP header */
tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
/* Invalid TCP data offset? */
if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
goto skip_offload;
}
/* ETH_MTU = ip header len + tcp header len + payload */
int tcp_data_len = ip_data_len - tcp_hlen;
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
"data len %d TCP chunk size %d\n", ip_data_len,
tcp_hlen, tcp_data_len, tcp_chunk_size);
/* note the cycle below overwrites IP header data,
but restores it from saved_ip_header before sending packet */
int is_last_frame = 0;
for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
{
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
uint16_t chunk_size = tcp_chunk_size;
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
"frame data %d specified MSS=%d\n", ETH_MTU,
ip_data_len, saved_size - ETH_HLEN, large_send_mss);
int tcp_send_offset = 0;
int send_count = 0;
/* maximum IP header length is 60 bytes */
uint8_t saved_ip_header[60];
/* save IP header template; data area is used in tcp checksum calculation */
memcpy(saved_ip_header, eth_payload_data, hlen);
/* a placeholder for checksum calculation routine in tcp case */
uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
// size_t data_to_checksum_len = eth_payload_len - hlen + 12;
/* pointer to TCP header */
tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
/* ETH_MTU = ip header len + tcp header len + payload */
int tcp_data_len = ip_data_len - tcp_hlen;
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
"data len %d TCP chunk size %d\n", ip_data_len,
tcp_hlen, tcp_data_len, tcp_chunk_size);
/* note the cycle below overwrites IP header data,
but restores it from saved_ip_header before sending packet */
int is_last_frame = 0;
for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
/* check if this is the last frame */
if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
{
uint16_t chunk_size = tcp_chunk_size;
/* check if this is the last frame */
if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
{
is_last_frame = 1;
chunk_size = tcp_data_len - tcp_send_offset;
}
DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
be32_to_cpu(p_tcp_hdr->th_seq));
/* add 4 TCP pseudoheader fields */
/* copy IP source and destination fields */
memcpy(data_to_checksum, saved_ip_header + 12, 8);
DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
"packet with %d bytes data\n", tcp_hlen +
chunk_size);
if (tcp_send_offset)
{
memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
}
/* keep PUSH and FIN flags only for the last frame */
if (!is_last_frame)
{
TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
}
/* recalculate TCP checksum */
ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_tcpip_hdr->zeros = 0;
p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
p_tcp_hdr->th_sum = 0;
int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
tcp_checksum);
p_tcp_hdr->th_sum = tcp_checksum;
/* restore IP header */
memcpy(eth_payload_data, saved_ip_header, hlen);
/* set IP data length and recalculate IP checksum */
ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
/* increment IP id for subsequent frames */
ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
ip->ip_sum = 0;
ip->ip_sum = ip_checksum(eth_payload_data, hlen);
DPRINTF("+++ C+ mode TSO IP header len=%d "
"checksum=%04x\n", hlen, ip->ip_sum);
int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
DPRINTF("+++ C+ mode TSO transferring packet size "
"%d\n", tso_send_size);
rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
0, (uint8_t *) dot1q_buffer);
/* add transferred count to TCP sequence number */
p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
++send_count;
is_last_frame = 1;
chunk_size = tcp_data_len - tcp_send_offset;
}
/* Stop sending this frame */
saved_size = 0;
}
else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
{
DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
/* maximum IP header length is 60 bytes */
uint8_t saved_ip_header[60];
memcpy(saved_ip_header, eth_payload_data, hlen);
uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
// size_t data_to_checksum_len = eth_payload_len - hlen + 12;
DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
be32_to_cpu(p_tcp_hdr->th_seq));
/* add 4 TCP pseudoheader fields */
/* copy IP source and destination fields */
memcpy(data_to_checksum, saved_ip_header + 12, 8);
if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
"packet with %d bytes data\n", tcp_hlen +
chunk_size);
if (tcp_send_offset)
{
DPRINTF("+++ C+ mode calculating TCP checksum for "
"packet with %d bytes data\n", ip_data_len);
ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_tcpip_hdr->zeros = 0;
p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
p_tcp_hdr->th_sum = 0;
int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
DPRINTF("+++ C+ mode TCP checksum %04x\n",
tcp_checksum);
p_tcp_hdr->th_sum = tcp_checksum;
memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
}
else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
/* keep PUSH and FIN flags only for the last frame */
if (!is_last_frame)
{
DPRINTF("+++ C+ mode calculating UDP checksum for "
"packet with %d bytes data\n", ip_data_len);
ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_udpip_hdr->zeros = 0;
p_udpip_hdr->ip_proto = IP_PROTO_UDP;
p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
p_udp_hdr->uh_sum = 0;
int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
DPRINTF("+++ C+ mode UDP checksum %04x\n",
udp_checksum);
p_udp_hdr->uh_sum = udp_checksum;
TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
}
/* recalculate TCP checksum */
ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_tcpip_hdr->zeros = 0;
p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
p_tcp_hdr->th_sum = 0;
int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
tcp_checksum);
p_tcp_hdr->th_sum = tcp_checksum;
/* restore IP header */
memcpy(eth_payload_data, saved_ip_header, hlen);
/* set IP data length and recalculate IP checksum */
ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
/* increment IP id for subsequent frames */
ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
ip->ip_sum = 0;
ip->ip_sum = ip_checksum(eth_payload_data, hlen);
DPRINTF("+++ C+ mode TSO IP header len=%d "
"checksum=%04x\n", hlen, ip->ip_sum);
int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
DPRINTF("+++ C+ mode TSO transferring packet size "
"%d\n", tso_send_size);
rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
0, (uint8_t *) dot1q_buffer);
/* add transferred count to TCP sequence number */
p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
++send_count;
}
/* Stop sending this frame */
saved_size = 0;
}
else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
{
DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
/* maximum IP header length is 60 bytes */
uint8_t saved_ip_header[60];
memcpy(saved_ip_header, eth_payload_data, hlen);
uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
// size_t data_to_checksum_len = eth_payload_len - hlen + 12;
/* add 4 TCP pseudoheader fields */
/* copy IP source and destination fields */
memcpy(data_to_checksum, saved_ip_header + 12, 8);
if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
{
DPRINTF("+++ C+ mode calculating TCP checksum for "
"packet with %d bytes data\n", ip_data_len);
ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_tcpip_hdr->zeros = 0;
p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
p_tcp_hdr->th_sum = 0;
int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
DPRINTF("+++ C+ mode TCP checksum %04x\n",
tcp_checksum);
p_tcp_hdr->th_sum = tcp_checksum;
}
else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
{
DPRINTF("+++ C+ mode calculating UDP checksum for "
"packet with %d bytes data\n", ip_data_len);
ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
p_udpip_hdr->zeros = 0;
p_udpip_hdr->ip_proto = IP_PROTO_UDP;
p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
p_udp_hdr->uh_sum = 0;
int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
DPRINTF("+++ C+ mode UDP checksum %04x\n",
udp_checksum);
p_udp_hdr->uh_sum = udp_checksum;
}
/* restore IP header */
memcpy(eth_payload_data, saved_ip_header, hlen);
}
}
skip_offload:
/* update tally counter */
++s->tally_counters.TxOk;

View File

@ -1138,7 +1138,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
ssize_t ret, len;
unsigned int out_num = elem.out_num;
struct iovec *out_sg = &elem.out_sg[0];
struct iovec sg[VIRTQUEUE_MAX_SIZE];
struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1];
struct virtio_net_hdr_mrg_rxbuf mhdr;
if (out_num < 1) {
error_report("virtio-net header not in first element");
@ -1146,13 +1147,25 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
}
if (n->has_vnet_hdr) {
if (out_sg[0].iov_len < n->guest_hdr_len) {
if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
n->guest_hdr_len) {
error_report("virtio-net header incorrect");
exit(1);
}
virtio_net_hdr_swap(vdev, (void *) out_sg[0].iov_base);
if (virtio_needs_swap(vdev)) {
virtio_net_hdr_swap(vdev, (void *) &mhdr);
sg2[0].iov_base = &mhdr;
sg2[0].iov_len = n->guest_hdr_len;
out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
out_sg, out_num,
n->guest_hdr_len, -1);
if (out_num == VIRTQUEUE_MAX_SIZE) {
goto drop;
}
out_num += 1;
out_sg = sg2;
}
}
/*
* If host wants to see the guest header as is, we can
* pass it on unchanged. Otherwise, copy just the parts
@ -1182,7 +1195,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
}
len += ret;
drop:
virtqueue_push(q->tx_vq, &elem, 0);
virtio_notify(vdev, q->tx_vq);
@ -1309,7 +1322,7 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
n->multiqueue = multiqueue;
for (i = 2; i <= n->max_queues * 2 + 1; i++) {
for (i = 2; i < n->max_queues * 2 + 1; i++) {
virtio_del_queue(vdev, i);
}

View File

@ -218,7 +218,7 @@ static Property s390_ipl_properties[] = {
* - -1 if no valid boot device was found
* - ccw id of the boot device otherwise
*/
static uint32_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
static uint64_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
{
DeviceState *dev_st;
@ -248,7 +248,7 @@ static uint32_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
return -1;
out:
return ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno;
return (uint32_t) (ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno);
}
int s390_ipl_update_diag308(IplParameterBlock *iplb)

View File

@ -295,6 +295,25 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
return 0;
}
static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
{
virtio_ccw_stop_ioeventfd(dev);
virtio_reset(vdev);
if (dev->indicators) {
release_indicator(&dev->routes.adapter, dev->indicators);
dev->indicators = NULL;
}
if (dev->indicators2) {
release_indicator(&dev->routes.adapter, dev->indicators2);
dev->indicators2 = NULL;
}
if (dev->summary_indicator) {
release_indicator(&dev->routes.adapter, dev->summary_indicator);
dev->summary_indicator = NULL;
}
dev->sch->thinint_active = false;
}
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
{
int ret;
@ -351,8 +370,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
}
break;
case CCW_CMD_VDEV_RESET:
virtio_ccw_stop_ioeventfd(dev);
virtio_reset(vdev);
virtio_ccw_reset_virtio(dev, vdev);
ret = 0;
break;
case CCW_CMD_READ_FEAT:
@ -480,7 +498,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
}
virtio_set_status(vdev, status);
if (vdev->status == 0) {
virtio_reset(vdev);
virtio_ccw_reset_virtio(dev, vdev);
}
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
virtio_ccw_start_ioeventfd(dev);
@ -1098,21 +1116,8 @@ static void virtio_ccw_reset(DeviceState *d)
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
virtio_ccw_stop_ioeventfd(dev);
virtio_reset(vdev);
virtio_ccw_reset_virtio(dev, vdev);
css_reset_sch(dev->sch);
if (dev->indicators) {
release_indicator(&dev->routes.adapter, dev->indicators);
dev->indicators = NULL;
}
if (dev->indicators2) {
release_indicator(&dev->routes.adapter, dev->indicators2);
dev->indicators2 = NULL;
}
if (dev->summary_indicator) {
release_indicator(&dev->routes.adapter, dev->summary_indicator);
dev->summary_indicator = NULL;
}
}
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)

View File

@ -1239,10 +1239,15 @@ int scsi_cdb_length(uint8_t *buf) {
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
{
int rc;
int len;
cmd->lba = -1;
cmd->len = scsi_cdb_length(buf);
len = scsi_cdb_length(buf);
if (len < 0) {
return -1;
}
cmd->len = len;
switch (dev->type) {
case TYPE_TAPE:
rc = scsi_req_stream_xfer(cmd, dev, buf);

View File

@ -196,6 +196,12 @@ static uint64_t pit_ioport_read(void *opaque, hwaddr addr,
PITChannelState *s;
addr &= 3;
if (addr == 3) {
/* Mode/Command register is write only, read is ignored */
return 0;
}
s = &pit->channels[addr];
if (s->status_latched) {
s->status_latched = 0;

View File

@ -1310,6 +1310,10 @@ static int usbnet_can_receive(NetClientState *nc)
{
USBNetState *s = qemu_get_nic_opaque(nc);
if (!s->dev.config) {
return 0;
}
if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
return 1;
}

View File

@ -1516,7 +1516,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
memory_region_name(&quirk->mem),
vdev->vbasedev.name);
return quirk->data.address_match ^ 0x10000000U;
return quirk->data.address_match ^ 0x80000000U;
}
break;
case 0: /* data */
@ -1554,7 +1554,7 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
switch (addr) {
case 4: /* address */
if ((data & 0x7fff0000) == 0x10000) {
if (data & 0x10000000U &&
if (data & 0x80000000U &&
vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) {
trace_vfio_rtl8168_window_quirk_write_table(
@ -1562,8 +1562,9 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
vdev->vbasedev.name);
io_mem_write(&vdev->pdev.msix_table_mmio,
(hwaddr)(quirk->data.address_match & 0xfff),
data, size);
(hwaddr)(data & 0xfff),
(uint64_t)quirk->data.address_mask,
size);
}
quirk->data.flags = 1;
@ -3555,7 +3556,6 @@ static Property vfio_pci_dev_properties[] = {
VFIO_FEATURE_ENABLE_VGA_BIT, false),
DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features,
VFIO_FEATURE_ENABLE_REQ_BIT, true),
DEFINE_PROP_INT32("bootindex", VFIOPCIDevice, bootindex, -1),
DEFINE_PROP_BOOL("x-mmap", VFIOPCIDevice, vbasedev.allow_mmap, true),
/*
* TODO - support passed fds... is this necessary?

View File

@ -921,7 +921,7 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
VirtioBusState *vbus = VIRTIO_BUS(qbus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int i, r;
int i, r, e;
if (!k->set_host_notifier) {
fprintf(stderr, "binding does not support host notifiers\n");
r = -ENOSYS;
@ -939,12 +939,12 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
return 0;
fail_vq:
while (--i >= 0) {
r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
if (r < 0) {
e = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
if (e < 0) {
fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
fflush(stderr);
}
assert (r >= 0);
assert (e >= 0);
}
fail:
return r;

View File

@ -361,6 +361,10 @@ bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
BlockDriverState *base,
int64_t sector_num,
int nb_sectors, int *pnum);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
int *pnum);
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,

View File

@ -579,6 +579,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
* @mode: Whether to collapse all images in the chain to the target.
* @on_source_error: The action to take upon error reading from the source.
* @on_target_error: The action to take upon error writing to the target.
* @unmap: Whether to unmap target where source sectors only contain zeroes.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
* @errp: Error object.
@ -593,6 +594,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, int64_t granularity, int64_t buf_size,
MirrorSyncMode mode, BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb,
void *opaque, Error **errp);

View File

@ -126,6 +126,15 @@ static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
}
}
static inline bool virtio_needs_swap(VirtIODevice *vdev)
{
#ifdef HOST_WORDS_BIGENDIAN
return virtio_access_is_big_endian(vdev) ? false : true;
#else
return virtio_access_is_big_endian(vdev) ? true : false;
#endif
}
static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
{
#ifdef HOST_WORDS_BIGENDIAN

View File

@ -1142,9 +1142,17 @@ static int kvm_irqchip_get_virq(KVMState *s)
uint32_t *word = s->used_gsi_bitmap;
int max_words = ALIGN(s->gsi_count, 32) / 32;
int i, bit;
bool retry = true;
again:
/*
* PIC and IOAPIC share the first 16 GSI numbers, thus the available
* GSI numbers are more than the number of IRQ route. Allocating a GSI
* number can succeed even though a new route entry cannot be added.
* When this happens, flush dynamic MSI entries to free IRQ route entries.
*/
if (!s->direct_msi && s->irq_routes->nr == s->gsi_count) {
kvm_flush_dynamic_msi_routes(s);
}
/* Return the lowest unused GSI in the bitmap */
for (i = 0; i < max_words; i++) {
bit = ffs(~word[i]);
@ -1154,11 +1162,6 @@ again:
return bit - 1 + i * 32;
}
if (!s->direct_msi && retry) {
retry = false;
kvm_flush_dynamic_msi_routes(s);
goto again;
}
return -ENOSPC;
}

2
nbd.c
View File

@ -681,7 +681,7 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size)
TRACE("Setting size to %zd block(s)", (size_t)(size / BDRV_SECTOR_SIZE));
if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / (size_t)BDRV_SECTOR_SIZE) < 0) {
if (ioctl(fd, NBD_SET_SIZE_BLOCKS, (size_t)(size / BDRV_SECTOR_SIZE)) < 0) {
int serrno = errno;
LOG("Failed setting size (in blocks)");
return -serrno;

View File

@ -2669,6 +2669,7 @@
# Since: 1.3.0
#
# 'unmapped' and 'pause' since 2.0
# 'ro' and 'kp_comma' since 2.4
##
{ 'enum': 'QKeyCode',
'data': [ 'unmapped',
@ -2686,7 +2687,8 @@
'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end',
'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause' ] }
'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro',
'kp_comma' ] }
##
# @KeyValue

View File

@ -943,6 +943,11 @@
# @on-target-error: #optional the action to take on an error on the target,
# default 'report' (no limitations, since this applies to
# a different block device than @device).
# @unmap: #optional Whether to try to unmap target sectors where source has
# only zero. If true, and target unallocated sectors will read as zero,
# target image sectors will be unmapped; otherwise, zeroes will be
# written. Both will result in identical contents.
# Default is true. (Since 2.4)
#
# Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound
@ -955,7 +960,8 @@
'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
'*speed': 'int', '*granularity': 'uint32',
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } }
'*on-target-error': 'BlockdevOnError',
'*unmap': 'bool' } }
##
# @block_set_io_throttle:

View File

@ -2797,7 +2797,10 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
#ifdef MSG_CMSG_CLOEXEC
flags |= MSG_CMSG_CLOEXEC;
#endif
ret = recvmsg(s->fd, &msg, flags);
do {
ret = recvmsg(s->fd, &msg, flags);
} while (ret == -1 && errno == EINTR);
if (ret > 0 && s->is_unix) {
unix_process_msgfd(chr, &msg);
}
@ -2808,7 +2811,13 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
{
TCPCharDriver *s = chr->opaque;
return qemu_recv(s->fd, buf, len, 0);
ssize_t ret;
do {
ret = qemu_recv(s->fd, buf, len, 0);
} while (ret == -1 && socket_error() == EINTR);
return ret;
}
#endif

View File

@ -1332,11 +1332,7 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
struct FsMount *mount;
int fd;
Error *local_err = NULL;
struct fstrim_range r = {
.start = 0,
.len = -1,
.minlen = has_minimum ? minimum : 0,
};
struct fstrim_range r;
slog("guest-fstrim called");
@ -1360,6 +1356,9 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
* error means an unexpected error, so return it in those cases. In
* some other cases ENOTTY will be reported (e.g. CD-ROMs).
*/
r.start = 0;
r.len = -1;
r.minlen = has_minimum ? minimum : 0;
ret = ioctl(fd, FITRIM, &r);
if (ret == -1) {
if (errno != ENOTTY && errno != EOPNOTSUPP) {

View File

@ -1380,6 +1380,7 @@ EQMP
.args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?,"
"node-name:s?,replaces:s?,"
"on-source-error:s?,on-target-error:s?,"
"unmap:b?,"
"granularity:i?,buf-size:i?",
.mhandler.cmd_new = qmp_marshal_input_drive_mirror,
},
@ -1419,6 +1420,8 @@ Arguments:
(BlockdevOnError, default 'report')
- "on-target-error": the action to take on an error on the target
(BlockdevOnError, default 'report')
- "unmap": whether the target sectors should be discarded where source has only
zeroes. (json-bool, optional, default true)
The default value of the granularity is the image cluster size clamped
between 4096 and 65536, if the image format defines one. If the format

View File

@ -21,6 +21,9 @@ class QMPConnectError(QMPError):
class QMPCapabilitiesError(QMPError):
pass
class QMPTimeoutError(QMPError):
pass
class QEMUMonitorProtocol:
def __init__(self, address, server=False):
"""
@ -72,6 +75,44 @@ class QEMUMonitorProtocol:
error = socket.error
def __get_events(self, wait=False):
"""
Check for new events in the stream and cache them in __events.
@param wait (bool): block until an event is available.
@param wait (float): If wait is a float, treat it as a timeout value.
@raise QMPTimeoutError: If a timeout float is provided and the timeout
period elapses.
@raise QMPConnectError: If wait is True but no events could be retrieved
or if some other error occurred.
"""
# Check for new events regardless and pull them into the cache:
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
# Wait for new events, if needed.
# if wait is 0.0, this means "no wait" and is also implicitly false.
if not self.__events and wait:
if isinstance(wait, float):
self.__sock.settimeout(wait)
try:
ret = self.__json_read(only_event=True)
except socket.timeout:
raise QMPTimeoutError("Timeout waiting for event")
except:
raise QMPConnectError("Error while reading from socket")
if ret is None:
raise QMPConnectError("Error while reading from socket")
self.__sock.settimeout(None)
def connect(self, negotiate=True):
"""
Connect to the QMP Monitor and perform capabilities negotiation.
@ -140,43 +181,37 @@ class QEMUMonitorProtocol:
"""
Get and delete the first available QMP event.
@param wait: block until an event is available (bool)
@param wait (bool): block until an event is available.
@param wait (float): If wait is a float, treat it as a timeout value.
@raise QMPTimeoutError: If a timeout float is provided and the timeout
period elapses.
@raise QMPConnectError: If wait is True but no events could be retrieved
or if some other error occurred.
@return The first available QMP event, or None.
"""
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
if not self.__events and wait:
self.__json_read(only_event=True)
event = self.__events[0]
del self.__events[0]
return event
self.__get_events(wait)
if self.__events:
return self.__events.pop(0)
return None
def get_events(self, wait=False):
"""
Get a list of available QMP events.
@param wait: block until an event is available (bool)
"""
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
if not self.__events and wait:
ret = self.__json_read(only_event=True)
if ret == None:
# We are in blocking mode, if don't get anything, something
# went wrong
raise QMPConnectError("Error while reading from socket")
@param wait (bool): block until an event is available.
@param wait (float): If wait is a float, treat it as a timeout value.
@raise QMPTimeoutError: If a timeout float is provided and the timeout
period elapses.
@raise QMPConnectError: If wait is True but no events could be retrieved
or if some other error occurred.
@return The list of available QMP events.
"""
self.__get_events(wait)
return self.__events
def clear_events(self):

View File

@ -8423,18 +8423,53 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
}
} else {
int address_offset;
int load;
bool load = insn & (1 << 20);
bool doubleword = false;
/* Misc load/store */
rn = (insn >> 16) & 0xf;
rd = (insn >> 12) & 0xf;
if (!load && (sh & 2)) {
/* doubleword */
ARCH(5TE);
if (rd & 1) {
/* UNPREDICTABLE; we choose to UNDEF */
goto illegal_op;
}
load = (sh & 1) == 0;
doubleword = true;
}
addr = load_reg(s, rn);
if (insn & (1 << 24))
gen_add_datah_offset(s, insn, 0, addr);
address_offset = 0;
if (insn & (1 << 20)) {
if (doubleword) {
if (!load) {
/* store */
tmp = load_reg(s, rd);
gen_aa32_st32(tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = load_reg(s, rd + 1);
gen_aa32_st32(tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
} else {
/* load */
tmp = tcg_temp_new_i32();
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = tcg_temp_new_i32();
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
rd++;
}
address_offset = -4;
} else if (load) {
/* load */
tmp = tcg_temp_new_i32();
switch(sh) {
switch (sh) {
case 1:
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
break;
@ -8446,38 +8481,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
gen_aa32_ld16s(tmp, addr, get_mem_index(s));
break;
}
load = 1;
} else if (sh & 2) {
ARCH(5TE);
/* doubleword */
if (sh & 1) {
/* store */
tmp = load_reg(s, rd);
gen_aa32_st32(tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = load_reg(s, rd + 1);
gen_aa32_st32(tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
load = 0;
} else {
/* load */
tmp = tcg_temp_new_i32();
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = tcg_temp_new_i32();
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
rd++;
load = 1;
}
address_offset = -4;
} else {
/* store */
tmp = load_reg(s, rd);
gen_aa32_st16(tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
load = 0;
}
/* Perform base writeback before the loaded value to
ensure correct behavior with overlapping index registers.

View File

@ -240,10 +240,9 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
int32_t *addr)
{
uint64_t val64 = *addr;
struct kvm_one_reg cp0reg = {
.id = reg_id,
.addr = (uintptr_t)&val64
.addr = (uintptr_t)addr
};
return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
@ -275,18 +274,12 @@ static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id,
static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id,
int32_t *addr)
{
int ret;
uint64_t val64 = 0;
struct kvm_one_reg cp0reg = {
.id = reg_id,
.addr = (uintptr_t)&val64
.addr = (uintptr_t)addr
};
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
if (ret >= 0) {
*addr = val64;
}
return ret;
return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
}
static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64 reg_id,
@ -640,12 +633,12 @@ int kvm_arch_put_registers(CPUState *cs, int level)
/* Set the registers based on QEMU's view of things */
for (i = 0; i < 32; i++) {
regs.gpr[i] = env->active_tc.gpr[i];
regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i];
}
regs.hi = env->active_tc.HI[0];
regs.lo = env->active_tc.LO[0];
regs.pc = env->active_tc.PC;
regs.hi = (int64_t)(target_long)env->active_tc.HI[0];
regs.lo = (int64_t)(target_long)env->active_tc.LO[0];
regs.pc = (int64_t)(target_long)env->active_tc.PC;
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);

View File

@ -39,6 +39,7 @@
#include "sysemu/watchdog.h"
#include "trace.h"
#include "exec/gdbstub.h"
#include "sysemu/hostmem.h"
//#define DEBUG_KVM
@ -302,16 +303,11 @@ static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info)
kvm_get_fallback_smmu_info(cpu, info);
}
static long getrampagesize(void)
static long gethugepagesize(const char *mem_path)
{
struct statfs fs;
int ret;
if (!mem_path) {
/* guest RAM is backed by normal anonymous pages */
return getpagesize();
}
do {
ret = statfs(mem_path, &fs);
} while (ret != 0 && errno == EINTR);
@ -333,6 +329,55 @@ static long getrampagesize(void)
return fs.f_bsize;
}
static int find_max_supported_pagesize(Object *obj, void *opaque)
{
char *mem_path;
long *hpsize_min = opaque;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
mem_path = object_property_get_str(obj, "mem-path", NULL);
if (mem_path) {
long hpsize = gethugepagesize(mem_path);
if (hpsize < *hpsize_min) {
*hpsize_min = hpsize;
}
} else {
*hpsize_min = getpagesize();
}
}
return 0;
}
static long getrampagesize(void)
{
long hpsize = LONG_MAX;
Object *memdev_root;
if (mem_path) {
return gethugepagesize(mem_path);
}
/* it's possible we have memory-backend objects with
* hugepage-backed RAM. these may get mapped into system
* address space via -numa parameters or memory hotplug
* hooks. we want to take these into account, but we
* also want to make sure these supported hugepage
* sizes are applicable across the entire range of memory
* we may boot from, so we take the min across all
* backends, and assume normal pages in cases where a
* backend isn't backed by hugepages.
*/
memdev_root = object_resolve_path("/objects", NULL);
if (!memdev_root) {
return getpagesize();
}
object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
return (hpsize == LONG_MAX) ? getpagesize() : hpsize;
}
static bool kvm_valid_page_size(uint32_t flags, long rampgsize, uint32_t shift)
{
if (!(flags & KVM_PPC_PAGE_SIZES_REAL)) {

View File

@ -963,9 +963,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
}
/* Load the tlb comparator. */
tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
if (TARGET_LONG_BITS == 64) {
tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
tcg_out_opc_imm(s, OPC_LW, base, TCG_REG_A0, cmp_off + HI_OFF);
} else {
tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off);
}
/* Mask the page bits, keeping the alignment bits to compare against.
@ -1267,6 +1269,9 @@ static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
if (cbl) {
tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
} else if (rl == al && rl == bl) {
tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, 31);
tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
} else {
tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));

View File

@ -78,6 +78,19 @@ for align in 512 4k; do
echo
echo "== verifying patterns (2) =="
do_test $align "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io
echo
echo "== rewriting unaligned zeroes =="
do_test $align "write -P 0xb 0x0 0x1000" "$TEST_IMG" | _filter_qemu_io
do_test $align "write -z 0x200 0x200" "$TEST_IMG" | _filter_qemu_io
echo
echo "== verifying patterns (3) =="
do_test $align "read -P 0xb 0x0 0x200" "$TEST_IMG" | _filter_qemu_io
do_test $align "read -P 0x0 0x200 0x200" "$TEST_IMG" | _filter_qemu_io
do_test $align "read -P 0xb 0x400 0xc00" "$TEST_IMG" | _filter_qemu_io
echo
done
# success, all done

View File

@ -27,6 +27,21 @@ wrote 65536/65536 bytes at offset 65536
read 131072/131072 bytes at offset 1024
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== rewriting unaligned zeroes ==
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== verifying patterns (3) ==
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 3072/3072 bytes at offset 1024
3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== preparing image ==
wrote 1024/1024 bytes at offset 512
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@ -52,4 +67,19 @@ wrote 65536/65536 bytes at offset 65536
== verifying patterns (2) ==
read 131072/131072 bytes at offset 1024
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== rewriting unaligned zeroes ==
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== verifying patterns (3) ==
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 3072/3072 bytes at offset 1024
3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done

View File

@ -34,38 +34,8 @@ quorum_img3 = os.path.join(iotests.test_dir, 'quorum3.img')
quorum_repair_img = os.path.join(iotests.test_dir, 'quorum_repair.img')
quorum_snapshot_file = os.path.join(iotests.test_dir, 'quorum_snapshot.img')
class ImageMirroringTestCase(iotests.QMPTestCase):
'''Abstract base class for image mirroring test cases'''
def wait_ready(self, drive='drive0'):
'''Wait until a block job BLOCK_JOB_READY event'''
ready = False
while not ready:
for event in self.vm.get_qmp_events(wait=True):
if event['event'] == 'BLOCK_JOB_READY':
self.assert_qmp(event, 'data/type', 'mirror')
self.assert_qmp(event, 'data/device', drive)
ready = True
def wait_ready_and_cancel(self, drive='drive0'):
self.wait_ready(drive=drive)
event = self.cancel_and_wait(drive=drive)
self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
self.assert_qmp(event, 'data/type', 'mirror')
self.assert_qmp(event, 'data/offset', event['data']['len'])
def complete_and_wait(self, drive='drive0', wait_ready=True):
'''Complete a block job and wait for it to finish'''
if wait_ready:
self.wait_ready(drive=drive)
result = self.vm.qmp('block-job-complete', device=drive)
self.assert_qmp(result, 'return', {})
event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror')
class TestSingleDrive(ImageMirroringTestCase):
class TestSingleDrive(iotests.QMPTestCase):
image_len = 1 * 1024 * 1024 # MB
def setUp(self):
@ -221,17 +191,9 @@ class TestSingleDriveUnalignedLength(TestSingleDrive):
test_small_buffer2 = None
test_large_cluster = None
class TestMirrorNoBacking(ImageMirroringTestCase):
class TestMirrorNoBacking(iotests.QMPTestCase):
image_len = 2 * 1024 * 1024 # MB
def complete_and_wait(self, drive='drive0', wait_ready=True):
iotests.create_image(target_backing_img, TestMirrorNoBacking.image_len)
return ImageMirroringTestCase.complete_and_wait(self, drive, wait_ready)
def compare_images(self, img1, img2):
iotests.create_image(target_backing_img, TestMirrorNoBacking.image_len)
return iotests.compare_images(img1, img2)
def setUp(self):
iotests.create_image(backing_img, TestMirrorNoBacking.image_len)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
@ -242,7 +204,10 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
self.vm.shutdown()
os.remove(test_img)
os.remove(backing_img)
os.remove(target_backing_img)
try:
os.remove(target_backing_img)
except:
pass
os.remove(target_img)
def test_complete(self):
@ -257,7 +222,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
result = self.vm.qmp('query-block')
self.assert_qmp(result, 'return[0]/inserted/file', target_img)
self.vm.shutdown()
self.assertTrue(self.compare_images(test_img, target_img),
self.assertTrue(iotests.compare_images(test_img, target_img),
'target image does not match source after mirroring')
def test_cancel(self):
@ -272,7 +237,7 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
result = self.vm.qmp('query-block')
self.assert_qmp(result, 'return[0]/inserted/file', test_img)
self.vm.shutdown()
self.assertTrue(self.compare_images(test_img, target_img),
self.assertTrue(iotests.compare_images(test_img, target_img),
'target image does not match source after mirroring')
def test_large_cluster(self):
@ -283,7 +248,6 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
%(TestMirrorNoBacking.image_len), target_backing_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s'
% (TestMirrorNoBacking.image_len, target_backing_img), target_img)
os.remove(target_backing_img)
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
mode='existing', target=target_img)
@ -293,10 +257,10 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
result = self.vm.qmp('query-block')
self.assert_qmp(result, 'return[0]/inserted/file', target_img)
self.vm.shutdown()
self.assertTrue(self.compare_images(test_img, target_img),
self.assertTrue(iotests.compare_images(test_img, target_img),
'target image does not match source after mirroring')
class TestMirrorResized(ImageMirroringTestCase):
class TestMirrorResized(iotests.QMPTestCase):
backing_len = 1 * 1024 * 1024 # MB
image_len = 2 * 1024 * 1024 # MB
@ -344,7 +308,7 @@ class TestMirrorResized(ImageMirroringTestCase):
self.assertTrue(iotests.compare_images(test_img, target_img),
'target image does not match source after mirroring')
class TestReadErrors(ImageMirroringTestCase):
class TestReadErrors(iotests.QMPTestCase):
image_len = 2 * 1024 * 1024 # MB
# this should be a multiple of twice the default granularity
@ -498,7 +462,7 @@ new_state = "1"
self.assert_no_active_block_jobs()
self.vm.shutdown()
class TestWriteErrors(ImageMirroringTestCase):
class TestWriteErrors(iotests.QMPTestCase):
image_len = 2 * 1024 * 1024 # MB
# this should be a multiple of twice the default granularity
@ -624,7 +588,7 @@ new_state = "1"
self.assert_no_active_block_jobs()
self.vm.shutdown()
class TestSetSpeed(ImageMirroringTestCase):
class TestSetSpeed(iotests.QMPTestCase):
image_len = 80 * 1024 * 1024 # MB
def setUp(self):
@ -690,7 +654,7 @@ class TestSetSpeed(ImageMirroringTestCase):
self.wait_ready_and_cancel()
class TestUnbackedSource(ImageMirroringTestCase):
class TestUnbackedSource(iotests.QMPTestCase):
image_len = 2 * 1024 * 1024 # MB
def setUp(self):
@ -731,7 +695,7 @@ class TestUnbackedSource(ImageMirroringTestCase):
self.complete_and_wait()
self.assert_no_active_block_jobs()
class TestRepairQuorum(ImageMirroringTestCase):
class TestRepairQuorum(iotests.QMPTestCase):
""" This class test quorum file repair using drive-mirror.
It's mostly a fork of TestSingleDrive """
image_len = 1 * 1024 * 1024 # MB

View File

@ -93,6 +93,16 @@ $QEMU_IO -c "open -o l2-cache-size=1M,refcount-cache-size=0.25M $TEST_IMG" \
-c 'read -P 42 0 64k' \
| _filter_qemu_io
echo
echo '=== Testing minimal L2 cache and COW ==='
echo
$QEMU_IMG snapshot -c foo "$TEST_IMG"
# This requires a COW operation, which accesses two L2 tables simultaneously
# (COW source and destination), so there must be enough space in the cache to
# place both tables there (and qemu should not crash)
$QEMU_IO -c "open -o cache-size=0 $TEST_IMG" -c 'write 0 64k' | _filter_qemu_io
# success, all done
echo '*** done'
rm -f $seq.full

View File

@ -26,4 +26,9 @@ read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing minimal L2 cache and COW ===
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done

View File

@ -0,0 +1,59 @@
#!/usr/bin/env python
#
# Test mirror with unmap
#
# Copyright (C) 2015 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import time
import os
import iotests
from iotests import qemu_img, qemu_io
test_img = os.path.join(iotests.test_dir, 'test.img')
target_img = os.path.join(iotests.test_dir, 'target.img')
class TestSingleDrive(iotests.QMPTestCase):
image_len = 2 * 1024 * 1024 # MB
def setUp(self):
# Write data to the image so we can compare later
qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len))
qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 2M', test_img)
self.vm = iotests.VM().add_drive(test_img, 'discard=unmap')
self.vm.launch()
def tearDown(self):
self.vm.shutdown()
os.remove(test_img)
try:
os.remove(target_img)
except OSError:
pass
def test_mirror_discard(self):
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
target=target_img)
self.assert_qmp(result, 'return', {})
self.vm.hmp_qemu_io('drive0', 'discard 0 64k')
self.complete_and_wait('drive0')
self.vm.shutdown()
self.assertTrue(iotests.compare_images(test_img, target_img),
'target image does not match source after mirroring')
if __name__ == '__main__':
iotests.main(supported_fmts=['raw', 'qcow2'])

View File

@ -0,0 +1,5 @@
.
----------------------------------------------------------------------
Ran 1 tests
OK

View File

@ -0,0 +1,54 @@
#!/bin/bash
#
# Test VPC open of image with large Max Table Entries value.
#
# Copyright (C) 2015 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# creator
owner=jcody@redhat.com
seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
_supported_fmt vpc
_supported_proto generic
_supported_os Linux
_use_sample_img afl5.img.bz2
echo
echo "=== Verify image open and failure ===="
$QEMU_IMG info "$TEST_IMG" 2>&1| _filter_testdir
# success, all done
echo "*** done"
rm -f $seq.full
status=0

View File

@ -0,0 +1,5 @@
QA output created by 135
=== Verify image open and failure ====
qemu-img: Could not open 'TEST_DIR/afl5.img': Max Table Entries too large (1073741825)
*** done

View File

@ -125,3 +125,5 @@
123 rw auto quick
128 rw auto quick
130 rw auto quick
132 rw auto quick
135 rw auto

View File

@ -78,6 +78,23 @@ def create_image(name, size):
i = i + 512
file.close()
# Test if 'match' is a recursive subset of 'event'
def event_match(event, match=None):
if match is None:
return True
for key in match:
if key in event:
if isinstance(event[key], dict):
if not event_match(event[key], match[key]):
return False
elif event[key] != match[key]:
return False
else:
return False
return True
class VM(object):
'''A QEMU VM'''
@ -92,6 +109,7 @@ class VM(object):
'-machine', 'accel=qtest',
'-display', 'none', '-vga', 'none']
self._num_drives = 0
self._events = []
# This can be used to add an unused monitor instance.
def add_monitor_telnet(self, ip, port):
@ -202,14 +220,34 @@ class VM(object):
def get_qmp_event(self, wait=False):
'''Poll for one queued QMP events and return it'''
if len(self._events) > 0:
return self._events.pop(0)
return self._qmp.pull_event(wait=wait)
def get_qmp_events(self, wait=False):
'''Poll for queued QMP events and return a list of dicts'''
events = self._qmp.get_events(wait=wait)
events.extend(self._events)
del self._events[:]
self._qmp.clear_events()
return events
def event_wait(self, name='BLOCK_JOB_COMPLETED', timeout=60.0, match=None):
# Search cached events
for event in self._events:
if (event['event'] == name) and event_match(event, match):
self._events.remove(event)
return event
# Poll for new events
while True:
event = self._qmp.pull_event(wait=timeout)
if (event['event'] == name) and event_match(event, match):
return event
self._events.append(event)
return None
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
class QMPTestCase(unittest.TestCase):
@ -288,6 +326,29 @@ class QMPTestCase(unittest.TestCase):
self.assert_no_active_block_jobs()
return event
def wait_ready(self, drive='drive0'):
'''Wait until a block job BLOCK_JOB_READY event'''
f = {'data': {'type': 'mirror', 'device': drive } }
event = self.vm.event_wait(name='BLOCK_JOB_READY', match=f)
def wait_ready_and_cancel(self, drive='drive0'):
self.wait_ready(drive=drive)
event = self.cancel_and_wait(drive=drive)
self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
self.assert_qmp(event, 'data/type', 'mirror')
self.assert_qmp(event, 'data/offset', event['data']['len'])
def complete_and_wait(self, drive='drive0', wait_ready=True):
'''Complete a block job and wait for it to finish'''
if wait_ready:
self.wait_ready(drive=drive)
result = self.vm.qmp('block-job-complete', device=drive)
self.assert_qmp(result, 'return', {})
event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror')
def notrun(reason):
'''Skip this test suite'''
# Each test in qemu-iotests has a number ("seq")

Binary file not shown.

View File

@ -128,6 +128,10 @@ static const int qcode_to_number[] = {
[Q_KEY_CODE_INSERT] = 0xd2,
[Q_KEY_CODE_DELETE] = 0xd3,
[Q_KEY_CODE_RO] = 0x73,
[Q_KEY_CODE_KP_COMMA] = 0x7e,
[Q_KEY_CODE_MAX] = 0,
};

View File

@ -511,6 +511,10 @@ static void handle_windowevent(SDL_Event *ev)
{
struct sdl2_console *scon = get_scon_from_window(ev->window.windowID);
if (!scon) {
return;
}
switch (ev->window.event) {
case SDL_WINDOWEVENT_RESIZED:
{

View File

@ -199,7 +199,7 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
static const int blksize = 32;
int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize;
int dirty_top[blocks];
int y, yoff, x, xoff, blk, bw;
int y, yoff1, yoff2, x, xoff, blk, bw;
int bpp = surface_bytes_per_pixel(ssd->ds);
uint8_t *guest, *mirror;
@ -214,13 +214,14 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
guest = surface_data(ssd->ds);
mirror = (void *)pixman_image_get_data(ssd->mirror);
for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) {
yoff = y * surface_stride(ssd->ds);
yoff1 = y * surface_stride(ssd->ds);
yoff2 = y * pixman_image_get_stride(ssd->mirror);
for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) {
xoff = x * bpp;
blk = x / blksize;
bw = MIN(blksize, ssd->dirty.right - x);
if (memcmp(guest + yoff + xoff,
mirror + yoff + xoff,
if (memcmp(guest + yoff1 + xoff,
mirror + yoff2 + xoff,
bw * bpp) == 0) {
if (dirty_top[blk] != -1) {
QXLRect update = {

View File

@ -3482,7 +3482,14 @@ void vnc_display_open(const char *id, Error **errp)
h = strrchr(vnc, ':');
if (h) {
char *host = g_strndup(vnc, h - vnc);
char *host;
size_t hlen = h - vnc;
if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
host = g_strndup(vnc + 1, hlen - 2);
} else {
host = g_strndup(vnc, hlen);
}
qemu_opt_set(sopts, "host", host, &error_abort);
qemu_opt_set(wsopts, "host", host, &error_abort);
qemu_opt_set(sopts, "port", h+1, &error_abort);

View File

@ -94,7 +94,7 @@ static const uint8_t x_keycode_to_pc_keycode[115] = {
*/
static const uint8_t evdev_keycode_to_pc_keycode[61] = {
0, /* 97 EVDEV - RO ("Internet" Keyboards) */
0x73, /* 97 EVDEV - RO ("Internet" Keyboards) */
0, /* 98 EVDEV - KATA (Katakana) */
0, /* 99 EVDEV - HIRA (Hiragana) */
0x79, /* 100 EVDEV - HENK (Henkan) */
@ -126,7 +126,7 @@ static const uint8_t evdev_keycode_to_pc_keycode[61] = {
0, /* 126 EVDEV - I126 ("Internet" Keyboards) */
0, /* 127 EVDEV - PAUS */
0, /* 128 EVDEV - ???? */
0, /* 129 EVDEV - I129 ("Internet" Keyboards) */
0x7e, /* 129 EVDEV - KP_COMMA (brazilian) */
0xf1, /* 130 EVDEV - HNGL (Korean Hangul Latin toggle) */
0xf2, /* 131 EVDEV - HJCV (Korean Hangul Hanja toggle) */
0x7d, /* 132 AE13 (Yen)*/