Compare commits

...

476 Commits

Author SHA1 Message Date
Gerd Hoffmann
dbb2a1326a input: map INPUT_BUTTON_WHEEL_{UP,DOWN} to legacy input z axis moves.
Unbreaks mouse wheel.

Reported-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-10 13:49:44 +01:00
Gerd Hoffmann
c3aa84b68f input: sdl: fix guest_cursor logic.
Unbreaks relative mouse mode with SDL.

Reported-by: Gabriel L. Somlo <gsomlo@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-10 13:49:44 +01:00
Peter Maydell
f53f3d0a00 Merge remote-tracking branch 'remotes/kvaneesh/for-upstream' into staging
* remotes/kvaneesh/for-upstream:
  hw/9pfs: Include virtio-9p-device.o in build
  hw/9pfs: use g_strdup_printf() instead of PATH_MAX limitation
  hw/9pfs/virtio-9p-local.c: use snprintf() instead of sprintf()
  hw/9pfs/virtio-9p-local.c: move v9fs_string_free() to below "err_out:"
  fsdev: Fix overrun after readlink() fills buffer completely

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-08 12:38:43 +00:00
Peter Maydell
d7c698af8a Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches

# gpg: Signature made Fri 07 Mar 2014 13:30:04 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream:
  block: qemu-iotests 085 - live snapshots tests
  hw/ide/ahci.h: Avoid shifting left into sign bit
  block: Fix error path segfault in bdrv_open()
  qemu-iotests: Test a few blockdev-add error cases
  blockdev: Fix NULL pointer dereference in blockdev-add
  blockdev: Fail blockdev-add with encrypted images
  block/raw-win32: Strip "file:" prefix on creation
  block/raw-win32: Implement bdrv_parse_filename()
  block/raw-posix: Strip "file:" prefix on creation
  block/raw-posix: Implement bdrv_parse_filename()
  block: Keep "filename" option after parsing
  block: mirror - remove code cruft that has no function
  block: make bdrv_swap rebuild the bs graph node list field.
  block: Fix bs->request_alignment assertion for bs->sg=1
  iscsi: Use bs->sg for everything else than disks
  qemu-iotests: Test progress output for conversion
  qemu-img convert: Fix progress output
  gluster: Remove unused defines and header include
  gluster: Change licence to GPLv2+

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-08 12:17:17 +00:00
Lluís Vilanova
6570025e53 build: Fix installation of target-dependent files
Pass all the relevant sub-directory make variables.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20140120112153.5685.30949.stgit@fimbulvetr.bsc.es
2014-03-08 12:08:11 +00:00
Andreas Färber
80aaa0741f xenfb: Fix graphic_console_init() build failure
In commit 5643706a09 (console: add head
to index to qemu consoles.) graphic_console_init() was extended to take
an additional argument, but xenfb was not updated accordingly. Fix it.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Don Slutz <dslutz@verizon.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1394228528-31625-1-git-send-email-afaerber@suse.de
2014-03-08 11:27:00 +00:00
Peter Maydell
6fc0303b95 Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-4' into staging
Input handling rewrite.
SDL2 support.

# gpg: Signature made Wed 05 Mar 2014 11:16:08 GMT using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-input-4: (38 commits)
  ui/sdl2 : initial port to SDL 2.0 (v2.0)
  console: add QemuUIInfo
  console: add head to index to qemu consoles.
  input: remove index_from_keycode (no users)
  input: move do_mouse_set to new core
  input: move qmp_query_mice to new core
  input: add input_mouse_mode tracepoint
  input: move mouse mode notifier to new core
  input-legacy: remove kbd_mouse_event
  input-legacy: remove kbd_mouse_is_absolute
  input-legacy: remove kbd_mouse_has_absolute
  input-legacy: remove kbd_put_keycode
  input: trace events
  input: mouse: switch cocoa ui to new core
  input: keyboard: switch cocoa ui to new core
  input: mouse: switch monitor to new core
  input: mouse: switch spice ui to new core
  input: mouse: switch vnc ui to new core
  input: mouse: switch sdl ui to new core
  input: mouse: switch gtk ui to new core
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-07 18:29:33 +00:00
Peter Maydell
bb2b045034 Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-03-05

This pull request includes:

  - VSX emulation support
  - book3s pr/hv selection
  - some bug fixes
  - qdev stable numbering
  - eTSEC emulation

# gpg: Signature made Wed 05 Mar 2014 02:14:19 GMT using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found

* remotes/agraf/tags/signed-ppc-for-upstream: (130 commits)
  target-ppc: spapr: e500: fix to use cpu_dt_id
  target-ppc: add PowerPCCPU::cpu_dt_id
  target-ppc: Introduce hypervisor call H_GET_TCE
  target-ppc: Update ppc_hash64_store_hpte to support updating in-kernel htab
  target-ppc: Change the hpte store API
  target-ppc: Fix page table lookup with kvm enabled
  target-ppc: Fix htab_mask calculation
  target-ppc: Use Additional Temporary in stqcx Case
  target-ppc: Fix Compiler Warnings Due to 64-Bit Constants Declared as UL
  PPC: sPAPR: Only use getpagesize() when we run with kvm
  target-ppc/translate.c: Use ULL suffix for 64 bit constants
  spapr-vlan: flush queue whenever can_receive can go from false to true
  target-ppc: Altivec 2.07: Vector Permute and Exclusive OR
  target-ppc: Altivec 2.07: Vector SHA Sigma Instructions
  target-ppc: Altivec 2.07: AES Instructions
  target-ppc: Altivec 2.07: Binary Coded Decimal Instructions
  target-ppc: Altivec 2.07: Vector Polynomial Multiply Sum
  target-ppc: Altivec 2.07: Vector Gather Bits by Bytes
  target-ppc: Altivec 2.07: Doubleword Compares
  target-ppc: Altivec 2.07: vbpermq Instruction
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-07 16:36:38 +00:00
Peter Maydell
c3f8d28e45 Merge remote-tracking branch 'remotes/cohuck/tags/virtio-ccw-20140305' into staging
One patch introducing support for adapter interrupts in virtio-ccw.

This improves performance for those guests that issue the new
CCW_CMD_SET_IND_ADAPTER channel command.

# gpg: Signature made Wed 05 Mar 2014 08:48:18 GMT using RSA key ID C6F02FAF
# gpg: Can't check signature: public key not found

* remotes/cohuck/tags/virtio-ccw-20140305:
  s390x/virtio-ccw: Adapter interrupt support.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-07 15:58:28 +00:00
Jeff Cody
4089f7c6a0 block: qemu-iotests 085 - live snapshots tests
This adds tests for live snapshots, both through the single
snapshot command, and the transaction group snapshot command.

The snapshots are done through the QMP interface, using the
following commands for snapshots:

Single snapshot:
{ 'execute': 'blockdev-snapshot-sync', 'arguments':
             { 'device': 'virtio0', 'snapshot-file':'...',
               'format': 'qcow2' } }"

Group snapshot:
{ 'execute': 'transaction', 'arguments':
              {'actions': [
                  { 'type': 'blockdev-snapshot-sync', 'data' :
                    { 'device': 'virtio0', 'snapshot-file': '...' } },
                  { 'type': 'blockdev-snapshot-sync', 'data' :
                    { 'device': 'virtio1', 'snapshot-file': '...' } } ]
             } }

Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-07 11:36:12 +01:00
Peter Maydell
2c02f88780 hw/ide/ahci.h: Avoid shifting left into sign bit
Add 'U' suffixes to avoid undefined behaviour shifting left into
the signed bit of a signed integer type. Clang's sanitizer will
warn about this:

 hw/ide/ahci.c:1210:27: runtime error: left shift of 1 by 31 places cannot be represented in type 'int'

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-07 11:29:21 +01:00
Peter Maydell
4c288acbd6 configure: Always build with -fno-common
MacOSX doesn't pull .o files from .a archives if the symbol that it
requires is one which the .o file defines as a common symbol.
(Common symbols are those declared without "extern"; the linker
will merge together common symbols with the same name, so
redeclaring the same variable in two compilation units results in
them referring to the same symbol rather than a compilation error).

This MacOSX difference from traditional linker behaviour means that
"make check" produces link errors:

Undefined symbols for architecture x86_64:
  "_cur_mon", referenced from:
      _error_vprintf in libqemuutil.a(qemu-error.o)
      _error_printf in libqemuutil.a(qemu-error.o)
      _error_printf_unless_qmp in libqemuutil.a(qemu-error.o)
      _error_print_loc in libqemuutil.a(qemu-error.o)
      _error_report in libqemuutil.a(qemu-error.o)
ld: symbol(s) not found for architecture x86_64

in this case because "cur_mon" is a common symbol in
libqemustub.a(mon-set-error.o).

In QEMU we don't make any use at all of the common symbol
functionality, so we can avoid this problem entirely simply
by compiling with -fno-common. Enable this option for all
builds, not just MacOSX, so that if we ever inadvertently
introduce multiple definitions of some variable that will
be immediately spotted as a build error rather than only
breaking the MacOSX build.

Suggested-by:  Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1393451610-24617-1-git-send-email-peter.maydell@linaro.org
2014-03-06 21:26:44 +00:00
Peter Maydell
9c83ffd859 configure: Make C++ test work with --enable-werror
gcc's C++ compiler complains about being passed some -W options
which make sense for C but not for C++. This means we mustn't try
a C++ compile with QEMU_CFLAGS, but only with a filtered version
that removes the offending options. This filtering was already being
done for uses of C++ in the build itself, but was omitted for the
"does C++ work?" configure test. This only showed up when doing
builds which explicitly enabled -Werror with --enable-werror,
because the "do the compilers work" tests were mistakenly placed
above the "default werror based on whether compiling from git" code.
Another error in this category is that clang warns if you ask it to
compile C++ code from a file named "foo.c". Further, because we
were running do_cc in a subshell in the condition part of an "if",
the error_exit inside do_compiler wouldn't terminate configure and
we would plunge on regardless. Fix this complex of errors:

1. Move the default-werror code up so that there are no invocations
of compile_object and friends between it and the point where we
set $werror explicitly based on the --enable-werror command line
option.

2. Provide a mechanism for filtering QEMU_CFLAGS to create
QEMU_CXXFLAGS, and use it for the test we run here.

3. Provide a do_cxx function to run a test with the C++ compiler
rather than doing cute tricks with subshells and do_cc.

4. Use a new temporary file TMPCXX for the C++ program fragment.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1393352869-22257-1-git-send-email-peter.maydell@linaro.org
Tested-by: Andreas Färber <afaerber@suse.de>
2014-03-06 19:59:09 +00:00
Kevin Wolf
eb909c7f72 block: Fix error path segfault in bdrv_open()
Using an invalid option for a block device that is opened with
BDRV_O_PROTOCOL led to drv = NULL, and when trying to include the driver
name in the error message, qemu dereferenced it:

    $ x86_64-softmmu/qemu-system-x86_64 -drive file=/tmp/test.qcow2,file.foo=bar
    Segmentation fault (core dumped)

With this patch applied, the expected error message is printed:

    $ x86_64-softmmu/qemu-system-x86_64 -drive file=/tmp/test.qcow2,file.foo=bar
    qemu-system-x86_64: -drive file=/tmp/test.qcow2,file.foo=bar: could
    not open disk image /tmp/test.qcow2: Block protocol 'file' doesn't
    support the option 'foo'

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
2014-03-06 17:29:24 +01:00
Kevin Wolf
c75203c8d3 qemu-iotests: Test a few blockdev-add error cases
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
2014-03-06 17:28:24 +01:00
Kevin Wolf
c6e0bd9b70 blockdev: Fix NULL pointer dereference in blockdev-add
If aio=native, we check that cache.direct is set as well. If however
cache wasn't specified at all, qemu just segfaulted.

The old condition didn't make any sense anyway because it effectively
only checked for the default cache mode case, but not for an explicitly
set cache.direct=off mode.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-03-06 17:27:28 +01:00
Kevin Wolf
8ae8e904fc blockdev: Fail blockdev-add with encrypted images
Encrypted images need a password before they can be used, and we don't
want blockdev-add to create BDSes that aren't fully initialised. So for
now simply forbid encrypted images; we can come back to it later if we
need the functionality.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-03-06 17:27:23 +01:00
Max Reitz
d5546c5e77 block/raw-win32: Strip "file:" prefix on creation
The bdrv_create() implementation of the block/raw-win32 "file" protocol
driver should strip the "file:" prefix from filenames if present.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 16:18:12 +01:00
Max Reitz
7dc74db88b block/raw-win32: Implement bdrv_parse_filename()
The "file" protocol driver should strip the "file:" prefix from
filenames if present.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 16:18:11 +01:00
Max Reitz
464d9f641d block/raw-posix: Strip "file:" prefix on creation
The bdrv_create() implementation of the block/raw-posix "file" protocol
driver should strip the "file:" prefix from filenames if present.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 16:18:09 +01:00
Max Reitz
078896a9ee block/raw-posix: Implement bdrv_parse_filename()
The "file" protocol driver should strip the "file:" prefix from
filenames if present.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 16:18:06 +01:00
Max Reitz
cd5d031e75 block: Keep "filename" option after parsing
Currently, bdrv_file_open() always removes the "filename" option from
the options QDict after bdrv_parse_filename() has been (successfully)
called. However, for drivers with bdrv_needs_filename, it makes more
sense for bdrv_parse_filename() to overwrite the "filename" option and
for bdrv_file_open() to fetch the filename from there.

Since there currently are no drivers that implement
bdrv_parse_filename() and have bdrv_needs_filename set, this does not
change current behavior.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 16:18:01 +01:00
Jeff Cody
50c75136be block: mirror - remove code cruft that has no function
Originally, this built up the error message with the backing filename,
so that errp was set as follows:
    error_set(errp, QERR_OPEN_FILE_FAILED, backing_filename);

However, we now propagate the local_error from the
bdrv_open_backing_file() call instead, making these 2 lines useless
code.

Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 11:47:40 +01:00
Benoît Canet
90ce8a061b block: make bdrv_swap rebuild the bs graph node list field.
Moving only the node_name one field could lead to some inconsitencies where a
node_name was defined on a bs which was not registered in the graph node list.

bdrv_swap between a named node bs and a non named node bs would lead to this.

bdrv_make_anon would then crash because it would try to remove the bs from the
graph node list while it is not in it.

This patch remove named node bses from the graph node list before doing the swap
then insert them back.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-06 11:33:10 +01:00
Kevin Wolf
47ea2de2d6 block: Fix bs->request_alignment assertion for bs->sg=1
For sg backends, bs->request_alignment is meaningless and may be 0.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
2014-03-05 16:58:37 +01:00
Kevin Wolf
f47c3f5a80 iscsi: Use bs->sg for everything else than disks
The current iscsi block driver code makes the rather arbitrary decision
that TYPE_MEDIUM_CHANGER and TYPE_TAPE devices have bs->sg = 1 and all
other device types are disks.

Instead of this, check for TYPE_DISK to expose the disk interface and
make everything else bs->sg = 1. In particular, this includes devices
with TYPE_STORAGE_ARRAY, which is what LUN 0 of an iscsi target is.
(See https://bugzilla.redhat.com/show_bug.cgi?id=1067784 for the exact
scenario.)

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
2014-03-05 16:58:20 +01:00
Kevin Wolf
2fa4c042bc qemu-iotests: Test progress output for conversion
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-05 15:58:32 +01:00
Kevin Wolf
64bb01aa35 qemu-img convert: Fix progress output
Initialise progress output only when the -p and -q options have already
been parsed, otherwise it's always disabled.

Reported-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-03-05 15:58:32 +01:00
Bharata B Rao
b1f7d84fd2 gluster: Remove unused defines and header include
Remove the definitions of GLUSTER_FD_WRITE and GLUSTER_FD_READ which are
no longer used. Also sockets.h isn't needed any more.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-05 15:58:32 +01:00
Bharata B Rao
85c09bc016 gluster: Change licence to GPLv2+
Pipe handling mechanism in gluster driver was based on similar implementation
in RBD driver and hence had GPLv2 and associated copyright information.
After changing gluster driver to coroutine based implementation, the pipe
handling code no longer exists and hence change gluster driver's licence to
GPLv2+ and remove RBD copyrights.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-05 15:58:32 +01:00
Dave Airlie
47c03744b3 ui/sdl2 : initial port to SDL 2.0 (v2.0)
I've ported the SDL1.2 code over, and rewritten it to use the SDL2 interface.

The biggest changes were in the input handling, where SDL2 has done a major
overhaul, and I've had to include a generated translation file to get from
SDL2 codes back to qemu compatible ones. I'm still not sure how the keyboard
layout code works in qemu, so there may be further work if someone can point
me a test case that works with SDL1.2 and doesn't with SDL2.

Some SDL env vars we used to set are no longer used by SDL2,
Windows, OSX support is untested,

I don't think we can link to SDL1.2 and SDL2 at the same time, so I felt
using --with-sdlabi=2.0 to select the new code should be fine, like how
gtk does it.

v1.1: fix keys in text console
v1.2: fix shutdown, cleanups a bit of code, support ARGB cursor

v2.0: merge the SDL multihead patch into this, g_new the number of consoles
needed, wrap DCL inside per-console structure.

Signed-off-by: Dave Airlie <airlied@redhat.com>

Fixes & improvements by kraxel:
 * baum build fix
 * remove text console logic
 * adapt to new input core
 * codestyle fixups

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:05 +01:00
Gerd Hoffmann
6f90f3d786 console: add QemuUIInfo
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
5643706a09 console: add head to index to qemu consoles.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
5c07d00f1b input: remove index_from_keycode (no users)
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
70b52f62b8 input: move do_mouse_set to new core
This removes the last user of the lecagy input mouse handler list,
so we can remove more legacy bits with this.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
e842c68d44 input: move qmp_query_mice to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
a8dfb1c34f input: add input_mouse_mode tracepoint
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
4a33f45e2e input: move mouse mode notifier to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:04 +01:00
Gerd Hoffmann
4798648e32 input-legacy: remove kbd_mouse_event
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
2d0755d21c input-legacy: remove kbd_mouse_is_absolute
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
16b0ecd168 input-legacy: remove kbd_mouse_has_absolute
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
faecd955ce input-legacy: remove kbd_put_keycode
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
c43ce5512f input: trace events
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
21bae11a39 input: mouse: switch cocoa ui to new core
Build fixes by Peter Maydell.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
2e08c665cc input: keyboard: switch cocoa ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
c751a74afe input: mouse: switch monitor to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
f100db385d input: mouse: switch spice ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:03 +01:00
Gerd Hoffmann
14768eba46 input: mouse: switch vnc ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:02 +01:00
Gerd Hoffmann
3ab193e662 input: mouse: switch sdl ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:02 +01:00
Gerd Hoffmann
192f81bfce input: mouse: switch gtk ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:02 +01:00
Gerd Hoffmann
edd85a3d9e input: mouse: switch legacy handlers to new core
legacy mouse event handlers are registered in the new core,
so they receive events submitted to the new input core.

legacy kbd_mouse_event() continues to use the old code paths.
So new-core event handlers wouldn't see events submitted via
kbd_mouse_event.

This leads to the constrain that we we must transition all
kbd_mouse_event() users first to keep things working.  But
that is easier to handle than translating legacy mouse events
into new-core mouse events ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:02 +01:00
Gerd Hoffmann
502c8db5b4 input: mouse: add qemu_input_is_absolute()
Same as kbd_mouse_is_absolute(), but using new input core.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:02 +01:00
Gerd Hoffmann
d3535431e8 input: mouse: add graphic_rotate support
Transform absolute mouse events according to graphic_rotate.

Legacy input code does it for both absolute and relative events,
but the logic is broken for relative coordinates, so this is
most likely not used anyway.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:52:02 +01:00
Gerd Hoffmann
43579403a3 input: mouse: add helpers functions to core
Likewise a bunch of helper functions to manage mouse button
and movement events, again to make life easier for the ui code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:18 +01:00
Gerd Hoffmann
cd10032888 input: keyboard: switch curses ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:18 +01:00
Gerd Hoffmann
de8f580b23 input: keyboard: switch spice ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:18 +01:00
Gerd Hoffmann
8d447d10b7 input: keyboard: switch vnc ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:18 +01:00
Gerd Hoffmann
a25f545d68 input: keyboard: switch sdl ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:18 +01:00
Gerd Hoffmann
af98ba92ac input: keyboard: switch gtk ui to new core
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
d2a9260335 input: keyboard: switch qmp_send_key() to new core.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
9784e57930 input: keyboard: switch legacy handlers to new core
legacy kbd event handlers are registered in the new core,
so they receive events from the new input core code.
keycode -> scancode translation needed here.

legacy kbd_put_keycode() sends events to the new core.
scancode -> keycode translation needed here.

So with this patch the new input core is fully functional
for keyboard events.  New + legacy interfaces can be mixed
in any way.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
6567147588 input: keyboard: add helper functions to core
A bunch of helper functions to manage keyboard events,
to make life simpler for the ui code when submitting
keyboard events.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
c8b405b679 input: add core bits of the new input layer
Register and unregister handlers.
Event dispatcher code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
8b6b0c59a6 input: qapi: add pause key
It's missing.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
bbd1b1cc25 input: qapi: add unmapped key
Simplifies building something -> QkeyCode mapping tables.
Uninitialized entries can easily identified then.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
031fa96439 input: qapi: define event types
Define input event types, using qapi.  So we get nicely autogenerated
types for our input events.  And when it comes to qmp support some day
things will be a lot easier.

Types are modeled after the linux input layer.  There are separate
event types for each value.  There is a sync to indicate the end
of a event group.

Mouse events are split into motion events (one for each axis) and
button events, which are grouped by sync.

Keyboard events are using the existing KeyValue type.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
7ad95ff76c input: rename file to legacy
Rename ui/input.c to ui/input-legacy.c.
We are going to replace it step by step.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Gerd Hoffmann
d4c8533755 console: export QemuConsole index,width,height
Add functions to query QemuConsole properties.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-03-05 09:50:17 +01:00
Cornelia Huck
7e7494627f s390x/virtio-ccw: Adapter interrupt support.
Handle the new CCW_CMD_SET_IND_ADAPTER command enabling adapter interrupts
on guest request. When active, host->guest notifications will be handled
via global_indicator -> queue indicators instead of queue indicators +
subchannel I/O interrupt. Indicators for virtqueues may be present at an
offset.

Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-03-05 09:42:05 +01:00
Alexey Kardashevskiy
0f20ba62c3 target-ppc: spapr: e500: fix to use cpu_dt_id
This makes use of @cpu_dt_id and related API in:
1. emulated XICS hypercall handlers as they receive fixed CPU indexes;
2. XICS-KVM to enable in-kernel XICS on right CPU;
3. device-tree renderer.

This removes @cpu_index fixup as @cpu_dt_id is used instead so QEMU monitor
can accept command-line CPU indexes again.

This changes kvm_arch_vcpu_id() to use ppc_get_vcpu_dt_id() as at the moment
KVM CPU id and device tree ID are calculated using the same algorithm.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: Mike Day <ncmike@ncultra.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:04 +01:00
Alexey Kardashevskiy
0ce470cd4c target-ppc: add PowerPCCPU::cpu_dt_id
Normally CPUState::cpu_index is used to pick the right CPU for various
operations. However default consecutive numbering does not always work
for POWERPC.

These indexes are reflected in /proc/device-tree/cpus/PowerPC,POWER7@XX
and used to call KVM VCPU's ioctls. In order to achieve this,
kvmppc_fixup_cpu() was introduced. Roughly speaking, it multiplies
cpu_index by the number of threads per core.

This approach has disadvantages such as:
1. NUMA configuration stays broken after the fixup;
2. CPU-targeted commands from the QEMU Monitor do not work properly as
CPU indexes have been fixed and there is no clear way for the user to
know what the new CPU indexes are.

This introduces a @cpu_dt_id field in the CPUPPCState struct which
is initialized from @cpu_index by default and can be fixed later
to meet the device tree requirements.

This adds an API to handle @cpu_dt_id.

This removes kvmppc_fixup_cpu() as it is not more needed, @cpu_dt_id
is calculated in ppc_cpu_realize().

This will be used later in machine code.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: Mike Day <ncmike@ncultra.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:03 +01:00
Laurent Dufour
a0fcac9c21 target-ppc: Introduce hypervisor call H_GET_TCE
This patch introduces the hypervisor call H_GET_TCE which is basically the
reverse of H_PUT_TCE, as defined in the Power Architecture Platform
Requirements (PAPR).

The hcall H_GET_TCE is required by the kdump kernel which is calling it to
retrieve the TCE set up by the panicing kernel.

Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:03 +01:00
Aneesh Kumar K.V
c138593380 target-ppc: Update ppc_hash64_store_hpte to support updating in-kernel htab
This support updating htab managed by the hypervisor. Currently we don't have
any user for this feature. This actually bring the store_hpte interface
in-line with the load_hpte one. We may want to use this when we want to
emulate henter hcall in qemu for HV kvm.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[ folded fix for the "warn_unused_result" build break in
  kvmppc_hash64_write_pte(), Greg Kurz <gkurz@linux.vnet.ibm.com> ]
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:03 +01:00
Aneesh Kumar K.V
3f94170be3 target-ppc: Change the hpte store API
For updating in kernel htab we need to provide both pte0 and pte1, hence update
the interface to take pte0 and pte1 together

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[ ldq_phys() API change, Greg Kurz <gkurz@linux.vnet.ibm.com> ]
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:02 +01:00
Aneesh Kumar K.V
7c43bca004 target-ppc: Fix page table lookup with kvm enabled
With kvm enabled, we store the hash page table information in the hypervisor.
Use ioctl to read the htab contents. Without this we get the below error when
trying to read the guest address

 (gdb) x/10 do_fork
 0xc000000000098660 <do_fork>:   Cannot access memory at address 0xc000000000098660
 (gdb)

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[ fixes for 32 bit build (casts!), ldq_phys() API change,
  Greg Kurz <gkurz@linux.vnet.ibm.com ]
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:02 +01:00
Aneesh Kumar K.V
f3c75d42ad target-ppc: Fix htab_mask calculation
Correctly update the htab_mask using the return value of
KVM_PPC_ALLOCATE_HTAB ioctl. Also we don't update sdr1
on GET_SREGS for HV. We check for external htab and if
found true, we don't need to update sdr1

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[ fixed pte group offset computation in ppc_hash64_htab_lookup() that
  caused TCG to fail, Greg Kurz <gkurz@linux.vnet.ibm.com> ]
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:02 +01:00
Tom Musta
3707cd62db target-ppc: Use Additional Temporary in stqcx Case
Per Alex Graf's suggestion, the recently added case to gen_conditional_store
for stqcx should use an additional temporary when accessing the second
doubleword.  This avoids the mutation of the EA argument to the function,
which is counter intuitive.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:01 +01:00
Tom Musta
7dff9abe63 target-ppc: Fix Compiler Warnings Due to 64-Bit Constants Declared as UL
This patch fixes 64 bit constants that were erroneously declared as "ul" instead of
"ull".  The preferred form "ULL" is used.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:01 +01:00
Alexander Graf
3c3b0ddefa PPC: sPAPR: Only use getpagesize() when we run with kvm
We currently size the msi window trap page according to the host's page
size so that we poke a working hole into a memory slot in case we overlap.

However, this is only ever necessary with KVM active. Without KVM, we should
rather try to be host platform agnostic and use a constant size: 4k.

This fixes a build breakage on win32 hosts.

Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:01 +01:00
Peter Maydell
e5d7d2b0f5 target-ppc/translate.c: Use ULL suffix for 64 bit constants
64 bit constants need the "ULL" suffix, not just "UL", because
on 32 bit platforms 'long' is not large enough and this will
cause a compiler warning.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:00 +01:00
Alexey Kardashevskiy
0a61f3b478 spapr-vlan: flush queue whenever can_receive can go from false to true
When the guests adds buffers to receive queue, the network device
should flush its queue of pending packets. This is done with
qemu_flush_queued_packets.

This adds a call to qemu_flush_queued_packets() which wakes up the main
loop and let QEMU update the network device status which now is "can
receive". The patch basically does the same thing as e8b4c68 does.

Suggested-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:00 +01:00
Tom Musta
ac174549b7 target-ppc: Altivec 2.07: Vector Permute and Exclusive OR
This patch adds the Vector Permuate and Exclusive OR (vpermxor)
instruction introduced in Power ISA Version 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:00 +01:00
Tom Musta
57354f8f12 target-ppc: Altivec 2.07: Vector SHA Sigma Instructions
This patch adds the Vector SHA Sigma instructions introduced in Power
ISA Version 2.07:

  - Vector SHA-512 Sigma Doubleword (vshasigmad)
  - Vector SHA-256 Sigma Word (vshasigmaw)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:07:00 +01:00
Tom Musta
557d52fa69 target-ppc: Altivec 2.07: AES Instructions
This patch adds the Vector AES instructions introduced in Power ISA
Version 2.07:

   - Vector AES Cipher (vcipher)
   - Vector AES Cipher Last (vcipherlast)
   - Vector AES Inverse Cipher (vncipher)
   - Vector AES Inverse Cipher Last (vncipherlast)
   - Vector AES SubBytes (vsbox)

Note that the implementation of vncipher deviates from the RTL in
ISA V2.07.  However it does match the verbal description in the
third paragraph.  The RTL will be fixed in ISA V2.07B.  The
implementation here has been tested against actual P8 hardware.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:59 +01:00
Tom Musta
e8f7b27b99 target-ppc: Altivec 2.07: Binary Coded Decimal Instructions
This patch add the Binary Coded Decimal instructions bcdadd. and
bcdsub.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:59 +01:00
Tom Musta
b8476fc7c6 target-ppc: Altivec 2.07: Vector Polynomial Multiply Sum
This patch adds the Vectory Polynomial Multiply Sum instructions
introduced in Power ISA Version 2.07:

  - Vectory Polynomial Multiply Sum Byte (vpmsumb)
  - Vectory Polynomial Multiply Sum Halfword (vpmsumh)
  - Vectory Polynomial Multiply Sum Word (vpmsumw)
  - Vectory Polynomial Multiply Sum Doubleword (vpmsumd)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:59 +01:00
Tom Musta
f1064f612c target-ppc: Altivec 2.07: Vector Gather Bits by Bytes
This patch adds the Vector Gather Bits by Bytes Doubleword (vgbbd)
instruction which is introduced in Power ISA Version 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:58 +01:00
Tom Musta
6f3dab41fb target-ppc: Altivec 2.07: Doubleword Compares
This patch adds the Vector Compare Doubleword instructions introduced
by Power ISA Version 2.07:

  - Vector Compare Equal to Unsigned Doubleword (vcmpequd)
  - Vector Compare Greater Than Signed Doubleword (vcmpgtsd)
  - Vector Compare Greater Than Unsigned Doubleword (vcmpgtud)

These instructions are encoded with bit 31 set to 1 and so are duals with
vcmpeqfp, vcmpgtfp and vcmpbfp respectively.

The helper macro for integer compares is enhanced to account for 64-bit
operands.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:58 +01:00
Tom Musta
4d82038e41 target-ppc: Altivec 2.07: vbpermq Instruction
This patch adds the Vector Bit Permute Quadword (vbpermq) instruction
introduced in Power ISA Version 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:58 +01:00
Tom Musta
b41da4ebb2 target-ppc: Altivec 2.07: Quadword Addition and Subtracation
This patch adds the Vector Quadword Addition and Subtraction instructions
introduced in Power ISA Version 2.07:

  - Vector Add Unsigned Quadword Modulo (vadduqm)
  - Vector Add & Write Carry Unsigned Quadword (vaddcuq)
  - Vector Add Extended Unsigned Quadword (vaddeuqm)
  - Vector Add Extended & Write Carry Unsigned Quadword (vaddecuq)
  - Vector Subtract Unsigned Quadword Modulo (vsubuqm)
  - Vector Subtract & Write Carry Unsigned Quadword (vsubcuq)
  - Vector Subtract Extended Unsigned Quadword (vsubeuqm)
  - Vector Subtract Extended & Write Carry Unsigned Quadword (vsubecuq)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:57 +01:00
Tom Musta
2fdf78e649 target-ppc: Altivec 2.07: Vector Doubleword Rotate and Shift Instructions
This patch adds the vector doublword rotate and shift instructions
introduced in Power ISA Version 2.07:

  - Vector Rotate Left Doubleword instruction (vrld)
  - Vector Shift Left Doubleword (vsld)
  - Vector Shift Right Doubleword (vsrd)
  - Vector Shift Right Algegbraic Doubleword (vsrad)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:57 +01:00
Tom Musta
818692ff95 target-ppc: Altivec 2.07: Change Bit Masks to Support 64-bit Rotates and Shifts
Existing code in the VROTATE, VSL and VSR macros for the Altivec rotate and shift
helpers uses a formula to compute a bit mask used to extract the rotate/shift
amount from the VRB register.  What is desired is:

    mask = (1 << (3 + log2(sizeof(element)))) - 1

but what is implemented is:

    mask = (1 << (3 + (sizeof(element)/2))) - 1

This produces correct answers when "element" is uint8_t, uint16_t or uint_32t.  But
it breaks down when element is uint64_t.

This patch corrects the situation.  Since the mask is known at compile time, the
macros are changed to simply accept the mask as an argument.

Subsequent patches in this series will add double-word variants of rotates and
shifts and thus take advantage of this fix.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:57 +01:00
Tom Musta
e0ffe77f27 target-ppc: Altivec 2.07: Vector Merge Instructions
This patch adds the Vector Merge Even Word (vmrgew) and Vector
Merge Odd Word (vmrgow) instructions introduced in Power ISA
Version 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:56 +01:00
Tom Musta
4430e07663 target-ppc: Altivec 2.07: Unpack Signed Word Instructions
This patch adds the Unpack Signed Word instructions introduced in
Power ISA Version 2.07:

  - Vector Unpack High Signed Word (vupkusw)
  - Vector Unpack Low Signed Word (vupklsw)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:56 +01:00
Tom Musta
024215b242 target-ppc: Altivec 2.07: Pack Doubleword Instructions
This patch adds the Vector Pack Doubleword instructions introduced in
Power ISA Version 2.07:

 - Vector Pack Signed Doubleword Signed Saturate (vpksdss)
 - Vector Pack Signed Doubleword Unsigned Saturate (vpksdus)
 - Vector Pack Unsigned Doubleword Unsigned Modulo (vpkudum)
 - Vector Pack Unsigned Doubleword Unsigned Saturate (vpkudus)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:56 +01:00
Tom Musta
8203e31b54 target-ppc: Altivec 2.07: Vector Min/Max Doubleword Instructions
This patch adds the Vector Minimum and Maximum Doubleword instructions
that are introduced in Power ISA Version 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:55 +01:00
Tom Musta
e13500b3c3 target-ppc: Altivec 2.07: Vector Population Count Instructions
This patch adds the Vector Population Count instructions introduced in Power
ISA Version 2.07: vpopcntb, vpopcnth, vpopcntw and vpopcntd.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:55 +01:00
Tom Musta
f293f04ab5 target-ppc: Altivec 2.07: Add Vector Count Leading Zeroes
This patch adds the Vector Count Leading Zeroes instructions introduced
in Power ISA Version 2.07 - vclzb, vclzh, vclzw and vclzd.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:55 +01:00
Tom Musta
953f0f5842 target-ppc: Altivec 2.07: vmuluw Instruction
This patch adds the Vector Multiply Unsigned Word Modulo (vmuluwm)
instruction.

The existing VARITH_DO macro is re-used to (trivially) instantiate
the helper code.

Since bits 21-31 of any vmuluwm instruction is 137, the instruction
is coded as a dual to vmulouw (bits 21-31 = 136).

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:54 +01:00
Tom Musta
63be09365a target-ppc: Altivec 2.07: Multiply Even/Odd Word Instructions
This patch adds the Multilpy Even/Odd Word instructions that are introduced
in Power ISA Version 2.07:

  - Vector Multiply Even Unsigned Word (vmuleuw)
  - Vector Multiply Even Signed Word (vmulesw)
  - Vector Multiply Odd Unsigned Word (vmulouw)
  - Vector Multiply Odd Signed Word (vmulosw)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:54 +01:00
Tom Musta
aa9e930c88 target-ppc: Altivec 2.07: Change VMUL_DO to Support 64-bit Integers
This VMUL_DO macro provides support for the various vmule* and vmulo*
instructions.  These instructions multiply vector elements, producing
products that are one size larger; e.g. vmuleub multiplies unsigned 8-bit
elements and produces a 16 bit unsigned element.

The existing macro works correctly for the existing instructions (8-bit,
and 16-bit source elements) but does not work correctly for 32-bit
source elements.

This patch adds an explicit cast to the multiplicands, forcing them to be
of the target element type.  This is required for the forthcoming patches
that add the vmul[eo][us]w instructions.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:54 +01:00
Tom Musta
56eabc7508 target-ppc: Altivec 2.07: Add/Subtract Unsigned Doubleword Modulo
This patch adds two Altivec unsigned doublword modulo instructions that
are introduced in Power ISA Version V2.07:

  - vaddudm : Vector Add Unsigned Doubleword Modulo
  - vsubudm : Vector Subtrace Unsigned Doubleword Modulo

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:53 +01:00
Tom Musta
111c5f54a1 target-ppc: Altivec 2.07: Vector Logical Instructions
This patch adds the Vector Logical Instructions that are introduced
in Power ISA Version 2.07: veqv, vnand and vorc.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:53 +01:00
Tom Musta
a737d3ebc8 target-ppc: Altivec 2.07: Add Support for R-Form Dual Instructions
Some Alitvec instructions introduced in Power ISA Version 2.07 use bit 31
(aka the "Rc" bit) as an opcode but also use bit 21 as an actual Rc
bit.  QEMU for PowerPC typically uses bits 0-5 and 21-30 for opcodes.

This patch introduces a generator macro that injects an auxiliary handler
which decodes both bits 21 and 31 and invokes one of four standard
handlers.  Since the instructions are not, in general, from the same version
of the ISA, two sets of PPC_*/PPC2_* flags are supported.

This patch also introduces a macro to insert two entries into the opcode
table -- one for bit 21 equal to 0 and one for bit 21 equal to 1.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:53 +01:00
Tom Musta
50f5fc0cf2 target-ppc: Altivec 2.07: Add Opcode Macro for VX Form Instructions
This patch adds a macro to insert an entry into the opcode table for Altivec
Power ISA Version 2.07 instructions.  The macro is similar to the GEN_VXFORM macro
except that it tags the entry with the PPC2_ALTIVEC_207 flag rather than
PPC_ALTIVEC.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:52 +01:00
Tom Musta
5dffff5a47 target-ppc: Altivec 2.07: Add Support for Dual Altivec Instructions
Some Alitvec instructions introduced in Power ISA Version 2.07 use bit 31
(aka the "Rc" bit) as an opcode bit.  However, QEMU for PowerPC uses
bits 0-5 and 21-30 for opcodes and not bit 31.

This patch introduces macros that will handle this situation by injecting
an auxiliary handler which decodes bit 31 in invokes one of two standard
handlers.  Since the instructions are not, in general, from the same version
of the ISA, two sets of PPC_*/PPC2_* instruction tags are supported.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:52 +01:00
Tom Musta
9b47bb490c target-ppc: Altivec 2.07: Add GEN_VXFORM3
This patch adds generator macro for Altivec instructions that have 3
source AVR operands.  The macro is similar to the 2 operand form.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:52 +01:00
Tom Musta
bb5275338d target-ppc: Altivec 2.07: Update AVR Structure
This patch updates the ppc_avr_t data structure to include elements for
signed 64-bit integers and (conditionally) unsigned 128 bit integers.
These elements will be in instructions models later on in this patch series.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:51 +01:00
Tom Musta
32ea54ab5f target-ppc: Altivec 2.07: Add Instruction Flag
This patch adds a flag that will be used to tag the Altivec instructions
introduced in Power ISA Version 2.07.

The flag is added to Power8 model since P8 supports these instructions.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:51 +01:00
Tom Musta
27b95bfe62 target-ppc: Add Store Quadword Conditional
This patch adds the Store Quadword Conditionl (stqcx.) instruction
which is introduced in Power ISA 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
[agraf: fix compile error when !TARGET_PPC64]
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:51 +01:00
Tom Musta
9c294d5ab3 target-ppc: Add Load Quadword and Reserve
This patch adds the Load Quadword and Reserve (lqarx) instruction,
which is new in Power ISA 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:50 +01:00
Tom Musta
84cab1e2f5 target-ppc: Store Quadword
This patch adds support for the Store Quadword instruction in user mode.  Prior
to Power ISA 2.07, stq was legal only in privileged mode.  Support for Little
Endian mode is also new in ISA 2.07.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:50 +01:00
Tom Musta
e0498daab5 target-ppc: Load Quadword
This patch adds the Book I (user space) Load Quadword (lq) instruction.
This instruction was introduced into Book I in Power ISA V2.07.  Previous
versions of the architecture supported this as a privileged instruction.
Previous versions of the architecture also did not support Little Endian
mode.

Note that this patch also adds the PPC_64BX flag to the Power8 model,
which enables the lq instruction.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:50 +01:00
Tom Musta
71a8c019c4 target-ppc: Add is_user_mode Utility Routine
This patch adds a boolean function is_user_mode that can be re-used
in translation code that is sensitive to the MSR[PR] (user-mode)
state.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:50 +01:00
Tom Musta
38a853375e target-ppc: Add Flag for ISA 2.07 Load/Store Quadword Instructions
This patch adds a flag to identify the load/store quadword instructions
that are introduced with Power ISA 2.07.

The flag is added to the Power8 model since P8 supports these
instructions.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:49 +01:00
Tom Musta
52a4984d97 target-ppc: Add bctar Instruction
This patch adds the Branch Conditional to Address Register (bctar)
instruction.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:49 +01:00
Tom Musta
60511041d6 target-ppc: Add Target Address SPR (TAR) to Power8
This patch adds support for the Target Address Register (TAR) to the Power8
model.

Because supported SPRs are typically identified in an init_proc_*()
function and because the Power8 model is currently just using the
init_proc_POWER7() function, a new init_proc_POWER8() function
is added and plugged into the P8 model.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:49 +01:00
Tom Musta
94840e0700 target-ppc: Add Flag for bctar
This patch adds a flag for the bctar instruction.  This instruction
is being introduced via Power ISA 2.07.

Also, the flag is added to the Power8 machine model since the P8
processor supports this instruction.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:48 +01:00
Tom Musta
f5bc1bfa35 target-ppc: Fix xxpermdi When T==A or T==B
The existing implementation of xxpermdi is defective if the target
VSR is also a source VSR.  This patch fixes the defect in this case
but also preserves the simpler, two TCG operation implementation
when the target is not once of the two sources.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:48 +01:00
Cédric Le Goater
3f34cf910c target-ppc: add extended opcodes for dcbt/dcbtst
The latest glibc provides a memrchr routine using an extended opcode
of the 'dcbt' instruction :

00000000000a7cc0 <memrchr>:
   a7cc0:       11 00 4c 3c     addis   r2,r12,17
   a7cc4:       b8 f8 42 38     addi    r2,r2,-1864
   a7cc8:       14 2a e3 7c     add     r7,r3,r5
   a7ccc:       d0 00 07 7c     neg     r0,r7
   a7cd0:       ff ff e7 38     addi    r7,r7,-1
   a7cd4:       78 1b 6a 7c     mr      r10,r3
   a7cd8:       24 06 e6 78     rldicr  r6,r7,0,56
   a7cdc:       60 00 20 39     li      r9,96
   a7ce0:       2c 32 09 7e     dcbtt   r9,r6
   ....

which breaks grep, and other commands, in TCG mode :

   invalid bits: 02000000 for opcode: 1f - 16 - 08 (7e09322c) 00003fff799feca0

This patch adds the extended opcodes for dcbt/dcbtst as no-ops just
like the 'dcbt' instruction.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:48 +01:00
Alexander Graf
61de36761b qdev: Keep global allocation counter per bus
When we have 2 separate qdev devices that both create a qbus of the
same type without specifying a bus name or device name, we end up
with two buses of the same name, such as ide.0 on the Mac machines:

  dev: macio-ide, id ""
    bus: ide.0
      type IDE
  dev: macio-ide, id ""
    bus: ide.0
      type IDE

If we now spawn a device that connects to a ide.0 the last created
bus gets the device, with the first created bus inaccessible to the
command line.

After some discussion on IRC we concluded that the best quick fix way
forward for this is to make automated bus-class type based allocation
count a global counter. That's what this patch implements. With this
we instead get

  dev: macio-ide, id ""
    bus: ide.1
      type IDE
  dev: macio-ide, id ""
    bus: ide.0
      type IDE

on the example mentioned above.

This also means that if you did -device ...,bus=ide.0 you got a device
on the first bus (the last created one) before this patch and get that
device on the second one (the first created one) now.  Breaks
migration unless you change bus=ide.0 to bus=ide.1 on the destination.

This is intended and makes the bus enumeration work as expected.

As per review request follows a list of otherwise affected boards and
the reasoning for the conclusion that they are ok:

   target      machine         bus id              times
   ------      -------         ------              -----

   aarch64     n800            i2c-bus.0           2
   aarch64     n810            i2c-bus.0           2
   arm         n800            i2c-bus.0           2
   arm         n810            i2c-bus.0           2

-> Devices are only created explicitly on one of the two buses, using
   s->mpu->i2c[0], so no change to the guest.

   aarch64     vexpress-a15    virtio-mmio-bus.0   4
   aarch64     vexpress-a9     virtio-mmio-bus.0   4
   aarch64     virt            virtio-mmio-bus.0   32
   arm         vexpress-a15    virtio-mmio-bus.0   4
   arm         vexpress-a9     virtio-mmio-bus.0   4
   arm         virt            virtio-mmio-bus.0   32

-> Makes -device bus= work for all virtio-mmio buses.  Breaks
   migration.  Workaround for migration from old to new: specify
   virtio-mmio-bus.4 or .32 respectively rather than .0 on the
   destination.

   aarch64     xilinx-zynq-a9  usb-bus.0           2
   arm         xilinx-zynq-a9  usb-bus.0           2
   mips64el    fulong2e        usb-bus.0           2

-> Normal USB operation not affected. Migration driver needs command
   line to use the other bus.

   i386        isapc           ide.0               2
   x86_64      isapc           ide.0               2
   mips        mips            ide.0               2
   mips64      mips            ide.0               2
   mips64el    mips            ide.0               2
   mipsel      mips            ide.0               2
   ppc         g3beige         ide.0               2
   ppc         mac99           ide.0               2
   ppc         prep            ide.0               2
   ppc64       g3beige         ide.0               2
   ppc64       mac99           ide.0               2
   ppc64       prep            ide.0               2

-> Makes -device bus= work for all IDE buses.  Breaks migration.
   Workaround for migration from old to new: specify ide.1 rather than
   ide.0 on the destination.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Andreas Faerber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:47 +01:00
Aneesh Kumar K.V
5736245c80 target-ppc: Update external_htab even when HTAB is managed by kernel
We will use this in later patches to make sure we use the right load
functions when copying hpte entries.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:47 +01:00
Alexey Kardashevskiy
3b66da82ce spapr: print more detailed error message on failed load_elf()
This makes use of new error codes which load_elf() can return and
prints more informative error message.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:47 +01:00
Alexey Kardashevskiy
18674b2678 elf-loader: add more return codes
The existing load_elf() just returns -1 if it fails to load ELF. However
it could be smarter than this and tell more about the failure such as
wrong endianness or incompatible platform.

This adds additional return codes for wrong architecture, wrong
endianness and if the image is not ELF at all.

This adds a load_elf_strerror() helper to convert return codes into
string messages.

This fixes handling of what load_elf() returns for s390x, other
callers just check the return value for <0 and this remains unchanged.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:46 +01:00
Alexey Kardashevskiy
6a2331d12e moxie: fix load_elf() usage
At the moment in the case of error, load_elf() returns -1 so load_kernel()
will not signal error at all.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:46 +01:00
Alexey Kardashevskiy
133e70ee88 spapr: support only ELF kernel images
Currently everybody uses ELF kernel images with "-kernel" option on
pseries machine but QEMU still tries to boot from an image even it
fails to recognize it is ELF. This produces undefined behaviour if
the user tries a kernel image compiled for another architecture.

This removes support of raw kernel images.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:46 +01:00
Fabien Chouteau
eb1e7c3e51 Add Enhanced Three-Speed Ethernet Controller (eTSEC)
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.

Signed-off-by: Fabien Chouteau <chouteau@adacore.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:45 +01:00
Alexey Kardashevskiy
b36f100e17 PPC: KVM: suppress warnings about not supported SPRs
PR KVM lacks support of many SPRs in set/get one register API but it does
really break PR KVM. So convert them to switchable traces for now.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:45 +01:00
Edgar E. Iglesias
0658aa9cba virtex_ml507: Add support for loading initrd images
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
[agraf: fix up stray quotes and newlines in strings]
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:45 +01:00
Alexey Kardashevskiy
69b31b907b PPC: KVM: store SLB slot number
When ppc_store_slb() is called from kvm_arch_get_registers(), it stores
a SLB in CPUPPCState::slb[slot]. However it drops the slot number from
ESID so when kvm_arch_put_registers() puts SLBs back to KVM, they do not
have correct "index" field anymore. This broke migration with LPCR_AIR
enabled as now the guest is handling interrupts in virtual mode and unable
to reconstruct correct SLBs anymore.

This adds "index" field for valid SLBs when putting them to KVM.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:44 +01:00
Tom Musta
66c3e32841 target-ppc: Add ISA2.06 lfiwzx Instruction
This patch adds the Load Floating Point as Integer Word and
Zero Indexed (lfiwzx) instruction which was introduced in
Power ISA 2.06.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:44 +01:00
Tom Musta
ce8ca30b39 target-ppc: Enable frsqrtes on Power7 and Power8
The frsqrtes instruction was introduced prior to ISA 2.06 and is
support on both the Power7 and Power8 processors.  However, this
instruction is handled as illegal in the current QEMU emulation
machines.  This patch enables the existing implemention of frsqrtes
in the P7 and P8 machines.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:43 +01:00
Tom Musta
6d41d146c9 target-ppc: Add ISA 2.06 ftsqrt
This patch adds the Floating Point Test for Square Root instruction
which was introduced in Power ISA 2.06.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:43 +01:00
Tom Musta
da29cb7bc7 target-ppc: Add ISA 2.06 ftdiv Instruction
This patch adds the Floating Point Test for Divide instruction which
was introduced in Power ISA 2.06B.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:43 +01:00
Tom Musta
29a0e4e9a1 target-ppc: Add Flag for Power ISA V2.06 Floating Point Test Instructions
This patch adds a flag for Floating Point Test instructions that were
introduced in Power ISA V2.06B.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:42 +01:00
Tom Musta
c73860803f target-ppc: Fix and enable fri[mnpz]
The fri* series of instructions was introduced prior to ISA 2.06 and
is supported on Power7 and Power8 hardware.  However, the instruction
is still considered illegal in the P7 and P8 QEMU emulation models.
This patch enables these instructions for the P7 and P8 machines.

Also, the existing helper is modified to correctly handle some of
the boundary cases (NaNs and the inexact flag).

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:42 +01:00
Tom Musta
28288b48a8 target-ppc: Add ISA 2.06 fcfid[u][s] Instructions
This patch adds the fcfids, fcfidu and fcfidus instructions which
were introduced in Power ISA 2.06B.  A common macro is provided to
eliminate repetitious code, and the existing fcfid instruction is
refactored to use this macro.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:42 +01:00
Tom Musta
fab7fe426f target-ppc: Add ISA2.06 Float to Integer Instructions
This patch adds the four floating point to integer conversion instructions
introduced by Power ISA V2.06:

  - Floating Convert to Integer Word Unsigned (fctiwu)
  - Floating Convert to Integer Word Unsigned with Round Toward
    Zero (fctiwuz)
  - Floating Convert to Integer Doubleword Unsigned (fctidu)
  - Floating Convert to Integer Doubleword Unsigned with Round
    Toward Zero (fctiduz)

A common macro is developed to eliminate repetitious code.  Existing instructions
are also refactoried to use this macro (fctiw, fctiwz, fctid, fctidz).

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:41 +01:00
Tom Musta
1b0bd0029f target-ppc: Add Flag for ISA V2.06 Floating Point Conversion
This patch adds a flag for the floating point conversion instructions
introduced in Power ISA 2.06B.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:41 +01:00
Tom Musta
587c51f74b target-ppc: Add ISA 2.06 stbcx. and sthcx. Instructions
This patch adds the byte and halfword variants of the Store Conditional
instructions.   A common macro is introduced and the existing implementations
of stwcx. and stdcx. are refactored to use this macro.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:41 +01:00
Tom Musta
5c77a786e2 target-ppc: Add ISA2.06 lbarx, lharx Instructions
This patch adds the byte and halfword variants of the Load and
Reserve instructions.   Since there is much commonality among
all forms of Load and Reserve, a macro is provided and the existing
implementations of lwarx and ldarx are refactoried to use this
macro.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:40 +01:00
Tom Musta
1fa6c53304 target-ppc: Add Flag for ISA2.06 Atomic Instructions
This patch adds a flag for the atomic instructions introduced
in Power ISA V2.06B.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:40 +01:00
Tom Musta
a98eb9e99d target-ppc: Add ISA 2.06 divwe[o] Instructions
This patch addes the signed Divide Word Extended instructions
which were introduced in Power ISA 2.06B.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:40 +01:00
Tom Musta
6a4fda3358 target-ppc: Add ISA 2.06 divweu[o] Instructions
This patch addes the Unsigned Divide Word Extended instructions
which were introduced in Power ISA 2.06B.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:39 +01:00
Tom Musta
e44259b6d4 target-ppc: Add ISA2.06 divde[o] Instructions
This patch adds the Divide Doubleword Extended instructions.
The implementation builds on the unsigned helper provided in
the previous patch.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:39 +01:00
Tom Musta
98d1eb2748 target-ppc: Add ISA2.06 divdeu[o] Instructions
This patch adds the Divide Doubleword Extended Unsigned
instructions.  This instruction requires dividing a 128-bit
value by a 64 bit value.  Since 128 bit integer division is
not supported in TCG, a helper is used.  An architecture
independent 128-bit division routine is added to host-utils.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
[agraf: use ||]
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:39 +01:00
Tom Musta
a824bc191a target-ppc: Add Flag for ISA2.06 Divide Extended Instructions
This patch adds a flag for the Divide Extended instructions that
were introduced in Power ISA V2.06B.  The flag is added to the
Power7 and Power8 models.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:38 +01:00
Tom Musta
86ba37edcb target-ppc: Add ISA2.06 bpermd Instruction
This patch adds the Bit Permute Doubleword (bpermd) instruction,
which was introduced in Power ISA 2.06 as part of the base 64-bit
architecture.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:38 +01:00
Tom Musta
7ee19fb9d6 target-ppc: Scalar Non-Signalling Conversions
This patch adds the non-signalling scalar conversion instructions:

  - VSX Scalar Convert Single Precision to Double Precision
    Non-Signalling (xscvspdpn)
  - VSX Scalar Convert Double Precision to Single Precision
    Non-Signalling (xscvdpspn)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:38 +01:00
Tom Musta
3d1140bf3e target-ppc: Scalar Round to Single Precision
This patch adds the VSX Scalar Round to Single Precision (xsrsp)
instruction.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:37 +01:00
Tom Musta
097ec5d850 target-ppc: Floating Merge Word Instructions
This patch adds the Floating Merge Even Word (fmrgew) and Floating
Merge Odd Word (fmrgow) instructions.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:37 +01:00
Tom Musta
f5c0f7f981 target-ppc: Move To/From VSR Instructions
This patch adds the Move To VSR instructions (mfvsrd, mfvsrwz)
and Move From VSR instructions (mtvsrd, mtvsrwa, mtvsrwz).  These
instructions are unusual in that they are considered a floating
point instruction if the indexed VSR is in the first half of the
array (0-31) but they are considered vector instructions if the
indexed VSR is in the second half of the array (32-63).

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:37 +01:00
Tom Musta
67a33f3727 target-ppc: VSX Stage 4: Add xxleqv, xxlnand and xxlorc
This patchs adds the VSX Logical instructions that are new with
ISA V2.07:

  - VSX Logical Equivalence (xxleqv)
  - VSX Logical NAND (xxlnand)
  - VSX Logical ORC (xxlorc)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:36 +01:00
Tom Musta
74698350ca target-ppc: VSX Stage 4: Add xscvsxdsp and xscvuxdsp
This patch adds the VSX Scalar Convert Unsigned Integer Doubleword
to Floating Point Format and Round to Single Precision (xscvuxdsp)
and VSX Scalar Convert Signed Integer Douglbeword to Floating Point
Format and Round to Single Precision (xscvsxdsp) instructions.

The existing integer to floating point conversion macro (VSX_CVT_INT_TO_FP)
is modified to support the rounding of the intermediate floating point
result to single precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:36 +01:00
Tom Musta
f53f81e08b target-ppc: VSX Stage 4: Add Scalar SP Fused Multiply-Adds
This patch adds the Single Precision VSX Scalar Fused Multiply-Add
instructions: xsmaddasp, xsmaddmsp, xssubasp, xssubmsp, xsnmaddasp,
xsnmaddmsp, xsnmsubasp, xsnmsubmsp.

The existing VSX_MADD() macro is modified to support rounding of the
intermediate double precision result to single precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:36 +01:00
Tom Musta
968e76bcab target-ppc: VSX Stage 4: add xsrsqrtesp
This patch adds the VSX Scalar Reciprocal Square Root Estimate
Single Precision (xsrsqrtesp) instruction.

The existing VSX_RSQRTE() macro is modified to support rounding
of the intermediate double-precision result to single precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:36 +01:00
Tom Musta
cea4e57473 target-ppc: VSX Stage 4: Add xssqrtsp
This patch adds the VSX Scalar Square Root Single Precision (xssqrtsp)
instruction.

The existing VSX_SQRT() macro is modified to support rounding of the
intermediate double-precision result to single-precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:35 +01:00
Tom Musta
2c0c52ae62 target-ppc: VSX Stage 4: Add xsresp
This patch adds the VSX Scalar Reciprocal Estimate Single Precision
(xsresp) instruction.

The existing VSX_RE macro is modified to support rounding of the
intermediate double precision result to single precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:35 +01:00
Tom Musta
b24d0b472b target-ppc: VSX Stage 4: Add xsdivsp
This patch adds the VSX Scalar Divide Single Precision (xsdivsp)
instruction.

The existing VSX_DIV macro is modified to support rounding of the
intermediate double precision result to single precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:35 +01:00
Tom Musta
ab9408a2d1 target-ppc: VSX Stage 4: Add xsmulsp
This patch adds the VSX Scalar Multiply Single-Precision (xsmulsp)
instruction.

The existing VSX_MUL macro is modified to support rounding of the
intermediate result to single precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:34 +01:00
Tom Musta
3fd0aadfc1 target-ppc: VSX Stage 4: Add xsaddsp and xssubsp
This patch adds the VSX Scalar Add Single-Precision (xsaddsp) and
VSX Scalar Subtract Single-Precision (xssubsp) instructions.

The existing VSX_ADD_SUB macro is modified to support the rounding
of the (intermediate) result to single-precision.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:34 +01:00
Tom Musta
e16a626b82 target-ppc: VSX Stage 4: Add stxsiwx and stxsspx
This patch adds two store scalar instructions:

  - Store VSX Scalar as Integer Word Indexed (stxsiwx)
  - Store VSX Scalar Single-Precision Indexed (stxsspx)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:34 +01:00
Tom Musta
f026da7830 target-ppc: VSX Stage 4: Refactor stxsdx
This patch refactors the stxsdx instruction.  Reusable code is
extracted into a macro which will be used in subsequent patches
in this series.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:33 +01:00
Tom Musta
cac7f0ba4a target-ppc: VSX Stage 4: Add lxsiwax, lxsiwzx and lxsspx
This patch adds the scalar load instructions introduced in ISA
V2.07:

  - Load VSX Scalar as Integer Word Algebraic Indexd (lxsiwax)
  - Load VSX Scalar as Integer Word and Zero Indexed (lxsiwzx)
  - Load VSX Scalar Single-Precision Indexed (lxsspx)

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:33 +01:00
Tom Musta
e072fe796e target-ppc: VSX Stage 4: Refactor lxsdx
This patch refactors the lxsdx generator. Resuable code is isolated
into a macro.  The macro will be used in subsequent patches in this
series to implement other scalar load instructions.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:33 +01:00
Tom Musta
dbcc48fa8f target-ppc: VSX Stage 4: Add VSX 2.07 Flag
This patch adds a flag to identify those VSX instructions that are
new to Power ISA V2.07.  The flag is added to the Power 8 processor
initialization so that the P8 models understand how to decode and
emulate instructions in this category.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:32 +01:00
Tom Musta
88e33d08c9 target-ppc: Add VSX Rounding Instructions
This patch adds the VSX Round to Floating Point Integer instructions:

  - xsrdpi, xsrdpic, xsrdpim, xsrdpip, xsrdpiz
  - xvrdpi, xvrdpic, xvrdpim, xvrdpip, xvrdpiz
  - xvrspi, xvrspic, xvrspim, xvrspip, xvrspiz

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:32 +01:00
Tom Musta
5177d2ca93 target-ppc: Add VSX ISA2.06 Integer Conversion Instructions
This patch adds the VSX Integer Conversion instructions defined by
V2.06 of the PowerPC ISA:

  - xscvdpsxds, xscvdpsxws, xscvdpuxds, xscvdpuxws
  - xvcvdpsxds, xvcvdpsxws, xvcvdpuxds, xvcvdpuxws
  - xvcvspsxds, xvcvspsxws, xvcvspuxds, xvcvspuxws
  - xscvsxddp, xscvuxddp
  - xvcvsxddp, xscvsxwdp, xvcvuxddp, xvcvuxwdp
  - xvcvsxdsp, xscvsxwsp, xvcvuxdsp, xvcvuxwsp

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:32 +01:00
Tom Musta
ed8ac5686a target-ppc: Add VSX Floating Point to Floating Point Conversion Instructions
This patch adds the VSX instructions that convert between floating
point formats: xscvdpsp, xscvspdp, xvcvdpsp, xvcvspdp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:31 +01:00
Tom Musta
354a6decf1 target-ppc: Add VSX Vector Compare Instructions
This patch adds the VSX floating point compare vector instructions:

  - xvcmpeqdp[.], xvcmpgedp[.], xvcmpgtdp[.]
  - xvcmpeqsp[.], xvcmpgesp[.], xvcmpgtsp[.]

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:31 +01:00
Tom Musta
959e9c9d1e target-ppc: Add VSX xmax/xmin Instructions
This patch adds the VSX floating point maximum and minimum
instructions:

  - xsmaxdp, xvmaxdp, xvmaxsp
  - xsmindp, xvmindp, xvminsp

Because of the Power ISA definitions of maximum and minimum
on various boundary cases, the standard softfloat comparison
routines (e.g. float64_lt) do not work as well as one might
think.  Therefore specific routines for comparing 64 and 32
bit floating point numbers are implemented in the PowerPC
helper code.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:31 +01:00
Tom Musta
4f17e9c738 target-ppc: Add VSX xscmp*dp Instructions
This patch adds the VSX scalar floating point compare ordered
and unordered instructions.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:30 +01:00
Tom Musta
595c6eefb7 target-ppc: Add VSX ISA2.06 Multiply Add Instructions
This patch adds the VSX floating point multiply/add instructions
defined by V2.06 of the PowerPC ISA:

  - xsmaddadp,  xvmaddadp,  xvmaddasp
  - xsmaddmdp,  xvmaddmdp,  xvmaddmsp
  - xsmsubadp,  xvmsubadp,  xvmsubasp
  - xsmsubmdp,  xvmsubmdp,  xvmsubmsp
  - xsnmaddadp, xvnmaddadp, xvnmaddasp
  - xsnmaddmdp, xvnmaddmdp, xvnmaddmsp
  - xsnmsubadp, xvnmsubadp, xvnmsubasp
  - xsnmsubmdp, xvnmsubmdp, xvnmsubmsp

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:30 +01:00
Tom Musta
5cb151acb1 target-ppc: Add VSX ISA2.06 xtsqrt Instructions
This patch adds the VSX floating point test for software square
root instructions defined by V2.06 of the PowerPC ISA: xstsqrtdp,
xvtsqrtdp, xvtsqrtsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:30 +01:00
Tom Musta
bc80838f86 target-ppc: Add VSX ISA2.06 xtdiv Instructions
This patch adds the VSX floating point test for software divide
instructions defined by V2.06 of the PowerPC ISA: xstdivdp, xvtdivdp,
and xvtdivsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:29 +01:00
Tom Musta
d3f9df8fb8 target-ppc: Add VSX ISA2.06 xrsqrte Instructions
This patch adds the VSX floating point reciprocal square root
estimate instructions defined by V2.06 of the PowerPC ISA: xsrsqrtedp,
xvrsqrtedp, xvrsqrtesp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:29 +01:00
Tom Musta
d32404fe42 target-ppc: Add VSX ISA2.06 xsqrt Instructions
This patch adds the VSX floating point square root instructions
defined by V2.06 of the PowerPC ISA: xssqrtdp, xvsqrtdp, xvsqrtsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:29 +01:00
Tom Musta
2009227fbe target-ppc: Add VSX ISA2.06 xre Instructions
This patch adds the VSX floating point reciprocal estimate instructions
defined by V2.06 of the PowerPC ISA: xsredp, xvredp, xvresp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:29 +01:00
Tom Musta
4b98eeef50 target-ppc: Add VSX ISA2.06 xdiv Instructions
This patch adds the VSX floating point divide instructions defined
by V2.06 of the PowerPC ISA: xsdivdp, xvdivdp, xvdivsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:28 +01:00
Tom Musta
5e591d8812 target-ppc: Add VSX ISA2.06 xmul Instructions
This patch adds the VSX floating point multiply instructions defined
by V2.06 of the PowerPC ISA: xsmuldp, xvmuldp, xvmulsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:28 +01:00
Tom Musta
ee6e02c0ac target-ppc: Add VSX ISA2.06 xadd/xsub Instructions
This patch adds the floating point addition and subtraction
instructions defined by V2.06 of the PowerPC ISA: xssubdp,
xvsubdp and xvsubsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:28 +01:00
Tom Musta
3c3cbbdc84 target-ppc: General Support for VSX Helpers
This patch adds general support that will be used by the VSX helper
routines:

  - a union describing the various VSR subfields.
  - access routines to get and set VSRs
  - VSX decoders
  - a general routine to generate a handler that invokes a VSX
    helper.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:27 +01:00
Tom Musta
59800ec8e5 target-ppc: Add set_fprf Argument to fload_invalid_op_excp()
The fload_invalid_op_excp() function sets assorted invalid
operation status bits.  However, it also implicitly modifies
the FPRF field of the PowerPC FPSCR.  Many VSX instructions
set invalid operation bits but do not alter FPRF.  Thus the
function is more generally useful if the setting of the FPRF
field is made conditional via a parameter.

All invocations of this routine in existing instructions are
modified to pass 1 and thus retain their current behavior.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:27 +01:00
Alexey Kardashevskiy
4e38181979 target-ppc: disable unsupported modes for SPR_CTRL/SPR_UCTRL
The Figure 17 "SPR encodings" of the PowerISA 2.07 describes CTRL SPR as:

                       priviledged
#   spr5-9 spr0-4 name mtspr mfspr len cat
136 00100  01000  CTRL   -    no    32  S
152 00100  11000  CTRL  yes    -    32  S

According to this chart, the hypervisor's CTRL (#152) does not support
reading, the user-space's CTRL (UCTRL, #136) does not support writing.

This replaces unsupported operations with the default SPR_NOACCESS hook.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:27 +01:00
Nathan Whitehorn
3052f0d594 spapr_vscsi: Fix REPORT_LUNS handling
Intercept REPORT_LUNS commands addressed either to SRP LUN 0 or the well-known
LUN for REPORT_LUNS commands. This is required to implement the SAM and SPC
specifications.

Since SRP implements only a single SCSI target port per connection, the SRP
target is required to report all available LUNs in response to a REPORT_LUNS
command addressed either to LUN 0 or the well-known LUN. Instead, QEMU was
forwarding such requests to the first QEMU SCSI target, with the result that
initiators that relied on this feature would only see LUNs on the first QEMU
SCSI target.

Behavior for REPORT_LUNS commands addressed to any other LUN is not specified
by the standard and so is left unchanged. This preserves behavior under Linux
and SLOF, which enumerate possible LUNs by hand and so address no commands
either to LUN 0 or the well-known REPORT_LUNS LUN.

Signed-off-by: Nathan Whitehorn <nwhitehorn@freebsd.org>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
[agraf: define constant as ULL for 32bit hosts]
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:26 +01:00
Alexey Kardashevskiy
09aa9a526a spapr-pci: enable adding PHB via -device
Recent changes introduced cannot_instantiate_with_device_add_yet
and removed capability of adding yet another PCI host bridge via
command line for SPAPR platform (POWERPC64 server).

This brings the capability back and puts SPAPR PHB into "bridge"
category.

This is not much use for emulated PHB but it is absolutely required
for VFIO as we put an IOMMU group onto a separate PHB on SPAPR.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:26 +01:00
Greg Kurz
6cd8712c5f PPC: KVM: add support for LPCR
The LPCR special purpose register was introduced with the PowerPC 970MP family.

This patch initializes LPCR for the following families:
- 970 MP
- POWER5+
- POWER7
- POWER8

Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:26 +01:00
Alexey Kardashevskiy
7a7c05d77d PPC: KVM: fix "set one register"
Due to missing @one_reg_id assignment in _spr_register(),
the kvm_get_one_reg/kvm_set_one_reg API has never really been working.

This reenables the API by assigning the @one_reg_id field in the SPR
descriptor.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:25 +01:00
Cédric Le Goater
363248e8c9 mmu-hash64: fix Virtual Page Class Key Protection
commit f80872e21c (mmu-hash64: Implement
Virtual Page Class Key Protection) added a new page protection
mechanism based on page keys and the AMR register to control access.

The AMR register allows or prohibits reads and/or writes on a page
depending on the control bits associated to the key. A store or a load
is only permitted if the associate bit is 0 (Power ISA), and not 1 as
the code is currently doing. This patch modifies ppc_hash64_amr_prot()
to correct the protection check.

This issue was unvailed by commit ccfb53ed6360cac0d5f6f7915ca9ae7eed866412
(target-ppc: fix Authority Mask Register init value) which changed the
initialisation value of the AMR register to 0.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:25 +01:00
Alexey Kardashevskiy
0dc083fe10 target-ppc: fix Authority Mask Register init value
The existing default value (-1) of the AMR register forbids data access
to all 32 classes. Since the guest linux does not change this register,
we end up with the guest hanging right after switching from the real to
protected mode.

This sets the default AMR value to zero what enables data access for all
classes.

The only reason for not hitting this bug before is that
kvm_arch_put_registers() did not put any SPR to KVM due to missing
assignment of @one_reg_id in _spr_register() (which is going to be fixed
by a separate patch).

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:25 +01:00
Anton Blanchard
ca480de664 target-ppc: dump DAR and DSISR
The DAR and DSISR can be very useful when debugging issues, so add
them to ppc_cpu_dump_state. We had another bug in this area: all
of the v2.06 MMU types were missing.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:24 +01:00
Aneesh Kumar K.V
135a129a1c kvm: Add a new machine option kvm-type
Targets like ppc64 support different types of KVM, one which use
hypervisor mode and the other which doesn't. Add a new machine
option kvm-type that helps in selecting the respective ones
We also add a new QEMUMachine callback get_vm_type that helps
in mapping the string representation of kvm type specified.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[agraf: spelling fixes, use error_report(), use qemumachine.h]
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:24 +01:00
Alexander Graf
9c06a1f79f KVM: Split QEMUMachine typedef into separate header
Older gcc versions (such as the one in SLES11) get confused when you declare
a typedef on the same struct twice.

To work around that limitation, let's extract the QEMUMachine typedef into a
separate header file that is guarded by preprocessor duplicate include checks.

This fixes the following type of compile errors for me:

  In file included from vl.c:125:
  include/hw/xen/xen.h:39: error: redefinition of typedef "QEMUMachine"
  include/sysemu/kvm.h:155: error: previous declaration of "QEMUMachine" was here

Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:24 +01:00
Alexey Kardashevskiy
88ccd23a0c target-ppc: remove unsupported SPRs from 970 and P5+
SPR_750FX_HID2 and L2CR are not defined in 970* user manuals nor POWER5
bookIV nor PowerISA 2.04, the numbers assigned to them are not defined
either so remove them.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:23 +01:00
Alexey Kardashevskiy
401949176c target-ppc: remove embedded MMU SPRs from 970, P5+/7/7+/8
PowerISA 2.04+ puts MMUCFG and MMUCSR0 SPRs to "E" (embedded) category so
remove it from POWER7/8 class as it is "S" (server) category.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:23 +01:00
Alexey Kardashevskiy
0bfe9299da target-ppc: fix SPR_CTRL/SPR_UCTRL register numbers
Assuming that "U" in SPR_UCTRL is for "user", there is inconsistency with
970 user manuals/P5-bookIV/PowerISA204 which define the number as:

                       priviledged
#   spr5-9 spr0-4 name mtspr mfspr len cat
136 00100  01000  CTRL   -    no    32  S
152 00100  11000  CTRL  yes    -    32  S

This swaps the numbers. No effect from this change is expected though.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:23 +01:00
Alexey Kardashevskiy
81d2fb4dfd target-ppc: remove powerpc 970gx
The 970GX definition was added in 2007 and it made sense then but this
version has never been released to the markets and it does not exist in
the real world so there is no point in emulating it.

This removes 970GX.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:23 +01:00
Alexey Kardashevskiy
6475c9f05c target-ppc: fix LPCR SPR number
PowerISA defines LPCR SPR number as 318=0x13E but QEMU uses the value of
316.

This fixes the definition of LPCR SPR.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:22 +01:00
Alexey Kardashevskiy
a5100e752b target-ppc: fix compile error when PPC_DUMP_CPU is enabled
Since last use of PPC_DUMP_CPU by whoever he/she was, env->tlb became
a union and POWERPC CPU class got QOM'ed so defining PPC_DUMP_CPU
breaks compile.

This fixes compiler errors.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-03-05 03:06:22 +01:00
Andreas Färber
f55ea6297c block/gluster: Add missing argument to qemu_gluster_init() call
Commit adccfbcd60 (block: gluster - add
reopen support.) did not supply the qemu_gluster_init() Error **
argument, needed since commit a7451cb850
(gluster: correctly propagate errors).

Pass through qemu_gluster_reopen_prepare()'s errp, as done in
qemu_gluster_open().

Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 20:20:57 +00:00
Peter Maydell
ac458e121c Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-2014-03-04' into staging
trivial patches for 2014-03-04

# gpg: Signature made Tue 04 Mar 2014 06:13:56 GMT using RSA key ID 74F0C838
# gpg: Good signature from "Michael Tokarev <mjt@tls.msk.ru>"
# gpg:                 aka "Michael Tokarev <mjt@corpit.ru>"
# gpg:                 aka "Michael Tokarev <mjt@debian.org>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6EE1 95D1 886E 8FFB 810D  4324 457C E0A0 8044 65C5
#      Subkey fingerprint: E190 8639 3B10 B51B AC2C  8B73 5253 C5AD 74F0 C838

* remotes/mjt/tags/trivial-patches-2014-03-04:
  vl: Remove unneeded include file
  qga: Remove unneeded include file
  qemu-img: Remove unneeded include files
  exec: Remove unneeded include files
  util/iov: Use qemu/sockets.h instead of conditional code
  qjson.h: Remove spurious GCC_FMT_ATTR markup from qobject_from_json() declaration
  tests/test-int128: Don't use __noclone__ attribute on clang
  stubs: Optimize dependencies for gdbstub.c
  tcg: Fix typo in comment (dependancies -> dependencies)
  bswap: Modify prototypes of st[wl]_{le, be}_p (avoid type conversions)
  bswap: Modify prototype of stb_p (avoid type conversions)
  object: Report type in error when not user creatable.
  include/qemu/host-utils.h: Trivial typo: ctz->cto

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 18:12:02 +00:00
Peter Maydell
e00ef747f0 Merge remote-tracking branch 'remotes/qmp-unstable/queue/qmp' into staging
* remotes/qmp-unstable/queue/qmp: (32 commits)
  qapi: Add missing null check to opts_start_struct()
  qapi: Clean up superfluous null check in qapi_dealloc_type_str()
  qapi: Clean up null checking in generated visitors
  qapi: Drop unused code in qapi-commands.py
  qapi: Drop nonsensical header guard in generated qapi-visit.c
  qapi: Fix licensing of scripts
  tests/qapi-schema: Cover flat union types
  tests/qapi-schema: Cover union types with base
  tests/qapi-schema: Cover complex types with base
  tests/qapi-schema: Cover anonymous union types
  tests/qapi-schema: Cover simple argument types
  tests/qapi-schema: Cover optional command arguments
  tests/qapi-schema: Actually check successful QMP command response
  monitor: Remove left-over code in do_info_profile.
  qerror: Improve QERR_DEVICE_NOT_ACTIVE message
  qmp: Check for returned data from __json_read in get_events
  dump: add 'query-dump-guest-memory-capability' command
  Define the architecture for compressed dump format
  dump: make kdump-compressed format available for 'dump-guest-memory'
  dump: add API to write dump pages
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 17:01:07 +00:00
Peter Maydell
4a29420ea1 Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request

# gpg: Signature made Fri 28 Feb 2014 18:27:24 GMT using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/block-pull-request:
  block/vmdk: do not report file offset for compressed extents
  discard rbd error output when not relevant in qemu-iotests
  block: use /var/tmp instead of /tmp for -snapshot
  qemu-io-test: Disable Quorum test when not compiled in.
  qmp: Make Quorum error events more palatable.
  qmp: Fix BlockdevOptionQuorum.
  block: gluster - add reopen support.
  block: gluster - code movements, state storage changes
  qemu-iotests: add more tests to the "quick" group

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 16:33:25 +00:00
Peter Maydell
4fd42afe61 Merge remote-tracking branch 'remotes/rth/i386-fix' into staging
* remotes/rth/i386-fix:
  target-i386: Fix ucomis and comis memory access
  target-i386: Fix SSE status flag corruption
  target-i386: Fix CC_OP_CLR vs PF

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 15:53:01 +00:00
Peter Maydell
c2cb92f9ea Merge remote-tracking branch 'remotes/borntraeger/tags/kvm-s390-20140227' into staging
Several features, fixes and cleanups for kvm/s390:

- sclp event facility: cleanup structure. This allows to use
  realize/unrealize   as well as migration support via vmsd
- reboot: Two fixes that make reboot much more reliable
- ipl: make elf loading more robust
- flic interrupt controller: This allows to migrate floating
  interrupts, as well as clear them on reset etc.
- enable async_pf feature of KVM on s390
- several sclp fixes and cleanups
- several sigp fixes and cleanups

* remotes/borntraeger/tags/kvm-s390-20140227: (22 commits)
  s390x/ipl: Fix crash of ELF images with arbitrary entry points
  s390x/kvm: Rework priv instruction handlers
  s390x/kvm: Add missing SIGP CPU RESET order
  s390x/kvm: Rework SIGP INITIAL CPU RESET handler
  s390x/cpu: Use ioctl to reset state in the kernel
  s390-ccw.img: new binary rom to match latest fixes
  s390-ccw.img: Fix sporadic errors with ccw boot image - initialize css
  s390-ccw.img: Fix sporadic reboot hangs: Initialize next_idx
  s390x/event-facility: exploit realize/unrealize
  s390x/event-facility: add support for live migration
  s390x/event-facility: code restructure
  s390x/event-facility: some renaming
  s390x/sclp: Fixed setting of condition code register
  s390x/sclp: Add missing checks to SCLP handler
  s390x/sclp: Fixed the size of sccb and code parameter
  s390x/eventfacility: mask out commands
  s390x/virtio-hcall: Specification exception for illegal subcodes
  s390x/virtio-hcall: Add range check for hypervisor call
  s390x/kvm: Fixed bad SIGP SET-ARCHITECTURE handler
  s390x/async_pf: Check for apf extension and enable pfault
  ...

Conflicts:
	linux-headers/linux/kvm.h

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 14:50:46 +00:00
Peter Maydell
739aa555b8 Merge remote-tracking branch 'remotes/bonzini/scsi-next' into staging
* remotes/bonzini/scsi-next:
  block/iscsi: fix segfault if writesame fails
  scsi-disk: Add support for port WWN and index descriptors in VPD page 83h
  block/iscsi: query for supported VPD pages
  block/iscsi: fix deadlock on scsi check condition
  scsi-bus: Fix transfer length for VERIFY with BYTCHK=11b
  scsi: report thin provisioning errors with werror=report
  scsi: Change scsi sense buf size to 252

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 14:25:34 +00:00
Peter Maydell
d47e95c0c8 Merge remote-tracking branch 'remotes/mcayland/qemu-sparc' into staging
* remotes/mcayland/qemu-sparc:
  sun4m: Add Sun CG3 framebuffer initialisation function
  sun4m: Add Sun CG3 framebuffer and corresponding OpenBIOS FCode ROM
  sun4m: fix slavio timer RUN/STOP bit
  sun4m: Set HostID in NVRAM

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 13:09:06 +00:00
Stefan Weil
57f45b6207 Makefile: Add missing dependency for system emulation (fix build)
Comment from Makefile.objs:

The system emulation needs this dependency (which was missing in Makefile),
otherwise builds without tools (or massive parallel builds) fail.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-04 13:02:23 +00:00
Aneesh Kumar K.V
993c91a0e9 hw/9pfs: Include virtio-9p-device.o in build
After commit ba1183da9a we are including
hw/Makefile.objs directly from Makefile.target. Make sure hw/Makefile.objs
rules doesn't depend on variable defined in Makefile.objs

Tested-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
2014-03-04 09:20:49 +05:30
Chen Gang
4fa4ce7107 hw/9pfs: use g_strdup_printf() instead of PATH_MAX limitation
When path is truncated by PATH_MAX limitation, it causes QEMU to access
incorrect file. So use original full path instead of PATH_MAX within
9pfs (need check/process ENOMEM for related memory allocation).

The related test:

 - Environments (for qemu-devel):

   - Host is under fedora17 desktop with ext4fs:

     qemu-system-x86_64 -hda test.img -m 1024 \
       -net nic,vlan=4,model=virtio,macaddr=00:16:35:AF:94:04 \
       -net tap,vlan=4,ifname=tap4,script=no,downscript=no \
       -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
       -fsdev local,security_model=passthrough,id=fsdev0,\
         path=/upstream/vm/data/share/1234567890abcdefghijklmnopqrstuvwxyz\
           ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmnopqrstuvwxyz\
           ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111111111\
           1111111111111111111111111111111111111111111111111111222222222222\
           2222222222222222222222222222222222222222222222222222222222222222\
           2222222222222222222222222222222222233333333333333333333333333333\
           3333333333333333333333333333333333

    - Guest is ubuntu12 server with 9pfs.

      mount -t 9p -o trans=virtio,version=9p2000.L hostshare /share

    - Limitations:

      full path limitation is PATH_MAX (4096B include nul) under Linux.
      file/dir node name maximized length is 256 (include nul) under ext4.

 - Special test:

    Under host, modify the file: "/upstream/vm/data/share/1234567890abcdefg\
      hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmno\
      pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111\
      111111111111111111111111111111111111111111111111111111111122222222222\
      222222222222222222222222222222222222222222222222222222222222222222222\
      222222222222222222222222222222233333333333333333333333333333333333333\
      3333333333333333333333333/4444444444444444444444444444444444444444444\
      444444444444444444444444444444444444444444444444444444444444444444444\
      444444444444444444444444444444444444444444444444444444444444444444444\
      444444444444444444444444444444444444444/55555555555555555555555555555\
      555555555555555555555555555555555555555555555555555555555555555555555\
      555555555555555555555555555555555555555555555555555555555555555555555\
      555555555555555555555555555555555555555555555555555555555555555555555\
      55555555/666666666666666666666666666666666666666666666666666666666666\
      666666666666666666666666666666666666666666666666666666666666666666666\
      666666666666666666666666666666666666666666666666666666666666666666666\
      666666666666666666666/77777777777777777777777777777777777777777777777\
      777777777777777777777777777777777777777777777777777777777777777777777\
      777777777777777777777777777777777777777777777777777777777777777777777\
      77777777777777777777777777777777777777777777777777777777777/888888888\
      888888888888888888888888888888888888888888888888888888888888888888888\
      888888888888888888888888888888888888888888888888888888888888888888888\
      888888888888888888888888888888888888888888888888888888888888888888888\
      888888888/99999999999999999999999999999999999999999999999999999999999\
      999999999999999999999999999999999999999999999999999999999999999999999\
      999999999999999999999999999999999999999999999999999999999999999999999\
      99999999999999999999999999999999999999999/000000000000000000000000000\
      000000000000000000000000000000000000000000000000000000000000000000000\
      000000000000000000000000000000000000000000000000000000000000000000000\
      000000000000000000000000000000000000000000000000/aaaaaaaaaaaaaaaaaaaa\
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbb\
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccc\
      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
      ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
      cccccccccc/dddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
      dddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
      eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
      eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
      eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/fffffffffffffff\
      fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
      fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
      ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/gggggggggg\
      ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
      ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
      ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
      ggggggggggggggggggggggg/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
      iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
      iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
      iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj\
      jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\
      jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj/ppppppppppppppppppppp\
      ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\
      ppppppppppppppppppppppppppppppppppppppp/test1234567890file.log"
        (need enter dir firstly, then modify file, or can not open it).

   Under guest, still allow modify "test1234567890file.log" (will generate
   "test123456" file with contents).

   After apply this patch, can not open "test1234567890file.log" under guest
   (permission denied).

 - Common test:

   All are still OK after apply this path.

     "mkdir -p", "create/open file/dir", "modify file/dir", "rm file/dir".
     change various mount point paths under host and/or guest.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
2014-03-04 00:57:57 +05:30
Chen Gang
fae0864573 hw/9pfs/virtio-9p-local.c: use snprintf() instead of sprintf()
'ctx->fs_root' + 'path'/'fullname.data' may be larger than PATH_MAX, so
need use snprintf() instead of sprintf() just like another area have done
in 9pfs. This could possibly result in the truncation of pathname, which we
address in the follow up patch.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
2014-03-03 21:56:31 +05:30
Chen Gang
75b7931ec6 hw/9pfs/virtio-9p-local.c: move v9fs_string_free() to below "err_out:"
When "goto err_out", 'v9fs_string' already was allocated, so still need
free 'v9fs_string' before return.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
2014-03-03 21:55:01 +05:30
Markus Armbruster
b774539743 qapi: Add missing null check to opts_start_struct()
Argument is null when visiting an unboxed struct.  I can't see such a
visit in the current code.  Fix it anyway.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:17:45 -05:00
Markus Armbruster
25a7017555 qapi: Clean up superfluous null check in qapi_dealloc_type_str()
Argument can't be null.  No other Visitor method type_str() checks for
null.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:17:45 -05:00
Markus Armbruster
949ceeb31b qapi: Clean up null checking in generated visitors
Visitors get passed a pointer to the visited object.  The generated
visitors try to cope with this pointer being null in some places, for
instance like this:

    visit_start_optional(m, obj ? &(*obj)->has_name : NULL, "name", &err);

visit_start_optional() passes its second argument to Visitor method
start_optional.  Three out of three methods dereference it
unconditionally.

I fail to see how this pointer could legitimately be null.

All this useless null checking is highly redundant, which Coverity
duly reports.  About 200 times.

Remove the useless null checks.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:17:20 -05:00
Markus Armbruster
56bed4135f qapi: Drop unused code in qapi-commands.py
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:46 -05:00
Markus Armbruster
a105acbce3 qapi: Drop nonsensical header guard in generated qapi-visit.c
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
678e48a2e4 qapi: Fix licensing of scripts
The scripts carry this copyright notice:

    # This work is licensed under the terms of the GNU GPLv2.
    # See the COPYING.LIB file in the top-level directory.

The sentences contradict each other, as COPYING.LIB contains the LGPL
2.1.  Michael Roth says this was a simple pasto, and he meant to refer
COPYING.  Let's fix that.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
2fc0043283 tests/qapi-schema: Cover flat union types
The test demonstrates a generator bug: the generated struct
UserDefFlatUnion doesn't include members for the indirect base
UserDefZero.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
7ad993b480 tests/qapi-schema: Cover union types with base
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
aabbd472a0 tests/qapi-schema: Cover complex types with base
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
2c38b60010 tests/qapi-schema: Cover anonymous union types
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
c2216a8a7a tests/qapi-schema: Cover simple argument types
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
ab22ad96ce tests/qapi-schema: Cover optional command arguments
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Markus Armbruster
357765fed5 tests/qapi-schema: Actually check successful QMP command response
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-03-03 11:16:45 -05:00
Stefan Weil
25254a7191 vl: Remove unneeded include file
This file does not depend on windows.h.

Cc: Anthony Liguori <aliguori@amazon.com>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-03 09:46:27 +04:00
Stefan Weil
cae8a9289b qga: Remove unneeded include file
This file does not depend on windows.h.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-03 09:46:27 +04:00
Stefan Weil
67d065c3db qemu-img: Remove unneeded include files
There is no dependency on windows.h, and the standard include files are
already included by qemu-common.h.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-03 09:46:27 +04:00
Stefan Weil
777872e5c6 exec: Remove unneeded include files
This file does not depend on windows.h.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-03 09:46:27 +04:00
Stefan Weil
cc99c6f5ff util/iov: Use qemu/sockets.h instead of conditional code
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-03 09:46:27 +04:00
Peter Maydell
aa830cdc28 qjson.h: Remove spurious GCC_FMT_ATTR markup from qobject_from_json() declaration
The function qobject_from_json() doesn't actually allow its
argument to be a format string -- it passes a NULL va_list*
to qobject_from_jsonv(), and the parser code will then never
actually interpret %-escape sequences (it tests whether the
va_list pointer is NULL and will stop with a parse error).

The spurious attribute markup causes clang warnings in some
of the test cases where we programmatically construct JSON
to feed to qobject_from_json():

 tests/test-qmp-input-visitor.c:76:35: warning: format string is not a
 string literal (potentially insecure) [-Wformat-security]
    data->obj = qobject_from_json(json_string);
                                  ^~~~~~~~~~~

Remove the incorrect attribute.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-03 09:45:46 +04:00
Peter Maydell
7edd9ddc97 tests/test-int128: Don't use __noclone__ attribute on clang
clang doesn't support the __noclone__ attribute and emits a warning about
it. Fortunately clang also implements a mechanism for asking if a particular
attribute is implemented; use it. We assume that if the compiler doesn't
support __has_attribute() then it must be GCC and must support __noclone__.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:20:37 +04:00
Stefan Weil
8ead601883 stubs: Optimize dependencies for gdbstub.c
It does not need qemu-common.h. Including exec/gdbstub.h fixes a warning
from static code analyzers and avoids mismatching declarations for
xml_builtin.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:13:31 +04:00
Stefan Weil
c5d3c49896 tcg: Fix typo in comment (dependancies -> dependencies)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:12:51 +04:00
Stefan Weil
55e7c29e46 bswap: Modify prototypes of st[wl]_{le, be}_p (avoid type conversions)
The functions use uint16_t or uint32_t values, so show this in the function
prototypes. Non-optimizing compilers will avoid unnecessary type
conversions when generating calls of these inline functions.

stq_le_p, stq_be_p already use similar prototypes.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:12:41 +04:00
Stefan Weil
0064aceb29 bswap: Modify prototype of stb_p (avoid type conversions)
The function uses an uint8_t value, so show this in the function
prototype. Non-optimizing compilers will avoid unnecessary type
conversions from (u)int8_t to int and back to uint8_t when generating
calls of this inline function.

stw_p, stl_p and stq_p already use similar prototypes.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:12:41 +04:00
Hani Benhabiles
de580dafad object: Report type in error when not user creatable.
Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Hu Tao <hutao@cn.fujitsu.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:12:41 +04:00
Dr. David Alan Gilbert
1c884abede include/qemu/host-utils.h: Trivial typo: ctz->cto
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-03-02 17:12:41 +04:00
Hani Benhabiles
de92f3f86a monitor: Remove left-over code in do_info_profile.
This is a left-over from 4a1418e.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 13:49:42 -05:00
Hani Benhabiles
ffe9fe3a25 qerror: Improve QERR_DEVICE_NOT_ACTIVE message
The error message as currently used is confusing as there are no "balloon" or
"spice" devices.

(qemu) balloon 1024
balloon: Device 'balloon' has not been activated

With this patch:

(qemu) balloon 1024
balloon: No balloon device has been activated

Signed-off-by: Hani Benhabiles <hani@linux.com>
Suggested-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 13:39:25 -05:00
Fam Zheng
4864512389 qmp: Check for returned data from __json_read in get_events
When QEMU process aborts and socket is closed, qmp client will not
detect it. When this happens, some qemu-iotests scripts will enter an
endless loop waiting for qmp events.

It's better we raise an exception in qmp.py to catch this and make the
test script stop.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 13:35:53 -05:00
Peter Lieven
3eba13ec25 block/vmdk: do not report file offset for compressed extents
Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:07 +01:00
Loic Dachary
9147d019f3 discard rbd error output when not relevant in qemu-iotests
Suppress rbd progress messages with --no-progress so they are not
confused with an error output when comparing test results ( progress is
displayed on stderr ).

Signed-off-by: Loic Dachary <loic@dachary.org>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:07 +01:00
Amit Shah
69bef7931e block: use /var/tmp instead of /tmp for -snapshot
If TMPDIR is not specified, the default was to use /tmp for the working
copy of the block devices.  Update this to /var/tmp instead, so systems
using tmp-on-tmpfs don't end up inadvertently using RAM for the block
device.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:07 +01:00
Benoît Canet
4b350f1de1 qemu-io-test: Disable Quorum test when not compiled in.
Quorum is not compiled by default: make the quorum 081 test aware of this.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:07 +01:00
Benoît Canet
0c762736df qmp: Make Quorum error events more palatable.
Insert quorum QMP events documentation alphabetically.

Also change the "ret" errno value by an optional "error" being an strerror(-ret)
in the QUORUM_REPORT_BAD qmp event.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:06 +01:00
Benoît Canet
a9e6a0cbe2 qmp: Fix BlockdevOptionQuorum.
Fix some nits before QEMU 2.0 freeze.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:06 +01:00
Jeff Cody
adccfbcd60 block: gluster - add reopen support.
Gluster does parse open flags in its .bdrv_open() implementation,
and the .bdrv_reopen_* implementations need to do the same.

A new gluster connection to the image file to be created is established
in the .bdrv_reopen_prepare(), and the image file opened with the new
flags.

If this is successful, then the old image file is closed, and the
old connection torn down. The relevant structure pointers in the gluster
state structure are updated to the new connection.

If it is not successful, then the new file handle and connection is
abandoned (if it exists), while the old connection is not modified at
all.

With reopen supported, block-commit (and offline commit) is now also
supported for image files whose base image uses the native gluster
protocol driver.

Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:06 +01:00
Jeff Cody
1b37b3442f block: gluster - code movements, state storage changes
In preparation for supporting reopen on gluster, move flag
parsing out to a function.  Also, add a NULL check in the
gconf cleanup.

Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:06 +01:00
Paolo Bonzini
9a05feabd5 qemu-iotests: add more tests to the "quick" group
None of these needs QEMU_PROG, and they all take but a few seconds.
We need to point the launching script to qemu-nbd, though.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-28 18:59:06 +01:00
qiaonuohan
7d6dc7f30c dump: add 'query-dump-guest-memory-capability' command
'query-dump-guest-memory-capability' is used to query the available formats for
'dump-guest-memory'. The output of the command will be like:

-> { "execute": "query-dump-guest-memory-capability" }
<- { "return": { "formats":
                    ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] }

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
4ab23a9182 Define the architecture for compressed dump format
Signed-off-by: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
b53ccc30c4 dump: make kdump-compressed format available for 'dump-guest-memory'
Make monitor command 'dump-guest-memory' be able to dump in kdump-compressed
format. The command's usage:

  dump [-p] protocol [begin] [length] [format]

'format' is used to specified the format of vmcore and can be:
1. 'elf': ELF format, without compression
2. 'kdump-zlib': kdump-compressed format, with zlib-compressed
3. 'kdump-lzo': kdump-compressed format, with lzo-compressed
4. 'kdump-snappy': kdump-compressed format, with snappy-compressed
Without 'format' being set, it is same as 'elf'. And if non-elf format is
specified, paging and filter is not allowed.

Note:
  1. The kdump-compressed format is readable only with the crash utility and
     makedumpfile, and it can be smaller than the ELF format because of the
     compression support.
  2. The kdump-compressed format is the 6th edition.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
d12f57ec66 dump: add API to write dump pages
functions are used to write page to vmcore. vmcore is written page by page.
page desc is used to store the information of a page, including a page's size,
offset, compression format, etc.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
64cfba6a47 dump: add APIs to operate DataCache
DataCache is used to store data temporarily, then the data will be written to
vmcore. These functions will be called later when writing data of page to
vmcore.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
d0686c7291 dump: add API to write dump_bitmap
functions are used to write 1st and 2nd dump_bitmap of kdump-compressed format,
which is used to indicate whether the corresponded page is existed in vmcore.
1st and 2nd dump_bitmap are same, because dump level is specified to 1 here.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
298f116827 dump: add API to write dump header
the functions are used to write header of kdump-compressed format to vmcore.
Header of kdump-compressed format includes:
1. common header: DiskDumpHeader32 / DiskDumpHeader64
2. sub header: KdumpSubHeader32 / KdumpSubHeader64
3. extra information: only elf notes here

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
7aad248d35 dump: add members to DumpState and init some of them
add some members to DumpState that will be used in writing vmcore in
kdump-compressed format. some of them, like page_size, will be initialized
in the patch.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
607dacd0a0 dump: add support for lzo/snappy
kdump-compressed format supports three compression format, zlib/lzo/snappy.
Currently, only zlib is available. This patch is used to support lzo/snappy.
'--enable-lzo/--enable-snappy' is needed to be specified with configure to make
lzo/snappy available for qemu

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:52:03 -05:00
qiaonuohan
4835ef7784 dump: add API to write elf notes to buffer
the function can be used by write_elf32_notes/write_elf64_notes to write notes
to a buffer. If fd_write_vmcore is used, write_elf32_notes/write_elf64_notes
will write elf notes to vmcore directly. Instead, if buf_write_note is used,
elf notes will be written to opaque->note_buf at first.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:49:02 -05:00
qiaonuohan
5d31babe5c dump: add API to write vmcore
Function is used to write vmcore in flatten format. In flatten format, data is
written block by block, and in front of each block, a struct
MakedumpfileDataHeader is stored there to indicate the offset and size of the
data block.

struct MakedumpfileDataHeader {
    int64_t offset;
    int64_t buf_size;
};

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:49:02 -05:00
qiaonuohan
fda053875e dump: add API to write header of flatten format
flatten format will be used when writing kdump-compressed format. The format is
also used by makedumpfile, you can refer to the following URL to get more
detailed information about flatten format of kdump-compressed format:
http://sourceforge.net/projects/makedumpfile/

The two functions here are used to write start flat header and end flat header
to vmcore, and they will be called later when flatten format is used.

struct MakedumpfileHeader stored at the head of vmcore is used to indicate the
vmcore is in flatten format.

struct MakedumpfileHeader {
    char signature[16];     /* = "makedumpfile" */
    int64_t type;           /* = 1 */
    int64_t version;        /* = 1 */
};

And struct MakedumpfileDataHeader, with offset and buf_size set to -1, is used
to indicate the end of vmcore in flatten format.

struct MakedumpfileDataHeader {
    int64_t offset;         /* = -1 */
    int64_t buf_size;       /* = -1 */
};

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:49:02 -05:00
qiaonuohan
6a519918b3 dump: add argument to write_elfxx_notes
write_elf32_notes/wirte_elf64_notes use fd_write_vmcore to write elf notes to
vmcore. Adding parameter "WriteCoreDumpFunction f" makes it available to choose
the method of writing elf notes

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:49:02 -05:00
qiaonuohan
b5ba1cc626 dump: const-qualify the buf of WriteCoreDumpFunction
WriteCoreDumpFunction is a function pointer that points to the function used to
write content in "buf" into core file, so "buf" should be const-qualify.

Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:49:02 -05:00
Richard Henderson
cb48da7f81 target-i386: Fix ucomis and comis memory access
We were loading 16 bytes for both single and double-precision
scalar comparisons.

Reported-by: Alexander Bluhm <bluhm@openbsd.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-02-28 08:44:26 -08:00
Richard Henderson
4e47e39ab0 target-i386: Fix SSE status flag corruption
When we restore the mxcsr register with FXRSTOR, or set it with gdb,
we need to update the various SSE status flags in CPUX86State

Reported-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-02-28 08:44:01 -08:00
Richard Henderson
d2fe51bda8 target-i386: Fix CC_OP_CLR vs PF
Parity should be set for a zero result.

Cc: qemu-stable@nongnu.org
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-02-28 08:43:15 -08:00
Luiz Capitulino
fbb0621a0f MAINTAINERS: update status for HMP, QAPI and QMP trees
This commit updates the status for the HMP, QAPI and QMP trees from
"Supported" to "Maintained".

In practice this means that patch review and pull requests may take
longer. Also, I'll rely more on reviewers such as Eric Blake so that
I'm able to send pull requests regularly.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:41:43 -05:00
Fam Zheng
cd159d0954 QMP: Allow dot separated dict path arguments in qmp-shell
As another convenience to allow using commands that expect a dict as
argument, this patch adds support for foo.bar=value syntax, similar to
command line argument style:

  (QEMU) blockdev-add options.driver=file options.id=drive1 options.filename=...

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-02-28 11:41:43 -05:00
Fam Zheng
d844a7b656 modules: Fix building with --enable-modules
Compiling util/modules.c with modules enabled fails now.

Fix it by including qemu-common.h before #ifdef testing in module.c.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-id: 1393453893-12125-1-git-send-email-famz@redhat.com
Reviewed-by: Hu Tao <hutao@cn.fujitsu.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-28 12:30:13 +00:00
Peter Maydell
9fbee91a13 Merge remote-tracking branch 'remotes/kvm/uq/master' into staging
* remotes/kvm/uq/master:
  KVM: Use return value for error print

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-27 16:00:31 +00:00
Peter Maydell
73795cea96 Merge remote-tracking branch 'remotes/awilliam/tags/vfio-pci-for-qemu-20140226.0' into staging
Updates include:
 - Coverify fixes for vfio & pci-assign (Markus)
 - VFIO blacklisting support for known brokwn PCI option ROMs (Bandan)

# gpg: Signature made Wed 26 Feb 2014 18:15:28 GMT using RSA key ID 3BB08B22
# gpg: Can't check signature: public key not found

* remotes/awilliam/tags/vfio-pci-for-qemu-20140226.0:
  vfio: blacklist loading of unstable roms
  qdev-monitor: set DeviceState opts before calling realize
  pci-assign: Fix potential read beyond buffer on -EBUSY
  vfio: Fix overrun after readlink() fills buffer completely

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-27 11:31:52 +00:00
Mark Cave-Ayland
af87bf290f sun4m: Add Sun CG3 framebuffer initialisation function
In order to allow the user to choose the framebuffer for sparc-softmmu, add
-vga tcx and -vga cg3 options to the QEMU command line. If no option is
specified, the default TCX framebuffer is used.

Since proprietary FCode ROMs use a resolution of 1152x900, slightly relax the
validation rules to allow both displays to be initiated at the higher
resolution used by these ROMs upon request (OpenBIOS FCode ROMs default to
the normal QEMU sun4m default resolution of 1024x768).

Finally move any fprintf(stderr ...) statements in the areas affected by this
patch over to the new error_report() function.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
CC: Blue Swirl <blauwirbel@gmail.com>
CC: Anthony Liguori <aliguori@amazon.com>
CC: Peter Maydell <peter.maydell@linaro.org>
CC: Bob Breuer <breuerr@mc.net>
CC: Artyom Tarasenko <atar4qemu@gmail.com>
2014-02-27 10:01:41 +00:00
Mark Cave-Ayland
9eb08a435a sun4m: Add Sun CG3 framebuffer and corresponding OpenBIOS FCode ROM
The CG3 framebuffer is a simple 8-bit framebuffer for use with operating
systems such as early Solaris that do not have drivers for TCX.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
CC: Blue Swirl <blauwirbel@gmail.com>
CC: Anthony Liguori <aliguori@amazon.com>
CC: Peter Maydell <peter.maydell@linaro.org>
CC: Bob Breuer <breuerr@mc.net>
CC: Artyom Tarasenko <atar4qemu@gmail.com>
2014-02-27 10:01:41 +00:00
Mark Cave-Ayland
ead4cf04f8 sun4m: fix slavio timer RUN/STOP bit
The sun4m architecture has one 'system' timer and one timer per CPU.
The CPU timers can be configured in two modes:

  * 22 bits Counter/Timer. Periodic interrupts.
  * 54 bits User timer. For profiling. In this mode, the Run/Stop bit
    controls the timer.

The run/stop bit controls the timer only when it is in "User" mode, but
its state shall be persistent.

Signed-off-by: Olivier Danet <odanet@caramail.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2014-02-27 10:01:41 +00:00
Mark Cave-Ayland
f9681f116c sun4m: Set HostID in NVRAM
On SparcStations, the HostID field in the NVRAM is equal to the last
three bytes of the MAC address (which is also stored in the NVRAM).

This constant is used as an identification/serial number on Solaris.

Signed-off-by: Olivier Danet <odanet@caramail.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2014-02-27 10:01:40 +00:00
Thomas Huth
7f00eb30fe s390x/ipl: Fix crash of ELF images with arbitrary entry points
When loading S390 kernels, the current code expects an ELF file with the
start address 0x10000. Other ELF files cause a segmentation fault. To avoid
these crashes, we should get the start address from the ELF file instead
of always using a hard-coded address.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:26 +01:00
Frank Blaschka
1eecf41b3e s390x/kvm: Rework priv instruction handlers
The current implementation uses the second byte of the instruction
to identify the instruction handler. This is not sufficient to
support instructions not starting with 0xb2. This patch
adds separate handlers for 0xb2, 0xb9 and 0xeb to be able to
support the full instruction set.

Signed-off-by: Frank Blaschka <blaschka@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:26 +01:00
Thomas Huth
04c2b5168e s390x/kvm: Add missing SIGP CPU RESET order
The SIGP order CPU RESET was still missing in the list of our
supported handler. This patch now adds a simple implementation,
by using the cpu_reset() function that is already available in
target-s390x/cpu.c.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:26 +01:00
Thomas Huth
f7d3e46676 s390x/kvm: Rework SIGP INITIAL CPU RESET handler
The s390_cpu_initial_reset() function had two deficiencies: First, it
used an ioctl for the destination CPU, and this ioctl could block
nearly forever, as long as the destination CPU was running in the SIE
loop. Second, it also cleared the general purpose registers - something
it should not do according to the Principles of Operations.
Since we've already got another function for the initial CPU reset in
cpu.c, we can also use that function instead. And by using run_on_cpu()
for executing this code, we make sure that the destination CPU is
correctly kicked out of kernel mode now.

Suggested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:26 +01:00
Thomas Huth
49f5c9e98a s390x/cpu: Use ioctl to reset state in the kernel
Some of the state in the kernel can not be reset from QEMU yet.
For this we've got to use the KVM_S390_INITIAL_RESET ioctl to make
sure that the state in the kernel is set to the right values during
initial CPU reset, too.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:26 +01:00
Christian Borntraeger
0ca3611221 s390-ccw.img: new binary rom to match latest fixes
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:26 +01:00
Christian Borntraeger
5d739a4787 s390-ccw.img: Fix sporadic errors with ccw boot image - initialize css
We have to set the cssid to 0, otherwise the stsch code will
return an operand exception without the m bit. In the same way
we should set m=0.

This case was triggered in some cases during reboot, if for some
reason the location of blk_schid.cssid contains 1 and m was 0.
Turns out that the qemu elf loader does not zero out the bss section
on reboot.

The symptom was an dump of the old kernel with several areas
overwritten. The bootloader does not register a program check
handler, so bios exception jumped back into the old kernel.

Lets just use a local struct with a designed initializer. That
will guarantee that all other subelements are initialized to 0.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-02-27 09:51:26 +01:00
Christian Borntraeger
d1028f1b5b s390-ccw.img: Fix sporadic reboot hangs: Initialize next_idx
The current code does not initialize next_idx in the virtio ring.
As the ccw bios will always use guest memory at a fixed location,
this queue might != 0 after a reboot.
Lets make the initialization explicit.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-02-27 09:51:25 +01:00
Heinz Graalfs
c804c2a717 s390x/event-facility: exploit realize/unrealize
init/exit functionality of abstract SCLPEvent class is now exploiting
realize/unrealize.

Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Heinz Graalfs
6fbef18a4c s390x/event-facility: add support for live migration
Add support for live migration using VMStateDescription.

Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Heinz Graalfs
477a72a1ef s390x/event-facility: code restructure
Code restructure in order to simplify class hierarchy
  - remove S390SCLPDevice abstract base class
    and move function pointers into new SCLPEventFacilityClass
  - implement SCLPEventFacility as SysBusDevice
  - use define constants for instance creation strings

The following ascii-art shows the class structure wrt the SCLP EventFacility
before (CURRENT) and after the restructure (NEW):

----
CURRENT:

   "s390-sclp-events-bus"
   +-------------------------+
   |      SCLPEventsBus      |
   |-------------------------|
   |BusState qbus            |
   +-------------------------+

   +-------------------------+
   |   SCLPEventFacility     |  - to be replaced by new SCLPEventFacility,
   |-------------------------|    which will be a SysBusDevice
   |SCLPEventsBus sbus       |
   |DeviceState *qdev        |
   |unsigned int receive_mask|
   +-------------------------+

   +-------------------------+
   |   S390SCLPDeviceClass   |  - to be replaced by new SCLPEventFacilityClass
   |-------------------------|
   |DeviceClass qdev         |
   |*(init)()                |
   +-------------------------+

   "s390-sclp-event-facility"
             |
         instance-of
             |
             V
   "s390-sclp-device"           - this is an abstract class
   +-------------------------+
   |     S390SCLPDevice   (A)|  - to be replaced by new SCLPEventFacility
   |-------------------------|
   |SysBusDevice busdev      |
   |SCLPEventFacility *ef    |
   |                         |
   |*(sclp_command_handler)()|  - these 2 go to new SCLPEventFacilityClass
   |*(event_pending)()       |
   +-------------------------+

----
NEW:

   "s390-sclp-events-bus"
   +-------------------------+
   |      SCLPEventsBus      |
   |-------------------------|
   |BusState qbus            |
   +-------------------------+

   +-------------------------+
   | SCLPEventFacilityClass  |
   |-------------------------|
   |DeviceClass parent_class |
   |                         |
   |*(init)()                |
   |*(command_handler)()     |
   |*(event_pending)()       |
   +-------------------------+

   "s390-sclp-event-facility"
   +-------------------------+
   |   SCLPEventFacility     |
   |-------------------------|
   |SysBusDevice parent_class|
   |SCLPEventsBus sbus       |
   |unsigned int receive_mask|
   +-------------------------+

Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Heinz Graalfs
65e526c24e s390x/event-facility: some renaming
Do some renaming to shorten some identifiers and to emphasize sclp.

Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Thomas Huth
e8803d93df s390x/sclp: Fixed setting of condition code register
In the SCLP handler function, the condition code register must
only be set if no exception occured.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Thomas Huth
6e25280216 s390x/sclp: Add missing checks to SCLP handler
If the 51 most significant bits of the SCCB address are zero or equal to
the prefix, we should throw an specification exception, too.
Also moved the check for privileged mode to sclp_service_call() to have
all program checks in one place now.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Thomas Huth
a0fa2cb8cc s390x/sclp: Fixed the size of sccb and code parameter
The pointer to the SCCB should not be limited to 32 bits only.
In contrast to this, the command word parameter is only 32 bits
(the upper 32 bits should be ignored).

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Christian Borntraeger
9da45bb217 s390x/eventfacility: mask out commands
As a followup to commit 5f04c14a10
(s390-sclp: Define New SCLP Codes) we should mask the sclp command
not only in base sclp, but also in the event facility.

Based on an initial patch from Ralf Hoppe.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Thomas Huth
77319f2263 s390x/virtio-hcall: Specification exception for illegal subcodes
So far, the DIAG 500 hypervisor call was only setting -EINVAL in
R2 when a guest tried to call this function with an illegal subcode.
This patch now changes the behavior so that a specification exception
is thrown instead, since this is the common behavior of other DIAG
functions (and other CPU instructions) when being called with illegal
parameters.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Thomas Huth
f2c55d1735 s390x/virtio-hcall: Add range check for hypervisor call
The handler for diag 500 did not check whether the requested function
was in the supported range, so illegal values could crash QEMU in the
worst case.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
CC: qemu-stable@nongnu.org
2014-02-27 09:51:25 +01:00
Thomas Huth
0788082a4b s390x/kvm: Fixed bad SIGP SET-ARCHITECTURE handler
The SET-ARCHITECTURE handler in QEMU caused a program interruption.
This is wrong according to the "Principles of Operations" specification
(since SIGP should never cause a program interrupt) and was likely only
introduced for debugging purposes. Since we handle SET-ARCHITECTURE in
the kernel already and only dropped to user space in case of bad mode
parameters, we should just report INVALID PARAMETER in QEMU instead.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Dominik Dingel
819bd3091e s390x/async_pf: Check for apf extension and enable pfault
S390 can also use async page faults, to enhance guest scheduling.
In case of live migration we want to disable the feature and let
all pending request finish.

Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Jens Freimann
3a553fc658 s390x/kvm: implement floating-interrupt controller device
This patch implements a floating-interrupt controller device (flic)
which interacts with the s390 flic kvm_device.

Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:51:25 +01:00
Christian Borntraeger
216db403d0 update linux headers to kvm/next
This updates the kvm headers to
commit d3714010c307d26df251c45be9cd12ab6d41f0c4
    KVM: x86: emulator_cmpxchg_emulated should mark_page_dirty
in kvm/next.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2014-02-27 09:50:45 +01:00
Peter Maydell
2ce5868ca1 Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140226' into staging
target-arm queue:
 * fixes for various Coverity-spotted bugs
 * support new KVM device control API for VGIC
 * support KVM VGIC save/restore/migration
 * more AArch64 system mode foundations
 * support ARMv8 CRC instructions for A32/T32
 * PL330 minor fixes and cleanup

# gpg: Signature made Wed 26 Feb 2014 17:51:32 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140226: (45 commits)
  dma/pl330: implement dmaadnh instruction
  dma/pl330: Fix buffer depth
  dma/pl330: Add event debugging printfs
  dma/pl330: Rename parent_obj
  dma/pl330: printf format type sweep.
  dma/pl330: Fix misleading type
  dma/pl330: Delete overly verbose debug printf
  target-arm: Add support for AArch32 ARMv8 CRC32 instructions
  include/qemu/crc32c.h: Rename include guards to match filename
  target-arm: Add utility function for checking AA32/64 state of an EL
  target-arm: Implement AArch64 view of CPACR
  target-arm: A64: Implement MSR (immediate) instructions
  target-arm: Store AIF bits in env->pstate for AArch32
  target-arm: A64: Implement WFI
  target-arm: Get MMU index information correct for A64 code
  target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI
  target-arm: Implement AArch64 dummy breakpoint and watchpoint registers
  target-arm: Implement AArch64 ID and feature registers
  target-arm: Implement AArch64 generic timers
  target-arm: Implement AArch64 MPIDR
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 22:53:51 +00:00
Peter Maydell
6f6831f61a Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20140225' into staging
migration/next for 20140225

# gpg: Signature made Tue 25 Feb 2014 14:04:31 GMT using RSA key ID 5872D723
# gpg: Can't check signature: public key not found

* remotes/juanquintela/tags/migration/20140225:
  rdma: rename 'x-rdma' => 'rdma'
  Fix two XBZRLE corruption issues
  Fix vmstate_info_int32_le comparison/assign
  qemu_file: use fwrite() correctly

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 22:31:10 +00:00
Peter Maydell
bc3fbad816 Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging
Net patches

# gpg: Signature made Tue 25 Feb 2014 13:32:33 GMT using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/net-pull-request:
  virtio-net: use qemu_get_queue() where possible
  vhost_net: use offload API instead of bypassing it
  net: remove implicit peer from offload API
  net: Disable netmap backend when not supported
  net: add offloading support to netmap backend
  net: make tap offloading callbacks static
  net: virtio-net and vmxnet3 use offloading API
  net: TAP uses NetClientInfo offloading callbacks
  net: extend NetClientInfo for offloading
  net: change vnet-hdr TAP prototypes
  opencores_eth: flush queue whenever can_receive can go from false to true

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 20:04:37 +00:00
Peter Maydell
28c05edff5 Merge remote-tracking branch 'remotes/kraxel/tags/pull-audio-3' into staging
hda-audio: qom cleanups

# gpg: Signature made Mon 24 Feb 2014 12:19:48 GMT using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-audio-3:
  hda-audio: qom cleanups

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 18:22:11 +00:00
Bandan Das
4b9430294e vfio: blacklist loading of unstable roms
Certain cards such as the Broadcom BCM57810 have rom quirks
that exhibit unstable system behavior duing device assignment. In
the particular case of 57810, rom execution hangs and if a FLR
follows, the device becomes inoperable until a power cycle. This
change blacklists loading of rom for such cards unless the user
specifies a romfile or rombar=1 on the cmd line

Signed-off-by: Bandan Das <bsd@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2014-02-26 10:33:45 -07:00
Bandan Das
52aa17cbd8 qdev-monitor: set DeviceState opts before calling realize
Setting opts before the realize property is set allows the
following patch to make decisions based on whether the user
specified "rombar". This also avoids having to create a new
tristate property especially for this purpose

Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Bandan Das <bsd@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2014-02-26 10:32:40 -07:00
Markus Armbruster
82d0794565 pci-assign: Fix potential read beyond buffer on -EBUSY
readlink() doesn't write a terminating null byte.
assign_failed_examine() passes the unterminated string to strrchr().
Oops.  Terminate it.

Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2014-02-26 10:30:03 -07:00
Markus Armbruster
13665a2d2f vfio: Fix overrun after readlink() fills buffer completely
readlink() returns the number of bytes written to the buffer, and it
doesn't write a terminating null byte.  vfio_init() writes it itself.
Overruns the buffer when readlink() filled it completely.

Fix by treating readlink() filling the buffer completely as error,
like we do in pci-assign.c's assign_failed_examine().

Spotted by Coverity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2014-02-26 10:28:36 -07:00
Peter Crosthwaite
c04018e933 dma/pl330: implement dmaadnh instruction
Implement the missing DMAADNH instruction. This is a minor variant
of the DMAADDH instruction, so factor out to a common implementation
for both (dmaadxh).

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 73ab13532a7cae53441da89b46c279b5f50785e3.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:09 +00:00
Peter Crosthwaite
a5ae7e3984 dma/pl330: Fix buffer depth
This is the product of the data-width and the depth arguments, I.e the
depth of the FIFO is in terms of data entries and not bytes (which is
what the original implementation was suggesting). Fix.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: c34de31031511538ccdb3164b48ee8a6a973ebd4.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:08 +00:00
Peter Crosthwaite
432a0a130e dma/pl330: Add event debugging printfs
These are helpful to anyone trying to debug event sequencing.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: e82a0ad804db3de4f46839e55a9d287735ef870d.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:08 +00:00
Peter Crosthwaite
1c8be73d4e dma/pl330: Rename parent_obj
As per current QOM conventions.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: abb137347ea1ee9c31487b544f3d5435fb17f6a4.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:08 +00:00
Peter Crosthwaite
c3143ba877 dma/pl330: printf format type sweep.
Use PRI formats as appropriate rather than raw %x and %d. This fixes
debug printfery on some host platforms. Fix types of debug only
variables as appropriate.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: dbb5f5fd048b2d4a3cb5c6357577d11211a7a585.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:08 +00:00
Peter Crosthwaite
024c6e2ea5 dma/pl330: Fix misleading type
This type really should just be a regular int as no usages rely on it's
32 bitness (it's only meaningful as a bit position and not a bit mask).
This also fixes a printf which uses the variable with a regular %d.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 2a99d31f377aee371476d9da8fd0d1b7efa30f63.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:08 +00:00
Peter Crosthwaite
63a31905cb dma/pl330: Delete overly verbose debug printf
When using event synchronisation, this particular debug printf floods.
Just delete it.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: dd94d19493f97c47497b9d8caf74ca43e70d58fd.1393372019.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:07 +00:00
Will Newton
eb0ecd5ad9 target-arm: Add support for AArch32 ARMv8 CRC32 instructions
Add support for AArch32 CRC32 and CRC32C instructions added in ARMv8
and add a CPU feature flag to enable these instructions.

The CRC32-C implementation used is the built-in qemu implementation
and The CRC-32 implementation is from zlib. This requires adding zlib
to LIBS to ensure it is linked for the linux-user binary.

Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1393411566-24104-3-git-send-email-will.newton@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:07 +00:00
Will Newton
0956ff5a4e include/qemu/crc32c.h: Rename include guards to match filename
Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1393411566-24104-2-git-send-email-will.newton@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:07 +00:00
Peter Maydell
1f79ee32b5 target-arm: Add utility function for checking AA32/64 state of an EL
There are various situations where we need to behave differently
depending on whether a given exception level is in AArch64 or
AArch32 state. The state of the current exception level is stored
in env->aarch64, but there's no equivalent guest-visible architected
state bits for the status of the exception levels "above" the
current one which may still affect execution. At the moment we
only support EL1 (ie no EL2 or EL3) and insist that AArch64
capable CPUs run with EL1 in AArch64 state, but these may change
in the future, so abstract out the "what state is this?" check
into a utility function which can be enhanced later if necessary.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:07 +00:00
Peter Maydell
34222fb810 target-arm: Implement AArch64 view of CPACR
Implement the AArch64 view of the CPACR. The AArch64
CPACR is defined to have a lot of RES0 bits, but since
the architecture defines that RES0 bits may be implemented
as reads-as-written and we know that a v8 CPU will have
no registered coprocessors for cp0..cp13 we can safely
implement the whole register this way.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:06 +00:00
Peter Maydell
9cfa0b4e4c target-arm: A64: Implement MSR (immediate) instructions
Implement the MSR (immediate) instructions, which can update the
PSTATE SP and DAIF fields.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:06 +00:00
Peter Maydell
4cc35614a0 target-arm: Store AIF bits in env->pstate for AArch32
To avoid complication in code that otherwise would not need to
care about whether EL1 is AArch32 or AArch64, we should store
the interrupt mask bits (CPSR.AIF in AArch32 and PSTATE.DAIF
in AArch64) in one place consistently regardless of EL1's mode.
Since AArch64 has an extra enable bit (D for debug exceptions)
which isn't visible in AArch32, this means we need to keep
the enables in env->pstate. (This is also consistent with the
general approach we're taking that we handle 32 bit CPUs as
being like AArch64/ARMv8 CPUs but which only run in 32 bit mode.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:06 +00:00
Peter Maydell
1ed69e82b8 target-arm: A64: Implement WFI
Implement the WFI instruction for A64; this just involves wiring
up the instruction, and adding a gen_a64_set_pc_im() which was
accidentally omitted from the A64 decoder top loop.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:06 +00:00
Peter Maydell
d9ea7d290b target-arm: Get MMU index information correct for A64 code
Emit the correct MMU index information for loads and stores from
A64 code, rather than hardwiring it to "always kernel mode",
by storing the exception level in the TB flags, and make
cpu_mmu_index() return the right answer when the CPU is in
AArch64 mode.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:05 +00:00
Peter Maydell
cd5c11b84b target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI
Define a dummy version of the AArch64 OSLAR_EL1 system register
which just ignores writes. Linux will always write to this (it
is the OS lock used for debugging), but we don't support debug.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:05 +00:00
Peter Maydell
0b45451e58 target-arm: Implement AArch64 dummy breakpoint and watchpoint registers
In AArch64 the breakpoint and watchpoint registers are mandatory, so the
kernel always accesses them on bootup. Implement dummy versions, which
read as written but have no actual effect.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:05 +00:00
Peter Maydell
e60cef860f target-arm: Implement AArch64 ID and feature registers
Implement the AArch64-specific ID and feature registers. Although
many of these are currently not used by the architecture (and so
always zero for all implementations), we define the full set of
fields in the ARMCPU struct for symmetry.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:05 +00:00
Peter Maydell
a7adc4b779 target-arm: Implement AArch64 generic timers
Implement the AArch64 view of the generic timer system registers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:05 +00:00
Peter Maydell
4b7fff2fab target-arm: Implement AArch64 MPIDR
Implement the AArch64 MPIDR system register.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:04 +00:00
Peter Maydell
327ed10fa2 target-arm: Implement AArch64 TTBR*
Implement the AArch64 TTBR* registers. For v7 these were already 64 bits
to handle LPAE, but implemented as two separate uint32_t fields.
Combine them into a single uint64_t which can be used for all purposes.
Since this requires touching every use, take the opportunity to rename
the field to the architectural name.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:04 +00:00
Peter Maydell
a505d7fe5f target-arm: Implement AArch64 VBAR_EL1
Implement the A64 view of the VBAR system register.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:04 +00:00
Peter Maydell
cb2e37dffa target-arm: Implement AArch64 TCR_EL1
Implement the AArch64 TCR_EL1, which is the 64 bit view of
the AArch32 TTBCR. (The uses of the bits in the register are
completely different, but in any given situation the CPU will
always interpret them one way or the other. In fact for QEMU EL1
is always 64 bit, but we share the state field because this
is the correct mapping to permit a future implementation of EL2.)
We also make the AArch64 view the 'master' as far as migration
and reset is concerned.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:04 +00:00
Peter Maydell
5ebafdf31a target-arm: Implement AArch64 SCTLR_EL1
Implement the AArch64 view of the system control register SCTLR_EL1.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:03 +00:00
Peter Maydell
b0fe242751 target-arm: Implement AArch64 memory attribute registers
Implement the AArch64 memory attribute registers. Since QEMU doesn't
model caches it does not need to care about memory attributes at all,
and we can simply make these read-as-written.

We did not previously implement the AArch32 versions of the MAIR
registers, which went unnoticed because of the overbroad TLB_LOCKDOWN
reginfo definition; provide them now to keep the 64<->32 register
relationship clear.

We already provided AMAIR registers for 32 bit as simple RAZ/WI;
extend that to provide a 64 bit RAZ/WI AMAIR_EL1.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:03 +00:00
Peter Maydell
91e240698f target-arm: Implement AArch64 dummy MDSCR_EL1
We don't support letting the guest do debug, but Linux prods the
monitor debug system control register anyway, so implement a dummy
RAZ/WI version.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:03 +00:00
Peter Maydell
168aa23bb0 target-arm: Implement AArch64 TLB invalidate ops
Implement the AArch64 TLB invalidate operations. This is
the full set of TLBI ops defined for a CPU which doesn't
implement EL2 or EL3.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:03 +00:00
Peter Maydell
8af35c37d2 target-arm: Implement AArch64 cache invalidate/clean ops
Implement all the AArch64 cache invalidate and clean ops
(which are all NOPs since QEMU doesn't emulate the cache).
The only remaining unimplemented cache op is DC ZVA.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:02 +00:00
Peter Maydell
cd4da63177 target-arm: Implement AArch64 MIDR_EL1
Implement the AArch64 view of the MIDR system register
(for AArch64 it is a simple constant, unlike the complicated
mess that TI925 imposes on the 32-bit view).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:02 +00:00
Peter Maydell
0eef9d9833 target-arm: Implement AArch64 CurrentEL sysreg
Implement the CurrentEL sysreg.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:02 +00:00
Peter Maydell
7da845b0f4 target-arm: A64: Make cache ID registers visible to AArch64
Make the cache ID system registers (CLIDR, CSSELR, CCSIDR, CTR)
visible to AArch64. These are mostly simple 64-bit extensions of the
existing 32 bit system registers and so can share reginfo definitions.
CTR needs to have a split definition, but we can clean up the
temporary user-mode implementation in favour of using the CPU-specified
reset value, and implement the system-mode-required semantics of
restricting its EL0 accessibility if SCTLR.UCT is not set.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-02-26 17:20:01 +00:00
Peter Maydell
67ed771ded target-arm: Fix raw read and write functions on AArch64 registers
The raw read and write functions were using the ARM_CP_64BIT flag in
ri->type to determine whether to treat the register's state field as
uint32_t or uint64_t; however AArch64 register info structs don't use
that flag. Abstract out the "how big is the field?" test into a
function and fix it to work for AArch64 registers. For this to work
we must ensure that the reginfo structs put into the hashtable have
the correct state field for their use, not the placeholder STATE_BOTH.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:01 +00:00
Christoffer Dall
855011be05 hw: arm_gic_kvm: Add KVM VGIC save/restore logic
Save and restore the ARM KVM VGIC state from the kernel.  We rely on
QEMU to marshal the GICState data structure and therefore simply
synchronize the kernel state with the QEMU emulated state in both
directions.

We take some care on the restore path to check the VGIC has been
configured with enough IRQs and CPU interfaces that we can properly
restore the state, and for separate set/clear registers we first fully
clear the registers and then set the required bits.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1392687921-26921-1-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:01 +00:00
Christoffer Dall
1da41cc1c6 arm: vgic device control api support
Support creating the ARM vgic device through the device control API and
setting the base address for the distributor and cpu interfaces in KVM
VMs using this API.

Because the older KVM_CREATE_IRQCHIP interface needs the irq chip to be
created prior to creating the VCPUs, we first test if we can use the
device control API in kvm_arch_irqchip_create (using the test flag from
the device control API).  If we cannot, it means we have to fall back to
KVM_CREATE_IRQCHIP and use the older ioctl at this point in time.  If
however, we can use the device control API, we don't do anything and
wait until the arm_gic_kvm driver initializes and let that use the
device control API.

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1392687720-26806-5-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:00 +00:00
Christoffer Dall
0a6a7ccaae kvm: Common device control API functions
Introduces two simple functions:
    int kvm_device_ioctl(int fd, int type, ...);
    int kvm_create_device(KVMState *s, uint64_t type, bool test);

These functions wrap the basic ioctl-based interactions with KVM in a
way similar to other KVM ioctl wrappers.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1392687720-26806-4-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:00 +00:00
Christoffer Dall
d6032e06d1 kvm: Introduce kvm_arch_irqchip_create
Introduce kvm_arch_irqchip_create an arch-specific hook in preparation
for architecture-specific use of the device control API to create IRQ
chips.

Following patches will implement the ARM irqchip create method to prefer
the device control API over the older KVM_CREATE_IRQCHIP API.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1392687720-26806-3-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:00 +00:00
Christoffer Dall
876074c228 linux-headers: Update from v3.14-rc3
Update to tag v3.14-rc3 (6d0abeca3242a88cab8232e4acd7e2bf088f3bc2)

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1392687720-26806-2-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:20:00 +00:00
Christoffer Dall
6453fa998a hw/intc/arm_gic: Fix GIC_SET_LEVEL
The GIC_SET_LEVEL macro unfortunately overwrote the entire level
bitmask instead of just or'ing on the necessary bits, causing active
level PPIs on a core to clear PPIs on other cores.

Cc: qemu-stable@nongnu.org
Reported-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1393031030-8692-1-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-26 17:19:59 +00:00
Peter Maydell
c10f7fc3d1 target-arm: Load correct access bits from ARMv5 level 2 page table descriptors
In ARMv5 level 2 page table descriptors, each 4K or 64K page is split into
four subpages, each of which can have different access permission settings,
which are specified by four two-bit fields in the l2 descriptor. A
long-standing cut-and-paste error meant we were using the wrong bits in
the virtual address to select the access-permission field for 4K pages.

The error has presumably not been noticed before because most guests don't
make use of the ability to set the access permissions differently for
each 1K subpage: if the guest gives the whole page the same access
permissions it doesn't matter which of the 4 AP fields we select.
(The whole issue is irrelevant for ARMv7 CPUs anyway because subpages
aren't supported there.)

Reported-by: Vivek Rai <Vivek.Rai@emulex.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1392667690-8731-1-git-send-email-peter.maydell@linaro.org
2014-02-26 17:19:59 +00:00
Peter Maydell
cf143ad350 hw/arm/musicpal: Remove nonexistent CDTP2, CDTP3 registers
The ethernet device in the musicpal only has two tx queues,
but we modelled it with four CTDP registers, presumably a
cut and paste from the rx queue registers. Since the tx_queue[]
array is only 2 entries long this allowed a guest to overrun
this buffer. Remove the nonexistent registers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1392737293-10073-1-git-send-email-peter.maydell@linaro.org
Acked-by: Jan Kiszka <jan.kiszka@web.de>
Cc: qemu-stable@nongnu.org
2014-02-26 17:19:59 +00:00
Peter Maydell
fce0a82608 hw/intc/exynos4210_combiner: Don't overrun output_irq array in init
The Exynos4210 combiner has IIC_NIRQ inputs and IIC_NGRP outputs;
use the correct constant in the loop initializing our output
sysbus IRQs so that we don't overrun the output_irq[] array.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1392659611-8439-1-git-send-email-peter.maydell@linaro.org
Reviewed-by: Andreas Färber <afaerber@suse.de>
Cc: qemu-stable@nongnu.org
2014-02-26 17:19:58 +00:00
Peter Maydell
775fda92a1 target-arm: Fix incorrect arithmetic constructing short-form PAR for ATS ops
Correct some obviously nonsensical bit manipulation spotted by Coverity
when constructing the short-form PAR value for ATS operations.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1392659525-8335-1-git-send-email-peter.maydell@linaro.org
2014-02-26 17:19:58 +00:00
Peter Maydell
cba933b225 hw/timer/arm_timer: Avoid array overrun for bad addresses
The integrator's timer read/write functions log an error for
bad addresses in guest accesses, but were falling through and
using an out of bounds array index rather than returning early.
Fix this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Message-id: 1392647854-8067-4-git-send-email-peter.maydell@linaro.org
Cc: qemu-stable@nongnu.org
2014-02-26 17:19:58 +00:00
Peter Maydell
106a73b6d2 hw/net/stellaris_enet: Avoid unintended sign extension
Add a cast to avoid an unintended sign extension that
would mean we returned 0xffffffff in the high 32 bits
for an IA0 read if bit 31 in the MAC address was 1.
(This is harmless since we'll only be doing 4 byte
reads, but it could be confusing, so best avoided.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Message-id: 1392647854-8067-3-git-send-email-peter.maydell@linaro.org
2014-02-26 17:19:58 +00:00
Peter Maydell
ec1efab957 hw/misc/arm_sysctl: Fix bad boundary check on mb clock accesses
Fix incorrect use of sizeof() rather than ARRAY_SIZE() to guard
accesses into the mb_clock[] array, which was allowing a malicious
guest to overwrite the end of the array.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Message-id: 1392647854-8067-2-git-send-email-peter.maydell@linaro.org
Cc: qemu-stable@nongnu.org
2014-02-26 17:19:57 +00:00
Markus Armbruster
d77f7779b4 fsdev: Fix overrun after readlink() fills buffer completely
readlink() returns the number of bytes written to the buffer, and it
doesn't write a terminating null byte.  do_readlink() writes it
itself.  Overruns the buffer when readlink() filled it completely.

Fix by reserving space for the null byte when calling readlink(), like
we do elsewhere.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
2014-02-26 12:24:07 +05:30
Peter Crosthwaite
d5001cf787 xilinx: Delete hw/include/xilinx.h
This is now obsolete - remove the header and all its inclusions.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
d91a68a73b xilinx: Inline usages of xilinx_axi*_init()
Inline the only usage of each of xilinx_axiethernet_init and
xilinx_axidma_init. Converts this init to at least a semi-recent QOM
styling.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
b8d4e1c43b xilinx: Inline usage of xilinx_ethlite_create()
Inline the only usage. Converts this init to at least a semi-recent QOM
styling.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
29873712e6 xilinx: Inline usages of xilinx_timer_create()
Inline these usages. Converts these init to at least a semi-recent QOM
styling.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
13c9bfbfbb xilinx: Inline usages of xilinx_intc_create()
Inline these usages. Converts these init to at least a semi-recent QOM
styling.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
8174196b7f microblaze/ml605: Define macros for irq/memory maps
Define (missing) macros for the interrupt and memory maps for the sake
of self documentation.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
81cce07ec6 ppc/virtex_ml507: Define macros for irq/memory maps
Define macros for the interrupt and memory maps for the sake of self
documentation.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Peter Crosthwaite
05a738c4ec microblaze/s3adsp_1800: Define macros for irq map
Define macros for the interrupt map for the sake of self documentation.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-02-26 14:54:45 +10:00
Paolo Bonzini
aa0d1f4488 modules: do not include gmodule-2.0 in static builds
gmodule-2.0's pkg-config files include -Wl,--export-dynamic, which breaks
static builds.  It is a glib bug, but we need to support --static builds for
the linux-user targets, and in the end all that is needed to fix this is:

* outlaw --enable-modules --static, which makes little sense anyway

* only include gmodule-2.0's cflags and ldflags if --enable-modules is
specified on the command line.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1393346215-5636-1-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-25 18:34:28 +00:00
Peter Maydell
a89d97df1f Merge remote-tracking branch 'remotes/spice/tags/pull-spice-3' into staging
qxl: add sanity check

# gpg: Signature made Mon 24 Feb 2014 12:01:27 GMT using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/spice/tags/pull-spice-3:
  qxl: add sanity check

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-25 15:17:24 +00:00
Stefan Hajnoczi
ad37bb3b00 virtio-net: use qemu_get_queue() where possible
qemu_get_queue() is a shorthand for qemu_get_subqueue(n->nic, 0).  Use
the shorthand where possible.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 14:31:05 +01:00
Stefan Hajnoczi
e3e48565c1 vhost_net: use offload API instead of bypassing it
There is no need to access backend->info->has_vnet_hdr() and friends
anymore.  Use the qemu_has_vnet_hdr() API instead.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 14:31:05 +01:00
Stefan Hajnoczi
d6085e3ace net: remove implicit peer from offload API
The virtio_net offload APIs are used on the NIC's peer (i.e. the tap
device).  The API was defined to implicitly use nc->peer, saving the
caller the trouble.

This wasn't ideal because:
1. There are callers who have the peer but not the NIC.  Currently they
   are forced to bypass the API and access peer->info->... directly.
2. The rest of the net.h API uses nc, not nc->peer, so it is
   inconsistent.

This patch pushes nc->peer back up to callers.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 14:31:05 +01:00
Michael R. Hines
41310c6878 rdma: rename 'x-rdma' => 'rdma'
As far as we can tell, all known bugs have been fixed:

1. Parallel migrations are working
2. IPv6 migration is working
3. virt-test is working

I'm not comfortable sending the revised libvirt patch
until this is accepted or review suggestions are addressed,
(including pin-all support. It does not make sense to
remove experimental for one thing and not the other. That's
too many trips through the libvirt community).

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
2014-02-25 14:30:28 +01:00
Dr. David Alan Gilbert
6d3cb1f970 Fix two XBZRLE corruption issues
Push zero'd pages into the XBZRLE cache
    A page that was cached by XBZRLE, zero'd and then XBZRLE'd again
    was being compared against a stale cache value

Don't use 'qemu_put_buffer_async' to put pages from the XBZRLE cache
    Since the cache might change before the data hits the wire

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
2014-02-25 14:30:28 +01:00
Dr. David Alan Gilbert
24a370ef23 Fix vmstate_info_int32_le comparison/assign
Fix comparison of vmstate_info_int32_le so that it succeeds if loaded
value is (l)ess than or (e)qual

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

Fix up comment and name text

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
2014-02-25 14:30:28 +01:00
Juan Quintela
aded6539d9 qemu_file: use fwrite() correctly
fwrite() returns the number of items written.  But when there is one
error, it can return a short write.

In the particular bug that I was tracking, I did a migration to a
read-only filesystem.  And it was able to finish the migration
correctly.  fwrite() never returned a negative error code, nor zero,
always 4096. (migration writes chunks of about 14000 bytes).  And it
was able to "complete" the migration with success (yes, reading the
file was a bit more difficult).

To add insult to injury, if your amount of memory was big enough (12GB
on my case), it overwrote some important structure, and from them,
malloc failed.  This check makes the problem go away.

Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
2014-02-25 14:26:59 +01:00
Peter Maydell
0459650d94 Merge remote-tracking branch 'remotes/mdroth/qga-pull-2014-02-24' into staging
* remotes/mdroth/qga-pull-2014-02-24:
  qemu-ga: isa-serial support on Windows
  qga: Fix memory allocation pasto
  qga: Don't require 'time' argument in guest-set-time command
  qga: vss-win32: Fix interference with snapshot deletion by other VSS request
  qga: vss-win32: Fix interference with snapshot creation by other VSS requesters
  qga: vss-win32: Use NULL as an invalid pointer for OpenEvent and CreateEvent

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-25 12:30:01 +00:00
Peter Maydell
05fd3bf2a1 Merge remote-tracking branch 'remotes/xtensa/tags/20140224-xtensa' into staging
Xtensa fixes and improvements queue 2014-02-24:
- add support for ML605 and KC705 FPGA boards;
- flush opencores_eth queue when new RX descriptor is available;
- add basic checks to cache opcodes;
- make core configuration available to tests;
- implement HW config ID special registers.

# gpg: Signature made Mon 24 Feb 2014 00:52:42 GMT using RSA key ID F83FA044
# gpg: Good signature from "Max Filippov <max.filippov@cogentembedded.com>"
# gpg:                 aka "Max Filippov <jcmvbkbc@gmail.com>"

* remotes/xtensa/tags/20140224-xtensa:
  target-xtensa: provide HW confg ID registers
  target-xtensa: refactor standard core configuration
  target-xtensa: add basic tests for cache opcodes
  target-xtensa: allow using core configuration in tests
  target-xtensa: add overridable test_init macro
  target-xtensa: add basic checks to icache opcodes
  target-xtensa: add basic checks to dcache opcodes
  target-xtensa: add RRRI4 opcode format fields
  opencores_eth: flush queue whenever can_receive can go from false to true
  hw/xtensa: add support for ML605 and KC705 FPGA board

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-25 11:54:40 +00:00
Vincenzo Maffione
0a985b3727 net: Disable netmap backend when not supported
This patch fixes configure so that the netmap backend is not compiled in if the
host doesn't support an API version >= 11. A version upper bound (15) has been
added so that the netmap API can be extended with some minor features without
requiring QEMU code modifications.

Moreover, some changes have been done to net/netmap.c in order to reflect the
current netmap API/ABI (11).

The NETMAP_WITH_LIBS macro makes possible to include some utilities (e.g.
netmap ring macros, D(), RD() and other high level functions) through the netmap
headers. In this way we get rid of the D and RD macro definitions in the QEMU
code, and we open the way for further code simplifications that will be
introduced by future patches.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:17 +01:00
Vincenzo Maffione
f6c65bfb93 net: add offloading support to netmap backend
Whit this patch, the netmap backend supports TSO/UFO/CSUM
offloadings, and accepts the virtio-net header, similarly to what
happens with TAP. The offloading callbacks in the NetClientInfo
interface have been implemented.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:17 +01:00
Vincenzo Maffione
3bac80d31a net: make tap offloading callbacks static
Since TAP offloadings are manipulated through a new API, it's
not necessary to export them in include/net/tap.h anymore.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:17 +01:00
Vincenzo Maffione
cf528b8958 net: virtio-net and vmxnet3 use offloading API
With this patch, virtio-net and vmxnet3 frontends make
use of the qemu_peer_* API for backend offloadings manipulations,
instead of calling TAP-specific functions directly.
We also remove the existing checks which prevent those frontends
from using offloadings with backends different from TAP (e.g. netmap).

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:17 +01:00
Vincenzo Maffione
2e753bcc7d net: TAP uses NetClientInfo offloading callbacks
The TAP NetClientInfo structure is inizialized with the TAP-specific
functions that manipulates offloading features.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:17 +01:00
Vincenzo Maffione
1f55ac4586 net: extend NetClientInfo for offloading
Some new callbacks have been added to generalize the operations done
by virtio-net and vmxnet3 frontends to manipulate TAP offloadings.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:17 +01:00
Vincenzo Maffione
e96dfd110e net: change vnet-hdr TAP prototypes
The tap_has_vnet_hdr() and tap_has_vnet_hdr_len() functions used
to return int, even though they only return true/false values.
This patch changes the prototypes to return bool.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:16 +01:00
Max Filippov
6e50d18847 opencores_eth: flush queue whenever can_receive can go from false to true
The following registers control whether MAC can receive frames:
- MODER.RXEN bit that enables/disables receiver;
- TX_BD_NUM register that specifies number of RX descriptors.
Notify QEMU networking core when the MAC is ready to receive frames.
Discard frame and raise BUSY interrupt when the frame arrives but the
current RX descriptor is not empty.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-02-25 11:50:16 +01:00
Peter Maydell
e7a1d6c52a Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches

# gpg: Signature made Fri 21 Feb 2014 21:42:24 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream: (54 commits)
  iotests: Mixed quorum child device specifications
  quorum: Simplify quorum_open()
  quorum: Add unit test.
  quorum: Add quorum_open() and quorum_close().
  quorum: Implement recursive .bdrv_recurse_is_first_non_filter in quorum.
  quorum: Add quorum_co_flush().
  quorum: Add quorum_invalidate_cache().
  quorum: Add quorum_getlength().
  quorum: Add quorum mechanism.
  quorum: Add quorum_aio_readv.
  blkverify: Extract qemu_iovec_clone() and qemu_iovec_compare() from blkverify.
  quorum: Add quorum_aio_writev and its dependencies.
  quorum: Create BDRVQuorumState and BlkDriver and do init.
  quorum: Create quorum.c, add QuorumChildRequest and QuorumAIOCB.
  check-qdict: Test termination of qdict_array_split()
  check-qdict: Adjust test for qdict_array_split()
  qdict: Extract non-QDicts in qdict_array_split()
  qemu-config: Sections must consist of keys
  qemu-iotests: Check qemu-img command line parsing
  qemu-img: Allow -o help with incomplete argument list
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-25 10:50:11 +00:00
Peter Maydell
c58e291591 Merge remote-tracking branch 'remotes/sstabellini/xen-140220' into staging
* remotes/sstabellini/xen-140220:
  xen_disk: fix io accounting
  Call pci_piix3_xen_ide_unplug from unplug_disks

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-24 16:12:55 +00:00
Peter Maydell
6dedf0522c Merge remote-tracking branch 'remotes/bonzini/configure' into staging
* remotes/bonzini/configure:
  build: softmmu targets do not have a "main.o" file
  configure: Disable libtool if -fPIE does not work with it (bug #1257099)
  block: convert block drivers linked with libs to modules
  Makefile: introduce common-obj-m and block-obj-m for DSO
  Makefile: install modules with "make install"
  module: implement module loading
  rules.mak: introduce DSO rules
  darwin: do not use -mdynamic-no-pic
  block: use per-object cflags and libs
  rules.mak: allow per object cflags and libs
  rules.mak: fix $(obj) to a real relative path
  util: Split out exec_dir from os_find_datadir

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-02-24 15:38:00 +00:00
Peter Maydell
98b21dcdb3 configure: check that C++ compiler actually works
Check that the C++ compiler works with the C compiler; if it
does not, then don't pass CXX to the build process. This
fixes a regression where QEMU was no longer building if the
build environment didn't have a C++ compiler (introduced
in commit 3144f78b, which incorrectly assumed that rules.mak
would only see a non-empty $(CXX) if configure had actually
found a working C++ compiler).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reported-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Tested-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-id: 1392909016-14028-1-git-send-email-peter.maydell@linaro.org
2014-02-24 14:53:27 +00:00
Gerd Hoffmann
9c70434f82 qxl: add sanity check
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
2014-02-24 13:00:52 +01:00
Max Filippov
604e1f9cd0 target-xtensa: provide HW confg ID registers
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:02 +04:00
Max Filippov
676056d4f1 target-xtensa: refactor standard core configuration
Coalesce all standard configuration sections into single
DEFAULT_SECTIONS macro for all cores. This allows to add new features in
a single place: overlay_tool.h

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:02 +04:00
Max Filippov
2c09eee112 target-xtensa: add basic tests for cache opcodes
Test that non-locking prefetch operations don't cause exceptions on
missing TLB and that other 'hit' cache operations do.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:02 +04:00
Max Filippov
a2e67072b7 target-xtensa: allow using core configuration in tests
Add path to the core configuration directory to test build command and
replace .include asm directive with #include to enable preprocessing.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:01 +04:00
Max Filippov
d0fa1f0df3 target-xtensa: add overridable test_init macro
Some test suites, like MMU, need per-test initialization. Don't make them
redefine test macro, add test_init for that purpose.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:01 +04:00
Max Filippov
e848dd4248 target-xtensa: add basic checks to icache opcodes
Check privilege level for privileged instructions (IHU, III, IIU and IPFL
are privileged), memory accessibility for instructions that reference memory
(IH* and IPFL) and windowed register validity for all instruction cache
instructions.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:01 +04:00
Max Filippov
7c84259019 target-xtensa: add basic checks to dcache opcodes
Check privilege level for privileged instructions (DHI, DHU, DII, DIU, DIWB,
DIWBI, DPFL are privileged), memory accessibility for instructions that
reference memory (all DH* and DPFL) and windowed register validity for all
data cache instructions.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:01 +04:00
Max Filippov
6502668237 target-xtensa: add RRRI4 opcode format fields
This encoding is used by cache instructions.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
2014-02-24 04:47:01 +04:00
Max Filippov
b807b5ff89 opencores_eth: flush queue whenever can_receive can go from false to true
The following registers control whether MAC can receive frames:
- MODER.RXEN bit that enables/disables receiver;
- TX_BD_NUM register that specifies number of RX descriptors.
Notify QEMU networking core when the MAC is ready to receive frames.
Discard frame and raise BUSY interrupt when the frame arrives but the
current RX descriptor is not empty.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-24 04:47:01 +04:00
Max Filippov
e0db904d1d hw/xtensa: add support for ML605 and KC705 FPGA board
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
2014-02-24 04:47:01 +04:00
Miki Mishael
a749f42da5 qemu-ga: isa-serial support on Windows
Add support for isa-serial method for qemu-ga on Windows,
Added -p command line parameter for serial port name
specification, e.g. "-p COM15".

Signed-off-by: Miki Mishael <mmishael@redhat.com>
Signed-off-by: Dmitry Fleytman <dfleytma@redhat.com>

*added default isa-serial path to help output

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-02-23 18:38:18 -06:00
Markus Armbruster
10b7c5dd0d qga: Fix memory allocation pasto
qmp_guest_file_seek() allocates memory for a GuestFileRead object
instead of the GuestFileSeek object it actually uses.  Harmless,
because the GuestFileRead is slightly larger.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-02-23 13:13:52 -06:00
Michal Privoznik
2c958923bc qga: Don't require 'time' argument in guest-set-time command
As the description to the guest-set-time states, the command is
there to ease time synchronization after resume. If guest was
suspended for longer period of time, its system time can go off
so badly, that even NTP refuses to set it. That's why the command
was invented: to give users chance to set the time (not
necessarily 100% correct). However, there's is no real need for
us to require users to pass an arbitrary time. Especially if we
can read the correct value from RTC (boiling down to reading
host's time). Hence this commit enables logic:

guest-set-time() == guest-set-time($now_from_rtc)

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-02-23 13:11:56 -06:00
Tomoki Sekiyama
d9e1f574cb qga: vss-win32: Fix interference with snapshot deletion by other VSS request
When a VSS requester such as vshadow.exe or diskshadow.exe requests to
delete snapshots, qemu-ga VSS provider's DeleteSnapshots() is also called
and returns E_NOTIMPL, that makes the deletion fail.
To avoid this issue, return S_OK and set values that represent no snapshots
are deleted by qemu-ga VSS provider.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Reviewed-by: Gal Hammer <ghammer@redhat.com>
Reviewed-by: Yan Vugenfirer <yvugenfi@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-02-23 13:11:52 -06:00
Tomoki Sekiyama
ff8adbcfdb qga: vss-win32: Fix interference with snapshot creation by other VSS requesters
When a VSS requester such as vshadow.exe or diskshadow.exe requests to
create disk snapshots, Windows may choose qemu-ga VSS provider if it is
only provider registered on the system. However, because it provides only a
function to freeze the filesystem, the snapshotting fails.

This patch adds a check into CQGAVssProvider::IsVolumeSupported() to reject
the request from other VSS requesters, so that the other provider is chosen.

The check of requester is done by confirming event channels between
qemu-ga's requester and provider established. To ensure that the events are
initialized when CQGAVssProvider::IsVolumeSupported() is called, it moves
the initialization earlier.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Reviewed-by: Gal Hammer <ghammer@redhat.com>
Reviewed-by: Yan Vugenfirer <yvugenfi@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-02-23 13:11:26 -06:00
Tomoki Sekiyama
4c1b8f1e83 qga: vss-win32: Use NULL as an invalid pointer for OpenEvent and CreateEvent
OpenEvent and CreateEvent WinAPI return NULL when failed to open/create
events handles, instead of INVALID_HANDLE_VALUE (although their return
types are HANDLE).
This replaces INVALID_HANDLE_VALUE related to event handles with NULL.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Reviewed-by: Gal Hammer <ghammer@redhat.com>
Reviewed-by: Yan Vugenfirer <yvugenfi@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-02-23 13:10:20 -06:00
Peter Lieven
d9738fd246 block/iscsi: fix segfault if writesame fails
commit fa6252b0 introduced a segfault because it tries
to read iTask.task->sense after iTask.task has been
freed.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 15:59:24 +01:00
Roland Dreier
64cc22841e scsi-disk: Add support for port WWN and index descriptors in VPD page 83h
To make a VM more convincing to my application, it's useful to be able
to add a port WWN and relative target port index to the descriptors
returned for VPD page 83h.  Add device properties to allow setting
these, and return them from INQUIRY commands.

Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 10:02:24 +01:00
Peter Lieven
24d3bd67ac block/iscsi: query for supported VPD pages
this patch ensures that we only query for block provisioning and
block limits vpd pages if they are advertised. It also cleans
up the inquiry code and eliminates some redundant code.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 10:02:23 +01:00
Peter Lieven
837c390137 block/iscsi: fix deadlock on scsi check condition
the retry logic was broken because the complete status
of the task structure was not reset. this resulted in
an infinite loop retrying the command over and over.

CC: qemu-stable@nongnu.org
Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 10:02:23 +01:00
Markus Armbruster
7ef8cf9a08 scsi-bus: Fix transfer length for VERIFY with BYTCHK=11b
The transfer length depends on field BYTCHK, which is encoded in byte
1, bits 1..2.  However, the guard for for case BYTCHK=11b doesn't
work, and we get case 01b instead.  Fix it.

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

Screwed up in commit d12ad44.  Spotted by Coverity.

Cc: qemu-stable@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 10:02:23 +01:00
Paolo Bonzini
703dd81aca scsi: report thin provisioning errors with werror=report
SCSI defines a status code for when a thin-provisioned LUNs would
exceed the allocated space, map ENOSPC to it.

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 10:02:23 +01:00
Fam Zheng
c5f52875b9 scsi: Change scsi sense buf size to 252
Current buffer size fails the assersion check in like

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

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

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

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

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

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

Also remove duplicated define for the macro.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-22 10:02:23 +01:00
Max Reitz
6141f3bd69 iotests: Mixed quorum child device specifications
Add a test case to test 081 for mixing full option dicts and reference
strings of specifying the quorum child block devices through QMP.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:40:19 +01:00
Max Reitz
8a87f3d722 quorum: Simplify quorum_open()
Although it may not look like it, this patch simplifies quorum_open().
qdict_array_split() is now able to return QLists with different objects
than only QDicts, therefore it will now do all the work and
quorum_open() does not have to handle reference strings by itself.

This allows mixing full option dicts and reference strings for
specifying the child block devices of quorum; furthermore, it improves
handling of malformed specifications.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:32:24 +01:00
Benoît Canet
c7fc5bc2a4 quorum: Add unit test.
Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:51 +01:00
Benoît Canet
c88a1de51a quorum: Add quorum_open() and quorum_close().
Example of command line:

-drive if=virtio,driver=quorum,\
children.0.file.filename=1.raw,\
children.0.node-name=1.raw,\
children.0.driver=raw,\
children.1.file.filename=2.raw,\
children.1.node-name=2.raw,\
children.1.driver=raw,\
children.2.file.filename=3.raw,\
children.2.node-name=3.raw,\
children.2.driver=raw,\
vote-threshold=2

blkverify=on with vote-threshold=2 and two files can be passed to
emulate blkverify.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:51 +01:00
Benoît Canet
98a7a38f81 quorum: Implement recursive .bdrv_recurse_is_first_non_filter in quorum.
This is used to activate quorum snapshot.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:51 +01:00
Benoît Canet
1c508d174d quorum: Add quorum_co_flush().
Makes a vote to select error if any.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:51 +01:00
Benoît Canet
a28e4c408b quorum: Add quorum_invalidate_cache().
We really want that live migration works with quorum so implement
quorum_invalidate_cache().

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:50 +01:00
Benoît Canet
d55dee2044 quorum: Add quorum_getlength().
Check that every bs file returns the same length.
Otherwise, return -EIO to disable the quorum and
avoid length discrepancy.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:50 +01:00
Benoît Canet
95c6bff356 quorum: Add quorum mechanism.
This patchset enables the core of the quorum mechanism.
The num_children reads are compared to get the majority version and if this
version exists more than threshold times the guest won't see the error at all.

If a block is corrupted or if an error occurs during an IO or if the quorum
cannot be established QMP events are used to report to the management.

Use gnutls's SHA-256 to compare versions.

--enable-quorum must be used to enable the feature.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:50 +01:00
Benoît Canet
7db6982a19 quorum: Add quorum_aio_readv.
Add code to do num_children reads in parallel and cleanup the structures
afterwards.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:49 +01:00
Benoît Canet
f70d7f7e4d blkverify: Extract qemu_iovec_clone() and qemu_iovec_compare() from blkverify.
qemu_iovec_compare() will be used to compare IOs vectors in quorum blkverify
mode. The patch extracts these functions in order to factorize the code.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:49 +01:00
Benoît Canet
13e7956e31 quorum: Add quorum_aio_writev and its dependencies.
Writes are mirrored num_children times on num_children devices.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:49 +01:00
Benoît Canet
cadebd7a2a quorum: Create BDRVQuorumState and BlkDriver and do init.
Create the structure holding the quorum settings and write the minimal block
driver instanciation boilerplate.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:48 +01:00
Benoît Canet
27cec15e4e quorum: Create quorum.c, add QuorumChildRequest and QuorumAIOCB.
Quorum is a block filter mirroring writes to num_children children.
For reads quorum reads each children and does a vote.
If more than vote_threshold versions are identical the quorum is reached and
this winning version is returned to the guest. So quorum prevents bit corruption.
For high availability purpose minority errors are reported via QMP but the guest
does not see them.

This patch creates the driver C source file and introduces the structures that
will be used in asynchronous reads and writes.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:29:48 +01:00
Max Reitz
64757582da check-qdict: Test termination of qdict_array_split()
qdict_array_split() should terminate if it encounters both an entry with
a key of "%u" and entries with keys prefixed "%u." for the same index.

This patch adds a test for this case.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:18:26 +01:00
Max Reitz
7841c76884 check-qdict: Adjust test for qdict_array_split()
Test the new functionality of qdict_array_split(), that is, splitting
off single objects.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:11:26 +01:00
Max Reitz
bae3f92a01 qdict: Extract non-QDicts in qdict_array_split()
Currently, qdict_array_split() only splits off entries with a key prefix
of "%u.", packing them into a new QDict. This patch makes it support
entries with the plain key "%u" as well, directly putting them into the
new QList without creating a QDict.

If there is both an entry with a key of "%u" and other entries with keys
prefixed "%u." (for the same index), the function simply terminates.

To do this, this patch also adds a static function which tests whether a
given QDict contains any keys with the given prefix. This is used to test
whether entries with a key prefixed "%u." do exist in the source QDict
without modifying it.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:11:23 +01:00
Max Reitz
ae39c4b201 qemu-config: Sections must consist of keys
In config_parse_qdict_section(), the QList returned by
qdict_array_split() is assumed to only contain QDicts. Currently, this
is true but it may (and will) change in the future. Therefore, check
whether the assumption actually holds.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 22:11:17 +01:00
Kevin Wolf
a33cc31d08 qemu-iotests: Check qemu-img command line parsing
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 22:10:31 +01:00
Kevin Wolf
a283cb6e58 qemu-img: Allow -o help with incomplete argument list
This patch allows using 'qemu-img $subcmd -o help' for the create,
convert and amend subcommands, without specifying the previously
required filename arguments.

Note that it's still allowed and meaningful to specify a filename: An
invocation like 'qemu-img create -o help sheepdog:foo' will also display
options that are provided by the Sheepdog driver.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 22:10:28 +01:00
Kevin Wolf
626f84f39d qemu-img amend: Support multiple -o options
Instead of ignoring all option values but the last one, multiple -o
options now have the same meaning as having a single option with all
settings in the order of their respective -o options.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 22:10:26 +01:00
Kevin Wolf
2dc8328b4c qemu-img convert: Support multiple -o options
Instead of ignoring all option values but the last one, multiple -o
options now have the same meaning as having a single option with all
settings in the order of their respective -o options.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 22:10:24 +01:00
Kevin Wolf
77386bf6eb qemu-img create: Support multiple -o options
If you specified multiple -o options for qemu-img create, it would
silently ignore all but the last one. This patch fixes the problem.

Now multiple -o options has the same meaning as having a single option
with all settings in the order of their respective -o options.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 22:10:21 +01:00
Kevin Wolf
7cc07ab8da qemu-option: has_help_option() and is_valid_option_list()
has_help_option() checks if any help option ('help' or '?') occurs
anywhere in an option string, so that things like 'cluster_size=4k,help'
are recognised.

is_valid_option_list() ensures that the option list doesn't have options
with leading commas or trailing unescaped commas.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 22:10:17 +01:00
Paolo Bonzini
5b7aa9b56d vdi: say why an image is bad
Instead of just putting it in debugging output, we can now put the
value in an Error.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:24 +01:00
Paolo Bonzini
76abe4071d block: do not abuse EMEDIUMTYPE
Returning "Wrong medium type" for an image that does not have a valid
header is a bit weird.  Improve the error by mentioning what format
was trying to open it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:24 +01:00
Paolo Bonzini
89ac8480a8 vmdk: correctly propagate errors
Now that we can return the "right" errors, use the Error** parameter
to pass them back instead of just printing them.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:24 +01:00
Paolo Bonzini
37f09e5e3d vmdk: do not try opening a file as both image and descriptor
This prepares for propagating errors from vmdk_open_sparse and
vmdk_open_desc_file up to the caller of vmdk_open.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:24 +01:00
Paolo Bonzini
d1833ef52b vmdk: push vmdk_read_desc up to caller
Currently, we just try reading a VMDK file as both image and descriptor.
This makes it hard to choose which of the two attempts gave the best error.
We'll decide in advance if the file looks like an image or a descriptor,
and this patch is the first step to that end.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:24 +01:00
Paolo Bonzini
a8842e6d2a vmdk: extract vmdk_read_desc
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:24 +01:00
Paolo Bonzini
c0f92b526d vvfat: correctly propagate errors
Before:
    $ ./qemu-io-old
    qemu-io-old> open -r -o driver=vvfat,fat-type=24,dir=i386-softmmu
    Valid FAT types are only 12, 16 and 32
    qemu-io-old: can't open device (null): Could not open image: Invalid argument

After:
    $ ./qemu-io
    qemu-io> open -r -o driver=vvfat,fat-type=24,dir=i386-softmmu
    qemu-io: can't open device (null): Valid FAT types are only 12, 16 and 32

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
6890aad46b vhdx: correctly propagate errors
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
0fea6b7972 qed: correctly propagate errors
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
b6d5066d32 qcow: correctly propagate errors
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
2a94fee3f6 curl: correctly propagate errors
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
f8d924e481 cow: correctly propagate errors
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
a7451cb850 gluster: correctly propagate errors
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
24897a767b gluster: default scheme to gluster:// and host to localhost.
Currently, "gluster:///volname/img" and (using file. options)
"file.driver=gluster,file.filename=foo" will segfault.  Also,
"//host/volname/img" will be rejected, but it is a valid URL
that should be accepted just fine with "file.driver=gluster".
Accept all of these, by inferring missing transport and host
as TCP and localhost respectively.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
f2917853f7 iscsi: correctly propagate errors in iscsi_open
Before:
    $ ./qemu-io-old
    qemu-io-old> open -r -o file.driver=iscsi,file.filename=foo
    Failed to parse URL : foo
    qemu-io-old: can't open device (null): Could not open 'foo': Invalid argument

After:
    $ ./qemu-io
    qemu-io> open -r -o file.driver=iscsi,file.filename=foo
    qemu-io: can't open device (null): Failed to parse URL : foo

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
35cb1748d5 iscsi: fix indentation
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
537b41f501 nbd: move socket wrappers to qemu-nbd
qemu-nbd is one of the few valid users of qerror_report_err.  Move
the error-reporting socket wrappers there.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:23 +01:00
Paolo Bonzini
c06b72781d nbd: inline tcp_socket_incoming_spec into sole caller
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Paolo Bonzini
77e8b9ca64 nbd: correctly propagate errors
Before:
    $ ./qemu-io-old
    qemu-io-old> open -r -o file.driver=nbd
    one of path and host must be specified.
    qemu-io-old: can't open device (null): Could not open image: Invalid argument
    $ ./qemu-io-old
    qemu-io-old> open -r -o file.driver=nbd,file.host=foo,file.path=bar
    path and host may not be used at the same time.
    qemu-io-old: can't open device (null): Could not open image: Invalid argument

After:
    $ ./qemu-io
    qemu-io> open -r -o file.driver=nbd
    qemu-io: can't open device (null): one of path and host must be specified.
    $ ./qemu-io
    qemu-io> open -r -o file.driver=nbd,file.host=foo,file.path=bar
    qemu-io: can't open device (null): path and host may not be used at the same time.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Paolo Bonzini
a69d9af449 nbd: produce a better error if neither host nor port is passed
Before:
    $ qemu-io-old
    qemu-io-old> open -r -o file.driver=nbd
    qemu-io-old: can't open device (null): Could not open image: Invalid argument
    $ ./qemu-io-old
    qemu-io-old> open -r -o file.driver=nbd,file.host=foo,file.path=bar
    path and host may not be used at the same time.
    qemu-io-old: can't open device (null): Could not open image: Invalid argument

After:
    $ ./qemu-io
    qemu-io> open -r -o file.driver=nbd
    one of path and host must be specified.
    qemu-io: can't open device (null): Could not open image: Invalid argument
    $ ./qemu-io
    qemu-io> open -r -o file.driver=nbd,file.host=foo,file.path=bar
    path and host may not be used at the same time.
    qemu-io: can't open device (null): Could not open image: Invalid argument

Next patch will fix the error propagation.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
f7d9fd8c72 block: Remove bdrv_open_image()'s force_raw option
This option is now unnecessary since specifying BDRV_O_PROTOCOL as flag
will do exactly the same.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
5acd9d81e1 block: Reuse success path from bdrv_open()
The fail and success paths of bdrv_file_open() may be further shortened
by reusing code already existent in bdrv_open(). This includes
bdrv_file_open() not taking the reference to options which allows the
removal of QDECREF(options) in that function.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
5469a2a688 block: Handle bs->options in bdrv_open() only
The fail paths of bdrv_file_open() and bdrv_open() naturally exhibit
similarities, thus it is possible to reuse the one from bdrv_open() and
shorten the one in bdrv_file_open() accordingly.

Also, setting bs->options in bdrv_file_open() is not necessary if it is
already done in bdrv_open().

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
d4446eae63 block: Remove bdrv_new() from bdrv_file_open()
Change bdrv_file_open() to take a simple pointer to an already existing
BDS instead of an indirect one. The BDS will be created in bdrv_open()
if necessary.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
5d12aa63c7 block: Reuse reference handling from bdrv_open()
Remove the reference parameter and the related handling code from
bdrv_file_open(), since it exists in bdrv_open() now as well.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
2e40134bfd block: Make bdrv_file_open() static
Add the bdrv_open() option BDRV_O_PROTOCOL which results in passing the
call to bdrv_file_open(). Additionally, make bdrv_file_open() static and
therefore bdrv_open() the only way to call it.

Consequently, all existing calls to bdrv_file_open() have to be adjusted
to use bdrv_open() with the BDRV_O_PROTOCOL flag instead.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
ddf5636dc9 block: Add reference parameter to bdrv_open()
Allow bdrv_open() to handle references to existing block devices just as
bdrv_file_open() is already capable of.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:22 +01:00
Max Reitz
f67503e5bd block: Change BDS parameter of bdrv_open() to **
Make bdrv_open() take a pointer to a BDS pointer, similarly to
bdrv_file_open(). If a pointer to a NULL pointer is given, bdrv_open()
will create a new BDS with an empty name; if the BDS pointer is not
NULL, that existing BDS will be reused (in the same way as bdrv_open()
already did).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-02-21 21:02:21 +01:00
Kevin Wolf
e6dc8a1f83 block: Fix bdrv_is_first_non_filter()
Consider top level BlockDriverStates as well.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Tested-by: Benoit Canet <benoit@irqsave.net>
2014-02-21 21:02:21 +01:00
Kevin Wolf
a71835a0cc qcow2: Set zero flag for discarded clusters
Instead of making the backing file contents visible again after a discard
request, set the zero flag if possible (i.e. on version >= 3).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-02-21 21:02:21 +01:00
Alexander Graf
521f438e36 KVM: Use return value for error print
Commit 94ccff13 introduced a more verbose failure message and retry
operations on KVM VM creation. However, it ended up using a variable
for its failure message that hasn't been initialized yet.

Fix it to use the value it meant to set.

Cc: qemu-stable@nongnu.org
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-21 11:19:34 +01:00
Olaf Hering
58da5b1e01 xen_disk: fix io accounting
bdrv_acct_done was called unconditional. But in case the ioreq has no
segments there is no matching bdrv_acct_start call. This could lead to
bogus accounting values.

Found by code inspection.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2014-02-20 17:57:13 +00:00
Stefano Stabellini
15e8159e76 Call pci_piix3_xen_ide_unplug from unplug_disks
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 17:28:08 +00:00
Paolo Bonzini
f966f9ddd1 build: softmmu targets do not have a "main.o" file
Thus this rule is useless.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Don Slutz
66518bf668 configure: Disable libtool if -fPIE does not work with it (bug #1257099)
Adjust TMPO and added TMPB, TMPL, and TMPA.  libtool needs the names
to be fixed (TMPB).

Add new functions do_libtool and libtool_prog.

Add check for broken gcc and libtool.

Signed-off-by: Don Slutz <dslutz@verizon.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Fam Zheng
d3399d7cf8 block: convert block drivers linked with libs to modules
The converted block drivers are:

    curl
    iscsi
    rbd
    ssh
    glusterfs

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Fam Zheng
cc47569881 Makefile: introduce common-obj-m and block-obj-m for DSO
$(common-obj-m) will include $(block-obj-m), like $(common-obj-y) does
for $(block-obj-y).

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Fam Zheng
e3be6f0ecc Makefile: install modules with "make install"
Install all the modules to ${MODDIR}.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Fam Zheng
e26110cfc6 module: implement module loading
This patch adds loading, stamp checking and initialization of modules.

The init function of dynamic module is no longer directly called as
__attribute__((constructor)) in static linked version, it is called
only after passed the checking of presense of stamp symbol:

    qemu_stamp_$RELEASEHASH

where $RELEASEHASH is generated by hashing version strings and content
of configure script.

With this, modules built from a different tree/version/configure will
not be loaded.

The module loading code requires gmodule-2.0.

Modules are searched under
 - CONFIG_MODDIR
 - executable folder (to allow running qemu-{img,io} in the build
   directory)
 - ../ of executable folder (to allow running system emulator in the
   build directory)

Modules are linked under their subdir respectively, then copied to top
level of build directory for above convinience, e.g.:
    $(BUILD_DIR)/block/curl.so -> $(BUILD_DIR)/block-curl.so

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Fam Zheng
17969268f5 rules.mak: introduce DSO rules
Add necessary rules and flags for shared object generation.
The new rules introduced here are:

1) %.o in $(common-obj-m) is compiled to %.o, then linked to %.so.

2) %.mo in $(common-obj-m) is the placeholder for %.so for pattern
matching in Makefile. It's linked to "-shared" with all its dependencies
(multiple *.o) as input. Which means the list of depended objects must
be specified in each sub-Makefile.objs:

    foo.mo-objs := bar.o baz.o qux.o

in the same style with foo.o-cflags and foo.o-libs. The objects here
will be prefixed with "$(obj)/" if it's a subdirectory Makefile.objs.

3) For all files ending up in %.so, the following is added automatically:

    foo.o-cflags += -fPIC -DBUILD_DSO

Also introduce --enable-modules in configure, the option will enable
support of shared object build. Otherwise objects are static linked to
executables.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:14:18 +01:00
Paolo Bonzini
13b6ce0ec9 darwin: do not use -mdynamic-no-pic
While -mdynamic-no-pic can speed up the code somewhat, it is only used
on the legacy PowerPC Mac OS X, and I am not sure if anyone is still
testing that.  Disabling PIC can cause problems when enabling modules,
so do not do that.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:12:54 +01:00
Fam Zheng
6ebc91e5d0 block: use per-object cflags and libs
No longer adds flags and libs for them to global variables, instead
create config-host.mak variables like FOO_CFLAGS and FOO_LIBS, which is
used as per object cflags and libs.

This removes unwanted dependencies from libcacard.

Signed-off-by: Fam Zheng <famz@redhat.com>
[Split from Fam's patch to enable modules. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:12:54 +01:00
Fam Zheng
5c0d52bcd3 rules.mak: allow per object cflags and libs
Adds extract-libs in LINK to expand any "per object libs", the syntax to define
such a libs options is like:

        foo.o-libs := $(CURL_LIBS)

in block/Makefile.objs.

Similarly,

        foo.o-cflags := $(FOO_CFLAGS)

is also supported.

"foo.o" must be listed in a nested var (e.g. common-obj-y) to make the
option variables effective.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:12:54 +01:00
Fam Zheng
ba1183da9a rules.mak: fix $(obj) to a real relative path
Makefile.target includes rule.mak and unnested common-obj-y, then prefix
them with '../', this will ignore object specific QEMU_CFLAGS in subdir
Makefile.objs:

    $(obj)/curl.o: QEMU_CFLAGS += $(CURL_CFLAGS)

Because $(obj) here is './block', instead of '../block'. This doesn't
hurt compiling because we basically build all .o from top Makefile,
before entering Makefile.target, but it will affact arriving per-object
libs support.

The starting point of $(obj) is passed in as argument of unnest-vars, as
well as nested variables, so that different Makefiles can pass in a
right value.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:12:54 +01:00
Fam Zheng
10f5bff622 util: Split out exec_dir from os_find_datadir
With this change, main() calls qemu_init_exec_dir and uses argv[0] to
init exec_dir. The saved value can be retrieved with
qemu_get_exec_dir later. It will be reused by module loading.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-02-20 13:12:54 +01:00
363 changed files with 19226 additions and 3656 deletions

3
.gitignore vendored
View File

@@ -66,6 +66,9 @@ libuser
*.cp *.cp
*.dvi *.dvi
*.exe *.exe
*.dll
*.so
*.mo
*.fn *.fn
*.ky *.ky
*.log *.log

View File

@@ -726,7 +726,7 @@ F: vl.c
Human Monitor (HMP) Human Monitor (HMP)
M: Luiz Capitulino <lcapitulino@redhat.com> M: Luiz Capitulino <lcapitulino@redhat.com>
S: Supported S: Maintained
F: monitor.c F: monitor.c
F: hmp.c F: hmp.c
F: hmp-commands.hx F: hmp-commands.hx
@@ -758,7 +758,7 @@ T: git git://github.com/bonzini/qemu.git nbd-next
QAPI QAPI
M: Luiz Capitulino <lcapitulino@redhat.com> M: Luiz Capitulino <lcapitulino@redhat.com>
M: Michael Roth <mdroth@linux.vnet.ibm.com> M: Michael Roth <mdroth@linux.vnet.ibm.com>
S: Supported S: Maintained
F: qapi/ F: qapi/
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
@@ -772,7 +772,7 @@ T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
QMP QMP
M: Luiz Capitulino <lcapitulino@redhat.com> M: Luiz Capitulino <lcapitulino@redhat.com>
S: Supported S: Maintained
F: qmp.c F: qmp.c
F: monitor.c F: monitor.c
F: qmp-commands.hx F: qmp-commands.hx

View File

@@ -127,13 +127,29 @@ defconfig:
ifneq ($(wildcard config-host.mak),) ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/Makefile.objs include $(SRC_PATH)/Makefile.objs
endif
dummy := $(call unnest-vars,, \
stub-obj-y \
util-obj-y \
qga-obj-y \
block-obj-y \
block-obj-m \
common-obj-y \
common-obj-m)
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/tests/Makefile include $(SRC_PATH)/tests/Makefile
endif endif
ifeq ($(CONFIG_SMARTCARD_NSS),y) ifeq ($(CONFIG_SMARTCARD_NSS),y)
include $(SRC_PATH)/libcacard/Makefile include $(SRC_PATH)/libcacard/Makefile
endif endif
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
config-host.h: config-host.h-timestamp config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak config-host.h-timestamp: config-host.mak
@@ -143,6 +159,7 @@ qemu-options.def: $(SRC_PATH)/qemu-options.hx
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS)) SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES)) SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak $(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
subdir-%: subdir-%:
@@ -192,6 +209,9 @@ Makefile: $(version-obj-y) $(version-lobj-y)
libqemustub.a: $(stub-obj-y) libqemustub.a: $(stub-obj-y)
libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL
util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
###################################################################### ######################################################################
qemu-img.o: qemu-img-cmds.h qemu-img.o: qemu-img-cmds.h
@@ -247,6 +267,8 @@ clean:
rm -f qemu-options.def rm -f qemu-options.def
find . -name '*.[oda]' -type f -exec rm -f {} + find . -name '*.[oda]' -type f -exec rm -f {} +
find . -name '*.l[oa]' -type f -exec rm -f {} + find . -name '*.l[oa]' -type f -exec rm -f {} +
find . -name '*$(DSOSUF)' -type f -exec rm -f {} +
find . -name '*.mo' -type f -exec rm -f {} +
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -f fsdev/*.pod rm -f fsdev/*.pod
rm -rf .libs */.libs rm -rf .libs */.libs
@@ -298,7 +320,7 @@ ifdef INSTALL_BLOBS
BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \ BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \ vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
acpi-dsdt.aml q35-acpi-dsdt.aml \ acpi-dsdt.aml q35-acpi-dsdt.aml \
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin \ ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \ pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \ efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
@@ -354,6 +376,12 @@ install-datadir install-localstatedir
ifneq ($(TOOLS),) ifneq ($(TOOLS),)
$(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)" $(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)"
endif endif
ifneq ($(CONFIG_MODULES),)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
for s in $(patsubst %.mo,%$(DSOSUF),$(modules-m)); do \
$(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$${s//\//-}"; \
done
endif
ifneq ($(HELPERS-y),) ifneq ($(HELPERS-y),)
$(INSTALL_DIR) "$(DESTDIR)$(libexecdir)" $(INSTALL_DIR) "$(DESTDIR)$(libexecdir)"
$(INSTALL_PROG) $(STRIP_OPT) $(HELPERS-y) "$(DESTDIR)$(libexecdir)" $(INSTALL_PROG) $(STRIP_OPT) $(HELPERS-y) "$(DESTDIR)$(libexecdir)"
@@ -371,7 +399,7 @@ endif
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \ $(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
done done
for d in $(TARGET_DIRS); do \ for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \ $(MAKE) $(SUBDIR_MAKEFLAGS) TARGET_DIR=$$d/ -C $$d $@ || exit 1 ; \
done done
# various test targets # various test targets

View File

@@ -19,11 +19,8 @@ block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
block-obj-y += qemu-coroutine-sleep.o block-obj-y += qemu-coroutine-sleep.o
block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) block-obj-m = block/
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
# only pull in the actual virtio-9p device if we also enabled virtio.
CONFIG_REALLY_VIRTFS=y
endif
###################################################################### ######################################################################
# smartcard # smartcard
@@ -41,7 +38,7 @@ libcacard-y += libcacard/vcardt.o
# single QEMU executable should support all CPUs and machines. # single QEMU executable should support all CPUs and machines.
ifeq ($(CONFIG_SOFTMMU),y) ifeq ($(CONFIG_SOFTMMU),y)
common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/ common-obj-y = blockdev.o blockdev-nbd.o block/
common-obj-y += net/ common-obj-y += net/
common-obj-y += qdev-monitor.o device-hotplug.o common-obj-y += qdev-monitor.o device-hotplug.o
common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_WIN32) += os-win32.o
@@ -111,18 +108,3 @@ version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
# by libqemuutil.a. These should be moved to a separate .json schema. # by libqemuutil.a. These should be moved to a separate .json schema.
qga-obj-y = qga/ qapi-types.o qapi-visit.o qga-obj-y = qga/ qapi-types.o qapi-visit.o
qga-vss-dll-obj-y = qga/ qga-vss-dll-obj-y = qga/
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
QEMU_CFLAGS+=$(GLIB_CFLAGS)
nested-vars += \
stub-obj-y \
util-obj-y \
qga-obj-y \
qga-vss-dll-obj-y \
block-obj-y \
common-obj-y
dummy := $(call unnest-vars)

View File

@@ -130,8 +130,6 @@ else
obj-y += hw/$(TARGET_BASE_ARCH)/ obj-y += hw/$(TARGET_BASE_ARCH)/
endif endif
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
endif # CONFIG_SOFTMMU endif # CONFIG_SOFTMMU
@@ -139,13 +137,26 @@ endif # CONFIG_SOFTMMU
# Workaround for http://gcc.gnu.org/PR55489, see configure. # Workaround for http://gcc.gnu.org/PR55489, see configure.
%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS) %/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
nested-vars += obj-y dummy := $(call unnest-vars,,obj-y)
# This resolves all nested paths, so it must come last # we are making another call to unnest-vars with different vars, protect obj-y,
# it can be overriden in subdir Makefile.objs
obj-y-save := $(obj-y)
block-obj-y :=
common-obj-y :=
include $(SRC_PATH)/Makefile.objs include $(SRC_PATH)/Makefile.objs
dummy := $(call unnest-vars,.., \
block-obj-y \
block-obj-m \
common-obj-y \
common-obj-m)
all-obj-y = $(obj-y) # Now restore obj-y
all-obj-y += $(addprefix ../, $(common-obj-y)) obj-y := $(obj-y-save)
all-obj-y = $(obj-y) $(common-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
ifndef CONFIG_HAIKU ifndef CONFIG_HAIKU
LIBS+=-lm LIBS+=-lm

View File

@@ -122,7 +122,6 @@ static void check_guest_throttling(void);
#define RAM_SAVE_FLAG_XBZRLE 0x40 #define RAM_SAVE_FLAG_XBZRLE 0x40
/* 0x80 is reserved in migration.h start with 0x100 next */ /* 0x80 is reserved in migration.h start with 0x100 next */
static struct defconfig_file { static struct defconfig_file {
const char *filename; const char *filename;
/* Indicates it is an user config file (disabled by -no-user-config) */ /* Indicates it is an user config file (disabled by -no-user-config) */
@@ -133,6 +132,7 @@ static struct defconfig_file {
{ NULL }, /* end of list */ { NULL }, /* end of list */
}; };
static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
int qemu_read_default_config_files(bool userconfig) int qemu_read_default_config_files(bool userconfig)
{ {
@@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
return size; return size;
} }
/* This is the last block that we have visited serching for dirty pages
*/
static RAMBlock *last_seen_block;
/* This is the last block from where we have sent data */
static RAMBlock *last_sent_block;
static ram_addr_t last_offset;
static unsigned long *migration_bitmap;
static uint64_t migration_dirty_pages;
static uint32_t last_version;
static bool ram_bulk_stage;
/* Update the xbzrle cache to reflect a page that's been sent as all 0.
* The important thing is that a stale (not-yet-0'd) page be replaced
* by the new data.
* As a bonus, if the page wasn't in the cache it gets added so that
* when a small write is made into the 0'd page it gets XBZRLE sent
*/
static void xbzrle_cache_zero_page(ram_addr_t current_addr)
{
if (ram_bulk_stage || !migrate_use_xbzrle()) {
return;
}
/* We don't care if this fails to allocate a new cache page
* as long as it updated an old one */
cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
}
#define ENCODING_FLAG_XBZRLE 0x1 #define ENCODING_FLAG_XBZRLE 0x1
static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
@@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
return bytes_sent; return bytes_sent;
} }
/* This is the last block that we have visited serching for dirty pages
*/
static RAMBlock *last_seen_block;
/* This is the last block from where we have sent data */
static RAMBlock *last_sent_block;
static ram_addr_t last_offset;
static unsigned long *migration_bitmap;
static uint64_t migration_dirty_pages;
static uint32_t last_version;
static bool ram_bulk_stage;
static inline static inline
ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr, ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
ram_addr_t start) ram_addr_t start)
@@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
} else { } else {
int ret; int ret;
uint8_t *p; uint8_t *p;
bool send_async = true;
int cont = (block == last_sent_block) ? int cont = (block == last_sent_block) ?
RAM_SAVE_FLAG_CONTINUE : 0; RAM_SAVE_FLAG_CONTINUE : 0;
@@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
ret = ram_control_save_page(f, block->offset, ret = ram_control_save_page(f, block->offset,
offset, TARGET_PAGE_SIZE, &bytes_sent); offset, TARGET_PAGE_SIZE, &bytes_sent);
current_addr = block->offset + offset;
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) { if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
if (ret != RAM_SAVE_CONTROL_DELAYED) { if (ret != RAM_SAVE_CONTROL_DELAYED) {
if (bytes_sent > 0) { if (bytes_sent > 0) {
@@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
RAM_SAVE_FLAG_COMPRESS); RAM_SAVE_FLAG_COMPRESS);
qemu_put_byte(f, 0); qemu_put_byte(f, 0);
bytes_sent++; bytes_sent++;
/* Must let xbzrle know, otherwise a previous (now 0'd) cached
* page would be stale
*/
xbzrle_cache_zero_page(current_addr);
} else if (!ram_bulk_stage && migrate_use_xbzrle()) { } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
current_addr = block->offset + offset;
bytes_sent = save_xbzrle_page(f, p, current_addr, block, bytes_sent = save_xbzrle_page(f, p, current_addr, block,
offset, cont, last_stage); offset, cont, last_stage);
if (!last_stage) { if (!last_stage) {
/* We must send exactly what's in the xbzrle cache
* even if the page wasn't xbzrle compressed, so that
* it's right next time.
*/
p = get_cached_data(XBZRLE.cache, current_addr); p = get_cached_data(XBZRLE.cache, current_addr);
/* Can't send this cached data async, since the cache page
* might get updated before it gets to the wire
*/
send_async = false;
} }
} }
/* XBZRLE overflow or normal page */ /* XBZRLE overflow or normal page */
if (bytes_sent == -1) { if (bytes_sent == -1) {
bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE); bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE); if (send_async) {
qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
} else {
qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
}
bytes_sent += TARGET_PAGE_SIZE; bytes_sent += TARGET_PAGE_SIZE;
acct_info.norm_pages++; acct_info.norm_pages++;
} }

View File

@@ -566,7 +566,7 @@ CharDriverState *chr_baum_init(void)
BaumDriverState *baum; BaumDriverState *baum;
CharDriverState *chr; CharDriverState *chr;
brlapi_handle_t *handle; brlapi_handle_t *handle;
#ifdef CONFIG_SDL #if defined(CONFIG_SDL) && SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
SDL_SysWMinfo info; SDL_SysWMinfo info;
#endif #endif
int tty; int tty;
@@ -595,7 +595,7 @@ CharDriverState *chr_baum_init(void)
goto fail; goto fail;
} }
#ifdef CONFIG_SDL #if defined(CONFIG_SDL) && SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
SDL_VERSION(&info.version); SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info)) if (SDL_GetWMInfo(&info))

269
block.c
View File

@@ -547,8 +547,9 @@ int get_tmp_filename(char *filename, int size)
int fd; int fd;
const char *tmpdir; const char *tmpdir;
tmpdir = getenv("TMPDIR"); tmpdir = getenv("TMPDIR");
if (!tmpdir) if (!tmpdir) {
tmpdir = "/tmp"; tmpdir = "/var/tmp";
}
if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) { if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
return -EOVERFLOW; return -EOVERFLOW;
} }
@@ -934,7 +935,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
bdrv_refresh_limits(bs); bdrv_refresh_limits(bs);
assert(bdrv_opt_mem_align(bs) != 0); assert(bdrv_opt_mem_align(bs) != 0);
assert(bs->request_alignment != 0); assert((bs->request_alignment != 0) || bs->sg);
#ifndef _WIN32 #ifndef _WIN32
if (bs->is_temporary) { if (bs->is_temporary) {
@@ -955,53 +956,27 @@ free_and_fail:
/* /*
* Opens a file using a protocol (file, host_device, nbd, ...) * Opens a file using a protocol (file, host_device, nbd, ...)
* *
* options is a QDict of options to pass to the block drivers, or NULL for an * options is an indirect pointer to a QDict of options to pass to the block
* empty set of options. The reference to the QDict belongs to the block layer * drivers, or pointer to NULL for an empty set of options. If this function
* after the call (even on failure), so if the caller intends to reuse the * takes ownership of the QDict reference, it will set *options to NULL;
* dictionary, it needs to use QINCREF() before calling bdrv_file_open. * otherwise, it will contain unused/unrecognized options after this function
* returns. Then, the caller is responsible for freeing it. If it intends to
* reuse the QDict, QINCREF() should be called beforehand.
*/ */
int bdrv_file_open(BlockDriverState **pbs, const char *filename, static int bdrv_file_open(BlockDriverState *bs, const char *filename,
const char *reference, QDict *options, int flags, QDict **options, int flags, Error **errp)
Error **errp)
{ {
BlockDriverState *bs = NULL;
BlockDriver *drv; BlockDriver *drv;
const char *drvname; const char *drvname;
bool allow_protocol_prefix = false; bool allow_protocol_prefix = false;
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
/* NULL means an empty set of options */
if (options == NULL) {
options = qdict_new();
}
if (reference) {
if (filename || qdict_size(options)) {
error_setg(errp, "Cannot reference an existing block device with "
"additional options or a new filename");
return -EINVAL;
}
QDECREF(options);
bs = bdrv_lookup_bs(reference, reference, errp);
if (!bs) {
return -ENODEV;
}
bdrv_ref(bs);
*pbs = bs;
return 0;
}
bs = bdrv_new("");
bs->options = options;
options = qdict_clone_shallow(options);
/* Fetch the file name from the options QDict if necessary */ /* Fetch the file name from the options QDict if necessary */
if (!filename) { if (!filename) {
filename = qdict_get_try_str(options, "filename"); filename = qdict_get_try_str(*options, "filename");
} else if (filename && !qdict_haskey(options, "filename")) { } else if (filename && !qdict_haskey(*options, "filename")) {
qdict_put(options, "filename", qstring_from_str(filename)); qdict_put(*options, "filename", qstring_from_str(filename));
allow_protocol_prefix = true; allow_protocol_prefix = true;
} else { } else {
error_setg(errp, "Can't specify 'file' and 'filename' options at the " error_setg(errp, "Can't specify 'file' and 'filename' options at the "
@@ -1011,13 +986,13 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
} }
/* Find the right block driver */ /* Find the right block driver */
drvname = qdict_get_try_str(options, "driver"); drvname = qdict_get_try_str(*options, "driver");
if (drvname) { if (drvname) {
drv = bdrv_find_format(drvname); drv = bdrv_find_format(drvname);
if (!drv) { if (!drv) {
error_setg(errp, "Unknown driver '%s'", drvname); error_setg(errp, "Unknown driver '%s'", drvname);
} }
qdict_del(options, "driver"); qdict_del(*options, "driver");
} else if (filename) { } else if (filename) {
drv = bdrv_find_protocol(filename, allow_protocol_prefix); drv = bdrv_find_protocol(filename, allow_protocol_prefix);
if (!drv) { if (!drv) {
@@ -1036,46 +1011,35 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
/* Parse the filename and open it */ /* Parse the filename and open it */
if (drv->bdrv_parse_filename && filename) { if (drv->bdrv_parse_filename && filename) {
drv->bdrv_parse_filename(filename, options, &local_err); drv->bdrv_parse_filename(filename, *options, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
qdict_del(options, "filename");
if (!drv->bdrv_needs_filename) {
qdict_del(*options, "filename");
} else {
filename = qdict_get_str(*options, "filename");
}
} }
if (!drv->bdrv_file_open) { if (!drv->bdrv_file_open) {
ret = bdrv_open(bs, filename, options, flags, drv, &local_err); ret = bdrv_open(&bs, filename, NULL, *options, flags, drv, &local_err);
options = NULL; *options = NULL;
} else { } else {
ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err); ret = bdrv_open_common(bs, NULL, *options, flags, drv, &local_err);
} }
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto fail; goto fail;
} }
/* Check if any unknown options were used */
if (options && (qdict_size(options) != 0)) {
const QDictEntry *entry = qdict_first(options);
error_setg(errp, "Block protocol '%s' doesn't support the option '%s'",
drv->format_name, entry->key);
ret = -EINVAL;
goto fail;
}
QDECREF(options);
bs->growable = 1; bs->growable = 1;
*pbs = bs;
return 0; return 0;
fail: fail:
QDECREF(options);
if (!bs->drv) {
QDECREF(bs->options);
}
bdrv_unref(bs);
return ret; return ret;
} }
@@ -1115,8 +1079,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
sizeof(backing_filename)); sizeof(backing_filename));
} }
bs->backing_hd = bdrv_new("");
if (bs->backing_format[0] != '\0') { if (bs->backing_format[0] != '\0') {
back_drv = bdrv_find_format(bs->backing_format); back_drv = bdrv_find_format(bs->backing_format);
} }
@@ -1125,11 +1087,11 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
BDRV_O_COPY_ON_READ); BDRV_O_COPY_ON_READ);
ret = bdrv_open(bs->backing_hd, assert(bs->backing_hd == NULL);
*backing_filename ? backing_filename : NULL, options, ret = bdrv_open(&bs->backing_hd,
*backing_filename ? backing_filename : NULL, NULL, options,
back_flags, back_drv, &local_err); back_flags, back_drv, &local_err);
if (ret < 0) { if (ret < 0) {
bdrv_unref(bs->backing_hd);
bs->backing_hd = NULL; bs->backing_hd = NULL;
bs->open_flags |= BDRV_O_NO_BACKING; bs->open_flags |= BDRV_O_NO_BACKING;
error_setg(errp, "Could not open backing file: %s", error_setg(errp, "Could not open backing file: %s",
@@ -1153,10 +1115,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
* Opens a disk image whose options are given as BlockdevRef in another block * Opens a disk image whose options are given as BlockdevRef in another block
* device's options. * device's options.
* *
* If force_raw is true, bdrv_file_open() will be used, thereby preventing any
* image format auto-detection. If it is false and a filename is given,
* bdrv_open() will be used for auto-detection.
*
* If allow_none is true, no image will be opened if filename is false and no * If allow_none is true, no image will be opened if filename is false and no
* BlockdevRef is given. *pbs will remain unchanged and 0 will be returned. * BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
* *
@@ -1166,16 +1124,21 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
* BlockdevRef. * BlockdevRef.
* *
* The BlockdevRef will be removed from the options QDict. * The BlockdevRef will be removed from the options QDict.
*
* To conform with the behavior of bdrv_open(), *pbs has to be NULL.
*/ */
int bdrv_open_image(BlockDriverState **pbs, const char *filename, int bdrv_open_image(BlockDriverState **pbs, const char *filename,
QDict *options, const char *bdref_key, int flags, QDict *options, const char *bdref_key, int flags,
bool force_raw, bool allow_none, Error **errp) bool allow_none, Error **errp)
{ {
QDict *image_options; QDict *image_options;
int ret; int ret;
char *bdref_key_dot; char *bdref_key_dot;
const char *reference; const char *reference;
assert(pbs);
assert(*pbs == NULL);
bdref_key_dot = g_strdup_printf("%s.", bdref_key); bdref_key_dot = g_strdup_printf("%s.", bdref_key);
qdict_extract_subqdict(options, &image_options, bdref_key_dot); qdict_extract_subqdict(options, &image_options, bdref_key_dot);
g_free(bdref_key_dot); g_free(bdref_key_dot);
@@ -1192,30 +1155,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
goto done; goto done;
} }
if (filename && !force_raw) { ret = bdrv_open(pbs, filename, reference, image_options, flags, NULL, errp);
/* If a filename is given and the block driver should be detected
automatically (instead of using none), use bdrv_open() in order to do
that auto-detection. */
BlockDriverState *bs;
if (reference) {
error_setg(errp, "Cannot reference an existing block device while "
"giving a filename");
ret = -EINVAL;
goto done;
}
bs = bdrv_new("");
ret = bdrv_open(bs, filename, image_options, flags, NULL, errp);
if (ret < 0) {
bdrv_unref(bs);
} else {
*pbs = bs;
}
} else {
ret = bdrv_file_open(pbs, filename, reference, image_options, flags,
errp);
}
done: done:
qdict_del(options, bdref_key); qdict_del(options, bdref_key);
@@ -1229,17 +1169,58 @@ done:
* empty set of options. The reference to the QDict belongs to the block layer * empty set of options. The reference to the QDict belongs to the block layer
* after the call (even on failure), so if the caller intends to reuse the * after the call (even on failure), so if the caller intends to reuse the
* dictionary, it needs to use QINCREF() before calling bdrv_open. * dictionary, it needs to use QINCREF() before calling bdrv_open.
*
* If *pbs is NULL, a new BDS will be created with a pointer to it stored there.
* If it is not NULL, the referenced BDS will be reused.
*
* The reference parameter may be used to specify an existing block device which
* should be opened. If specified, neither options nor a filename may be given,
* nor can an existing BDS be reused (that is, *pbs has to be NULL).
*/ */
int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, int bdrv_open(BlockDriverState **pbs, const char *filename,
int flags, BlockDriver *drv, Error **errp) const char *reference, QDict *options, int flags,
BlockDriver *drv, Error **errp)
{ {
int ret; int ret;
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
char tmp_filename[PATH_MAX + 1]; char tmp_filename[PATH_MAX + 1];
BlockDriverState *file = NULL; BlockDriverState *file = NULL, *bs;
const char *drvname; const char *drvname;
Error *local_err = NULL; Error *local_err = NULL;
assert(pbs);
if (reference) {
bool options_non_empty = options ? qdict_size(options) : false;
QDECREF(options);
if (*pbs) {
error_setg(errp, "Cannot reuse an existing BDS when referencing "
"another block device");
return -EINVAL;
}
if (filename || options_non_empty) {
error_setg(errp, "Cannot reference an existing block device with "
"additional options or a new filename");
return -EINVAL;
}
bs = bdrv_lookup_bs(reference, reference, errp);
if (!bs) {
return -ENODEV;
}
bdrv_ref(bs);
*pbs = bs;
return 0;
}
if (*pbs) {
bs = *pbs;
} else {
bs = bdrv_new("");
}
/* NULL means an empty set of options */ /* NULL means an empty set of options */
if (options == NULL) { if (options == NULL) {
options = qdict_new(); options = qdict_new();
@@ -1248,6 +1229,20 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
bs->options = options; bs->options = options;
options = qdict_clone_shallow(options); options = qdict_clone_shallow(options);
if (flags & BDRV_O_PROTOCOL) {
assert(!drv);
ret = bdrv_file_open(bs, filename, &options, flags & ~BDRV_O_PROTOCOL,
&local_err);
if (!ret) {
drv = bs->drv;
goto done;
} else if (bs->drv) {
goto close_and_fail;
} else {
goto fail;
}
}
/* For snapshot=on, create a temporary qcow2 overlay */ /* For snapshot=on, create a temporary qcow2 overlay */
if (flags & BDRV_O_SNAPSHOT) { if (flags & BDRV_O_SNAPSHOT) {
BlockDriverState *bs1; BlockDriverState *bs1;
@@ -1260,12 +1255,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
instead of opening 'filename' directly */ instead of opening 'filename' directly */
/* Get the required size from the image */ /* Get the required size from the image */
bs1 = bdrv_new("");
QINCREF(options); QINCREF(options);
ret = bdrv_open(bs1, filename, options, BDRV_O_NO_BACKING, bs1 = NULL;
ret = bdrv_open(&bs1, filename, NULL, options, BDRV_O_NO_BACKING,
drv, &local_err); drv, &local_err);
if (ret < 0) { if (ret < 0) {
bdrv_unref(bs1);
goto fail; goto fail;
} }
total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK; total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
@@ -1322,9 +1316,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
flags |= BDRV_O_ALLOW_RDWR; flags |= BDRV_O_ALLOW_RDWR;
} }
assert(file == NULL);
ret = bdrv_open_image(&file, filename, options, "file", ret = bdrv_open_image(&file, filename, options, "file",
bdrv_open_flags(bs, flags | BDRV_O_UNMAP), true, true, bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
&local_err); BDRV_O_PROTOCOL, true, &local_err);
if (ret < 0) { if (ret < 0) {
goto fail; goto fail;
} }
@@ -1377,12 +1372,18 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
} }
} }
done:
/* Check if any unknown options were used */ /* Check if any unknown options were used */
if (qdict_size(options) != 0) { if (options && (qdict_size(options) != 0)) {
const QDictEntry *entry = qdict_first(options); const QDictEntry *entry = qdict_first(options);
error_setg(errp, "Block format '%s' used by device '%s' doesn't " if (flags & BDRV_O_PROTOCOL) {
"support the option '%s'", drv->format_name, bs->device_name, error_setg(errp, "Block protocol '%s' doesn't support the option "
entry->key); "'%s'", drv->format_name, entry->key);
} else {
error_setg(errp, "Block format '%s' used by device '%s' doesn't "
"support the option '%s'", drv->format_name,
bs->device_name, entry->key);
}
ret = -EINVAL; ret = -EINVAL;
goto close_and_fail; goto close_and_fail;
@@ -1393,6 +1394,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
bdrv_dev_change_media_cb(bs, true); bdrv_dev_change_media_cb(bs, true);
} }
*pbs = bs;
return 0; return 0;
unlink_and_fail: unlink_and_fail:
@@ -1406,13 +1408,24 @@ fail:
QDECREF(bs->options); QDECREF(bs->options);
QDECREF(options); QDECREF(options);
bs->options = NULL; bs->options = NULL;
if (!*pbs) {
/* If *pbs is NULL, a new BDS has been created in this function and
needs to be freed now. Otherwise, it does not need to be closed,
since it has not really been opened yet. */
bdrv_unref(bs);
}
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }
return ret; return ret;
close_and_fail: close_and_fail:
bdrv_close(bs); /* See fail path, but now the BDS has to be always closed */
if (*pbs) {
bdrv_close(bs);
} else {
bdrv_unref(bs);
}
QDECREF(options); QDECREF(options);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
@@ -1840,11 +1853,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name), pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
bs_src->device_name); bs_src->device_name);
bs_dest->device_list = bs_src->device_list; bs_dest->device_list = bs_src->device_list;
/* keep the same entry in graph_bdrv_states
* We do want to swap name but don't want to swap linked list entries
*/
bs_dest->node_list = bs_src->node_list;
} }
/* /*
@@ -1863,6 +1871,17 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
{ {
BlockDriverState tmp; BlockDriverState tmp;
/* The code needs to swap the node_name but simply swapping node_list won't
* work so first remove the nodes from the graph list, do the swap then
* insert them back if needed.
*/
if (bs_new->node_name[0] != '\0') {
QTAILQ_REMOVE(&graph_bdrv_states, bs_new, node_list);
}
if (bs_old->node_name[0] != '\0') {
QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
}
/* bs_new must be anonymous and shouldn't have anything fancy enabled */ /* bs_new must be anonymous and shouldn't have anything fancy enabled */
assert(bs_new->device_name[0] == '\0'); assert(bs_new->device_name[0] == '\0');
assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
@@ -1891,6 +1910,14 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
assert(bs_new->io_limits_enabled == false); assert(bs_new->io_limits_enabled == false);
assert(!throttle_have_timer(&bs_new->throttle_state)); assert(!throttle_have_timer(&bs_new->throttle_state));
/* insert the nodes back into the graph node list if needed */
if (bs_new->node_name[0] != '\0') {
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_new, node_list);
}
if (bs_old->node_name[0] != '\0') {
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_old, node_list);
}
bdrv_rebind(bs_new); bdrv_rebind(bs_new);
bdrv_rebind(bs_old); bdrv_rebind(bs_old);
} }
@@ -5290,9 +5317,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
back_flags = back_flags =
flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
bs = bdrv_new(""); bs = NULL;
ret = bdrv_open(&bs, backing_file->value.s, NULL, NULL, back_flags,
ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
backing_drv, &local_err); backing_drv, &local_err);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not open '%s': %s", error_setg_errno(errp, -ret, "Could not open '%s': %s",
@@ -5300,7 +5326,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
error_get_pretty(local_err)); error_get_pretty(local_err));
error_free(local_err); error_free(local_err);
local_err = NULL; local_err = NULL;
bdrv_unref(bs);
goto out; goto out;
} }
bdrv_get_geometry(bs, &size); bdrv_get_geometry(bs, &size);
@@ -5416,11 +5441,7 @@ bool bdrv_is_first_non_filter(BlockDriverState *candidate)
QTAILQ_FOREACH(bs, &bdrv_states, device_list) { QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
bool perm; bool perm;
if (!bs->file) { perm = bdrv_recurse_is_first_non_filter(bs, candidate);
continue;
}
perm = bdrv_recurse_is_first_non_filter(bs->file, candidate);
/* candidate is the first non filter */ /* candidate is the first non filter */
if (perm) { if (perm) {

View File

@@ -3,6 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-c
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o block-obj-y += qed-check.o
block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
block-obj-$(CONFIG_QUORUM) += quorum.o
block-obj-y += parallels.o blkdebug.o blkverify.o block-obj-y += parallels.o blkdebug.o blkverify.o
block-obj-y += snapshot.o qapi.o block-obj-y += snapshot.o qapi.o
block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
@@ -24,4 +25,15 @@ common-obj-y += commit.o
common-obj-y += mirror.o common-obj-y += mirror.o
common-obj-y += backup.o common-obj-y += backup.o
$(obj)/curl.o: QEMU_CFLAGS+=$(CURL_CFLAGS) iscsi.o-cflags := $(LIBISCSI_CFLAGS)
iscsi.o-libs := $(LIBISCSI_LIBS)
curl.o-cflags := $(CURL_CFLAGS)
curl.o-libs := $(CURL_LIBS)
rbd.o-cflags := $(RBD_CFLAGS)
rbd.o-libs := $(RBD_LIBS)
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
gluster.o-libs := $(GLUSTERFS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS)
qcow.o-libs := -lz
linux-aio.o-libs := -laio

View File

@@ -410,8 +410,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
s->state = 1; s->state = 1;
/* Open the backing file */ /* Open the backing file */
assert(bs->file == NULL);
ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-image"), options, "image", ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-image"), options, "image",
flags, true, false, &local_err); flags | BDRV_O_PROTOCOL, false, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto out; goto out;

View File

@@ -135,16 +135,18 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
} }
/* Open the raw file */ /* Open the raw file */
assert(bs->file == NULL);
ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-raw"), options, ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-raw"), options,
"raw", flags, true, false, &local_err); "raw", flags | BDRV_O_PROTOCOL, false, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto fail; goto fail;
} }
/* Open the test file */ /* Open the test file */
assert(s->test_file == NULL);
ret = bdrv_open_image(&s->test_file, qemu_opt_get(opts, "x-image"), options, ret = bdrv_open_image(&s->test_file, qemu_opt_get(opts, "x-image"), options,
"test", flags, false, false, &local_err); "test", flags, false, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
s->test_file = NULL; s->test_file = NULL;
@@ -171,110 +173,6 @@ static int64_t blkverify_getlength(BlockDriverState *bs)
return bdrv_getlength(s->test_file); return bdrv_getlength(s->test_file);
} }
/**
* Check that I/O vector contents are identical
*
* @a: I/O vector
* @b: I/O vector
* @ret: Offset to first mismatching byte or -1 if match
*/
static ssize_t blkverify_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
{
int i;
ssize_t offset = 0;
assert(a->niov == b->niov);
for (i = 0; i < a->niov; i++) {
size_t len = 0;
uint8_t *p = (uint8_t *)a->iov[i].iov_base;
uint8_t *q = (uint8_t *)b->iov[i].iov_base;
assert(a->iov[i].iov_len == b->iov[i].iov_len);
while (len < a->iov[i].iov_len && *p++ == *q++) {
len++;
}
offset += len;
if (len != a->iov[i].iov_len) {
return offset;
}
}
return -1;
}
typedef struct {
int src_index;
struct iovec *src_iov;
void *dest_base;
} IOVectorSortElem;
static int sortelem_cmp_src_base(const void *a, const void *b)
{
const IOVectorSortElem *elem_a = a;
const IOVectorSortElem *elem_b = b;
/* Don't overflow */
if (elem_a->src_iov->iov_base < elem_b->src_iov->iov_base) {
return -1;
} else if (elem_a->src_iov->iov_base > elem_b->src_iov->iov_base) {
return 1;
} else {
return 0;
}
}
static int sortelem_cmp_src_index(const void *a, const void *b)
{
const IOVectorSortElem *elem_a = a;
const IOVectorSortElem *elem_b = b;
return elem_a->src_index - elem_b->src_index;
}
/**
* Copy contents of I/O vector
*
* The relative relationships of overlapping iovecs are preserved. This is
* necessary to ensure identical semantics in the cloned I/O vector.
*/
static void blkverify_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src,
void *buf)
{
IOVectorSortElem sortelems[src->niov];
void *last_end;
int i;
/* Sort by source iovecs by base address */
for (i = 0; i < src->niov; i++) {
sortelems[i].src_index = i;
sortelems[i].src_iov = &src->iov[i];
}
qsort(sortelems, src->niov, sizeof(sortelems[0]), sortelem_cmp_src_base);
/* Allocate buffer space taking into account overlapping iovecs */
last_end = NULL;
for (i = 0; i < src->niov; i++) {
struct iovec *cur = sortelems[i].src_iov;
ptrdiff_t rewind = 0;
/* Detect overlap */
if (last_end && last_end > cur->iov_base) {
rewind = last_end - cur->iov_base;
}
sortelems[i].dest_base = buf - rewind;
buf += cur->iov_len - MIN(rewind, cur->iov_len);
last_end = MAX(cur->iov_base + cur->iov_len, last_end);
}
/* Sort by source iovec index and build destination iovec */
qsort(sortelems, src->niov, sizeof(sortelems[0]), sortelem_cmp_src_index);
for (i = 0; i < src->niov; i++) {
qemu_iovec_add(dest, sortelems[i].dest_base, src->iov[i].iov_len);
}
}
static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write, static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
int64_t sector_num, QEMUIOVector *qiov, int64_t sector_num, QEMUIOVector *qiov,
int nb_sectors, int nb_sectors,
@@ -338,7 +236,7 @@ static void blkverify_aio_cb(void *opaque, int ret)
static void blkverify_verify_readv(BlkverifyAIOCB *acb) static void blkverify_verify_readv(BlkverifyAIOCB *acb)
{ {
ssize_t offset = blkverify_iovec_compare(acb->qiov, &acb->raw_qiov); ssize_t offset = qemu_iovec_compare(acb->qiov, &acb->raw_qiov);
if (offset != -1) { if (offset != -1) {
blkverify_err(acb, "contents mismatch in sector %" PRId64, blkverify_err(acb, "contents mismatch in sector %" PRId64,
acb->sector_num + (int64_t)(offset / BDRV_SECTOR_SIZE)); acb->sector_num + (int64_t)(offset / BDRV_SECTOR_SIZE));
@@ -356,7 +254,7 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
acb->verify = blkverify_verify_readv; acb->verify = blkverify_verify_readv;
acb->buf = qemu_blockalign(bs->file, qiov->size); acb->buf = qemu_blockalign(bs->file, qiov->size);
qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov); qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov);
blkverify_iovec_clone(&acb->raw_qiov, qiov, acb->buf); qemu_iovec_clone(&acb->raw_qiov, qiov, acb->buf);
bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors, bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
blkverify_aio_cb, acb); blkverify_aio_cb, acb);

View File

@@ -129,7 +129,8 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
strcmp(bochs.subtype, GROWING_TYPE) || strcmp(bochs.subtype, GROWING_TYPE) ||
((le32_to_cpu(bochs.version) != HEADER_VERSION) && ((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
(le32_to_cpu(bochs.version) != HEADER_V1))) { (le32_to_cpu(bochs.version) != HEADER_V1))) {
return -EMEDIUMTYPE; error_setg(errp, "Image not in Bochs format");
return -EINVAL;
} }
if (le32_to_cpu(bochs.version) == HEADER_V1) { if (le32_to_cpu(bochs.version) == HEADER_V1) {

View File

@@ -74,7 +74,8 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
} }
if (be32_to_cpu(cow_header.magic) != COW_MAGIC) { if (be32_to_cpu(cow_header.magic) != COW_MAGIC) {
ret = -EMEDIUMTYPE; error_setg(errp, "Image not in COW format");
ret = -EINVAL;
goto fail; goto fail;
} }
@@ -82,7 +83,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
char version[64]; char version[64];
snprintf(version, sizeof(version), snprintf(version, sizeof(version),
"COW version %d", cow_header.version); "COW version %d", cow_header.version);
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "cow", version); bs->device_name, "cow", version);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
@@ -346,16 +347,15 @@ static int cow_create(const char *filename, QEMUOptionParameter *options,
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
return ret; return ret;
} }
ret = bdrv_file_open(&cow_bs, filename, NULL, NULL, BDRV_O_RDWR, cow_bs = NULL;
&local_err); ret = bdrv_open(&cow_bs, filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
return ret; return ret;
} }

View File

@@ -456,30 +456,27 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
static int inited = 0; static int inited = 0;
if (flags & BDRV_O_RDWR) { if (flags & BDRV_O_RDWR) {
qerror_report(ERROR_CLASS_GENERIC_ERROR, error_setg(errp, "curl block device does not support writes");
"curl block device does not support writes");
return -EROFS; return -EROFS;
} }
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err); qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) { if (local_err) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
goto out_noclean; goto out_noclean;
} }
s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE); s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE);
if ((s->readahead_size & 0x1ff) != 0) { if ((s->readahead_size & 0x1ff) != 0) {
fprintf(stderr, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512\n", error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
s->readahead_size); s->readahead_size);
goto out_noclean; goto out_noclean;
} }
file = qemu_opt_get(opts, "url"); file = qemu_opt_get(opts, "url");
if (file == NULL) { if (file == NULL) {
qerror_report(ERROR_CLASS_GENERIC_ERROR, "curl block driver requires " error_setg(errp, "curl block driver requires an 'url' option");
"an 'url' option");
goto out_noclean; goto out_noclean;
} }

View File

@@ -3,21 +3,12 @@
* *
* Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com> * Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
* *
* Pipe handling mechanism in AIO implementation is derived from * This work is licensed under the terms of the GNU GPL, version 2 or later.
* block/rbd.c. Hence, * See the COPYING file in the top-level directory.
* *
* Copyright (C) 2010-2011 Christian Brunner <chb@muc.de>,
* Josh Durgin <josh.durgin@dreamhost.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/ */
#include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs.h>
#include "block/block_int.h" #include "block/block_int.h"
#include "qemu/sockets.h"
#include "qemu/uri.h" #include "qemu/uri.h"
typedef struct GlusterAIOCB { typedef struct GlusterAIOCB {
@@ -32,9 +23,6 @@ typedef struct BDRVGlusterState {
struct glfs_fd *fd; struct glfs_fd *fd;
} BDRVGlusterState; } BDRVGlusterState;
#define GLUSTER_FD_READ 0
#define GLUSTER_FD_WRITE 1
typedef struct GlusterConf { typedef struct GlusterConf {
char *server; char *server;
int port; int port;
@@ -45,11 +33,13 @@ typedef struct GlusterConf {
static void qemu_gluster_gconf_free(GlusterConf *gconf) static void qemu_gluster_gconf_free(GlusterConf *gconf)
{ {
g_free(gconf->server); if (gconf) {
g_free(gconf->volname); g_free(gconf->server);
g_free(gconf->image); g_free(gconf->volname);
g_free(gconf->transport); g_free(gconf->image);
g_free(gconf); g_free(gconf->transport);
g_free(gconf);
}
} }
static int parse_volume_options(GlusterConf *gconf, char *path) static int parse_volume_options(GlusterConf *gconf, char *path)
@@ -127,7 +117,7 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
} }
/* transport */ /* transport */
if (!strcmp(uri->scheme, "gluster")) { if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
gconf->transport = g_strdup("tcp"); gconf->transport = g_strdup("tcp");
} else if (!strcmp(uri->scheme, "gluster+tcp")) { } else if (!strcmp(uri->scheme, "gluster+tcp")) {
gconf->transport = g_strdup("tcp"); gconf->transport = g_strdup("tcp");
@@ -163,7 +153,7 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
} }
gconf->server = g_strdup(qp->p[0].value); gconf->server = g_strdup(qp->p[0].value);
} else { } else {
gconf->server = g_strdup(uri->server); gconf->server = g_strdup(uri->server ? uri->server : "localhost");
gconf->port = uri->port; gconf->port = uri->port;
} }
@@ -175,7 +165,8 @@ out:
return ret; return ret;
} }
static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename) static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
Error **errp)
{ {
struct glfs *glfs = NULL; struct glfs *glfs = NULL;
int ret; int ret;
@@ -183,8 +174,8 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename)
ret = qemu_gluster_parseuri(gconf, filename); ret = qemu_gluster_parseuri(gconf, filename);
if (ret < 0) { if (ret < 0) {
error_report("Usage: file=gluster[+transport]://[server[:port]]/" error_setg(errp, "Usage: file=gluster[+transport]://[server[:port]]/"
"volname/image[?socket=...]"); "volname/image[?socket=...]");
errno = -ret; errno = -ret;
goto out; goto out;
} }
@@ -211,9 +202,11 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename)
ret = glfs_init(glfs); ret = glfs_init(glfs);
if (ret) { if (ret) {
error_report("Gluster connection failed for server=%s port=%d " error_setg_errno(errp, errno,
"volume=%s image=%s transport=%s", gconf->server, gconf->port, "Gluster connection failed for server=%s port=%d "
gconf->volname, gconf->image, gconf->transport); "volume=%s image=%s transport=%s", gconf->server,
gconf->port, gconf->volname, gconf->image,
gconf->transport);
goto out; goto out;
} }
return glfs; return glfs;
@@ -269,11 +262,28 @@ static QemuOptsList runtime_opts = {
}, },
}; };
static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags)
{
assert(open_flags != NULL);
*open_flags |= O_BINARY;
if (bdrv_flags & BDRV_O_RDWR) {
*open_flags |= O_RDWR;
} else {
*open_flags |= O_RDONLY;
}
if ((bdrv_flags & BDRV_O_NOCACHE)) {
*open_flags |= O_DIRECT;
}
}
static int qemu_gluster_open(BlockDriverState *bs, QDict *options, static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
int bdrv_flags, Error **errp) int bdrv_flags, Error **errp)
{ {
BDRVGlusterState *s = bs->opaque; BDRVGlusterState *s = bs->opaque;
int open_flags = O_BINARY; int open_flags = 0;
int ret = 0; int ret = 0;
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
QemuOpts *opts; QemuOpts *opts;
@@ -283,29 +293,20 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err); qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) { if (local_err) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
filename = qemu_opt_get(opts, "filename"); filename = qemu_opt_get(opts, "filename");
s->glfs = qemu_gluster_init(gconf, filename); s->glfs = qemu_gluster_init(gconf, filename, errp);
if (!s->glfs) { if (!s->glfs) {
ret = -errno; ret = -errno;
goto out; goto out;
} }
if (bdrv_flags & BDRV_O_RDWR) { qemu_gluster_parse_flags(bdrv_flags, &open_flags);
open_flags |= O_RDWR;
} else {
open_flags |= O_RDONLY;
}
if ((bdrv_flags & BDRV_O_NOCACHE)) {
open_flags |= O_DIRECT;
}
s->fd = glfs_open(s->glfs, gconf->image, open_flags); s->fd = glfs_open(s->glfs, gconf->image, open_flags);
if (!s->fd) { if (!s->fd) {
@@ -327,6 +328,96 @@ out:
return ret; return ret;
} }
typedef struct BDRVGlusterReopenState {
struct glfs *glfs;
struct glfs_fd *fd;
} BDRVGlusterReopenState;
static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
int ret = 0;
BDRVGlusterReopenState *reop_s;
GlusterConf *gconf = NULL;
int open_flags = 0;
assert(state != NULL);
assert(state->bs != NULL);
state->opaque = g_malloc0(sizeof(BDRVGlusterReopenState));
reop_s = state->opaque;
qemu_gluster_parse_flags(state->flags, &open_flags);
gconf = g_malloc0(sizeof(GlusterConf));
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
if (reop_s->glfs == NULL) {
ret = -errno;
goto exit;
}
reop_s->fd = glfs_open(reop_s->glfs, gconf->image, open_flags);
if (reop_s->fd == NULL) {
/* reops->glfs will be cleaned up in _abort */
ret = -errno;
goto exit;
}
exit:
/* state->opaque will be freed in either the _abort or _commit */
qemu_gluster_gconf_free(gconf);
return ret;
}
static void qemu_gluster_reopen_commit(BDRVReopenState *state)
{
BDRVGlusterReopenState *reop_s = state->opaque;
BDRVGlusterState *s = state->bs->opaque;
/* close the old */
if (s->fd) {
glfs_close(s->fd);
}
if (s->glfs) {
glfs_fini(s->glfs);
}
/* use the newly opened image / connection */
s->fd = reop_s->fd;
s->glfs = reop_s->glfs;
g_free(state->opaque);
state->opaque = NULL;
return;
}
static void qemu_gluster_reopen_abort(BDRVReopenState *state)
{
BDRVGlusterReopenState *reop_s = state->opaque;
if (reop_s == NULL) {
return;
}
if (reop_s->fd) {
glfs_close(reop_s->fd);
}
if (reop_s->glfs) {
glfs_fini(reop_s->glfs);
}
g_free(state->opaque);
state->opaque = NULL;
return;
}
#ifdef CONFIG_GLUSTERFS_ZEROFILL #ifdef CONFIG_GLUSTERFS_ZEROFILL
static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs, static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags) int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
@@ -389,9 +480,9 @@ static int qemu_gluster_create(const char *filename,
int64_t total_size = 0; int64_t total_size = 0;
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
glfs = qemu_gluster_init(gconf, filename); glfs = qemu_gluster_init(gconf, filename, errp);
if (!glfs) { if (!glfs) {
ret = -errno; ret = -EINVAL;
goto out; goto out;
} }
@@ -617,6 +708,9 @@ static BlockDriver bdrv_gluster = {
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create, .bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_getlength = qemu_gluster_getlength,
@@ -641,6 +735,9 @@ static BlockDriver bdrv_gluster_tcp = {
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create, .bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_getlength = qemu_gluster_getlength,
@@ -665,6 +762,9 @@ static BlockDriver bdrv_gluster_unix = {
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create, .bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_getlength = qemu_gluster_getlength,
@@ -689,6 +789,9 @@ static BlockDriver bdrv_gluster_rdma = {
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
.bdrv_close = qemu_gluster_close, .bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create, .bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength, .bdrv_getlength = qemu_gluster_getlength,

View File

@@ -145,12 +145,13 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION) { && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi));
iTask->do_retry = 1; iTask->do_retry = 1;
goto out; goto out;
} }
if (status != SCSI_STATUS_GOOD) { if (status != SCSI_STATUS_GOOD) {
error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi)); error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
} }
out: out:
@@ -325,6 +326,7 @@ retry:
} }
if (iTask.do_retry) { if (iTask.do_retry) {
iTask.complete = 0;
goto retry; goto retry;
} }
@@ -399,6 +401,7 @@ retry:
} }
if (iTask.do_retry) { if (iTask.do_retry) {
iTask.complete = 0;
goto retry; goto retry;
} }
@@ -433,6 +436,7 @@ retry:
} }
if (iTask.do_retry) { if (iTask.do_retry) {
iTask.complete = 0;
goto retry; goto retry;
} }
@@ -683,6 +687,7 @@ retry:
scsi_free_scsi_task(iTask.task); scsi_free_scsi_task(iTask.task);
iTask.task = NULL; iTask.task = NULL;
} }
iTask.complete = 0;
goto retry; goto retry;
} }
@@ -767,6 +772,7 @@ retry:
} }
if (iTask.do_retry) { if (iTask.do_retry) {
iTask.complete = 0;
goto retry; goto retry;
} }
@@ -830,24 +836,26 @@ retry:
qemu_coroutine_yield(); qemu_coroutine_yield();
} }
if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
/* WRITE SAME is not supported by the target */
iscsilun->has_write_same = false;
scsi_free_scsi_task(iTask.task);
return -ENOTSUP;
}
if (iTask.task != NULL) { if (iTask.task != NULL) {
scsi_free_scsi_task(iTask.task); scsi_free_scsi_task(iTask.task);
iTask.task = NULL; iTask.task = NULL;
} }
if (iTask.do_retry) { if (iTask.do_retry) {
iTask.complete = 0;
goto retry; goto retry;
} }
if (iTask.status != SCSI_STATUS_GOOD) { if (iTask.status != SCSI_STATUS_GOOD) {
if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
/* WRITE SAME is not supported by the target */
iscsilun->has_write_same = false;
return -ENOTSUP;
}
return -EIO; return -EIO;
} }
@@ -856,7 +864,8 @@ retry:
#endif /* SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED */ #endif /* SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED */
static int parse_chap(struct iscsi_context *iscsi, const char *target) static void parse_chap(struct iscsi_context *iscsi, const char *target,
Error **errp)
{ {
QemuOptsList *list; QemuOptsList *list;
QemuOpts *opts; QemuOpts *opts;
@@ -865,37 +874,35 @@ static int parse_chap(struct iscsi_context *iscsi, const char *target)
list = qemu_find_opts("iscsi"); list = qemu_find_opts("iscsi");
if (!list) { if (!list) {
return 0; return;
} }
opts = qemu_opts_find(list, target); opts = qemu_opts_find(list, target);
if (opts == NULL) { if (opts == NULL) {
opts = QTAILQ_FIRST(&list->head); opts = QTAILQ_FIRST(&list->head);
if (!opts) { if (!opts) {
return 0; return;
} }
} }
user = qemu_opt_get(opts, "user"); user = qemu_opt_get(opts, "user");
if (!user) { if (!user) {
return 0; return;
} }
password = qemu_opt_get(opts, "password"); password = qemu_opt_get(opts, "password");
if (!password) { if (!password) {
error_report("CHAP username specified but no password was given"); error_setg(errp, "CHAP username specified but no password was given");
return -1; return;
} }
if (iscsi_set_initiator_username_pwd(iscsi, user, password)) { if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
error_report("Failed to set initiator username and password"); error_setg(errp, "Failed to set initiator username and password");
return -1;
} }
return 0;
} }
static void parse_header_digest(struct iscsi_context *iscsi, const char *target) static void parse_header_digest(struct iscsi_context *iscsi, const char *target,
Error **errp)
{ {
QemuOptsList *list; QemuOptsList *list;
QemuOpts *opts; QemuOpts *opts;
@@ -928,7 +935,7 @@ static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
} else if (!strcmp(digest, "NONE-CRC32C")) { } else if (!strcmp(digest, "NONE-CRC32C")) {
iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
} else { } else {
error_report("Invalid header-digest setting : %s", digest); error_setg(errp, "Invalid header-digest setting : %s", digest);
} }
} }
@@ -986,12 +993,11 @@ static void iscsi_nop_timed_event(void *opaque)
} }
#endif #endif
static int iscsi_readcapacity_sync(IscsiLun *iscsilun) static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
{ {
struct scsi_task *task = NULL; struct scsi_task *task = NULL;
struct scsi_readcapacity10 *rc10 = NULL; struct scsi_readcapacity10 *rc10 = NULL;
struct scsi_readcapacity16 *rc16 = NULL; struct scsi_readcapacity16 *rc16 = NULL;
int ret = 0;
int retries = ISCSI_CMD_RETRIES; int retries = ISCSI_CMD_RETRIES;
do { do {
@@ -1006,8 +1012,7 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
if (task != NULL && task->status == SCSI_STATUS_GOOD) { if (task != NULL && task->status == SCSI_STATUS_GOOD) {
rc16 = scsi_datain_unmarshall(task); rc16 = scsi_datain_unmarshall(task);
if (rc16 == NULL) { if (rc16 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity16 data."); error_setg(errp, "iSCSI: Failed to unmarshall readcapacity16 data.");
ret = -EINVAL;
} else { } else {
iscsilun->block_size = rc16->block_length; iscsilun->block_size = rc16->block_length;
iscsilun->num_blocks = rc16->returned_lba + 1; iscsilun->num_blocks = rc16->returned_lba + 1;
@@ -1021,8 +1026,7 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
if (task != NULL && task->status == SCSI_STATUS_GOOD) { if (task != NULL && task->status == SCSI_STATUS_GOOD) {
rc10 = scsi_datain_unmarshall(task); rc10 = scsi_datain_unmarshall(task);
if (rc10 == NULL) { if (rc10 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity10 data."); error_setg(errp, "iSCSI: Failed to unmarshall readcapacity10 data.");
ret = -EINVAL;
} else { } else {
iscsilun->block_size = rc10->block_size; iscsilun->block_size = rc10->block_size;
if (rc10->lba == 0) { if (rc10->lba == 0) {
@@ -1035,20 +1039,18 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
} }
break; break;
default: default:
return 0; return;
} }
} while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
&& retries-- > 0); && retries-- > 0);
if (task == NULL || task->status != SCSI_STATUS_GOOD) { if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_report("iSCSI: failed to send readcapacity10 command."); error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
ret = -EINVAL;
} }
if (task) { if (task) {
scsi_free_scsi_task(task); scsi_free_scsi_task(task);
} }
return ret;
} }
/* TODO Convert to fine grained options */ /* TODO Convert to fine grained options */
@@ -1065,35 +1067,41 @@ static QemuOptsList runtime_opts = {
}, },
}; };
static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
int lun, int evpd, int pc) { int evpd, int pc, void **inq, Error **errp)
int full_size; {
struct scsi_task *task = NULL; int full_size;
task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, 64); struct scsi_task *task = NULL;
task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, 64);
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
goto fail;
}
full_size = scsi_datain_getfullsize(task);
if (full_size > task->datain.size) {
scsi_free_scsi_task(task);
/* we need more data for the full list */
task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, full_size);
if (task == NULL || task->status != SCSI_STATUS_GOOD) { if (task == NULL || task->status != SCSI_STATUS_GOOD) {
goto fail; goto fail;
} }
full_size = scsi_datain_getfullsize(task); }
if (full_size > task->datain.size) {
scsi_free_scsi_task(task);
/* we need more data for the full list */ *inq = scsi_datain_unmarshall(task);
task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, full_size); if (*inq == NULL) {
if (task == NULL || task->status != SCSI_STATUS_GOOD) { error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
goto fail; goto fail;
} }
}
return task; return task;
fail: fail:
error_report("iSCSI: Inquiry command failed : %s", error_setg(errp, "iSCSI: Inquiry command failed : %s",
iscsi_get_error(iscsi)); iscsi_get_error(iscsi));
if (task) { if (task != NULL) {
scsi_free_scsi_task(task); scsi_free_scsi_task(task);
return NULL; }
} return NULL;
return NULL;
} }
/* /*
@@ -1112,34 +1120,33 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
struct iscsi_url *iscsi_url = NULL; struct iscsi_url *iscsi_url = NULL;
struct scsi_task *task = NULL; struct scsi_task *task = NULL;
struct scsi_inquiry_standard *inq = NULL; struct scsi_inquiry_standard *inq = NULL;
struct scsi_inquiry_supported_pages *inq_vpd;
char *initiator_name = NULL; char *initiator_name = NULL;
QemuOpts *opts; QemuOpts *opts;
Error *local_err = NULL; Error *local_err = NULL;
const char *filename; const char *filename;
int ret; int i, ret;
if ((BDRV_SECTOR_SIZE % 512) != 0) { if ((BDRV_SECTOR_SIZE % 512) != 0) {
error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. " error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
"BDRV_SECTOR_SIZE(%lld) is not a multiple " "BDRV_SECTOR_SIZE(%lld) is not a multiple "
"of 512", BDRV_SECTOR_SIZE); "of 512", BDRV_SECTOR_SIZE);
return -EINVAL; return -EINVAL;
} }
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err); qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) { if (local_err) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
filename = qemu_opt_get(opts, "filename"); filename = qemu_opt_get(opts, "filename");
iscsi_url = iscsi_parse_full_url(iscsi, filename); iscsi_url = iscsi_parse_full_url(iscsi, filename);
if (iscsi_url == NULL) { if (iscsi_url == NULL) {
error_report("Failed to parse URL : %s", filename); error_setg(errp, "Failed to parse URL : %s", filename);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@@ -1150,13 +1157,13 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
iscsi = iscsi_create_context(initiator_name); iscsi = iscsi_create_context(initiator_name);
if (iscsi == NULL) { if (iscsi == NULL) {
error_report("iSCSI: Failed to create iSCSI context."); error_setg(errp, "iSCSI: Failed to create iSCSI context.");
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
if (iscsi_set_targetname(iscsi, iscsi_url->target)) { if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
error_report("iSCSI: Failed to set target name."); error_setg(errp, "iSCSI: Failed to set target name.");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@@ -1165,21 +1172,22 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
iscsi_url->passwd); iscsi_url->passwd);
if (ret != 0) { if (ret != 0) {
error_report("Failed to set initiator username and password"); error_setg(errp, "Failed to set initiator username and password");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
} }
/* check if we got CHAP username/password via the options */ /* check if we got CHAP username/password via the options */
if (parse_chap(iscsi, iscsi_url->target) != 0) { parse_chap(iscsi, iscsi_url->target, &local_err);
error_report("iSCSI: Failed to set CHAP user/password"); if (local_err != NULL) {
error_propagate(errp, local_err);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) { if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
error_report("iSCSI: Failed to set session type to normal."); error_setg(errp, "iSCSI: Failed to set session type to normal.");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@@ -1187,10 +1195,15 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
/* check if we got HEADER_DIGEST via the options */ /* check if we got HEADER_DIGEST via the options */
parse_header_digest(iscsi, iscsi_url->target); parse_header_digest(iscsi, iscsi_url->target, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto out;
}
if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) { if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
error_report("iSCSI: Failed to connect to LUN : %s", error_setg(errp, "iSCSI: Failed to connect to LUN : %s",
iscsi_get_error(iscsi)); iscsi_get_error(iscsi));
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@@ -1198,79 +1211,76 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
iscsilun->iscsi = iscsi; iscsilun->iscsi = iscsi;
iscsilun->lun = iscsi_url->lun; iscsilun->lun = iscsi_url->lun;
task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_report("iSCSI: failed to send inquiry command.");
ret = -EINVAL;
goto out;
}
inq = scsi_datain_unmarshall(task);
if (inq == NULL) {
error_report("iSCSI: Failed to unmarshall inquiry data.");
ret = -EINVAL;
goto out;
}
iscsilun->type = inq->periperal_device_type;
iscsilun->has_write_same = true; iscsilun->has_write_same = true;
if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) { task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0,
(void **) &inq, errp);
if (task == NULL) {
ret = -EINVAL;
goto out;
}
iscsilun->type = inq->periperal_device_type;
scsi_free_scsi_task(task);
task = NULL;
iscsi_readcapacity_sync(iscsilun, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
goto out; goto out;
} }
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun); bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
bs->request_alignment = iscsilun->block_size; bs->request_alignment = iscsilun->block_size;
/* Medium changer or tape. We dont have any emulation for this so this must /* We don't have any emulation for devices other than disks and CD-ROMs, so
* be sg ioctl compatible. We force it to be sg, otherwise qemu will try * this must be sg ioctl compatible. We force it to be sg, otherwise qemu
* to read from the device to guess the image format. * will try to read from the device to guess the image format.
*/ */
if (iscsilun->type == TYPE_MEDIUM_CHANGER || if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {
iscsilun->type == TYPE_TAPE) {
bs->sg = 1; bs->sg = 1;
} }
if (iscsilun->lbpme) { task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,
(void **) &inq_vpd, errp);
if (task == NULL) {
ret = -EINVAL;
goto out;
}
for (i = 0; i < inq_vpd->num_pages; i++) {
struct scsi_task *inq_task;
struct scsi_inquiry_logical_block_provisioning *inq_lbp; struct scsi_inquiry_logical_block_provisioning *inq_lbp;
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING);
if (task == NULL) {
ret = -EINVAL;
goto out;
}
inq_lbp = scsi_datain_unmarshall(task);
if (inq_lbp == NULL) {
error_report("iSCSI: failed to unmarshall inquiry datain blob");
ret = -EINVAL;
goto out;
}
memcpy(&iscsilun->lbp, inq_lbp,
sizeof(struct scsi_inquiry_logical_block_provisioning));
scsi_free_scsi_task(task);
task = NULL;
}
if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
struct scsi_inquiry_block_limits *inq_bl; struct scsi_inquiry_block_limits *inq_bl;
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1, switch (inq_vpd->pages[i]) {
SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS); case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
if (task == NULL) { inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
ret = -EINVAL; SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
goto out; (void **) &inq_lbp, errp);
if (inq_task == NULL) {
ret = -EINVAL;
goto out;
}
memcpy(&iscsilun->lbp, inq_lbp,
sizeof(struct scsi_inquiry_logical_block_provisioning));
scsi_free_scsi_task(inq_task);
break;
case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,
(void **) &inq_bl, errp);
if (inq_task == NULL) {
ret = -EINVAL;
goto out;
}
memcpy(&iscsilun->bl, inq_bl,
sizeof(struct scsi_inquiry_block_limits));
scsi_free_scsi_task(inq_task);
break;
default:
break;
} }
inq_bl = scsi_datain_unmarshall(task);
if (inq_bl == NULL) {
error_report("iSCSI: failed to unmarshall inquiry datain blob");
ret = -EINVAL;
goto out;
}
memcpy(&iscsilun->bl, inq_bl,
sizeof(struct scsi_inquiry_block_limits));
scsi_free_scsi_task(task);
task = NULL;
} }
scsi_free_scsi_task(task);
task = NULL;
#if defined(LIBISCSI_FEATURE_NOP_COUNTER) #if defined(LIBISCSI_FEATURE_NOP_COUNTER)
/* Set up a timer for sending out iSCSI NOPs */ /* Set up a timer for sending out iSCSI NOPs */
@@ -1353,14 +1363,16 @@ static int iscsi_reopen_prepare(BDRVReopenState *state,
static int iscsi_truncate(BlockDriverState *bs, int64_t offset) static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
{ {
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;
int ret = 0; Error *local_err = NULL;
if (iscsilun->type != TYPE_DISK) { if (iscsilun->type != TYPE_DISK) {
return -ENOTSUP; return -ENOTSUP;
} }
if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) { iscsi_readcapacity_sync(iscsilun, &local_err);
return ret; if (local_err != NULL) {
error_free(local_err);
return -EIO;
} }
if (offset > iscsi_getlength(bs)) { if (offset > iscsi_getlength(bs)) {

View File

@@ -520,9 +520,6 @@ static void mirror_complete(BlockJob *job, Error **errp)
ret = bdrv_open_backing_file(s->target, NULL, &local_err); ret = bdrv_open_backing_file(s->target, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
char backing_filename[PATH_MAX];
bdrv_get_full_backing_filename(s->target, backing_filename,
sizeof(backing_filename));
error_propagate(errp, local_err); error_propagate(errp, local_err);
return; return;
} }

View File

@@ -188,31 +188,28 @@ out:
g_free(file); g_free(file);
} }
static int nbd_config(BDRVNBDState *s, QDict *options, char **export) static void nbd_config(BDRVNBDState *s, QDict *options, char **export,
Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
if (qdict_haskey(options, "path")) { if (qdict_haskey(options, "path") == qdict_haskey(options, "host")) {
if (qdict_haskey(options, "host")) { if (qdict_haskey(options, "path")) {
qerror_report(ERROR_CLASS_GENERIC_ERROR, "path and host may not " error_setg(errp, "path and host may not be used at the same time.");
"be used at the same time."); } else {
return -EINVAL; error_setg(errp, "one of path and host must be specified.");
} }
s->client.is_unix = true; return;
} else if (qdict_haskey(options, "host")) {
s->client.is_unix = false;
} else {
return -EINVAL;
} }
s->client.is_unix = qdict_haskey(options, "path");
s->socket_opts = qemu_opts_create(&socket_optslist, NULL, 0, s->socket_opts = qemu_opts_create(&socket_optslist, NULL, 0,
&error_abort); &error_abort);
qemu_opts_absorb_qdict(s->socket_opts, options, &local_err); qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
if (local_err) { if (local_err) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err); return;
return -EINVAL;
} }
if (!qemu_opt_get(s->socket_opts, "port")) { if (!qemu_opt_get(s->socket_opts, "port")) {
@@ -223,19 +220,17 @@ static int nbd_config(BDRVNBDState *s, QDict *options, char **export)
if (*export) { if (*export) {
qdict_del(options, "export"); qdict_del(options, "export");
} }
return 0;
} }
static int nbd_establish_connection(BlockDriverState *bs) static int nbd_establish_connection(BlockDriverState *bs, Error **errp)
{ {
BDRVNBDState *s = bs->opaque; BDRVNBDState *s = bs->opaque;
int sock; int sock;
if (s->client.is_unix) { if (s->client.is_unix) {
sock = unix_socket_outgoing(qemu_opt_get(s->socket_opts, "path")); sock = unix_connect_opts(s->socket_opts, errp, NULL, NULL);
} else { } else {
sock = tcp_socket_outgoing_opts(s->socket_opts); sock = inet_connect_opts(s->socket_opts, errp, NULL, NULL);
if (sock >= 0) { if (sock >= 0) {
socket_set_nodelay(sock); socket_set_nodelay(sock);
} }
@@ -256,17 +251,19 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
BDRVNBDState *s = bs->opaque; BDRVNBDState *s = bs->opaque;
char *export = NULL; char *export = NULL;
int result, sock; int result, sock;
Error *local_err = NULL;
/* Pop the config into our state object. Exit if invalid. */ /* Pop the config into our state object. Exit if invalid. */
result = nbd_config(s, options, &export); nbd_config(s, options, &export, &local_err);
if (result != 0) { if (local_err) {
return result; error_propagate(errp, local_err);
return -EINVAL;
} }
/* establish TCP connection, return error if it fails /* establish TCP connection, return error if it fails
* TODO: Configurable retry-until-timeout behaviour. * TODO: Configurable retry-until-timeout behaviour.
*/ */
sock = nbd_establish_connection(bs); sock = nbd_establish_connection(bs, errp);
if (sock < 0) { if (sock < 0) {
return sock; return sock;
} }

View File

@@ -85,7 +85,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
if (memcmp(ph.magic, HEADER_MAGIC, 16) || if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
(le32_to_cpu(ph.version) != HEADER_VERSION)) { (le32_to_cpu(ph.version) != HEADER_VERSION)) {
ret = -EMEDIUMTYPE; error_setg(errp, "Image not in Parallels format");
ret = -EINVAL;
goto fail; goto fail;
} }

View File

@@ -113,23 +113,26 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
be64_to_cpus(&header.l1_table_offset); be64_to_cpus(&header.l1_table_offset);
if (header.magic != QCOW_MAGIC) { if (header.magic != QCOW_MAGIC) {
ret = -EMEDIUMTYPE; error_setg(errp, "Image not in qcow format");
ret = -EINVAL;
goto fail; goto fail;
} }
if (header.version != QCOW_VERSION) { if (header.version != QCOW_VERSION) {
char version[64]; char version[64];
snprintf(version, sizeof(version), "QCOW version %d", header.version); snprintf(version, sizeof(version), "QCOW version %d", header.version);
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "qcow", version); bs->device_name, "qcow", version);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} }
if (header.size <= 1 || header.cluster_bits < 9) { if (header.size <= 1 || header.cluster_bits < 9) {
error_setg(errp, "invalid value in qcow header");
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
if (header.crypt_method > QCOW_CRYPT_AES) { if (header.crypt_method > QCOW_CRYPT_AES) {
error_setg(errp, "invalid encryption method in qcow header");
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
@@ -686,16 +689,15 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
return ret; return ret;
} }
ret = bdrv_file_open(&qcow_bs, filename, NULL, NULL, BDRV_O_RDWR, qcow_bs = NULL;
&local_err); ret = bdrv_open(&qcow_bs, filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
return ret; return ret;
} }

View File

@@ -1367,13 +1367,31 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
uint64_t old_offset; uint64_t old_offset;
old_offset = be64_to_cpu(l2_table[l2_index + i]); old_offset = be64_to_cpu(l2_table[l2_index + i]);
if ((old_offset & L2E_OFFSET_MASK) == 0) {
/*
* Make sure that a discarded area reads back as zeroes for v3 images
* (we cannot do it for v2 without actually writing a zero-filled
* buffer). We can skip the operation if the cluster is already marked
* as zero, or if it's unallocated and we don't have a backing file.
*
* TODO We might want to use bdrv_get_block_status(bs) here, but we're
* holding s->lock, so that doesn't work today.
*/
if (old_offset & QCOW_OFLAG_ZERO) {
continue;
}
if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) {
continue; continue;
} }
/* First remove L2 entries */ /* First remove L2 entries */
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
l2_table[l2_index + i] = cpu_to_be64(0); if (s->qcow_version >= 3) {
l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
} else {
l2_table[l2_index + i] = cpu_to_be64(0);
}
/* Then decrease the refcount */ /* Then decrease the refcount */
qcow2_free_any_clusters(bs, old_offset, 1, type); qcow2_free_any_clusters(bs, old_offset, 1, type);

View File

@@ -449,7 +449,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
if (header.magic != QCOW_MAGIC) { if (header.magic != QCOW_MAGIC) {
error_setg(errp, "Image is not in qcow2 format"); error_setg(errp, "Image is not in qcow2 format");
ret = -EMEDIUMTYPE; ret = -EINVAL;
goto fail; goto fail;
} }
if (header.version < 2 || header.version > 3) { if (header.version < 2 || header.version > 3) {
@@ -1493,7 +1493,9 @@ static int qcow2_create2(const char *filename, int64_t total_size,
return ret; return ret;
} }
ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err); bs = NULL;
ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return ret; return ret;
@@ -1543,7 +1545,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
goto out; goto out;
} }
bdrv_close(bs); bdrv_unref(bs);
bs = NULL;
/* /*
* And now open the image and make it consistent first (i.e. increase the * And now open the image and make it consistent first (i.e. increase the
@@ -1552,7 +1555,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
*/ */
BlockDriver* drv = bdrv_find_format("qcow2"); BlockDriver* drv = bdrv_find_format("qcow2");
assert(drv != NULL); assert(drv != NULL);
ret = bdrv_open(bs, filename, NULL, ret = bdrv_open(&bs, filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err); BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
@@ -1599,10 +1602,11 @@ static int qcow2_create2(const char *filename, int64_t total_size,
} }
} }
bdrv_close(bs); bdrv_unref(bs);
bs = NULL;
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */ /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
ret = bdrv_open(bs, filename, NULL, ret = bdrv_open(&bs, filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING,
drv, &local_err); drv, &local_err);
if (local_err) { if (local_err) {
@@ -1612,7 +1616,9 @@ static int qcow2_create2(const char *filename, int64_t total_size,
ret = 0; ret = 0;
out: out:
bdrv_unref(bs); if (bs) {
bdrv_unref(bs);
}
return ret; return ret;
} }

View File

@@ -391,14 +391,15 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
qed_header_le_to_cpu(&le_header, &s->header); qed_header_le_to_cpu(&le_header, &s->header);
if (s->header.magic != QED_MAGIC) { if (s->header.magic != QED_MAGIC) {
return -EMEDIUMTYPE; error_setg(errp, "Image not in QED format");
return -EINVAL;
} }
if (s->header.features & ~QED_FEATURE_MASK) { if (s->header.features & ~QED_FEATURE_MASK) {
/* image uses unsupported feature bits */ /* image uses unsupported feature bits */
char buf[64]; char buf[64];
snprintf(buf, sizeof(buf), "%" PRIx64, snprintf(buf, sizeof(buf), "%" PRIx64,
s->header.features & ~QED_FEATURE_MASK); s->header.features & ~QED_FEATURE_MASK);
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "QED", buf); bs->device_name, "QED", buf);
return -ENOTSUP; return -ENOTSUP;
} }
@@ -545,7 +546,8 @@ static void bdrv_qed_close(BlockDriverState *bs)
static int qed_create(const char *filename, uint32_t cluster_size, static int qed_create(const char *filename, uint32_t cluster_size,
uint64_t image_size, uint32_t table_size, uint64_t image_size, uint32_t table_size,
const char *backing_file, const char *backing_fmt) const char *backing_file, const char *backing_fmt,
Error **errp)
{ {
QEDHeader header = { QEDHeader header = {
.magic = QED_MAGIC, .magic = QED_MAGIC,
@@ -562,20 +564,20 @@ static int qed_create(const char *filename, uint32_t cluster_size,
size_t l1_size = header.cluster_size * header.table_size; size_t l1_size = header.cluster_size * header.table_size;
Error *local_err = NULL; Error *local_err = NULL;
int ret = 0; int ret = 0;
BlockDriverState *bs = NULL; BlockDriverState *bs;
ret = bdrv_create_file(filename, NULL, &local_err); ret = bdrv_create_file(filename, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
return ret; return ret;
} }
ret = bdrv_file_open(&bs, filename, NULL, NULL, bs = NULL;
BDRV_O_RDWR | BDRV_O_CACHE_WB, &local_err); ret = bdrv_open(&bs, filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_PROTOCOL, NULL,
&local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
return ret; return ret;
} }
@@ -665,7 +667,7 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options,
} }
return qed_create(filename, cluster_size, image_size, table_size, return qed_create(filename, cluster_size, image_size, table_size,
backing_file, backing_fmt); backing_file, backing_fmt, errp);
} }
typedef struct { typedef struct {

873
block/quorum.c Normal file
View File

@@ -0,0 +1,873 @@
/*
* Quorum Block filter
*
* Copyright (C) 2012-2014 Nodalink, EURL.
*
* Author:
* Benoît Canet <benoit.canet@irqsave.net>
*
* Based on the design and code of blkverify.c (Copyright (C) 2010 IBM, Corp)
* and blkmirror.c (Copyright (C) 2011 Red Hat, Inc).
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include "block/block_int.h"
#include "qapi/qmp/qjson.h"
#define HASH_LENGTH 32
#define QUORUM_OPT_VOTE_THRESHOLD "vote-threshold"
#define QUORUM_OPT_BLKVERIFY "blkverify"
/* This union holds a vote hash value */
typedef union QuorumVoteValue {
char h[HASH_LENGTH]; /* SHA-256 hash */
int64_t l; /* simpler 64 bits hash */
} QuorumVoteValue;
/* A vote item */
typedef struct QuorumVoteItem {
int index;
QLIST_ENTRY(QuorumVoteItem) next;
} QuorumVoteItem;
/* this structure is a vote version. A version is the set of votes sharing the
* same vote value.
* The set of votes will be tracked with the items field and its cardinality is
* vote_count.
*/
typedef struct QuorumVoteVersion {
QuorumVoteValue value;
int index;
int vote_count;
QLIST_HEAD(, QuorumVoteItem) items;
QLIST_ENTRY(QuorumVoteVersion) next;
} QuorumVoteVersion;
/* this structure holds a group of vote versions together */
typedef struct QuorumVotes {
QLIST_HEAD(, QuorumVoteVersion) vote_list;
bool (*compare)(QuorumVoteValue *a, QuorumVoteValue *b);
} QuorumVotes;
/* the following structure holds the state of one quorum instance */
typedef struct BDRVQuorumState {
BlockDriverState **bs; /* children BlockDriverStates */
int num_children; /* children count */
int threshold; /* if less than threshold children reads gave the
* same result a quorum error occurs.
*/
bool is_blkverify; /* true if the driver is in blkverify mode
* Writes are mirrored on two children devices.
* On reads the two children devices' contents are
* compared and if a difference is spotted its
* location is printed and the code aborts.
* It is useful to debug other block drivers by
* comparing them with a reference one.
*/
} BDRVQuorumState;
typedef struct QuorumAIOCB QuorumAIOCB;
/* Quorum will create one instance of the following structure per operation it
* performs on its children.
* So for each read/write operation coming from the upper layer there will be
* $children_count QuorumChildRequest.
*/
typedef struct QuorumChildRequest {
BlockDriverAIOCB *aiocb;
QEMUIOVector qiov;
uint8_t *buf;
int ret;
QuorumAIOCB *parent;
} QuorumChildRequest;
/* Quorum will use the following structure to track progress of each read/write
* operation received by the upper layer.
* This structure hold pointers to the QuorumChildRequest structures instances
* used to do operations on each children and track overall progress.
*/
struct QuorumAIOCB {
BlockDriverAIOCB common;
/* Request metadata */
uint64_t sector_num;
int nb_sectors;
QEMUIOVector *qiov; /* calling IOV */
QuorumChildRequest *qcrs; /* individual child requests */
int count; /* number of completed AIOCB */
int success_count; /* number of successfully completed AIOCB */
QuorumVotes votes;
bool is_read;
int vote_ret;
};
static void quorum_vote(QuorumAIOCB *acb);
static void quorum_aio_cancel(BlockDriverAIOCB *blockacb)
{
QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common);
BDRVQuorumState *s = acb->common.bs->opaque;
int i;
/* cancel all callbacks */
for (i = 0; i < s->num_children; i++) {
bdrv_aio_cancel(acb->qcrs[i].aiocb);
}
g_free(acb->qcrs);
qemu_aio_release(acb);
}
static AIOCBInfo quorum_aiocb_info = {
.aiocb_size = sizeof(QuorumAIOCB),
.cancel = quorum_aio_cancel,
};
static void quorum_aio_finalize(QuorumAIOCB *acb)
{
BDRVQuorumState *s = acb->common.bs->opaque;
int i, ret = 0;
if (acb->vote_ret) {
ret = acb->vote_ret;
}
acb->common.cb(acb->common.opaque, ret);
if (acb->is_read) {
for (i = 0; i < s->num_children; i++) {
qemu_vfree(acb->qcrs[i].buf);
qemu_iovec_destroy(&acb->qcrs[i].qiov);
}
}
g_free(acb->qcrs);
qemu_aio_release(acb);
}
static bool quorum_sha256_compare(QuorumVoteValue *a, QuorumVoteValue *b)
{
return !memcmp(a->h, b->h, HASH_LENGTH);
}
static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b)
{
return a->l == b->l;
}
static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s,
BlockDriverState *bs,
QEMUIOVector *qiov,
uint64_t sector_num,
int nb_sectors,
BlockDriverCompletionFunc *cb,
void *opaque)
{
QuorumAIOCB *acb = qemu_aio_get(&quorum_aiocb_info, bs, cb, opaque);
int i;
acb->common.bs->opaque = s;
acb->sector_num = sector_num;
acb->nb_sectors = nb_sectors;
acb->qiov = qiov;
acb->qcrs = g_new0(QuorumChildRequest, s->num_children);
acb->count = 0;
acb->success_count = 0;
acb->votes.compare = quorum_sha256_compare;
QLIST_INIT(&acb->votes.vote_list);
acb->is_read = false;
acb->vote_ret = 0;
for (i = 0; i < s->num_children; i++) {
acb->qcrs[i].buf = NULL;
acb->qcrs[i].ret = 0;
acb->qcrs[i].parent = acb;
}
return acb;
}
static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret)
{
QObject *data;
assert(node_name);
data = qobject_from_jsonf("{ 'node-name': %s"
", 'sector-num': %" PRId64
", 'sectors-count': %d }",
node_name, acb->sector_num, acb->nb_sectors);
if (ret < 0) {
QDict *dict = qobject_to_qdict(data);
qdict_put(dict, "error", qstring_from_str(strerror(-ret)));
}
monitor_protocol_event(QEVENT_QUORUM_REPORT_BAD, data);
qobject_decref(data);
}
static void quorum_report_failure(QuorumAIOCB *acb)
{
QObject *data;
const char *reference = acb->common.bs->device_name[0] ?
acb->common.bs->device_name :
acb->common.bs->node_name;
data = qobject_from_jsonf("{ 'reference': %s"
", 'sector-num': %" PRId64
", 'sectors-count': %d }",
reference, acb->sector_num, acb->nb_sectors);
monitor_protocol_event(QEVENT_QUORUM_FAILURE, data);
qobject_decref(data);
}
static int quorum_vote_error(QuorumAIOCB *acb);
static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
{
BDRVQuorumState *s = acb->common.bs->opaque;
if (acb->success_count < s->threshold) {
acb->vote_ret = quorum_vote_error(acb);
quorum_report_failure(acb);
return true;
}
return false;
}
static void quorum_aio_cb(void *opaque, int ret)
{
QuorumChildRequest *sacb = opaque;
QuorumAIOCB *acb = sacb->parent;
BDRVQuorumState *s = acb->common.bs->opaque;
sacb->ret = ret;
acb->count++;
if (ret == 0) {
acb->success_count++;
} else {
quorum_report_bad(acb, sacb->aiocb->bs->node_name, ret);
}
assert(acb->count <= s->num_children);
assert(acb->success_count <= s->num_children);
if (acb->count < s->num_children) {
return;
}
/* Do the vote on read */
if (acb->is_read) {
quorum_vote(acb);
} else {
quorum_has_too_much_io_failed(acb);
}
quorum_aio_finalize(acb);
}
static void quorum_report_bad_versions(BDRVQuorumState *s,
QuorumAIOCB *acb,
QuorumVoteValue *value)
{
QuorumVoteVersion *version;
QuorumVoteItem *item;
QLIST_FOREACH(version, &acb->votes.vote_list, next) {
if (acb->votes.compare(&version->value, value)) {
continue;
}
QLIST_FOREACH(item, &version->items, next) {
quorum_report_bad(acb, s->bs[item->index]->node_name, 0);
}
}
}
static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source)
{
int i;
assert(dest->niov == source->niov);
assert(dest->size == source->size);
for (i = 0; i < source->niov; i++) {
assert(dest->iov[i].iov_len == source->iov[i].iov_len);
memcpy(dest->iov[i].iov_base,
source->iov[i].iov_base,
source->iov[i].iov_len);
}
}
static void quorum_count_vote(QuorumVotes *votes,
QuorumVoteValue *value,
int index)
{
QuorumVoteVersion *v = NULL, *version = NULL;
QuorumVoteItem *item;
/* look if we have something with this hash */
QLIST_FOREACH(v, &votes->vote_list, next) {
if (votes->compare(&v->value, value)) {
version = v;
break;
}
}
/* It's a version not yet in the list add it */
if (!version) {
version = g_new0(QuorumVoteVersion, 1);
QLIST_INIT(&version->items);
memcpy(&version->value, value, sizeof(version->value));
version->index = index;
version->vote_count = 0;
QLIST_INSERT_HEAD(&votes->vote_list, version, next);
}
version->vote_count++;
item = g_new0(QuorumVoteItem, 1);
item->index = index;
QLIST_INSERT_HEAD(&version->items, item, next);
}
static void quorum_free_vote_list(QuorumVotes *votes)
{
QuorumVoteVersion *version, *next_version;
QuorumVoteItem *item, *next_item;
QLIST_FOREACH_SAFE(version, &votes->vote_list, next, next_version) {
QLIST_REMOVE(version, next);
QLIST_FOREACH_SAFE(item, &version->items, next, next_item) {
QLIST_REMOVE(item, next);
g_free(item);
}
g_free(version);
}
}
static int quorum_compute_hash(QuorumAIOCB *acb, int i, QuorumVoteValue *hash)
{
int j, ret;
gnutls_hash_hd_t dig;
QEMUIOVector *qiov = &acb->qcrs[i].qiov;
ret = gnutls_hash_init(&dig, GNUTLS_DIG_SHA256);
if (ret < 0) {
return ret;
}
for (j = 0; j < qiov->niov; j++) {
ret = gnutls_hash(dig, qiov->iov[j].iov_base, qiov->iov[j].iov_len);
if (ret < 0) {
break;
}
}
gnutls_hash_deinit(dig, (void *) hash);
return ret;
}
static QuorumVoteVersion *quorum_get_vote_winner(QuorumVotes *votes)
{
int max = 0;
QuorumVoteVersion *candidate, *winner = NULL;
QLIST_FOREACH(candidate, &votes->vote_list, next) {
if (candidate->vote_count > max) {
max = candidate->vote_count;
winner = candidate;
}
}
return winner;
}
/* qemu_iovec_compare is handy for blkverify mode because it returns the first
* differing byte location. Yet it is handcoded to compare vectors one byte
* after another so it does not benefit from the libc SIMD optimizations.
* quorum_iovec_compare is written for speed and should be used in the non
* blkverify mode of quorum.
*/
static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
{
int i;
int result;
assert(a->niov == b->niov);
for (i = 0; i < a->niov; i++) {
assert(a->iov[i].iov_len == b->iov[i].iov_len);
result = memcmp(a->iov[i].iov_base,
b->iov[i].iov_base,
a->iov[i].iov_len);
if (result) {
return false;
}
}
return true;
}
static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "quorum: sector_num=%" PRId64 " nb_sectors=%d ",
acb->sector_num, acb->nb_sectors);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
static bool quorum_compare(QuorumAIOCB *acb,
QEMUIOVector *a,
QEMUIOVector *b)
{
BDRVQuorumState *s = acb->common.bs->opaque;
ssize_t offset;
/* This driver will replace blkverify in this particular case */
if (s->is_blkverify) {
offset = qemu_iovec_compare(a, b);
if (offset != -1) {
quorum_err(acb, "contents mismatch in sector %" PRId64,
acb->sector_num +
(uint64_t)(offset / BDRV_SECTOR_SIZE));
}
return true;
}
return quorum_iovec_compare(a, b);
}
/* Do a vote to get the error code */
static int quorum_vote_error(QuorumAIOCB *acb)
{
BDRVQuorumState *s = acb->common.bs->opaque;
QuorumVoteVersion *winner = NULL;
QuorumVotes error_votes;
QuorumVoteValue result_value;
int i, ret = 0;
bool error = false;
QLIST_INIT(&error_votes.vote_list);
error_votes.compare = quorum_64bits_compare;
for (i = 0; i < s->num_children; i++) {
ret = acb->qcrs[i].ret;
if (ret) {
error = true;
result_value.l = ret;
quorum_count_vote(&error_votes, &result_value, i);
}
}
if (error) {
winner = quorum_get_vote_winner(&error_votes);
ret = winner->value.l;
}
quorum_free_vote_list(&error_votes);
return ret;
}
static void quorum_vote(QuorumAIOCB *acb)
{
bool quorum = true;
int i, j, ret;
QuorumVoteValue hash;
BDRVQuorumState *s = acb->common.bs->opaque;
QuorumVoteVersion *winner;
if (quorum_has_too_much_io_failed(acb)) {
return;
}
/* get the index of the first successful read */
for (i = 0; i < s->num_children; i++) {
if (!acb->qcrs[i].ret) {
break;
}
}
assert(i < s->num_children);
/* compare this read with all other successful reads stopping at quorum
* failure
*/
for (j = i + 1; j < s->num_children; j++) {
if (acb->qcrs[j].ret) {
continue;
}
quorum = quorum_compare(acb, &acb->qcrs[i].qiov, &acb->qcrs[j].qiov);
if (!quorum) {
break;
}
}
/* Every successful read agrees */
if (quorum) {
quorum_copy_qiov(acb->qiov, &acb->qcrs[i].qiov);
return;
}
/* compute hashes for each successful read, also store indexes */
for (i = 0; i < s->num_children; i++) {
if (acb->qcrs[i].ret) {
continue;
}
ret = quorum_compute_hash(acb, i, &hash);
/* if ever the hash computation failed */
if (ret < 0) {
acb->vote_ret = ret;
goto free_exit;
}
quorum_count_vote(&acb->votes, &hash, i);
}
/* vote to select the most represented version */
winner = quorum_get_vote_winner(&acb->votes);
/* if the winner count is smaller than threshold the read fails */
if (winner->vote_count < s->threshold) {
quorum_report_failure(acb);
acb->vote_ret = -EIO;
goto free_exit;
}
/* we have a winner: copy it */
quorum_copy_qiov(acb->qiov, &acb->qcrs[winner->index].qiov);
/* some versions are bad print them */
quorum_report_bad_versions(s, acb, &winner->value);
free_exit:
/* free lists */
quorum_free_vote_list(&acb->votes);
}
static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs,
int64_t sector_num,
QEMUIOVector *qiov,
int nb_sectors,
BlockDriverCompletionFunc *cb,
void *opaque)
{
BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num,
nb_sectors, cb, opaque);
int i;
acb->is_read = true;
for (i = 0; i < s->num_children; i++) {
acb->qcrs[i].buf = qemu_blockalign(s->bs[i], qiov->size);
qemu_iovec_init(&acb->qcrs[i].qiov, qiov->niov);
qemu_iovec_clone(&acb->qcrs[i].qiov, qiov, acb->qcrs[i].buf);
}
for (i = 0; i < s->num_children; i++) {
bdrv_aio_readv(s->bs[i], sector_num, &acb->qcrs[i].qiov, nb_sectors,
quorum_aio_cb, &acb->qcrs[i]);
}
return &acb->common;
}
static BlockDriverAIOCB *quorum_aio_writev(BlockDriverState *bs,
int64_t sector_num,
QEMUIOVector *qiov,
int nb_sectors,
BlockDriverCompletionFunc *cb,
void *opaque)
{
BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num, nb_sectors,
cb, opaque);
int i;
for (i = 0; i < s->num_children; i++) {
acb->qcrs[i].aiocb = bdrv_aio_writev(s->bs[i], sector_num, qiov,
nb_sectors, &quorum_aio_cb,
&acb->qcrs[i]);
}
return &acb->common;
}
static int64_t quorum_getlength(BlockDriverState *bs)
{
BDRVQuorumState *s = bs->opaque;
int64_t result;
int i;
/* check that all file have the same length */
result = bdrv_getlength(s->bs[0]);
if (result < 0) {
return result;
}
for (i = 1; i < s->num_children; i++) {
int64_t value = bdrv_getlength(s->bs[i]);
if (value < 0) {
return value;
}
if (value != result) {
return -EIO;
}
}
return result;
}
static void quorum_invalidate_cache(BlockDriverState *bs)
{
BDRVQuorumState *s = bs->opaque;
int i;
for (i = 0; i < s->num_children; i++) {
bdrv_invalidate_cache(s->bs[i]);
}
}
static coroutine_fn int quorum_co_flush(BlockDriverState *bs)
{
BDRVQuorumState *s = bs->opaque;
QuorumVoteVersion *winner = NULL;
QuorumVotes error_votes;
QuorumVoteValue result_value;
int i;
int result = 0;
QLIST_INIT(&error_votes.vote_list);
error_votes.compare = quorum_64bits_compare;
for (i = 0; i < s->num_children; i++) {
result = bdrv_co_flush(s->bs[i]);
result_value.l = result;
quorum_count_vote(&error_votes, &result_value, i);
}
winner = quorum_get_vote_winner(&error_votes);
result = winner->value.l;
quorum_free_vote_list(&error_votes);
return result;
}
static bool quorum_recurse_is_first_non_filter(BlockDriverState *bs,
BlockDriverState *candidate)
{
BDRVQuorumState *s = bs->opaque;
int i;
for (i = 0; i < s->num_children; i++) {
bool perm = bdrv_recurse_is_first_non_filter(s->bs[i],
candidate);
if (perm) {
return true;
}
}
return false;
}
static int quorum_valid_threshold(int threshold, int num_children, Error **errp)
{
if (threshold < 1) {
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
"vote-threshold", "value >= 1");
return -ERANGE;
}
if (threshold > num_children) {
error_setg(errp, "threshold may not exceed children count");
return -ERANGE;
}
return 0;
}
static QemuOptsList quorum_runtime_opts = {
.name = "quorum",
.head = QTAILQ_HEAD_INITIALIZER(quorum_runtime_opts.head),
.desc = {
{
.name = QUORUM_OPT_VOTE_THRESHOLD,
.type = QEMU_OPT_NUMBER,
.help = "The number of vote needed for reaching quorum",
},
{
.name = QUORUM_OPT_BLKVERIFY,
.type = QEMU_OPT_BOOL,
.help = "Trigger block verify mode if set",
},
{ /* end of list */ }
},
};
static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVQuorumState *s = bs->opaque;
Error *local_err = NULL;
QemuOpts *opts;
bool *opened;
QDict *sub = NULL;
QList *list = NULL;
const QListEntry *lentry;
int i;
int ret = 0;
qdict_flatten(options);
qdict_extract_subqdict(options, &sub, "children.");
qdict_array_split(sub, &list);
if (qdict_size(sub)) {
error_setg(&local_err, "Invalid option children.%s",
qdict_first(sub)->key);
ret = -EINVAL;
goto exit;
}
/* count how many different children are present */
s->num_children = qlist_size(list);
if (s->num_children < 2) {
error_setg(&local_err,
"Number of provided children must be greater than 1");
ret = -EINVAL;
goto exit;
}
opts = qemu_opts_create(&quorum_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
if (error_is_set(&local_err)) {
ret = -EINVAL;
goto exit;
}
s->threshold = qemu_opt_get_number(opts, QUORUM_OPT_VOTE_THRESHOLD, 0);
/* and validate it against s->num_children */
ret = quorum_valid_threshold(s->threshold, s->num_children, &local_err);
if (ret < 0) {
goto exit;
}
/* is the driver in blkverify mode */
if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
s->num_children == 2 && s->threshold == 2) {
s->is_blkverify = true;
} else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
fprintf(stderr, "blkverify mode is set by setting blkverify=on "
"and using two files with vote_threshold=2\n");
}
/* allocate the children BlockDriverState array */
s->bs = g_new0(BlockDriverState *, s->num_children);
opened = g_new0(bool, s->num_children);
for (i = 0, lentry = qlist_first(list); lentry;
lentry = qlist_next(lentry), i++) {
QDict *d;
QString *string;
switch (qobject_type(lentry->value))
{
/* List of options */
case QTYPE_QDICT:
d = qobject_to_qdict(lentry->value);
QINCREF(d);
ret = bdrv_open(&s->bs[i], NULL, NULL, d, flags, NULL,
&local_err);
break;
/* QMP reference */
case QTYPE_QSTRING:
string = qobject_to_qstring(lentry->value);
ret = bdrv_open(&s->bs[i], NULL, qstring_get_str(string), NULL,
flags, NULL, &local_err);
break;
default:
error_setg(&local_err, "Specification of child block device %i "
"is invalid", i);
ret = -EINVAL;
}
if (ret < 0) {
goto close_exit;
}
opened[i] = true;
}
g_free(opened);
goto exit;
close_exit:
/* cleanup on error */
for (i = 0; i < s->num_children; i++) {
if (!opened[i]) {
continue;
}
bdrv_unref(s->bs[i]);
}
g_free(s->bs);
g_free(opened);
exit:
/* propagate error */
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
}
QDECREF(list);
QDECREF(sub);
return ret;
}
static void quorum_close(BlockDriverState *bs)
{
BDRVQuorumState *s = bs->opaque;
int i;
for (i = 0; i < s->num_children; i++) {
bdrv_unref(s->bs[i]);
}
g_free(s->bs);
}
static BlockDriver bdrv_quorum = {
.format_name = "quorum",
.protocol_name = "quorum",
.instance_size = sizeof(BDRVQuorumState),
.bdrv_file_open = quorum_open,
.bdrv_close = quorum_close,
.authorizations = { true, true },
.bdrv_co_flush_to_disk = quorum_co_flush,
.bdrv_getlength = quorum_getlength,
.bdrv_aio_readv = quorum_aio_readv,
.bdrv_aio_writev = quorum_aio_writev,
.bdrv_invalidate_cache = quorum_invalidate_cache,
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
};
static void bdrv_quorum_init(void)
{
bdrv_register(&bdrv_quorum);
}
block_init(bdrv_quorum_init);

View File

@@ -336,6 +336,17 @@ error:
} }
#endif #endif
static void raw_parse_filename(const char *filename, QDict *options,
Error **errp)
{
/* The filename does not have to be prefixed by the protocol name, since
* "file" is the default protocol; therefore, the return value of this
* function call can be ignored. */
strstart(filename, "file:", &filename);
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
}
static QemuOptsList raw_runtime_opts = { static QemuOptsList raw_runtime_opts = {
.name = "raw", .name = "raw",
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head), .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
@@ -1230,6 +1241,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
int result = 0; int result = 0;
int64_t total_size = 0; int64_t total_size = 0;
strstart(filename, "file:", &filename);
/* Read out options */ /* Read out options */
while (options && options->name) { while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
@@ -1412,6 +1425,7 @@ static BlockDriver bdrv_file = {
.instance_size = sizeof(BDRVRawState), .instance_size = sizeof(BDRVRawState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_probe = NULL, /* no probe for protocols */ .bdrv_probe = NULL, /* no probe for protocols */
.bdrv_parse_filename = raw_parse_filename,
.bdrv_file_open = raw_open, .bdrv_file_open = raw_open,
.bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,

View File

@@ -251,6 +251,17 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
} }
} }
static void raw_parse_filename(const char *filename, QDict *options,
Error **errp)
{
/* The filename does not have to be prefixed by the protocol name, since
* "file" is the default protocol; therefore, the return value of this
* function call can be ignored. */
strstart(filename, "file:", &filename);
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
}
static QemuOptsList raw_runtime_opts = { static QemuOptsList raw_runtime_opts = {
.name = "raw", .name = "raw",
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head), .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
@@ -470,6 +481,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
int fd; int fd;
int64_t total_size = 0; int64_t total_size = 0;
strstart(filename, "file:", &filename);
/* Read out options */ /* Read out options */
while (options && options->name) { while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
@@ -504,6 +517,7 @@ static BlockDriver bdrv_file = {
.protocol_name = "file", .protocol_name = "file",
.instance_size = sizeof(BDRVRawState), .instance_size = sizeof(BDRVRawState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_parse_filename = raw_parse_filename,
.bdrv_file_open = raw_open, .bdrv_file_open = raw_open,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_create = raw_create, .bdrv_create = raw_create,

View File

@@ -1534,7 +1534,8 @@ static int sd_prealloc(const char *filename)
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err); ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
NULL, &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); qerror_report_err(local_err);
error_free(local_err); error_free(local_err);
@@ -1695,7 +1696,9 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
goto out; goto out;
} }
ret = bdrv_file_open(&bs, backing_file, NULL, NULL, 0, &local_err); bs = NULL;
ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL,
&local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); qerror_report_err(local_err);
error_free(local_err); error_free(local_err);

View File

@@ -395,43 +395,50 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
} }
if (header.signature != VDI_SIGNATURE) { if (header.signature != VDI_SIGNATURE) {
logout("bad vdi signature %08x\n", header.signature); error_setg(errp, "Image not in VDI format (bad signature %08x)", header.signature);
ret = -EMEDIUMTYPE; ret = -EINVAL;
goto fail; goto fail;
} else if (header.version != VDI_VERSION_1_1) { } else if (header.version != VDI_VERSION_1_1) {
logout("unsupported version %u.%u\n", error_setg(errp, "unsupported VDI image (version %u.%u)",
header.version >> 16, header.version & 0xffff); header.version >> 16, header.version & 0xffff);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (header.offset_bmap % SECTOR_SIZE != 0) { } else if (header.offset_bmap % SECTOR_SIZE != 0) {
/* We only support block maps which start on a sector boundary. */ /* We only support block maps which start on a sector boundary. */
logout("unsupported block map offset 0x%x B\n", header.offset_bmap); error_setg(errp, "unsupported VDI image (unaligned block map offset "
"0x%x)", header.offset_bmap);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (header.offset_data % SECTOR_SIZE != 0) { } else if (header.offset_data % SECTOR_SIZE != 0) {
/* We only support data blocks which start on a sector boundary. */ /* We only support data blocks which start on a sector boundary. */
logout("unsupported data offset 0x%x B\n", header.offset_data); error_setg(errp, "unsupported VDI image (unaligned data offset 0x%x)",
header.offset_data);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (header.sector_size != SECTOR_SIZE) { } else if (header.sector_size != SECTOR_SIZE) {
logout("unsupported sector size %u B\n", header.sector_size); error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
header.sector_size, SECTOR_SIZE);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (header.block_size != 1 * MiB) { } else if (header.block_size != 1 * MiB) {
logout("unsupported block size %u B\n", header.block_size); error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
header.block_size, 1 * MiB);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (header.disk_size > } else if (header.disk_size >
(uint64_t)header.blocks_in_image * header.block_size) { (uint64_t)header.blocks_in_image * header.block_size) {
logout("unsupported disk size %" PRIu64 " B\n", header.disk_size); error_setg(errp, "unsupported VDI image (disk size %" PRIu64 ", "
"image bitmap has room for %" PRIu64 ")",
header.disk_size,
(uint64_t)header.blocks_in_image * header.block_size);
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (!uuid_is_null(header.uuid_link)) { } else if (!uuid_is_null(header.uuid_link)) {
logout("link uuid != 0, unsupported\n"); error_setg(errp, "unsupported VDI image (non-NULL link UUID)");
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} else if (!uuid_is_null(header.uuid_parent)) { } else if (!uuid_is_null(header.uuid_parent)) {
logout("parent uuid != 0, unsupported\n"); error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
ret = -ENOTSUP; ret = -ENOTSUP;
goto fail; goto fail;
} }

View File

@@ -402,9 +402,10 @@ int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s,
} }
/* opens the specified header block from the VHDX file header section */ /* opens the specified header block from the VHDX file header section */
static int vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s) static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
Error **errp)
{ {
int ret = 0; int ret;
VHDXHeader *header1; VHDXHeader *header1;
VHDXHeader *header2; VHDXHeader *header2;
bool h1_valid = false; bool h1_valid = false;
@@ -462,7 +463,6 @@ static int vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s)
} else if (!h1_valid && h2_valid) { } else if (!h1_valid && h2_valid) {
s->curr_header = 1; s->curr_header = 1;
} else if (!h1_valid && !h2_valid) { } else if (!h1_valid && !h2_valid) {
ret = -EINVAL;
goto fail; goto fail;
} else { } else {
/* If both headers are valid, then we choose the active one by the /* If both headers are valid, then we choose the active one by the
@@ -473,27 +473,22 @@ static int vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s)
} else if (h2_seq > h1_seq) { } else if (h2_seq > h1_seq) {
s->curr_header = 1; s->curr_header = 1;
} else { } else {
ret = -EINVAL;
goto fail; goto fail;
} }
} }
vhdx_region_register(s, s->headers[s->curr_header]->log_offset, vhdx_region_register(s, s->headers[s->curr_header]->log_offset,
s->headers[s->curr_header]->log_length); s->headers[s->curr_header]->log_length);
ret = 0;
goto exit; goto exit;
fail: fail:
qerror_report(ERROR_CLASS_GENERIC_ERROR, "No valid VHDX header found"); error_setg_errno(errp, -ret, "No valid VHDX header found");
qemu_vfree(header1); qemu_vfree(header1);
qemu_vfree(header2); qemu_vfree(header2);
s->headers[0] = NULL; s->headers[0] = NULL;
s->headers[1] = NULL; s->headers[1] = NULL;
exit: exit:
qemu_vfree(buffer); qemu_vfree(buffer);
return ret;
} }
@@ -878,7 +873,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
int ret = 0; int ret = 0;
uint32_t i; uint32_t i;
uint64_t signature; uint64_t signature;
Error *local_err = NULL;
s->bat = NULL; s->bat = NULL;
s->first_visible_write = true; s->first_visible_write = true;
@@ -901,8 +896,10 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
* header update */ * header update */
vhdx_guid_generate(&s->session_guid); vhdx_guid_generate(&s->session_guid);
ret = vhdx_parse_header(bs, s); vhdx_parse_header(bs, s, &local_err);
if (ret < 0) { if (local_err != NULL) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail; goto fail;
} }
@@ -1797,7 +1794,9 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
goto exit; goto exit;
} }
ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err); bs = NULL;
ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto exit; goto exit;

View File

@@ -526,8 +526,34 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
return ret; return ret;
} }
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
uint64_t desc_offset, Error **errp); Error **errp);
static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
Error **errp)
{
int64_t size;
char *buf;
int ret;
size = bdrv_getlength(file);
if (size < 0) {
error_setg_errno(errp, -size, "Could not access file");
return NULL;
}
size = MIN(size, 1 << 20); /* avoid unbounded allocation */
buf = g_malloc0(size + 1);
ret = bdrv_pread(file, desc_offset, buf, size);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read from file");
g_free(buf);
return NULL;
}
return buf;
}
static int vmdk_open_vmdk4(BlockDriverState *bs, static int vmdk_open_vmdk4(BlockDriverState *bs,
BlockDriverState *file, BlockDriverState *file,
@@ -546,11 +572,18 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
error_setg_errno(errp, -ret, error_setg_errno(errp, -ret,
"Could not read header from file '%s'", "Could not read header from file '%s'",
file->filename); file->filename);
return -EINVAL;
} }
if (header.capacity == 0) { if (header.capacity == 0) {
uint64_t desc_offset = le64_to_cpu(header.desc_offset); uint64_t desc_offset = le64_to_cpu(header.desc_offset);
if (desc_offset) { if (desc_offset) {
return vmdk_open_desc_file(bs, flags, desc_offset << 9, errp); char *buf = vmdk_read_desc(file, desc_offset << 9, errp);
if (!buf) {
return -EINVAL;
}
ret = vmdk_open_desc_file(bs, flags, buf, errp);
g_free(buf);
return ret;
} }
} }
@@ -609,8 +642,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
char buf[64]; char buf[64];
snprintf(buf, sizeof(buf), "VMDK version %d", snprintf(buf, sizeof(buf), "VMDK version %d",
le32_to_cpu(header.version)); le32_to_cpu(header.version));
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "vmdk", buf); bs->device_name, "vmdk", buf);
return -ENOTSUP; return -ENOTSUP;
} else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) { } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
/* VMware KB 2064959 explains that version 3 added support for /* VMware KB 2064959 explains that version 3 added support for
@@ -622,7 +655,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
} }
if (le32_to_cpu(header.num_gtes_per_gt) > 512) { if (le32_to_cpu(header.num_gtes_per_gt) > 512) {
error_report("L2 table size too big"); error_setg(errp, "L2 table size too big");
return -EINVAL; return -EINVAL;
} }
@@ -638,8 +671,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
} }
if (bdrv_getlength(file) < if (bdrv_getlength(file) <
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) { le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
error_report("File truncated, expecting at least %lld bytes", error_setg(errp, "File truncated, expecting at least %lld bytes",
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE); le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE);
return -EINVAL; return -EINVAL;
} }
@@ -701,16 +734,12 @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
/* Open an extent file and append to bs array */ /* Open an extent file and append to bs array */
static int vmdk_open_sparse(BlockDriverState *bs, static int vmdk_open_sparse(BlockDriverState *bs,
BlockDriverState *file, BlockDriverState *file, int flags,
int flags, Error **errp) char *buf, Error **errp)
{ {
uint32_t magic; uint32_t magic;
if (bdrv_pread(file, 0, &magic, sizeof(magic)) != sizeof(magic)) { magic = ldl_be_p(buf);
return -EIO;
}
magic = be32_to_cpu(magic);
switch (magic) { switch (magic) {
case VMDK3_MAGIC: case VMDK3_MAGIC:
return vmdk_open_vmfs_sparse(bs, file, flags, errp); return vmdk_open_vmfs_sparse(bs, file, flags, errp);
@@ -719,7 +748,8 @@ static int vmdk_open_sparse(BlockDriverState *bs,
return vmdk_open_vmdk4(bs, file, flags, errp); return vmdk_open_vmdk4(bs, file, flags, errp);
break; break;
default: default:
return -EMEDIUMTYPE; error_setg(errp, "Image not in VMDK format");
return -EINVAL;
break; break;
} }
} }
@@ -776,8 +806,9 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
path_combine(extent_path, sizeof(extent_path), path_combine(extent_path, sizeof(extent_path),
desc_file_path, fname); desc_file_path, fname);
ret = bdrv_file_open(&extent_file, extent_path, NULL, NULL, extent_file = NULL;
bs->open_flags, errp); ret = bdrv_open(&extent_file, extent_path, NULL, NULL,
bs->open_flags | BDRV_O_PROTOCOL, NULL, errp);
if (ret) { if (ret) {
return ret; return ret;
} }
@@ -794,8 +825,14 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
extent->flat_start_offset = flat_offset << 9; extent->flat_start_offset = flat_offset << 9;
} else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) { } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
/* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/ /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/
ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, errp); char *buf = vmdk_read_desc(extent_file, 0, errp);
if (!buf) {
ret = -EINVAL;
} else {
ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf, errp);
}
if (ret) { if (ret) {
g_free(buf);
bdrv_unref(extent_file); bdrv_unref(extent_file);
return ret; return ret;
} }
@@ -818,29 +855,16 @@ next_line:
return 0; return 0;
} }
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
uint64_t desc_offset, Error **errp) Error **errp)
{ {
int ret; int ret;
char *buf = NULL;
char ct[128]; char ct[128];
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
int64_t size;
size = bdrv_getlength(bs->file);
if (size < 0) {
return -EINVAL;
}
size = MIN(size, 1 << 20); /* avoid unbounded allocation */
buf = g_malloc0(size + 1);
ret = bdrv_pread(bs->file, desc_offset, buf, size);
if (ret < 0) {
goto exit;
}
if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) { if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
ret = -EMEDIUMTYPE; error_setg(errp, "invalid VMDK image descriptor");
ret = -EINVAL;
goto exit; goto exit;
} }
if (strcmp(ct, "monolithicFlat") && if (strcmp(ct, "monolithicFlat") &&
@@ -856,24 +880,37 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
s->desc_offset = 0; s->desc_offset = 0;
ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp); ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp);
exit: exit:
g_free(buf);
return ret; return ret;
} }
static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp) Error **errp)
{ {
char *buf = NULL;
int ret; int ret;
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
uint32_t magic;
if (vmdk_open_sparse(bs, bs->file, flags, errp) == 0) { buf = vmdk_read_desc(bs->file, 0, errp);
s->desc_offset = 0x200; if (!buf) {
} else { return -EINVAL;
ret = vmdk_open_desc_file(bs, flags, 0, errp);
if (ret) {
goto fail;
}
} }
magic = ldl_be_p(buf);
switch (magic) {
case VMDK3_MAGIC:
case VMDK4_MAGIC:
ret = vmdk_open_sparse(bs, bs->file, flags, buf, errp);
s->desc_offset = 0x200;
break;
default:
ret = vmdk_open_desc_file(bs, flags, buf, errp);
break;
}
if (ret) {
goto fail;
}
/* try to open parent images, if exist */ /* try to open parent images, if exist */
ret = vmdk_parent_open(bs); ret = vmdk_parent_open(bs);
if (ret) { if (ret) {
@@ -888,10 +925,11 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
"vmdk", bs->device_name, "live migration"); "vmdk", bs->device_name, "live migration");
migrate_add_blocker(s->migration_blocker); migrate_add_blocker(s->migration_blocker);
g_free(buf);
return 0; return 0;
fail: fail:
g_free(buf);
g_free(s->create_type); g_free(s->create_type);
s->create_type = NULL; s->create_type = NULL;
vmdk_free_extents(bs); vmdk_free_extents(bs);
@@ -1146,7 +1184,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
break; break;
case VMDK_OK: case VMDK_OK:
ret = BDRV_BLOCK_DATA; ret = BDRV_BLOCK_DATA;
if (extent->file == bs->file) { if (extent->file == bs->file && !extent->compressed) {
ret |= BDRV_BLOCK_OFFSET_VALID | offset; ret |= BDRV_BLOCK_OFFSET_VALID | offset;
} }
@@ -1493,7 +1531,9 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
goto exit; goto exit;
} }
ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err); assert(bs == NULL);
ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto exit; goto exit;
@@ -1755,10 +1795,10 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
goto exit; goto exit;
} }
if (backing_file) { if (backing_file) {
BlockDriverState *bs = bdrv_new(""); BlockDriverState *bs = NULL;
ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp); ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_NO_BACKING, NULL,
errp);
if (ret != 0) { if (ret != 0) {
bdrv_unref(bs);
goto exit; goto exit;
} }
if (strcmp(bs->drv->format_name, "vmdk")) { if (strcmp(bs->drv->format_name, "vmdk")) {
@@ -1831,7 +1871,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
goto exit; goto exit;
} }
} }
ret = bdrv_file_open(&new_bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err); assert(new_bs == NULL);
ret = bdrv_open(&new_bs, filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not write description"); error_setg_errno(errp, -ret, "Could not write description");
goto exit; goto exit;

View File

@@ -190,7 +190,8 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
goto fail; goto fail;
} }
if (strncmp(footer->creator, "conectix", 8)) { if (strncmp(footer->creator, "conectix", 8)) {
ret = -EMEDIUMTYPE; error_setg(errp, "invalid VPC image");
ret = -EINVAL;
goto fail; goto fail;
} }
disk_type = VHD_FIXED; disk_type = VHD_FIXED;

View File

@@ -1086,16 +1086,14 @@ DLOG(if (stderr == NULL) {
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err); qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) { if (local_err) {
qerror_report_err(local_err); error_propagate(errp, local_err);
error_free(local_err);
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
dirname = qemu_opt_get(opts, "dir"); dirname = qemu_opt_get(opts, "dir");
if (!dirname) { if (!dirname) {
qerror_report(ERROR_CLASS_GENERIC_ERROR, "vvfat block driver requires " error_setg(errp, "vvfat block driver requires a 'dir' option");
"a 'dir' option");
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
@@ -1135,8 +1133,7 @@ DLOG(if (stderr == NULL) {
case 12: case 12:
break; break;
default: default:
qerror_report(ERROR_CLASS_GENERIC_ERROR, "Valid FAT types are only " error_setg(errp, "Valid FAT types are only 12, 16 and 32");
"12, 16 and 32");
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
@@ -2936,15 +2933,13 @@ static int enable_write_target(BDRVVVFATState *s)
goto err; goto err;
} }
s->qcow = bdrv_new(""); s->qcow = NULL;
ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL,
ret = bdrv_open(s->qcow, s->qcow_filename, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow,
&local_err); &local_err);
if (ret < 0) { if (ret < 0) {
qerror_report_err(local_err); qerror_report_err(local_err);
error_free(local_err); error_free(local_err);
bdrv_unref(s->qcow);
goto err; goto err;
} }

View File

@@ -504,7 +504,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
bdrv_flags |= ro ? 0 : BDRV_O_RDWR; bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
QINCREF(bs_opts); QINCREF(bs_opts);
ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error); ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error);
if (ret < 0) { if (ret < 0) {
error_setg(errp, "could not open disk image %s: %s", error_setg(errp, "could not open disk image %s: %s",
@@ -1330,12 +1330,12 @@ static void external_snapshot_prepare(BlkTransactionState *common,
qstring_from_str(snapshot_node_name)); qstring_from_str(snapshot_node_name));
} }
/* We will manually add the backing_hd field to the bs later */
state->new_bs = bdrv_new("");
/* TODO Inherit bs->options or only take explicit options with an /* TODO Inherit bs->options or only take explicit options with an
* extended QMP command? */ * extended QMP command? */
ret = bdrv_open(state->new_bs, new_image_file, options, assert(state->new_bs == NULL);
ret = bdrv_open(&state->new_bs, new_image_file, NULL, options,
flags | BDRV_O_NO_BACKING, drv, &local_err); flags | BDRV_O_NO_BACKING, drv, &local_err);
/* We will manually add the backing_hd field to the bs later */
if (ret != 0) { if (ret != 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }
@@ -1582,7 +1582,7 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename,
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv, &local_err); ret = bdrv_open(&bs, filename, NULL, NULL, bdrv_flags, drv, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return; return;
@@ -2018,10 +2018,9 @@ void qmp_drive_backup(const char *device, const char *target,
return; return;
} }
target_bs = bdrv_new(""); target_bs = NULL;
ret = bdrv_open(target_bs, target, NULL, flags, drv, &local_err); ret = bdrv_open(&target_bs, target, NULL, NULL, flags, drv, &local_err);
if (ret < 0) { if (ret < 0) {
bdrv_unref(target_bs);
error_propagate(errp, local_err); error_propagate(errp, local_err);
return; return;
} }
@@ -2162,11 +2161,10 @@ void qmp_drive_mirror(const char *device, const char *target,
/* Mirroring takes care of copy-on-write using the source's backing /* Mirroring takes care of copy-on-write using the source's backing
* file. * file.
*/ */
target_bs = bdrv_new(""); target_bs = NULL;
ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv, ret = bdrv_open(&target_bs, target, NULL, NULL, flags | BDRV_O_NO_BACKING,
&local_err); drv, &local_err);
if (ret < 0) { if (ret < 0) {
bdrv_unref(target_bs);
error_propagate(errp, local_err); error_propagate(errp, local_err);
return; return;
} }
@@ -2268,6 +2266,7 @@ void qmp_block_job_complete(const char *device, Error **errp)
void qmp_blockdev_add(BlockdevOptions *options, Error **errp) void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
{ {
QmpOutputVisitor *ov = qmp_output_visitor_new(); QmpOutputVisitor *ov = qmp_output_visitor_new();
DriveInfo *dinfo;
QObject *obj; QObject *obj;
QDict *qdict; QDict *qdict;
Error *local_err = NULL; Error *local_err = NULL;
@@ -2284,8 +2283,10 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
* *
* For now, simply forbidding the combination for all drivers will do. */ * For now, simply forbidding the combination for all drivers will do. */
if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) { if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
bool direct = options->cache->has_direct && options->cache->direct; bool direct = options->has_cache &&
if (!options->has_cache && !direct) { options->cache->has_direct &&
options->cache->direct;
if (!direct) {
error_setg(errp, "aio=native requires cache.direct=true"); error_setg(errp, "aio=native requires cache.direct=true");
goto fail; goto fail;
} }
@@ -2303,12 +2304,18 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
qdict_flatten(qdict); qdict_flatten(qdict);
blockdev_init(NULL, qdict, &local_err); dinfo = blockdev_init(NULL, qdict, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto fail; goto fail;
} }
if (bdrv_key_required(dinfo->bdrv)) {
drive_uninit(dinfo);
error_setg(errp, "blockdev-add doesn't support encrypted devices");
goto fail;
}
fail: fail:
qmp_output_visitor_cleanup(ov); qmp_output_visitor_cleanup(ov);
} }

386
configure vendored
View File

@@ -12,12 +12,16 @@ else
fi fi
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c" TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o" TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
TMPO="${TMPDIR1}/${TMPB}.o"
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
TMPL="${TMPDIR1}/${TMPB}.lo"
TMPA="${TMPDIR1}/lib${TMPB}.la"
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe" TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
# NB: do not call "exit" in the trap handler; this is buggy with some shells; # NB: do not call "exit" in the trap handler; this is buggy with some shells;
# see <1285349658-3122-1-git-send-email-loic.minier@linaro.org> # see <1285349658-3122-1-git-send-email-loic.minier@linaro.org>
trap "rm -f $TMPC $TMPO $TMPE" EXIT INT QUIT TERM trap "rm -f $TMPC $TMPO $TMPCXX $TMPE" EXIT INT QUIT TERM
rm -f config.log rm -f config.log
# Print a helpful header at the top of config.log # Print a helpful header at the top of config.log
@@ -51,10 +55,13 @@ error_exit() {
exit 1 exit 1
} }
do_cc() { do_compiler() {
# Run the compiler, capturing its output to the log. # Run the compiler, capturing its output to the log. First argument
echo $cc "$@" >> config.log # is compiler binary to execute.
$cc "$@" >> config.log 2>&1 || return $? local compiler="$1"
shift
echo $compiler "$@" >> config.log
$compiler "$@" >> config.log 2>&1 || return $?
# Test passed. If this is an --enable-werror build, rerun # Test passed. If this is an --enable-werror build, rerun
# the test with -Werror and bail out if it fails. This # the test with -Werror and bail out if it fails. This
# makes warning-generating-errors in configure test code # makes warning-generating-errors in configure test code
@@ -68,14 +75,39 @@ do_cc() {
return 0 return 0
;; ;;
esac esac
echo $cc -Werror "$@" >> config.log echo $compiler -Werror "$@" >> config.log
$cc -Werror "$@" >> config.log 2>&1 && return $? $compiler -Werror "$@" >> config.log 2>&1 && return $?
error_exit "configure test passed without -Werror but failed with -Werror." \ error_exit "configure test passed without -Werror but failed with -Werror." \
"This is probably a bug in the configure script. The failing command" \ "This is probably a bug in the configure script. The failing command" \
"will be at the bottom of config.log." \ "will be at the bottom of config.log." \
"You can run configure with --disable-werror to bypass this check." "You can run configure with --disable-werror to bypass this check."
} }
do_cc() {
do_compiler "$cc" "$@"
}
do_cxx() {
do_compiler "$cxx" "$@"
}
update_cxxflags() {
# Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those
# options which some versions of GCC's C++ compiler complain about
# because they only make sense for C programs.
QEMU_CXXFLAGS=
for arg in $QEMU_CFLAGS; do
case $arg in
-Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\
-Wold-style-declaration|-Wold-style-definition|-Wredundant-decls)
;;
*)
QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg
;;
esac
done
}
compile_object() { compile_object() {
do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC
} }
@@ -86,6 +118,38 @@ compile_prog() {
do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags
} }
do_libtool() {
local mode=$1
shift
# Run the compiler, capturing its output to the log.
echo $libtool $mode --tag=CC $cc "$@" >> config.log
$libtool $mode --tag=CC $cc "$@" >> config.log 2>&1 || return $?
# Test passed. If this is an --enable-werror build, rerun
# the test with -Werror and bail out if it fails. This
# makes warning-generating-errors in configure test code
# obvious to developers.
if test "$werror" != "yes"; then
return 0
fi
# Don't bother rerunning the compile if we were already using -Werror
case "$*" in
*-Werror*)
return 0
;;
esac
echo $libtool $mode --tag=CC $cc -Werror "$@" >> config.log
$libtool $mode --tag=CC $cc -Werror "$@" >> config.log 2>&1 && return $?
error_exit "configure test passed without -Werror but failed with -Werror." \
"This is probably a bug in the configure script. The failing command" \
"will be at the bottom of config.log." \
"You can run configure with --disable-werror to bypass this check."
}
libtool_prog() {
do_libtool --mode=compile $QEMU_CFLAGS -c -fPIE -DPIE -o $TMPO $TMPC || return $?
do_libtool --mode=link $LDFLAGS -o $TMPA $TMPL -rpath /usr/local/lib
}
# symbolically link $1 to $2. Portable version of "ln -sf". # symbolically link $1 to $2. Portable version of "ln -sf".
symlink() { symlink() {
rm -rf "$2" rm -rf "$2"
@@ -172,6 +236,7 @@ fdt=""
netmap="no" netmap="no"
pixman="" pixman=""
sdl="" sdl=""
sdlabi="1.2"
virtfs="" virtfs=""
vnc="yes" vnc="yes"
sparse="no" sparse="no"
@@ -205,6 +270,9 @@ mingw32="no"
gcov="no" gcov="no"
gcov_tool="gcov" gcov_tool="gcov"
EXESUF="" EXESUF=""
DSOSUF=".so"
LDFLAGS_SHARED="-shared"
modules="no"
prefix="/usr/local" prefix="/usr/local"
mandir="\${prefix}/share/man" mandir="\${prefix}/share/man"
datadir="\${prefix}/share" datadir="\${prefix}/share"
@@ -245,6 +313,8 @@ libusb=""
usb_redir="" usb_redir=""
glx="" glx=""
zlib="yes" zlib="yes"
lzo="no"
snappy="no"
guest_agent="" guest_agent=""
guest_agent_with_vss="no" guest_agent_with_vss="no"
vss_win32_sdk="" vss_win32_sdk=""
@@ -264,6 +334,7 @@ gtkabi="2.0"
tpm="no" tpm="no"
libssh2="" libssh2=""
vhdx="" vhdx=""
quorum="no"
# parse CC options first # parse CC options first
for opt do for opt do
@@ -325,12 +396,13 @@ query_pkg_config() {
} }
pkg_config=query_pkg_config pkg_config=query_pkg_config
sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}" sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}"
sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}"
# If the user hasn't specified ARFLAGS, default to 'rv', just as make does. # If the user hasn't specified ARFLAGS, default to 'rv', just as make does.
ARFLAGS="${ARFLAGS-rv}" ARFLAGS="${ARFLAGS-rv}"
# default flags for all hosts # default flags for all hosts
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" QEMU_CFLAGS="-fno-strict-aliasing -fno-common $QEMU_CFLAGS"
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
@@ -515,11 +587,10 @@ OpenBSD)
Darwin) Darwin)
bsd="yes" bsd="yes"
darwin="yes" darwin="yes"
LDFLAGS_SHARED="-bundle -undefined dynamic_lookup"
if [ "$cpu" = "x86_64" ] ; then if [ "$cpu" = "x86_64" ] ; then
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS" QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
LDFLAGS="-arch x86_64 $LDFLAGS" LDFLAGS="-arch x86_64 $LDFLAGS"
else
QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS"
fi fi
cocoa="yes" cocoa="yes"
audio_drv_list="coreaudio" audio_drv_list="coreaudio"
@@ -610,6 +681,7 @@ fi
if test "$mingw32" = "yes" ; then if test "$mingw32" = "yes" ; then
EXESUF=".exe" EXESUF=".exe"
DSOSUF=".dll"
QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS" QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
# enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS" QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
@@ -676,6 +748,9 @@ for opt do
;; ;;
--disable-debug-info) --disable-debug-info)
;; ;;
--enable-modules)
modules="yes"
;;
--cpu=*) --cpu=*)
;; ;;
--target-list=*) target_list="$optarg" --target-list=*) target_list="$optarg"
@@ -731,6 +806,8 @@ for opt do
;; ;;
--enable-sdl) sdl="yes" --enable-sdl) sdl="yes"
;; ;;
--with-sdlabi=*) sdlabi="$optarg"
;;
--disable-qom-cast-debug) qom_cast_debug="no" --disable-qom-cast-debug) qom_cast_debug="no"
;; ;;
--enable-qom-cast-debug) qom_cast_debug="yes" --enable-qom-cast-debug) qom_cast_debug="yes"
@@ -953,6 +1030,10 @@ for opt do
;; ;;
--disable-zlib-test) zlib="no" --disable-zlib-test) zlib="no"
;; ;;
--enable-lzo) lzo="yes"
;;
--enable-snappy) snappy="yes"
;;
--enable-guest-agent) guest_agent="yes" --enable-guest-agent) guest_agent="yes"
;; ;;
--disable-guest-agent) guest_agent="no" --disable-guest-agent) guest_agent="no"
@@ -1005,6 +1086,10 @@ for opt do
;; ;;
--disable-vhdx) vhdx="no" --disable-vhdx) vhdx="no"
;; ;;
--disable-quorum) quorum="no"
;;
--enable-quorum) quorum="yes"
;;
*) echo "ERROR: unknown option $opt"; show_help="yes" *) echo "ERROR: unknown option $opt"; show_help="yes"
;; ;;
esac esac
@@ -1131,7 +1216,8 @@ Advanced options (experts only):
--libdir=PATH install libraries in PATH --libdir=PATH install libraries in PATH
--sysconfdir=PATH install config in PATH$confsuffix --sysconfdir=PATH install config in PATH$confsuffix
--localstatedir=PATH install local state in PATH (set at runtime on win32) --localstatedir=PATH install local state in PATH (set at runtime on win32)
--with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix] --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix]
--enable-modules enable modules support
--enable-debug-tcg enable TCG debugging --enable-debug-tcg enable TCG debugging
--disable-debug-tcg disable TCG debugging (default) --disable-debug-tcg disable TCG debugging (default)
--enable-debug-info enable debugging information (default) --enable-debug-info enable debugging information (default)
@@ -1143,6 +1229,7 @@ Advanced options (experts only):
--disable-werror disable compilation abort on warning --disable-werror disable compilation abort on warning
--disable-sdl disable SDL --disable-sdl disable SDL
--enable-sdl enable SDL --enable-sdl enable SDL
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
--disable-gtk disable gtk UI --disable-gtk disable gtk UI
--enable-gtk enable gtk UI --enable-gtk enable gtk UI
--disable-virtfs disable VirtFS --disable-virtfs disable VirtFS
@@ -1242,6 +1329,8 @@ Advanced options (experts only):
--enable-libusb enable libusb (for usb passthrough) --enable-libusb enable libusb (for usb passthrough)
--disable-usb-redir disable usb network redirection support --disable-usb-redir disable usb network redirection support
--enable-usb-redir enable usb network redirection support --enable-usb-redir enable usb network redirection support
--enable-lzo enable the support of lzo compression library
--enable-snappy enable the support of snappy compression library
--disable-guest-agent disable building of the QEMU Guest Agent --disable-guest-agent disable building of the QEMU Guest Agent
--enable-guest-agent enable building of the QEMU Guest Agent --enable-guest-agent enable building of the QEMU Guest Agent
--with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent --with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent
@@ -1261,6 +1350,8 @@ Advanced options (experts only):
--enable-libssh2 enable ssh block device support --enable-libssh2 enable ssh block device support
--disable-vhdx disables support for the Microsoft VHDX image format --disable-vhdx disables support for the Microsoft VHDX image format
--enable-vhdx enable support for the Microsoft VHDX image format --enable-vhdx enable support for the Microsoft VHDX image format
--disable-quorum disable quorum block filter support
--enable-quorum enable quorum block filter support
NOTE: The object files are built at the place where configure is launched NOTE: The object files are built at the place where configure is launched
EOF EOF
@@ -1278,17 +1369,6 @@ if test "$ARCH" = "unknown"; then
fi fi
fi fi
# check that the C compiler works.
cat > $TMPC <<EOF
int main(void) { return 0; }
EOF
if compile_object ; then
: C compiler works ok
else
error_exit "\"$cc\" either does not exist or does not work"
fi
# Consult white-list to determine whether to enable werror # Consult white-list to determine whether to enable werror
# by default. Only enable by default for git builds # by default. Only enable by default for git builds
z_version=`cut -f3 -d. $source_path/VERSION` z_version=`cut -f3 -d. $source_path/VERSION`
@@ -1302,6 +1382,48 @@ if test -z "$werror" ; then
fi fi
fi fi
# check that the C compiler works.
cat > $TMPC <<EOF
int main(void) { return 0; }
EOF
if compile_object ; then
: C compiler works ok
else
error_exit "\"$cc\" either does not exist or does not work"
fi
# Check that the C++ compiler exists and works with the C compiler
if has $cxx; then
cat > $TMPC <<EOF
int c_function(void);
int main(void) { return c_function(); }
EOF
compile_object
cat > $TMPCXX <<EOF
extern "C" {
int c_function(void);
}
int c_function(void) { return 42; }
EOF
update_cxxflags
if do_cxx $QEMU_CXXFLAGS -o $TMPE $TMPCXX $TMPO $LDFLAGS; then
# C++ compiler $cxx works ok with C compiler $cc
:
else
echo "C++ compiler $cxx does not work with C compiler $cc"
echo "Disabling C++ specific optional code"
cxx=
fi
else
echo "No C++ compiler available; disabling C++ specific optional code"
cxx=
fi
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits" gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags" gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags" gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
@@ -1346,6 +1468,9 @@ if compile_prog "-Werror -fno-gcse" "" ; then
fi fi
if test "$static" = "yes" ; then if test "$static" = "yes" ; then
if test "$modules" = "yes" ; then
error_exit "static and modules are mutually incompatible"
fi
if test "$pie" = "yes" ; then if test "$pie" = "yes" ; then
error_exit "static and pie are mutually incompatible" error_exit "static and pie are mutually incompatible"
else else
@@ -1399,6 +1524,32 @@ EOF
fi fi
fi fi
# check for broken gcc and libtool in RHEL5
if test -n "$libtool" -a "$pie" != "no" ; then
cat > $TMPC <<EOF
void *f(unsigned char *buf, int len);
void *g(unsigned char *buf, int len);
void *
f(unsigned char *buf, int len)
{
return (void*)0L;
}
void *
g(unsigned char *buf, int len)
{
return f(buf, len);
}
EOF
if ! libtool_prog; then
echo "Disabling libtool due to broken toolchain support"
libtool=
fi
fi
########################################## ##########################################
# __sync_fetch_and_and requires at least -march=i486. Many toolchains # __sync_fetch_and_and requires at least -march=i486. Many toolchains
# use i686 as default anyway, but for those that don't, an explicit # use i686 as default anyway, but for those that don't, an explicit
@@ -1550,7 +1701,43 @@ EOF
"Make sure to have the zlib libs and headers installed." "Make sure to have the zlib libs and headers installed."
fi fi
fi fi
libs_softmmu="$libs_softmmu -lz" LIBS="$LIBS -lz"
##########################################
# lzo check
if test "$lzo" != "no" ; then
cat > $TMPC << EOF
#include <lzo/lzo1x.h>
int main(void) { lzo_version(); return 0; }
EOF
if compile_prog "" "-llzo2" ; then
:
else
error_exit "lzo check failed" \
"Make sure to have the lzo libs and headers installed."
fi
libs_softmmu="$libs_softmmu -llzo2"
fi
##########################################
# snappy check
if test "$snappy" != "no" ; then
cat > $TMPC << EOF
#include <snappy-c.h>
int main(void) { snappy_max_compressed_length(4096); return 0; }
EOF
if compile_prog "" "-lsnappy" ; then
:
else
error_exit "snappy check failed" \
"Make sure to have the snappy libs and headers installed."
fi
libs_softmmu="$libs_softmmu -lsnappy"
fi
########################################## ##########################################
# libseccomp check # libseccomp check
@@ -1804,12 +1991,22 @@ fi
# Look for sdl configuration program (pkg-config or sdl-config). Try # Look for sdl configuration program (pkg-config or sdl-config). Try
# sdl-config even without cross prefix, and favour pkg-config over sdl-config. # sdl-config even without cross prefix, and favour pkg-config over sdl-config.
if test "`basename $sdl_config`" != sdl-config && ! has ${sdl_config}; then
sdl_config=sdl-config if test $sdlabi = "2.0"; then
sdl_config=$sdl2_config
sdlname=sdl2
sdlconfigname=sdl2_config
else
sdlname=sdl
sdlconfigname=sdl_config
fi fi
if $pkg_config sdl --exists; then if test "`basename $sdl_config`" != $sdlconfigname && ! has ${sdl_config}; then
sdlconfig="$pkg_config sdl" sdl_config=$sdlconfigname
fi
if $pkg_config $sdlname --exists; then
sdlconfig="$pkg_config $sdlname"
_sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'` _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
elif has ${sdl_config}; then elif has ${sdl_config}; then
sdlconfig="$sdl_config" sdlconfig="$sdl_config"
@@ -1936,6 +2133,30 @@ EOF
fi fi
fi fi
##########################################
# Quorum probe (check for gnutls)
if test "$quorum" != "no" ; then
cat > $TMPC <<EOF
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
int main(void) {char data[4096], digest[32];
gnutls_hash_fast(GNUTLS_DIG_SHA256, data, 4096, digest);
return 0;
}
EOF
quorum_tls_cflags=`$pkg_config --cflags gnutls 2> /dev/null`
quorum_tls_libs=`$pkg_config --libs gnutls 2> /dev/null`
if compile_prog "$quorum_tls_cflags" "$quorum_tls_libs" ; then
qcow_tls=yes
libs_softmmu="$quorum_tls_libs $libs_softmmu"
libs_tools="$quorum_tls_libs $libs_softmmu"
QEMU_CFLAGS="$QEMU_CFLAGS $quorum_tls_cflags"
else
echo "gnutls > 2.10.0 required to compile Quorum"
exit 1
fi
fi
########################################## ##########################################
# VNC SASL detection # VNC SASL detection
if test "$vnc" = "yes" -a "$vnc_sasl" != "no" ; then if test "$vnc" = "yes" -a "$vnc_sasl" != "no" ; then
@@ -2118,13 +2339,21 @@ EOF
fi fi
########################################## ##########################################
# netmap headers probe # netmap support probe
# Apart from looking for netmap headers, we make sure that the host API version
# supports the netmap backend (>=11). The upper bound (15) is meant to simulate
# a minor/major version number. Minor new features will be marked with values up
# to 15, and if something happens that requires a change to the backend we will
# move above 15, submit the backend fixes and modify this two bounds.
if test "$netmap" != "no" ; then if test "$netmap" != "no" ; then
cat > $TMPC << EOF cat > $TMPC << EOF
#include <inttypes.h> #include <inttypes.h>
#include <net/if.h> #include <net/if.h>
#include <net/netmap.h> #include <net/netmap.h>
#include <net/netmap_user.h> #include <net/netmap_user.h>
#if (NETMAP_API < 11) || (NETMAP_API > 15)
#error
#endif
int main(void) { return 0; } int main(void) { return 0; }
EOF EOF
if compile_prog "" "" ; then if compile_prog "" "" ; then
@@ -2318,8 +2547,6 @@ EOF
curl_libs=`$curlconfig --libs 2>/dev/null` curl_libs=`$curlconfig --libs 2>/dev/null`
if compile_prog "$curl_cflags" "$curl_libs" ; then if compile_prog "$curl_cflags" "$curl_libs" ; then
curl=yes curl=yes
libs_tools="$curl_libs $libs_tools"
libs_softmmu="$curl_libs $libs_softmmu"
else else
if test "$curl" = "yes" ; then if test "$curl" = "yes" ; then
feature_not_found "curl" "Install libcurl devel" feature_not_found "curl" "Install libcurl devel"
@@ -2357,13 +2584,36 @@ if test "$mingw32" = yes; then
else else
glib_req_ver=2.12 glib_req_ver=2.12
fi fi
if $pkg_config --atleast-version=$glib_req_ver gthread-2.0; then glib_modules=gthread-2.0
glib_cflags=`$pkg_config --cflags gthread-2.0` if test "$modules" = yes; then
glib_libs=`$pkg_config --libs gthread-2.0` glib_modules="$glib_modules gmodule-2.0"
LIBS="$glib_libs $LIBS" fi
libs_qga="$glib_libs $libs_qga"
else for i in $glib_modules; do
error_exit "glib-$glib_req_ver required to compile QEMU" if $pkg_config --atleast-version=$glib_req_ver $i; then
glib_cflags=`$pkg_config --cflags $i`
glib_libs=`$pkg_config --libs $i`
CFLAGS="$glib_cflags $CFLAGS"
LIBS="$glib_libs $LIBS"
libs_qga="$glib_libs $libs_qga"
else
error_exit "glib-$glib_req_ver $i is required to compile QEMU"
fi
done
##########################################
# SHA command probe for modules
if test "$modules" = yes; then
shacmd_probe="sha1sum sha1 shasum"
for c in $shacmd_probe; do
if which $c &>/dev/null; then
shacmd="$c"
break
fi
done
if test "$shacmd" = ""; then
error_exit "one of the checksum commands is required to enable modules: $shacmd_probe"
fi
fi fi
########################################## ##########################################
@@ -2474,8 +2724,6 @@ EOF
rbd_libs="-lrbd -lrados" rbd_libs="-lrbd -lrados"
if compile_prog "" "$rbd_libs" ; then if compile_prog "" "$rbd_libs" ; then
rbd=yes rbd=yes
libs_tools="$rbd_libs $libs_tools"
libs_softmmu="$rbd_libs $libs_softmmu"
else else
if test "$rbd" = "yes" ; then if test "$rbd" = "yes" ; then
feature_not_found "rados block device" "Install librbd/ceph devel" feature_not_found "rados block device" "Install librbd/ceph devel"
@@ -2492,9 +2740,6 @@ if test "$libssh2" != "no" ; then
libssh2_cflags=`$pkg_config libssh2 --cflags` libssh2_cflags=`$pkg_config libssh2 --cflags`
libssh2_libs=`$pkg_config libssh2 --libs` libssh2_libs=`$pkg_config libssh2 --libs`
libssh2=yes libssh2=yes
libs_tools="$libssh2_libs $libs_tools"
libs_softmmu="$libssh2_libs $libs_softmmu"
QEMU_CFLAGS="$QEMU_CFLAGS $libssh2_cflags"
else else
if test "$libssh2" = "yes" ; then if test "$libssh2" = "yes" ; then
error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2" error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2"
@@ -2540,8 +2785,6 @@ int main(void) { io_setup(0, NULL); io_set_eventfd(NULL, 0); eventfd(0, 0); retu
EOF EOF
if compile_prog "" "-laio" ; then if compile_prog "" "-laio" ; then
linux_aio=yes linux_aio=yes
libs_softmmu="$libs_softmmu -laio"
libs_tools="$libs_tools -laio"
else else
if test "$linux_aio" = "yes" ; then if test "$linux_aio" = "yes" ; then
feature_not_found "linux AIO" "Install libaio devel" feature_not_found "linux AIO" "Install libaio devel"
@@ -2710,9 +2953,6 @@ if test "$glusterfs" != "no" ; then
glusterfs="yes" glusterfs="yes"
glusterfs_cflags=`$pkg_config --cflags glusterfs-api` glusterfs_cflags=`$pkg_config --cflags glusterfs-api`
glusterfs_libs=`$pkg_config --libs glusterfs-api` glusterfs_libs=`$pkg_config --libs glusterfs-api`
CFLAGS="$CFLAGS $glusterfs_cflags"
libs_tools="$glusterfs_libs $libs_tools"
libs_softmmu="$glusterfs_libs $libs_softmmu"
if $pkg_config --atleast-version=5 glusterfs-api; then if $pkg_config --atleast-version=5 glusterfs-api; then
glusterfs_discard="yes" glusterfs_discard="yes"
fi fi
@@ -3083,11 +3323,9 @@ EOF
libiscsi="yes" libiscsi="yes"
libiscsi_cflags=$($pkg_config --cflags libiscsi) libiscsi_cflags=$($pkg_config --cflags libiscsi)
libiscsi_libs=$($pkg_config --libs libiscsi) libiscsi_libs=$($pkg_config --libs libiscsi)
CFLAGS="$CFLAGS $libiscsi_cflags"
LIBS="$LIBS $libiscsi_libs"
elif compile_prog "" "-liscsi" ; then elif compile_prog "" "-liscsi" ; then
libiscsi="yes" libiscsi="yes"
LIBS="$LIBS -liscsi" libiscsi_libs="-liscsi"
else else
if test "$libiscsi" = "yes" ; then if test "$libiscsi" = "yes" ; then
feature_not_found "libiscsi" "Install libiscsi devel" feature_not_found "libiscsi" "Install libiscsi devel"
@@ -3688,6 +3926,7 @@ if test "$mingw32" = "yes" ; then
fi fi
qemu_confdir=$sysconfdir$confsuffix qemu_confdir=$sysconfdir$confsuffix
qemu_moddir=$libdir$confsuffix
qemu_datadir=$datadir$confsuffix qemu_datadir=$datadir$confsuffix
qemu_localedir="$datadir/locale" qemu_localedir="$datadir/locale"
@@ -3778,6 +4017,7 @@ echo "Install prefix $prefix"
echo "BIOS directory `eval echo $qemu_datadir`" echo "BIOS directory `eval echo $qemu_datadir`"
echo "binary directory `eval echo $bindir`" echo "binary directory `eval echo $bindir`"
echo "library directory `eval echo $libdir`" echo "library directory `eval echo $libdir`"
echo "module directory `eval echo $qemu_moddir`"
echo "libexec directory `eval echo $libexecdir`" echo "libexec directory `eval echo $libexecdir`"
echo "include directory `eval echo $includedir`" echo "include directory `eval echo $includedir`"
echo "config directory `eval echo $sysconfdir`" echo "config directory `eval echo $sysconfdir`"
@@ -3804,6 +4044,7 @@ echo "python $python"
if test "$slirp" = "yes" ; then if test "$slirp" = "yes" ; then
echo "smbd $smbd" echo "smbd $smbd"
fi fi
echo "module support $modules"
echo "host CPU $cpu" echo "host CPU $cpu"
echo "host big endian $bigendian" echo "host big endian $bigendian"
echo "target list $target_list" echo "target list $target_list"
@@ -3893,6 +4134,9 @@ echo "libssh2 support $libssh2"
echo "TPM passthrough $tpm_passthrough" echo "TPM passthrough $tpm_passthrough"
echo "QOM debugging $qom_cast_debug" echo "QOM debugging $qom_cast_debug"
echo "vhdx $vhdx" echo "vhdx $vhdx"
echo "Quorum $quorum"
echo "lzo support $lzo"
echo "snappy support $snappy"
if test "$sdl_too_old" = "yes"; then if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support" echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -3916,6 +4160,7 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak
echo "qemu_confdir=$qemu_confdir" >> $config_host_mak echo "qemu_confdir=$qemu_confdir" >> $config_host_mak
echo "qemu_datadir=$qemu_datadir" >> $config_host_mak echo "qemu_datadir=$qemu_datadir" >> $config_host_mak
echo "qemu_docdir=$qemu_docdir" >> $config_host_mak echo "qemu_docdir=$qemu_docdir" >> $config_host_mak
echo "qemu_moddir=$qemu_moddir" >> $config_host_mak
if test "$mingw32" = "no" ; then if test "$mingw32" = "no" ; then
echo "qemu_localstatedir=$local_statedir" >> $config_host_mak echo "qemu_localstatedir=$local_statedir" >> $config_host_mak
fi fi
@@ -4048,6 +4293,12 @@ echo "TARGET_DIRS=$target_list" >> $config_host_mak
if [ "$docs" = "yes" ] ; then if [ "$docs" = "yes" ] ; then
echo "BUILD_DOCS=yes" >> $config_host_mak echo "BUILD_DOCS=yes" >> $config_host_mak
fi fi
if test "$modules" = "yes"; then
# $shacmd can generate a hash started with digit, which the compiler doesn't
# like as an symbol. So prefix it with an underscore
echo "CONFIG_STAMP=_`(echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ `" >> $config_host_mak
echo "CONFIG_MODULES=y" >> $config_host_mak
fi
if test "$sdl" = "yes" ; then if test "$sdl" = "yes" ; then
echo "CONFIG_SDL=y" >> $config_host_mak echo "CONFIG_SDL=y" >> $config_host_mak
echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak
@@ -4119,8 +4370,9 @@ if test "$bswap_h" = "yes" ; then
echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak
fi fi
if test "$curl" = "yes" ; then if test "$curl" = "yes" ; then
echo "CONFIG_CURL=y" >> $config_host_mak echo "CONFIG_CURL=m" >> $config_host_mak
echo "CURL_CFLAGS=$curl_cflags" >> $config_host_mak echo "CURL_CFLAGS=$curl_cflags" >> $config_host_mak
echo "CURL_LIBS=$curl_libs" >> $config_host_mak
fi fi
if test "$brlapi" = "yes" ; then if test "$brlapi" = "yes" ; then
echo "CONFIG_BRLAPI=y" >> $config_host_mak echo "CONFIG_BRLAPI=y" >> $config_host_mak
@@ -4208,11 +4460,21 @@ if test "$glx" = "yes" ; then
echo "GLX_LIBS=$glx_libs" >> $config_host_mak echo "GLX_LIBS=$glx_libs" >> $config_host_mak
fi fi
if test "$lzo" = "yes" ; then
echo "CONFIG_LZO=y" >> $config_host_mak
fi
if test "$snappy" = "yes" ; then
echo "CONFIG_SNAPPY=y" >> $config_host_mak
fi
if test "$libiscsi" = "yes" ; then if test "$libiscsi" = "yes" ; then
echo "CONFIG_LIBISCSI=y" >> $config_host_mak echo "CONFIG_LIBISCSI=m" >> $config_host_mak
if test "$libiscsi_version" = "1.4.0"; then if test "$libiscsi_version" = "1.4.0"; then
echo "CONFIG_LIBISCSI_1_4=y" >> $config_host_mak echo "CONFIG_LIBISCSI_1_4=y" >> $config_host_mak
fi fi
echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
echo "LIBISCSI_LIBS=$libiscsi_libs" >> $config_host_mak
fi fi
if test "$libnfs" = "yes" ; then if test "$libnfs" = "yes" ; then
@@ -4237,7 +4499,9 @@ if test "$qom_cast_debug" = "yes" ; then
echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak
fi fi
if test "$rbd" = "yes" ; then if test "$rbd" = "yes" ; then
echo "CONFIG_RBD=y" >> $config_host_mak echo "CONFIG_RBD=m" >> $config_host_mak
echo "RBD_CFLAGS=$rbd_cflags" >> $config_host_mak
echo "RBD_LIBS=$rbd_libs" >> $config_host_mak
fi fi
echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak
@@ -4280,7 +4544,9 @@ if test "$getauxval" = "yes" ; then
fi fi
if test "$glusterfs" = "yes" ; then if test "$glusterfs" = "yes" ; then
echo "CONFIG_GLUSTERFS=y" >> $config_host_mak echo "CONFIG_GLUSTERFS=m" >> $config_host_mak
echo "GLUSTERFS_CFLAGS=$glusterfs_cflags" >> $config_host_mak
echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak
fi fi
if test "$glusterfs_discard" = "yes" ; then if test "$glusterfs_discard" = "yes" ; then
@@ -4292,7 +4558,13 @@ if test "$glusterfs_zerofill" = "yes" ; then
fi fi
if test "$libssh2" = "yes" ; then if test "$libssh2" = "yes" ; then
echo "CONFIG_LIBSSH2=y" >> $config_host_mak echo "CONFIG_LIBSSH2=m" >> $config_host_mak
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak
fi
if test "$quorum" = "yes" ; then
echo "CONFIG_QUORUM=y" >> $config_host_mak
fi fi
if test "$virtio_blk_data_plane" = "yes" ; then if test "$virtio_blk_data_plane" = "yes" ; then
@@ -4423,6 +4695,8 @@ echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
echo "LIBS+=$LIBS" >> $config_host_mak echo "LIBS+=$LIBS" >> $config_host_mak
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak echo "EXESUF=$EXESUF" >> $config_host_mak
echo "DSOSUF=$DSOSUF" >> $config_host_mak
echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
echo "POD2MAN=$POD2MAN" >> $config_host_mak echo "POD2MAN=$POD2MAN" >> $config_host_mak
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak

View File

@@ -477,7 +477,7 @@ int cpu_exec(CPUArchState *env)
} }
#elif defined(TARGET_ARM) #elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->uncached_cpsr & CPSR_F)) { && !(env->daif & PSTATE_F)) {
env->exception_index = EXCP_FIQ; env->exception_index = EXCP_FIQ;
cc->do_interrupt(cpu); cc->do_interrupt(cpu);
next_tb = 0; next_tb = 0;
@@ -493,7 +493,7 @@ int cpu_exec(CPUArchState *env)
pc contains a magic address. */ pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD if (interrupt_request & CPU_INTERRUPT_HARD
&& ((IS_M(env) && env->regs[15] < 0xfffffff0) && ((IS_M(env) && env->regs[15] < 0xfffffff0)
|| !(env->uncached_cpsr & CPSR_I))) { || !(env->daif & PSTATE_I))) {
env->exception_index = EXCP_IRQ; env->exception_index = EXCP_IRQ;
cc->do_interrupt(cpu); cc->do_interrupt(cpu);
next_tb = 0; next_tb = 0;

View File

@@ -47,4 +47,5 @@ CONFIG_E500=y
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
# For PReP # For PReP
CONFIG_MC146818RTC=y CONFIG_MC146818RTC=y
CONFIG_ETSEC=y
CONFIG_ISA_TESTDEV=y CONFIG_ISA_TESTDEV=y

View File

@@ -1,2 +1,3 @@
CONFIG_VIRTIO=y CONFIG_VIRTIO=y
CONFIG_SCLPCONSOLE=y CONFIG_SCLPCONSOLE=y
CONFIG_S390_FLIC=$(CONFIG_KVM)

View File

@@ -10,6 +10,7 @@ CONFIG_EMPTY_SLOT=y
CONFIG_PCNET_COMMON=y CONFIG_PCNET_COMMON=y
CONFIG_LANCE=y CONFIG_LANCE=y
CONFIG_TCX=y CONFIG_TCX=y
CONFIG_CG3=y
CONFIG_SLAVIO=y CONFIG_SLAVIO=y
CONFIG_CS4231=y CONFIG_CS4231=y
CONFIG_GRLIB=y CONFIG_GRLIB=y

View File

@@ -225,6 +225,45 @@ Data:
"timestamp": { "seconds": 1368697518, "microseconds": 326866 } } "timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
} }
QUORUM_FAILURE
--------------
Emitted by the Quorum block driver if it fails to establish a quorum.
Data:
- "reference": device name if defined else node name.
- "sector-num": Number of the first sector of the failed read operation.
- "sector-count": Failed read operation sector count.
Example:
{ "event": "QUORUM_FAILURE",
"data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 },
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
QUORUM_REPORT_BAD
-----------------
Emitted to report a corruption of a Quorum file.
Data:
- "error": Error message (json-string, optional)
Only present on failure. This field contains a human-readable
error message. There are no semantics other than that the
block layer reported an error and clients should not try to
interpret the error string.
- "node-name": The graph node name of the block driver state.
- "sector-num": Number of the first sector of the failed read operation.
- "sector-count": Failed read operation sector count.
Example:
{ "event": "QUORUM_REPORT_BAD",
"data": { "node-name": "1.raw", "sector-num": 345435, "sector-count": 5 },
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
RESET RESET
----- -----

View File

@@ -66,7 +66,7 @@ bulk-phase round of the migration and can be enabled for extremely
high-performance RDMA hardware using the following command: high-performance RDMA hardware using the following command:
QEMU Monitor Command: QEMU Monitor Command:
$ migrate_set_capability x-rdma-pin-all on # disabled by default $ migrate_set_capability rdma-pin-all on # disabled by default
Performing this action will cause all 8GB to be pinned, so if that's Performing this action will cause all 8GB to be pinned, so if that's
not what you want, then please ignore this step altogether. not what you want, then please ignore this step altogether.
@@ -93,12 +93,12 @@ $ migrate_set_speed 40g # or whatever is the MAX of your RDMA device
Next, on the destination machine, add the following to the QEMU command line: Next, on the destination machine, add the following to the QEMU command line:
qemu ..... -incoming x-rdma:host:port qemu ..... -incoming rdma:host:port
Finally, perform the actual migration on the source machine: Finally, perform the actual migration on the source machine:
QEMU Monitor Command: QEMU Monitor Command:
$ migrate -d x-rdma:host:port $ migrate -d rdma:host:port
PERFORMANCE PERFORMANCE
=========== ===========
@@ -120,8 +120,8 @@ For example, in the same 8GB RAM example with all 8GB of memory in
active use and the VM itself is completely idle using the same 40 gbps active use and the VM itself is completely idle using the same 40 gbps
infiniband link: infiniband link:
1. x-rdma-pin-all disabled total time: approximately 7.5 seconds @ 9.5 Gbps 1. rdma-pin-all disabled total time: approximately 7.5 seconds @ 9.5 Gbps
2. x-rdma-pin-all enabled total time: approximately 4 seconds @ 26 Gbps 2. rdma-pin-all enabled total time: approximately 4 seconds @ 26 Gbps
These numbers would of course scale up to whatever size virtual machine These numbers would of course scale up to whatever size virtual machine
you have to migrate using RDMA. you have to migrate using RDMA.
@@ -407,18 +407,14 @@ socket is broken during a non-RDMA based migration.
TODO: TODO:
===== =====
1. 'migrate x-rdma:host:port' and '-incoming x-rdma' options will be 1. Currently, 'ulimit -l' mlock() limits as well as cgroups swap limits
renamed to 'rdma' after the experimental phase of this work has
completed upstream.
2. Currently, 'ulimit -l' mlock() limits as well as cgroups swap limits
are not compatible with infinband memory pinning and will result in are not compatible with infinband memory pinning and will result in
an aborted migration (but with the source VM left unaffected). an aborted migration (but with the source VM left unaffected).
3. Use of the recent /proc/<pid>/pagemap would likely speed up 2. Use of the recent /proc/<pid>/pagemap would likely speed up
the use of KSM and ballooning while using RDMA. the use of KSM and ballooning while using RDMA.
4. Also, some form of balloon-device usage tracking would also 3. Also, some form of balloon-device usage tracking would also
help alleviate some issues. help alleviate some issues.
5. Move UNREGISTER requests to a separate thread. 4. Use LRU to provide more fine-grained direction of UNREGISTER
6. Use LRU to provide more fine-grained direction of UNREGISTER
requests for unpinning memory in an overcommitted environment. requests for unpinning memory in an overcommitted environment.
7. Expose UNREGISTER support to the user by way of workload-specific 5. Expose UNREGISTER support to the user by way of workload-specific
hints about application behavior. hints about application behavior.

960
dump.c

File diff suppressed because it is too large Load Diff

4
exec.c
View File

@@ -17,9 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include "config.h" #include "config.h"
#ifdef _WIN32 #ifndef _WIN32
#include <windows.h>
#else
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif

View File

@@ -1,4 +1,6 @@
ifeq ($(CONFIG_REALLY_VIRTFS),y) ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
# only pull in the actual virtio-9p device if we also enabled virtio.
common-obj-y = qemu-fsdev.o virtio-9p-marshal.o common-obj-y = qemu-fsdev.o virtio-9p-marshal.o
else else
common-obj-y = qemu-fsdev-dummy.o common-obj-y = qemu-fsdev-dummy.o

View File

@@ -595,7 +595,7 @@ static int do_readlink(struct iovec *iovec, struct iovec *out_iovec)
} }
buffer = g_malloc(size); buffer = g_malloc(size);
v9fs_string_init(&target); v9fs_string_init(&target);
retval = readlink(path.data, buffer, size); retval = readlink(path.data, buffer, size - 1);
if (retval > 0) { if (retval > 0) {
buffer[retval] = '\0'; buffer[retval] = '\0';
v9fs_string_sprintf(&target, "%s", buffer); v9fs_string_sprintf(&target, "%s", buffer);

5
hmp.c
View File

@@ -1311,8 +1311,11 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
const char *file = qdict_get_str(qdict, "filename"); const char *file = qdict_get_str(qdict, "filename");
bool has_begin = qdict_haskey(qdict, "begin"); bool has_begin = qdict_haskey(qdict, "begin");
bool has_length = qdict_haskey(qdict, "length"); bool has_length = qdict_haskey(qdict, "length");
/* kdump-compressed format is not supported for HMP */
bool has_format = false;
int64_t begin = 0; int64_t begin = 0;
int64_t length = 0; int64_t length = 0;
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
char *prot; char *prot;
if (has_begin) { if (has_begin) {
@@ -1325,7 +1328,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
prot = g_strconcat("file:", file, NULL); prot = g_strconcat("file:", file, NULL);
qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length, qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
&errp); has_format, dump_format, &errp);
hmp_handle_error(mon, &errp); hmp_handle_error(mon, &errp);
g_free(prot); g_free(prot);
} }

View File

@@ -17,35 +17,55 @@
#include "block/coroutine.h" #include "block/coroutine.h"
#include "virtio-9p-coth.h" #include "virtio-9p-coth.h"
static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
{
ssize_t len, maxlen = PATH_MAX;
buf->data = g_malloc(PATH_MAX);
for(;;) {
len = s->ops->readlink(&s->ctx, path, buf->data, maxlen);
if (len < 0) {
g_free(buf->data);
buf->data = NULL;
buf->size = 0;
break;
} else if (len == maxlen) {
/*
* We dodn't have space to put the NULL or we have more
* to read. Increase the size and try again
*/
maxlen *= 2;
g_free(buf->data);
buf->data = g_malloc(maxlen);
continue;
}
/*
* Null terminate the readlink output
*/
buf->data[len] = '\0';
buf->size = len;
break;
}
return len;
}
int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf) int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
{ {
int err; int err;
ssize_t len;
V9fsState *s = pdu->s; V9fsState *s = pdu->s;
if (v9fs_request_cancelled(pdu)) { if (v9fs_request_cancelled(pdu)) {
return -EINTR; return -EINTR;
} }
buf->data = g_malloc(PATH_MAX);
v9fs_path_read_lock(s); v9fs_path_read_lock(s);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
len = s->ops->readlink(&s->ctx, path, err = __readlink(s, path, buf);
buf->data, PATH_MAX - 1); if (err < 0) {
if (len > -1) {
buf->size = len;
buf->data[len] = 0;
err = 0;
} else {
err = -errno; err = -errno;
} }
}); });
v9fs_path_unlock(s); v9fs_path_unlock(s);
if (err) {
g_free(buf->data);
buf->data = NULL;
buf->size = 0;
}
return err; return err;
} }

View File

@@ -498,7 +498,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path, static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
const char *name, V9fsPath *target) const char *name, V9fsPath *target)
{ {
char buffer[PATH_MAX]; char *buffer;
struct file_handle *fh; struct file_handle *fh;
int dirfd, ret, mnt_id; int dirfd, ret, mnt_id;
struct handle_data *data = (struct handle_data *)ctx->private; struct handle_data *data = (struct handle_data *)ctx->private;
@@ -513,7 +513,9 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH); dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
} else { } else {
/* relative to export root */ /* relative to export root */
dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY); buffer = rpath(ctx, ".");
dirfd = open(buffer, O_DIRECTORY);
g_free(buffer);
} }
if (dirfd < 0) { if (dirfd < 0) {
return dirfd; return dirfd;
@@ -521,7 +523,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes); fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
fh->handle_bytes = data->handle_bytes; fh->handle_bytes = data->handle_bytes;
/* add a "./" at the beginning of the path */ /* add a "./" at the beginning of the path */
snprintf(buffer, PATH_MAX, "./%s", name); buffer = g_strdup_printf("./%s", name);
/* flag = 0 imply don't follow symlink */ /* flag = 0 imply don't follow symlink */
ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0); ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
if (!ret) { if (!ret) {
@@ -531,6 +533,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
g_free(fh); g_free(fh);
} }
close(dirfd); close(dirfd);
g_free(buffer);
return ret; return ret;
} }

View File

@@ -42,18 +42,18 @@
#define VIRTFS_META_DIR ".virtfs_metadata" #define VIRTFS_META_DIR ".virtfs_metadata"
static const char *local_mapped_attr_path(FsContext *ctx, static char *local_mapped_attr_path(FsContext *ctx, const char *path)
const char *path, char *buffer)
{ {
char *dir_name; char *dir_name;
char *tmp_path = g_strdup(path); char *tmp_path = g_strdup(path);
char *base_name = basename(tmp_path); char *base_name = basename(tmp_path);
char *buffer;
/* NULL terminate the directory */ /* NULL terminate the directory */
dir_name = tmp_path; dir_name = tmp_path;
*(base_name - 1) = '\0'; *(base_name - 1) = '\0';
snprintf(buffer, PATH_MAX, "%s/%s/%s/%s", buffer = g_strdup_printf("%s/%s/%s/%s",
ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name); ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
g_free(tmp_path); g_free(tmp_path);
return buffer; return buffer;
@@ -92,10 +92,11 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
{ {
FILE *fp; FILE *fp;
char buf[ATTR_MAX]; char buf[ATTR_MAX];
char attr_path[PATH_MAX]; char *attr_path;
local_mapped_attr_path(ctx, path, attr_path); attr_path = local_mapped_attr_path(ctx, path);
fp = local_fopen(attr_path, "r"); fp = local_fopen(attr_path, "r");
g_free(attr_path);
if (!fp) { if (!fp) {
return; return;
} }
@@ -118,12 +119,13 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{ {
int err; int err;
char buffer[PATH_MAX]; char *buffer;
char *path = fs_path->data; char *path = fs_path->data;
err = lstat(rpath(fs_ctx, path, buffer), stbuf); buffer = rpath(fs_ctx, path);
err = lstat(buffer, stbuf);
if (err) { if (err) {
return err; goto err_out;
} }
if (fs_ctx->export_flags & V9FS_SM_MAPPED) { if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
/* Actual credentials are part of extended attrs */ /* Actual credentials are part of extended attrs */
@@ -131,41 +133,42 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
gid_t tmp_gid; gid_t tmp_gid;
mode_t tmp_mode; mode_t tmp_mode;
dev_t tmp_dev; dev_t tmp_dev;
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid, if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
sizeof(uid_t)) > 0) {
stbuf->st_uid = tmp_uid; stbuf->st_uid = tmp_uid;
} }
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid, if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
sizeof(gid_t)) > 0) {
stbuf->st_gid = tmp_gid; stbuf->st_gid = tmp_gid;
} }
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode", if (getxattr(buffer, "user.virtfs.mode",
&tmp_mode, sizeof(mode_t)) > 0) { &tmp_mode, sizeof(mode_t)) > 0) {
stbuf->st_mode = tmp_mode; stbuf->st_mode = tmp_mode;
} }
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev, if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
sizeof(dev_t)) > 0) {
stbuf->st_rdev = tmp_dev; stbuf->st_rdev = tmp_dev;
} }
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
local_mapped_file_attr(fs_ctx, path, stbuf); local_mapped_file_attr(fs_ctx, path, stbuf);
} }
err_out:
g_free(buffer);
return err; return err;
} }
static int local_create_mapped_attr_dir(FsContext *ctx, const char *path) static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
{ {
int err; int err;
char attr_dir[PATH_MAX]; char *attr_dir;
char *tmp_path = g_strdup(path); char *tmp_path = g_strdup(path);
snprintf(attr_dir, PATH_MAX, "%s/%s/%s", attr_dir = g_strdup_printf("%s/%s/%s",
ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
err = mkdir(attr_dir, 0700); err = mkdir(attr_dir, 0700);
if (err < 0 && errno == EEXIST) { if (err < 0 && errno == EEXIST) {
err = 0; err = 0;
} }
g_free(attr_dir);
g_free(tmp_path); g_free(tmp_path);
return err; return err;
} }
@@ -176,10 +179,11 @@ static int local_set_mapped_file_attr(FsContext *ctx,
FILE *fp; FILE *fp;
int ret = 0; int ret = 0;
char buf[ATTR_MAX]; char buf[ATTR_MAX];
char attr_path[PATH_MAX]; char *attr_path;
int uid = -1, gid = -1, mode = -1, rdev = -1; int uid = -1, gid = -1, mode = -1, rdev = -1;
fp = local_fopen(local_mapped_attr_path(ctx, path, attr_path), "r"); attr_path = local_mapped_attr_path(ctx, path);
fp = local_fopen(attr_path, "r");
if (!fp) { if (!fp) {
goto create_map_file; goto create_map_file;
} }
@@ -241,6 +245,7 @@ update_map_file:
fclose(fp); fclose(fp);
err_out: err_out:
g_free(attr_path);
return ret; return ret;
} }
@@ -282,36 +287,43 @@ static int local_set_xattr(const char *path, FsCred *credp)
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path, static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
FsCred *credp) FsCred *credp)
{ {
char buffer[PATH_MAX]; char *buffer;
if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid, buffer = rpath(fs_ctx, path);
credp->fc_gid) < 0) { if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) {
/* /*
* If we fail to change ownership and if we are * If we fail to change ownership and if we are
* using security model none. Ignore the error * using security model none. Ignore the error
*/ */
if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
return -1; goto err;
} }
} }
if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) { if (chmod(buffer, credp->fc_mode & 07777) < 0) {
return -1; goto err;
} }
g_free(buffer);
return 0; return 0;
err:
g_free(buffer);
return -1;
} }
static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char *buf, size_t bufsz) char *buf, size_t bufsz)
{ {
ssize_t tsize = -1; ssize_t tsize = -1;
char buffer[PATH_MAX]; char *buffer;
char *path = fs_path->data; char *path = fs_path->data;
if ((fs_ctx->export_flags & V9FS_SM_MAPPED) || if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
(fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
int fd; int fd;
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW); buffer = rpath(fs_ctx, path);
fd = open(buffer, O_RDONLY | O_NOFOLLOW);
g_free(buffer);
if (fd == -1) { if (fd == -1) {
return -1; return -1;
} }
@@ -322,7 +334,9 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
return tsize; return tsize;
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz); buffer = rpath(fs_ctx, path);
tsize = readlink(buffer, buf, bufsz);
g_free(buffer);
} }
return tsize; return tsize;
} }
@@ -340,20 +354,24 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
static int local_open(FsContext *ctx, V9fsPath *fs_path, static int local_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs) int flags, V9fsFidOpenState *fs)
{ {
char buffer[PATH_MAX]; char *buffer;
char *path = fs_path->data; char *path = fs_path->data;
fs->fd = open(rpath(ctx, path, buffer), flags | O_NOFOLLOW); buffer = rpath(ctx, path);
fs->fd = open(buffer, flags | O_NOFOLLOW);
g_free(buffer);
return fs->fd; return fs->fd;
} }
static int local_opendir(FsContext *ctx, static int local_opendir(FsContext *ctx,
V9fsPath *fs_path, V9fsFidOpenState *fs) V9fsPath *fs_path, V9fsFidOpenState *fs)
{ {
char buffer[PATH_MAX]; char *buffer;
char *path = fs_path->data; char *path = fs_path->data;
fs->dir = opendir(rpath(ctx, path, buffer)); buffer = rpath(ctx, path);
fs->dir = opendir(buffer);
g_free(buffer);
if (!fs->dir) { if (!fs->dir) {
return -1; return -1;
} }
@@ -441,18 +459,23 @@ static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret = -1;
char *path = fs_path->data; char *path = fs_path->data;
if (fs_ctx->export_flags & V9FS_SM_MAPPED) { if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path, buffer), credp); buffer = rpath(fs_ctx, path);
ret = local_set_xattr(buffer, credp);
g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
return local_set_mapped_file_attr(fs_ctx, path, credp); return local_set_mapped_file_attr(fs_ctx, path, credp);
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode); buffer = rpath(fs_ctx, path);
ret = chmod(buffer, credp->fc_mode);
g_free(buffer);
} }
return -1; return ret;
} }
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -462,7 +485,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
int err = -1; int err = -1;
int serrno = 0; int serrno = 0;
V9fsString fullname; V9fsString fullname;
char buffer[PATH_MAX]; char *buffer;
v9fs_string_init(&fullname); v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -470,21 +493,23 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
/* Determine the security model */ /* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED) { if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
err = mknod(rpath(fs_ctx, path, buffer), buffer = rpath(fs_ctx, path);
SM_LOCAL_MODE_BITS|S_IFREG, 0); err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) { if (err == -1) {
g_free(buffer);
goto out; goto out;
} }
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); err = local_set_xattr(buffer, credp);
if (err == -1) { if (err == -1) {
serrno = errno; serrno = errno;
goto err_end; goto err_end;
} }
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
err = mknod(rpath(fs_ctx, path, buffer), buffer = rpath(fs_ctx, path);
SM_LOCAL_MODE_BITS|S_IFREG, 0); err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) { if (err == -1) {
g_free(buffer);
goto out; goto out;
} }
err = local_set_mapped_file_attr(fs_ctx, path, credp); err = local_set_mapped_file_attr(fs_ctx, path, credp);
@@ -494,9 +519,10 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
} }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode, buffer = rpath(fs_ctx, path);
credp->fc_rdev); err = mknod(buffer, credp->fc_mode, credp->fc_rdev);
if (err == -1) { if (err == -1) {
g_free(buffer);
goto out; goto out;
} }
err = local_post_create_passthrough(fs_ctx, path, credp); err = local_post_create_passthrough(fs_ctx, path, credp);
@@ -508,8 +534,9 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
goto out; goto out;
err_end: err_end:
remove(rpath(fs_ctx, path, buffer)); remove(buffer);
errno = serrno; errno = serrno;
g_free(buffer);
out: out:
v9fs_string_free(&fullname); v9fs_string_free(&fullname);
return err; return err;
@@ -522,7 +549,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
int err = -1; int err = -1;
int serrno = 0; int serrno = 0;
V9fsString fullname; V9fsString fullname;
char buffer[PATH_MAX]; char *buffer;
v9fs_string_init(&fullname); v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -530,19 +557,23 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
/* Determine the security model */ /* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED) { if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS); buffer = rpath(fs_ctx, path);
err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
if (err == -1) { if (err == -1) {
g_free(buffer);
goto out; goto out;
} }
credp->fc_mode = credp->fc_mode|S_IFDIR; credp->fc_mode = credp->fc_mode|S_IFDIR;
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); err = local_set_xattr(buffer, credp);
if (err == -1) { if (err == -1) {
serrno = errno; serrno = errno;
goto err_end; goto err_end;
} }
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS); buffer = rpath(fs_ctx, path);
err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
if (err == -1) { if (err == -1) {
g_free(buffer);
goto out; goto out;
} }
credp->fc_mode = credp->fc_mode|S_IFDIR; credp->fc_mode = credp->fc_mode|S_IFDIR;
@@ -553,8 +584,10 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
} }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode); buffer = rpath(fs_ctx, path);
err = mkdir(buffer, credp->fc_mode);
if (err == -1) { if (err == -1) {
g_free(buffer);
goto out; goto out;
} }
err = local_post_create_passthrough(fs_ctx, path, credp); err = local_post_create_passthrough(fs_ctx, path, credp);
@@ -566,8 +599,9 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
goto out; goto out;
err_end: err_end:
remove(rpath(fs_ctx, path, buffer)); remove(buffer);
errno = serrno; errno = serrno;
g_free(buffer);
out: out:
v9fs_string_free(&fullname); v9fs_string_free(&fullname);
return err; return err;
@@ -626,7 +660,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
int err = -1; int err = -1;
int serrno = 0; int serrno = 0;
V9fsString fullname; V9fsString fullname;
char buffer[PATH_MAX]; char *buffer;
/* /*
* Mark all the open to not follow symlinks * Mark all the open to not follow symlinks
@@ -639,21 +673,25 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
/* Determine the security model */ /* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED) { if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS); buffer = rpath(fs_ctx, path);
fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
if (fd == -1) { if (fd == -1) {
g_free(buffer);
err = fd; err = fd;
goto out; goto out;
} }
credp->fc_mode = credp->fc_mode|S_IFREG; credp->fc_mode = credp->fc_mode|S_IFREG;
/* Set cleint credentials in xattr */ /* Set cleint credentials in xattr */
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); err = local_set_xattr(buffer, credp);
if (err == -1) { if (err == -1) {
serrno = errno; serrno = errno;
goto err_end; goto err_end;
} }
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS); buffer = rpath(fs_ctx, path);
fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
if (fd == -1) { if (fd == -1) {
g_free(buffer);
err = fd; err = fd;
goto out; goto out;
} }
@@ -666,8 +704,10 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
} }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode); buffer = rpath(fs_ctx, path);
fd = open(buffer, flags, credp->fc_mode);
if (fd == -1) { if (fd == -1) {
g_free(buffer);
err = fd; err = fd;
goto out; goto out;
} }
@@ -683,8 +723,9 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
err_end: err_end:
close(fd); close(fd);
remove(rpath(fs_ctx, path, buffer)); remove(buffer);
errno = serrno; errno = serrno;
g_free(buffer);
out: out:
v9fs_string_free(&fullname); v9fs_string_free(&fullname);
return err; return err;
@@ -698,7 +739,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
int serrno = 0; int serrno = 0;
char *newpath; char *newpath;
V9fsString fullname; V9fsString fullname;
char buffer[PATH_MAX]; char *buffer;
v9fs_string_init(&fullname); v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -708,10 +749,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
if (fs_ctx->export_flags & V9FS_SM_MAPPED) { if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
int fd; int fd;
ssize_t oldpath_size, write_size; ssize_t oldpath_size, write_size;
fd = open(rpath(fs_ctx, newpath, buffer), buffer = rpath(fs_ctx, newpath);
O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
SM_LOCAL_MODE_BITS);
if (fd == -1) { if (fd == -1) {
g_free(buffer);
err = fd; err = fd;
goto out; goto out;
} }
@@ -730,7 +771,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
close(fd); close(fd);
/* Set cleint credentials in symlink's xattr */ /* Set cleint credentials in symlink's xattr */
credp->fc_mode = credp->fc_mode|S_IFLNK; credp->fc_mode = credp->fc_mode|S_IFLNK;
err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp); err = local_set_xattr(buffer, credp);
if (err == -1) { if (err == -1) {
serrno = errno; serrno = errno;
goto err_end; goto err_end;
@@ -738,10 +779,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
int fd; int fd;
ssize_t oldpath_size, write_size; ssize_t oldpath_size, write_size;
fd = open(rpath(fs_ctx, newpath, buffer), buffer = rpath(fs_ctx, newpath);
O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
SM_LOCAL_MODE_BITS);
if (fd == -1) { if (fd == -1) {
g_free(buffer);
err = fd; err = fd;
goto out; goto out;
} }
@@ -767,12 +808,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
} }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer)); buffer = rpath(fs_ctx, newpath);
err = symlink(oldpath, buffer);
if (err) { if (err) {
g_free(buffer);
goto out; goto out;
} }
err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid, err = lchown(buffer, credp->fc_uid, credp->fc_gid);
credp->fc_gid);
if (err == -1) { if (err == -1) {
/* /*
* If we fail to change ownership and if we are * If we fail to change ownership and if we are
@@ -788,8 +830,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
goto out; goto out;
err_end: err_end:
remove(rpath(fs_ctx, newpath, buffer)); remove(buffer);
errno = serrno; errno = serrno;
g_free(buffer);
out: out:
v9fs_string_free(&fullname); v9fs_string_free(&fullname);
return err; return err;
@@ -800,13 +843,16 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
{ {
int ret; int ret;
V9fsString newpath; V9fsString newpath;
char buffer[PATH_MAX], buffer1[PATH_MAX]; char *buffer, *buffer1;
v9fs_string_init(&newpath); v9fs_string_init(&newpath);
v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
ret = link(rpath(ctx, oldpath->data, buffer), buffer = rpath(ctx, oldpath->data);
rpath(ctx, newpath.data, buffer1)); buffer1 = rpath(ctx, newpath.data);
ret = link(buffer, buffer1);
g_free(buffer);
g_free(buffer1);
/* now link the virtfs_metadata files */ /* now link the virtfs_metadata files */
if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
@@ -815,8 +861,11 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
if (ret < 0) { if (ret < 0) {
goto err_out; goto err_out;
} }
ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer), buffer = local_mapped_attr_path(ctx, oldpath->data);
local_mapped_attr_path(ctx, newpath.data, buffer1)); buffer1 = local_mapped_attr_path(ctx, newpath.data);
ret = link(buffer, buffer1);
g_free(buffer);
g_free(buffer1);
if (ret < 0 && errno != ENOENT) { if (ret < 0 && errno != ENOENT) {
goto err_out; goto err_out;
} }
@@ -828,17 +877,21 @@ err_out:
static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret;
char *path = fs_path->data; char *path = fs_path->data;
return truncate(rpath(ctx, path, buffer), size); buffer = rpath(ctx, path);
ret = truncate(buffer, size);
g_free(buffer);
return ret;
} }
static int local_rename(FsContext *ctx, const char *oldpath, static int local_rename(FsContext *ctx, const char *oldpath,
const char *newpath) const char *newpath)
{ {
int err; int err;
char buffer[PATH_MAX], buffer1[PATH_MAX]; char *buffer, *buffer1;
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
err = local_create_mapped_attr_dir(ctx, newpath); err = local_create_mapped_attr_dir(ctx, newpath);
@@ -846,50 +899,69 @@ static int local_rename(FsContext *ctx, const char *oldpath,
return err; return err;
} }
/* rename the .virtfs_metadata files */ /* rename the .virtfs_metadata files */
err = rename(local_mapped_attr_path(ctx, oldpath, buffer), buffer = local_mapped_attr_path(ctx, oldpath);
local_mapped_attr_path(ctx, newpath, buffer1)); buffer1 = local_mapped_attr_path(ctx, newpath);
err = rename(buffer, buffer1);
g_free(buffer);
g_free(buffer1);
if (err < 0 && errno != ENOENT) { if (err < 0 && errno != ENOENT) {
return err; return err;
} }
} }
return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
buffer = rpath(ctx, oldpath);
buffer1 = rpath(ctx, newpath);
err = rename(buffer, buffer1);
g_free(buffer);
g_free(buffer1);
return err;
} }
static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret = -1;
char *path = fs_path->data; char *path = fs_path->data;
if ((credp->fc_uid == -1 && credp->fc_gid == -1) || if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
(fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) { (fs_ctx->export_flags & V9FS_SM_NONE)) {
return lchown(rpath(fs_ctx, path, buffer), buffer = rpath(fs_ctx, path);
credp->fc_uid, credp->fc_gid); ret = lchown(buffer, credp->fc_uid, credp->fc_gid);
g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path, buffer), credp); buffer = rpath(fs_ctx, path);
ret = local_set_xattr(buffer, credp);
g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
return local_set_mapped_file_attr(fs_ctx, path, credp); return local_set_mapped_file_attr(fs_ctx, path, credp);
} }
return -1; return ret;
} }
static int local_utimensat(FsContext *s, V9fsPath *fs_path, static int local_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf) const struct timespec *buf)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret;
char *path = fs_path->data; char *path = fs_path->data;
return qemu_utimens(rpath(s, path, buffer), buf); buffer = rpath(s, path);
ret = qemu_utimens(buffer, buf);
g_free(buffer);
return ret;
} }
static int local_remove(FsContext *ctx, const char *path) static int local_remove(FsContext *ctx, const char *path)
{ {
int err; int err;
struct stat stbuf; struct stat stbuf;
char buffer[PATH_MAX]; char *buffer;
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
err = lstat(rpath(ctx, path, buffer), &stbuf); buffer = rpath(ctx, path);
err = lstat(buffer, &stbuf);
g_free(buffer);
if (err) { if (err) {
goto err_out; goto err_out;
} }
@@ -898,8 +970,10 @@ static int local_remove(FsContext *ctx, const char *path)
* directory * directory
*/ */
if (S_ISDIR(stbuf.st_mode)) { if (S_ISDIR(stbuf.st_mode)) {
sprintf(buffer, "%s/%s/%s", ctx->fs_root, path, VIRTFS_META_DIR); buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
path, VIRTFS_META_DIR);
err = remove(buffer); err = remove(buffer);
g_free(buffer);
if (err < 0 && errno != ENOENT) { if (err < 0 && errno != ENOENT) {
/* /*
* We didn't had the .virtfs_metadata file. May be file created * We didn't had the .virtfs_metadata file. May be file created
@@ -912,7 +986,9 @@ static int local_remove(FsContext *ctx, const char *path)
* Now remove the name from parent directory * Now remove the name from parent directory
* .virtfs_metadata directory * .virtfs_metadata directory
*/ */
err = remove(local_mapped_attr_path(ctx, path, buffer)); buffer = local_mapped_attr_path(ctx, path);
err = remove(buffer);
g_free(buffer);
if (err < 0 && errno != ENOENT) { if (err < 0 && errno != ENOENT) {
/* /*
* We didn't had the .virtfs_metadata file. May be file created * We didn't had the .virtfs_metadata file. May be file created
@@ -921,7 +997,10 @@ static int local_remove(FsContext *ctx, const char *path)
goto err_out; goto err_out;
} }
} }
return remove(rpath(ctx, path, buffer));
buffer = rpath(ctx, path);
err = remove(buffer);
g_free(buffer);
err_out: err_out:
return err; return err;
} }
@@ -946,10 +1025,14 @@ static int local_fsync(FsContext *ctx, int fid_type,
static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret;
char *path = fs_path->data; char *path = fs_path->data;
return statfs(rpath(s, path, buffer), stbuf); buffer = rpath(s, path);
ret = statfs(buffer, stbuf);
g_free(buffer);
return ret;
} }
static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path, static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
@@ -1022,7 +1105,7 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
{ {
int ret; int ret;
V9fsString fullname; V9fsString fullname;
char buffer[PATH_MAX]; char *buffer;
v9fs_string_init(&fullname); v9fs_string_init(&fullname);
@@ -1033,9 +1116,10 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
* If directory remove .virtfs_metadata contained in the * If directory remove .virtfs_metadata contained in the
* directory * directory
*/ */
sprintf(buffer, "%s/%s/%s", ctx->fs_root, buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
fullname.data, VIRTFS_META_DIR); fullname.data, VIRTFS_META_DIR);
ret = remove(buffer); ret = remove(buffer);
g_free(buffer);
if (ret < 0 && errno != ENOENT) { if (ret < 0 && errno != ENOENT) {
/* /*
* We didn't had the .virtfs_metadata file. May be file created * We didn't had the .virtfs_metadata file. May be file created
@@ -1048,7 +1132,9 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
* Now remove the name from parent directory * Now remove the name from parent directory
* .virtfs_metadata directory. * .virtfs_metadata directory.
*/ */
ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer)); buffer = local_mapped_attr_path(ctx, fullname.data);
ret = remove(buffer);
g_free(buffer);
if (ret < 0 && errno != ENOENT) { if (ret < 0 && errno != ENOENT) {
/* /*
* We didn't had the .virtfs_metadata file. May be file created * We didn't had the .virtfs_metadata file. May be file created
@@ -1058,10 +1144,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
} }
} }
/* Remove the name finally */ /* Remove the name finally */
ret = remove(rpath(ctx, fullname.data, buffer)); buffer = rpath(ctx, fullname.data);
v9fs_string_free(&fullname); ret = remove(buffer);
g_free(buffer);
err_out: err_out:
v9fs_string_free(&fullname);
return ret; return ret;
} }

View File

@@ -26,8 +26,13 @@
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path, static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size) const char *name, void *value, size_t size)
{ {
char buffer[PATH_MAX]; char *buffer;
return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size); ssize_t ret;
buffer = rpath(ctx, path);
ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
g_free(buffer);
return ret;
} }
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path, static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
@@ -52,17 +57,23 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name, static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags) void *value, size_t size, int flags)
{ {
char buffer[PATH_MAX]; char *buffer;
return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, int ret;
size, flags);
buffer = rpath(ctx, path);
ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
g_free(buffer);
return ret;
} }
static int mp_pacl_removexattr(FsContext *ctx, static int mp_pacl_removexattr(FsContext *ctx,
const char *path, const char *name) const char *path, const char *name)
{ {
int ret; int ret;
char buffer[PATH_MAX]; char *buffer;
ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
buffer = rpath(ctx, path);
ret = lremovexattr(buffer, MAP_ACL_ACCESS);
if (ret == -1 && errno == ENODATA) { if (ret == -1 && errno == ENODATA) {
/* /*
* We don't get ENODATA error when trying to remove a * We don't get ENODATA error when trying to remove a
@@ -72,14 +83,20 @@ static int mp_pacl_removexattr(FsContext *ctx,
errno = 0; errno = 0;
ret = 0; ret = 0;
} }
g_free(buffer);
return ret; return ret;
} }
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path, static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size) const char *name, void *value, size_t size)
{ {
char buffer[PATH_MAX]; char *buffer;
return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size); ssize_t ret;
buffer = rpath(ctx, path);
ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
g_free(buffer);
return ret;
} }
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path, static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
@@ -104,17 +121,23 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name, static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags) void *value, size_t size, int flags)
{ {
char buffer[PATH_MAX]; char *buffer;
return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, int ret;
size, flags);
buffer = rpath(ctx, path);
ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
g_free(buffer);
return ret;
} }
static int mp_dacl_removexattr(FsContext *ctx, static int mp_dacl_removexattr(FsContext *ctx,
const char *path, const char *name) const char *path, const char *name)
{ {
int ret; int ret;
char buffer[PATH_MAX]; char *buffer;
ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
buffer = rpath(ctx, path);
ret = lremovexattr(buffer, MAP_ACL_DEFAULT);
if (ret == -1 && errno == ENODATA) { if (ret == -1 && errno == ENODATA) {
/* /*
* We don't get ENODATA error when trying to remove a * We don't get ENODATA error when trying to remove a
@@ -124,6 +147,7 @@ static int mp_dacl_removexattr(FsContext *ctx,
errno = 0; errno = 0;
ret = 0; ret = 0;
} }
g_free(buffer);
return ret; return ret;
} }

View File

@@ -21,7 +21,9 @@
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size) const char *name, void *value, size_t size)
{ {
char buffer[PATH_MAX]; char *buffer;
ssize_t ret;
if (strncmp(name, "user.virtfs.", 12) == 0) { if (strncmp(name, "user.virtfs.", 12) == 0) {
/* /*
* Don't allow fetch of user.virtfs namesapce * Don't allow fetch of user.virtfs namesapce
@@ -30,7 +32,10 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
errno = ENOATTR; errno = ENOATTR;
return -1; return -1;
} }
return lgetxattr(rpath(ctx, path, buffer), name, value, size); buffer = rpath(ctx, path);
ret = lgetxattr(buffer, name, value, size);
g_free(buffer);
return ret;
} }
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path, static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
@@ -69,7 +74,9 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name, static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags) void *value, size_t size, int flags)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret;
if (strncmp(name, "user.virtfs.", 12) == 0) { if (strncmp(name, "user.virtfs.", 12) == 0) {
/* /*
* Don't allow fetch of user.virtfs namesapce * Don't allow fetch of user.virtfs namesapce
@@ -78,13 +85,18 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
errno = EACCES; errno = EACCES;
return -1; return -1;
} }
return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags); buffer = rpath(ctx, path);
ret = lsetxattr(buffer, name, value, size, flags);
g_free(buffer);
return ret;
} }
static int mp_user_removexattr(FsContext *ctx, static int mp_user_removexattr(FsContext *ctx,
const char *path, const char *name) const char *path, const char *name)
{ {
char buffer[PATH_MAX]; char *buffer;
int ret;
if (strncmp(name, "user.virtfs.", 12) == 0) { if (strncmp(name, "user.virtfs.", 12) == 0) {
/* /*
* Don't allow fetch of user.virtfs namesapce * Don't allow fetch of user.virtfs namesapce
@@ -93,7 +105,10 @@ static int mp_user_removexattr(FsContext *ctx,
errno = EACCES; errno = EACCES;
return -1; return -1;
} }
return lremovexattr(rpath(ctx, path, buffer), name); buffer = rpath(ctx, path);
ret = lremovexattr(buffer, name);
g_free(buffer);
return ret;
} }
XattrOperations mapped_user_xattr = { XattrOperations mapped_user_xattr = {

View File

@@ -67,21 +67,24 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
void *value, size_t vsize) void *value, size_t vsize)
{ {
ssize_t size = 0; ssize_t size = 0;
char buffer[PATH_MAX]; char *buffer;
void *ovalue = value; void *ovalue = value;
XattrOperations *xops; XattrOperations *xops;
char *orig_value, *orig_value_start; char *orig_value, *orig_value_start;
ssize_t xattr_len, parsed_len = 0, attr_len; ssize_t xattr_len, parsed_len = 0, attr_len;
/* Get the actual len */ /* Get the actual len */
xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0); buffer = rpath(ctx, path);
xattr_len = llistxattr(buffer, value, 0);
if (xattr_len <= 0) { if (xattr_len <= 0) {
g_free(buffer);
return xattr_len; return xattr_len;
} }
/* Now fetch the xattr and find the actual size */ /* Now fetch the xattr and find the actual size */
orig_value = g_malloc(xattr_len); orig_value = g_malloc(xattr_len);
xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len); xattr_len = llistxattr(buffer, orig_value, xattr_len);
g_free(buffer);
/* store the orig pointer */ /* store the orig pointer */
orig_value_start = orig_value; orig_value_start = orig_value;

View File

@@ -54,23 +54,38 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path, static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size) const char *name, void *value, size_t size)
{ {
char buffer[PATH_MAX]; char *buffer;
return lgetxattr(rpath(ctx, path, buffer), name, value, size); ssize_t ret;
buffer = rpath(ctx, path);
ret = lgetxattr(buffer, name, value, size);
g_free(buffer);
return ret;
} }
static inline int pt_setxattr(FsContext *ctx, const char *path, static inline int pt_setxattr(FsContext *ctx, const char *path,
const char *name, void *value, const char *name, void *value,
size_t size, int flags) size_t size, int flags)
{ {
char buffer[PATH_MAX]; char *buffer;
return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags); int ret;
buffer = rpath(ctx, path);
ret = lsetxattr(buffer, name, value, size, flags);
g_free(buffer);
return ret;
} }
static inline int pt_removexattr(FsContext *ctx, static inline int pt_removexattr(FsContext *ctx,
const char *path, const char *name) const char *path, const char *name)
{ {
char buffer[PATH_MAX]; char *buffer;
return lremovexattr(rpath(ctx, path, buffer), name); int ret;
buffer = rpath(ctx, path);
ret = lremovexattr(path, name);
g_free(buffer);
return ret;
} }
static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path, static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,

View File

@@ -6,6 +6,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <utime.h> #include <utime.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <glib.h>
#include "hw/virtio/virtio.h" #include "hw/virtio/virtio.h"
#include "fsdev/file-op-9p.h" #include "fsdev/file-op-9p.h"
#include "fsdev/virtio-9p-marshal.h" #include "fsdev/virtio-9p-marshal.h"
@@ -112,10 +113,9 @@ enum p9_proto_version {
#define FID_REFERENCED 0x1 #define FID_REFERENCED 0x1
#define FID_NON_RECLAIMABLE 0x2 #define FID_NON_RECLAIMABLE 0x2
static inline const char *rpath(FsContext *ctx, const char *path, char *buffer) static inline char *rpath(FsContext *ctx, const char *path)
{ {
snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path); return g_strdup_printf("%s/%s", ctx->fs_root, path);
return buffer;
} }
/* /*

View File

@@ -1,4 +1,4 @@
devices-dirs-$(CONFIG_REALLY_VIRTFS) += 9pfs/ devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
devices-dirs-$(CONFIG_ACPI) += acpi/ devices-dirs-$(CONFIG_ACPI) += acpi/
devices-dirs-$(CONFIG_SOFTMMU) += audio/ devices-dirs-$(CONFIG_SOFTMMU) += audio/
devices-dirs-$(CONFIG_SOFTMMU) += block/ devices-dirs-$(CONFIG_SOFTMMU) += block/

View File

@@ -92,8 +92,6 @@
#define MP_ETH_CRDP3 0x4AC #define MP_ETH_CRDP3 0x4AC
#define MP_ETH_CTDP0 0x4E0 #define MP_ETH_CTDP0 0x4E0
#define MP_ETH_CTDP1 0x4E4 #define MP_ETH_CTDP1 0x4E4
#define MP_ETH_CTDP2 0x4E8
#define MP_ETH_CTDP3 0x4EC
/* MII PHY access */ /* MII PHY access */
#define MP_ETH_SMIR_DATA 0x0000FFFF #define MP_ETH_SMIR_DATA 0x0000FFFF
@@ -308,7 +306,7 @@ static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
case MP_ETH_CRDP0 ... MP_ETH_CRDP3: case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
return s->rx_queue[(offset - MP_ETH_CRDP0)/4]; return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
case MP_ETH_CTDP0 ... MP_ETH_CTDP3: case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
return s->tx_queue[(offset - MP_ETH_CTDP0)/4]; return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
default: default:
@@ -362,7 +360,7 @@ static void mv88w8618_eth_write(void *opaque, hwaddr offset,
s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value; s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
break; break;
case MP_ETH_CTDP0 ... MP_ETH_CTDP3: case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value; s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
break; break;
} }
@@ -632,7 +630,7 @@ static int musicpal_lcd_init(SysBusDevice *sbd)
"musicpal-lcd", MP_LCD_SIZE); "musicpal-lcd", MP_LCD_SIZE);
sysbus_init_mmio(sbd, &s->iomem); sysbus_init_mmio(sbd, &s->iomem);
s->con = graphic_console_init(dev, &musicpal_gfx_ops, s); s->con = graphic_console_init(dev, 0, &musicpal_gfx_ops, s);
qemu_console_resize(s->con, 128*3, 64*3); qemu_console_resize(s->con, 128*3, 64*3);
qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3); qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);

View File

@@ -272,11 +272,11 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
goto message; goto message;
case 3: case 3:
s->cpu->env.uncached_cpsr = s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
s->cpu->env.cp15.c1_sys = 0; s->cpu->env.cp15.c1_sys = 0;
s->cpu->env.cp15.c1_coproc = 0; s->cpu->env.cp15.c1_coproc = 0;
s->cpu->env.cp15.c2_base0 = 0; s->cpu->env.cp15.ttbr0_el1 = 0;
s->cpu->env.cp15.c3 = 0; s->cpu->env.cp15.c3 = 0;
s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */ s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */ s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */

View File

@@ -483,7 +483,18 @@ static void qemu_aio_complete(void *opaque, int ret)
ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
ioreq_unmap(ioreq); ioreq_unmap(ioreq);
ioreq_finish(ioreq); ioreq_finish(ioreq);
bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct); switch (ioreq->req.operation) {
case BLKIF_OP_WRITE:
case BLKIF_OP_FLUSH_DISKCACHE:
if (!ioreq->req.nr_segments) {
break;
}
case BLKIF_OP_READ:
bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct);
break;
default:
break;
}
qemu_bh_schedule(ioreq->blkdev->bh); qemu_bh_schedule(ioreq->blkdev->bh);
} }
@@ -813,8 +824,8 @@ static int blk_connect(struct XenDevice *xendev)
Error *local_err = NULL; Error *local_err = NULL;
BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto, BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
readonly); readonly);
if (bdrv_open(blkdev->bs, if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
blkdev->filename, NULL, qflags, drv, &local_err) != 0) drv, &local_err) != 0)
{ {
xen_be_printf(&blkdev->xendev, 0, "error: %s\n", xen_be_printf(&blkdev->xendev, 0, "error: %s\n",
error_get_pretty(local_err)); error_get_pretty(local_err));

View File

@@ -284,12 +284,30 @@ static void *load_at(int fd, int offset, int size)
#define SZ 64 #define SZ 64
#include "hw/elf_ops.h" #include "hw/elf_ops.h"
const char *load_elf_strerror(int error)
{
switch (error) {
case 0:
return "No error";
case ELF_LOAD_FAILED:
return "Failed to load ELF";
case ELF_LOAD_NOT_ELF:
return "The image is not ELF";
case ELF_LOAD_WRONG_ARCH:
return "The image is from incompatible architecture";
case ELF_LOAD_WRONG_ENDIAN:
return "The image has incorrect endianness";
default:
return "Unknown error";
}
}
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb) uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
{ {
int fd, data_order, target_data_order, must_swab, ret; int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT]; uint8_t e_ident[EI_NIDENT];
fd = open(filename, O_RDONLY | O_BINARY); fd = open(filename, O_RDONLY | O_BINARY);
@@ -302,8 +320,10 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
if (e_ident[0] != ELFMAG0 || if (e_ident[0] != ELFMAG0 ||
e_ident[1] != ELFMAG1 || e_ident[1] != ELFMAG1 ||
e_ident[2] != ELFMAG2 || e_ident[2] != ELFMAG2 ||
e_ident[3] != ELFMAG3) e_ident[3] != ELFMAG3) {
ret = ELF_LOAD_NOT_ELF;
goto fail; goto fail;
}
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
data_order = ELFDATA2MSB; data_order = ELFDATA2MSB;
#else #else
@@ -317,6 +337,7 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
} }
if (target_data_order != e_ident[EI_DATA]) { if (target_data_order != e_ident[EI_DATA]) {
ret = ELF_LOAD_WRONG_ENDIAN;
goto fail; goto fail;
} }
@@ -329,12 +350,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
pentry, lowaddr, highaddr, elf_machine, clear_lsb); pentry, lowaddr, highaddr, elf_machine, clear_lsb);
} }
close(fd);
return ret;
fail: fail:
close(fd); close(fd);
return -1; return ret;
} }
static void bswap_uboot_header(uboot_image_header_t *hdr) static void bswap_uboot_header(uboot_image_header_t *hdr)

View File

@@ -440,27 +440,33 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name) static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
{ {
const char *typename = object_get_typename(OBJECT(bus)); const char *typename = object_get_typename(OBJECT(bus));
BusClass *bc;
char *buf; char *buf;
int i,len; int i, len, bus_id;
bus->parent = parent; bus->parent = parent;
if (name) { if (name) {
bus->name = g_strdup(name); bus->name = g_strdup(name);
} else if (bus->parent && bus->parent->id) { } else if (bus->parent && bus->parent->id) {
/* parent device has id -> use it for bus name */ /* parent device has id -> use it plus parent-bus-id for bus name */
bus_id = bus->parent->num_child_bus;
len = strlen(bus->parent->id) + 16; len = strlen(bus->parent->id) + 16;
buf = g_malloc(len); buf = g_malloc(len);
snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus); snprintf(buf, len, "%s.%d", bus->parent->id, bus_id);
bus->name = buf; bus->name = buf;
} else { } else {
/* no id -> use lowercase bus type for bus name */ /* no id -> use lowercase bus type plus global bus-id for bus name */
bc = BUS_GET_CLASS(bus);
bus_id = bc->automatic_ids++;
len = strlen(typename) + 16; len = strlen(typename) + 16;
buf = g_malloc(len); buf = g_malloc(len);
len = snprintf(buf, len, "%s.%d", typename, len = snprintf(buf, len, "%s.%d", typename, bus_id);
bus->parent ? bus->parent->num_child_bus : 0); for (i = 0; i < len; i++) {
for (i = 0; i < len; i++)
buf[i] = qemu_tolower(buf[i]); buf[i] = qemu_tolower(buf[i]);
}
bus->name = buf; bus->name = buf;
} }

View File

@@ -28,6 +28,7 @@ obj-$(CONFIG_OMAP) += omap_lcdc.o
obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o
obj-$(CONFIG_SM501) += sm501.o obj-$(CONFIG_SM501) += sm501.o
obj-$(CONFIG_TCX) += tcx.o obj-$(CONFIG_TCX) += tcx.o
obj-$(CONFIG_CG3) += cg3.o
obj-$(CONFIG_VGA) += vga.o obj-$(CONFIG_VGA) += vga.o

View File

@@ -956,7 +956,7 @@ void *s1d13745_init(qemu_irq gpio_int)
s->fb = g_malloc(0x180000); s->fb = g_malloc(0x180000);
s->con = graphic_console_init(NULL, &blizzard_ops, s); s->con = graphic_console_init(NULL, 0, &blizzard_ops, s);
surface = qemu_console_surface(s->con); surface = qemu_console_surface(s->con);
switch (surface_bits_per_pixel(surface)) { switch (surface_bits_per_pixel(surface)) {

385
hw/display/cg3.c Normal file
View File

@@ -0,0 +1,385 @@
/*
* QEMU CG3 Frame buffer
*
* Copyright (c) 2012 Bob Breuer
* Copyright (c) 2013 Mark Cave-Ayland
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "ui/console.h"
#include "hw/sysbus.h"
#include "hw/loader.h"
/* Change to 1 to enable debugging */
#define DEBUG_CG3 0
#define CG3_ROM_FILE "QEMU,cgthree.bin"
#define FCODE_MAX_ROM_SIZE 0x10000
#define CG3_REG_SIZE 0x20
#define CG3_REG_BT458_ADDR 0x0
#define CG3_REG_BT458_COLMAP 0x4
#define CG3_REG_FBC_CTRL 0x10
#define CG3_REG_FBC_STATUS 0x11
#define CG3_REG_FBC_CURSTART 0x12
#define CG3_REG_FBC_CUREND 0x13
#define CG3_REG_FBC_VCTRL 0x14
/* Control register flags */
#define CG3_CR_ENABLE_INTS 0x80
/* Status register flags */
#define CG3_SR_PENDING_INT 0x80
#define CG3_SR_1152_900_76_B 0x60
#define CG3_SR_ID_COLOR 0x01
#define CG3_VRAM_SIZE 0x100000
#define CG3_VRAM_OFFSET 0x800000
#define DPRINTF(fmt, ...) do { \
if (DEBUG_CG3) { \
printf("CG3: " fmt , ## __VA_ARGS__); \
} \
} while (0);
#define TYPE_CG3 "cgthree"
#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)
typedef struct CG3State {
SysBusDevice parent_obj;
QemuConsole *con;
qemu_irq irq;
hwaddr prom_addr;
MemoryRegion vram_mem;
MemoryRegion rom;
MemoryRegion reg;
uint32_t vram_size;
int full_update;
uint8_t regs[16];
uint8_t r[256], g[256], b[256];
uint16_t width, height, depth;
uint8_t dac_index, dac_state;
} CG3State;
static void cg3_update_display(void *opaque)
{
CG3State *s = opaque;
DisplaySurface *surface = qemu_console_surface(s->con);
const uint8_t *pix;
uint32_t *data;
uint32_t dval;
int x, y, y_start;
unsigned int width, height;
ram_addr_t page, page_min, page_max;
if (surface_bits_per_pixel(surface) != 32) {
return;
}
width = s->width;
height = s->height;
y_start = -1;
page_min = -1;
page_max = 0;
page = 0;
pix = memory_region_get_ram_ptr(&s->vram_mem);
data = (uint32_t *)surface_data(surface);
for (y = 0; y < height; y++) {
int update = s->full_update;
page = (y * width) & TARGET_PAGE_MASK;
update |= memory_region_get_dirty(&s->vram_mem, page, page + width,
DIRTY_MEMORY_VGA);
if (update) {
if (y_start < 0) {
y_start = y;
}
if (page < page_min) {
page_min = page;
}
if (page > page_max) {
page_max = page;
}
for (x = 0; x < width; x++) {
dval = *pix++;
dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval];
*data++ = dval;
}
} else {
if (y_start >= 0) {
dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
y_start = -1;
}
pix += width;
data += width;
}
}
s->full_update = 0;
if (y_start >= 0) {
dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
}
if (page_max >= page_min) {
memory_region_reset_dirty(&s->vram_mem,
page_min, page_max - page_min + TARGET_PAGE_SIZE,
DIRTY_MEMORY_VGA);
}
/* vsync interrupt? */
if (s->regs[0] & CG3_CR_ENABLE_INTS) {
s->regs[1] |= CG3_SR_PENDING_INT;
qemu_irq_raise(s->irq);
}
}
static void cg3_invalidate_display(void *opaque)
{
CG3State *s = opaque;
memory_region_set_dirty(&s->vram_mem, 0, CG3_VRAM_SIZE);
}
static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
{
CG3State *s = opaque;
int val;
switch (addr) {
case CG3_REG_BT458_ADDR:
case CG3_REG_BT458_COLMAP:
val = 0;
break;
case CG3_REG_FBC_CTRL:
val = s->regs[0];
break;
case CG3_REG_FBC_STATUS:
/* monitor ID 6, board type = 1 (color) */
val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
break;
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
val = s->regs[addr - 0x10];
break;
default:
qemu_log_mask(LOG_UNIMP,
"cg3: Unimplemented register read "
"reg 0x%" HWADDR_PRIx " size 0x%x\n",
addr, size);
val = 0;
break;
}
DPRINTF("read %02x from reg %" HWADDR_PRIx "\n", val, addr);
return val;
}
static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
CG3State *s = opaque;
uint8_t regval;
int i;
DPRINTF("write %" PRIx64 " to reg %" HWADDR_PRIx " size %d\n",
val, addr, size);
switch (addr) {
case CG3_REG_BT458_ADDR:
s->dac_index = val;
s->dac_state = 0;
break;
case CG3_REG_BT458_COLMAP:
/* This register can be written to as either a long word or a byte */
if (size == 1) {
val <<= 24;
}
for (i = 0; i < size; i++) {
regval = val >> 24;
switch (s->dac_state) {
case 0:
s->r[s->dac_index] = regval;
s->dac_state++;
break;
case 1:
s->g[s->dac_index] = regval;
s->dac_state++;
break;
case 2:
s->b[s->dac_index] = regval;
/* Index autoincrement */
s->dac_index = (s->dac_index + 1) & 0xff;
default:
s->dac_state = 0;
break;
}
val <<= 8;
}
s->full_update = 1;
break;
case CG3_REG_FBC_CTRL:
s->regs[0] = val;
break;
case CG3_REG_FBC_STATUS:
if (s->regs[1] & CG3_SR_PENDING_INT) {
/* clear interrupt */
s->regs[1] &= ~CG3_SR_PENDING_INT;
qemu_irq_lower(s->irq);
}
break;
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
s->regs[addr - 0x10] = val;
break;
default:
qemu_log_mask(LOG_UNIMP,
"cg3: Unimplemented register write "
"reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
addr, size, val);
break;
}
}
static const MemoryRegionOps cg3_reg_ops = {
.read = cg3_reg_read,
.write = cg3_reg_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 4,
},
};
static const GraphicHwOps cg3_ops = {
.invalidate = cg3_invalidate_display,
.gfx_update = cg3_update_display,
};
static void cg3_realizefn(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
CG3State *s = CG3(dev);
int ret;
char *fcode_filename;
/* FCode ROM */
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
vmstate_register_ram_global(&s->rom);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
if (fcode_filename) {
ret = load_image_targphys(fcode_filename, s->prom_addr,
FCODE_MAX_ROM_SIZE);
if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
error_report("cg3: could not load prom '%s'", CG3_ROM_FILE);
}
}
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
CG3_REG_SIZE);
sysbus_init_mmio(sbd, &s->reg);
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
vmstate_register_ram_global(&s->vram_mem);
sysbus_init_mmio(sbd, &s->vram_mem);
sysbus_init_irq(sbd, &s->irq);
s->con = graphic_console_init(DEVICE(dev), 0, &cg3_ops, s);
qemu_console_resize(s->con, s->width, s->height);
}
static int vmstate_cg3_post_load(void *opaque, int version_id)
{
CG3State *s = opaque;
cg3_invalidate_display(s);
return 0;
}
static const VMStateDescription vmstate_cg3 = {
.name = "cg3",
.version_id = 1,
.minimum_version_id = 1,
.post_load = vmstate_cg3_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT16(height, CG3State),
VMSTATE_UINT16(width, CG3State),
VMSTATE_UINT16(depth, CG3State),
VMSTATE_BUFFER(r, CG3State),
VMSTATE_BUFFER(g, CG3State),
VMSTATE_BUFFER(b, CG3State),
VMSTATE_UINT8(dac_index, CG3State),
VMSTATE_UINT8(dac_state, CG3State),
VMSTATE_END_OF_LIST()
}
};
static void cg3_reset(DeviceState *d)
{
CG3State *s = CG3(d);
/* Initialize palette */
memset(s->r, 0, 256);
memset(s->g, 0, 256);
memset(s->b, 0, 256);
s->dac_state = 0;
s->full_update = 1;
qemu_irq_lower(s->irq);
}
static Property cg3_properties[] = {
DEFINE_PROP_UINT32("vram-size", CG3State, vram_size, -1),
DEFINE_PROP_UINT16("width", CG3State, width, -1),
DEFINE_PROP_UINT16("height", CG3State, height, -1),
DEFINE_PROP_UINT16("depth", CG3State, depth, -1),
DEFINE_PROP_UINT64("prom-addr", CG3State, prom_addr, -1),
DEFINE_PROP_END_OF_LIST(),
};
static void cg3_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = cg3_realizefn;
dc->reset = cg3_reset;
dc->vmsd = &vmstate_cg3;
dc->props = cg3_properties;
}
static const TypeInfo cg3_info = {
.name = TYPE_CG3,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CG3State),
.class_init = cg3_class_init,
};
static void cg3_register_types(void)
{
type_register_static(&cg3_info);
}
type_init(cg3_register_types)

View File

@@ -2917,7 +2917,7 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0, cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
isa_address_space(isadev), isa_address_space(isadev),
isa_address_space_io(isadev)); isa_address_space_io(isadev));
s->con = graphic_console_init(dev, s->hw_ops, s); s->con = graphic_console_init(dev, 0, s->hw_ops, s);
rom_add_vga(VGABIOS_CIRRUS_FILENAME); rom_add_vga(VGABIOS_CIRRUS_FILENAME);
/* XXX ISA-LFB support */ /* XXX ISA-LFB support */
/* FIXME not qdev yet */ /* FIXME not qdev yet */
@@ -2963,7 +2963,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
vga_common_init(&s->vga, OBJECT(dev)); vga_common_init(&s->vga, OBJECT(dev));
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev), cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
pci_address_space_io(dev)); pci_address_space_io(dev));
s->vga.con = graphic_console_init(DEVICE(dev), s->vga.hw_ops, &s->vga); s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
/* setup PCI */ /* setup PCI */

View File

@@ -1917,7 +1917,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s, memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s,
"exynos4210.fimd", FIMD_REGS_SIZE); "exynos4210.fimd", FIMD_REGS_SIZE);
sysbus_init_mmio(dev, &s->iomem); sysbus_init_mmio(dev, &s->iomem);
s->console = graphic_console_init(DEVICE(dev), &exynos4210_fimd_ops, s); s->console = graphic_console_init(DEVICE(dev), 0, &exynos4210_fimd_ops, s);
return 0; return 0;
} }

View File

@@ -484,7 +484,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
{ {
s->vram = g_malloc0(s->vram_size); s->vram = g_malloc0(s->vram_size);
s->con = graphic_console_init(dev, &g364fb_ops, s); s->con = graphic_console_init(dev, 0, &g364fb_ops, s);
memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000); memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",

View File

@@ -271,7 +271,7 @@ static int jazz_led_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1); memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1);
sysbus_init_mmio(dev, &s->iomem); sysbus_init_mmio(dev, &s->iomem);
s->con = graphic_console_init(DEVICE(dev), &jazz_led_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, &jazz_led_ops, s);
return 0; return 0;
} }

View File

@@ -290,7 +290,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
"milkymist-vgafb", R_MAX * 4); "milkymist-vgafb", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region); sysbus_init_mmio(dev, &s->regs_region);
s->con = graphic_console_init(DEVICE(dev), &vgafb_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, &vgafb_ops, s);
return 0; return 0;
} }

View File

@@ -406,7 +406,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
memory_region_init_io(&s->iomem, NULL, &omap_lcdc_ops, s, "omap.lcdc", 0x100); memory_region_init_io(&s->iomem, NULL, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
memory_region_add_subregion(sysmem, base, &s->iomem); memory_region_add_subregion(sysmem, base, &s->iomem);
s->con = graphic_console_init(NULL, &omap_ops, s); s->con = graphic_console_init(NULL, 0, &omap_ops, s);
return s; return s;
} }

View File

@@ -464,7 +464,7 @@ static int pl110_initfn(SysBusDevice *sbd)
sysbus_init_mmio(sbd, &s->iomem); sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq); sysbus_init_irq(sbd, &s->irq);
qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1); qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1);
s->con = graphic_console_init(dev, &pl110_gfx_ops, s); s->con = graphic_console_init(dev, 0, &pl110_gfx_ops, s);
return 0; return 0;
} }

View File

@@ -1013,7 +1013,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
"pxa2xx-lcd-controller", 0x00100000); "pxa2xx-lcd-controller", 0x00100000);
memory_region_add_subregion(sysmem, base, &s->iomem); memory_region_add_subregion(sysmem, base, &s->iomem);
s->con = graphic_console_init(NULL, &pxa2xx_ops, s); s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
surface = qemu_console_surface(s->con); surface = qemu_console_surface(s->con);
switch (surface_bits_per_pixel(surface)) { switch (surface_bits_per_pixel(surface)) {

View File

@@ -1429,7 +1429,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
return 1; return 1;
} }
static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) static void qxl_set_mode(PCIQXLDevice *d, unsigned int modenr, int loadvm)
{ {
pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr; pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start; pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start;
@@ -1439,6 +1439,12 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
.mem_start = start, .mem_start = start,
.mem_end = end .mem_end = end
}; };
if (modenr >= d->modes->n_modes) {
qxl_set_guest_bug(d, "mode number out of range");
return;
}
QXLSurfaceCreate surface = { QXLSurfaceCreate surface = {
.width = mode->x_res, .width = mode->x_res,
.height = mode->y_res, .height = mode->y_res,
@@ -2063,7 +2069,7 @@ static int qxl_init_primary(PCIDevice *dev)
portio_list_set_flush_coalesced(qxl_vga_port_list); portio_list_set_flush_coalesced(qxl_vga_port_list);
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0); portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
vga->con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl); vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
qemu_spice_display_init_common(&qxl->ssd); qemu_spice_display_init_common(&qxl->ssd);
rc = qxl_init_common(qxl); rc = qxl_init_common(qxl);
@@ -2088,7 +2094,7 @@ static int qxl_init_secondary(PCIDevice *dev)
qxl->vga.vram_size); qxl->vga.vram_size);
vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
qxl->vga.con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl); qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
return qxl_init_common(qxl); return qxl_init_common(qxl);
} }

View File

@@ -1449,5 +1449,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
} }
/* create qemu graphic console */ /* create qemu graphic console */
s->con = graphic_console_init(DEVICE(dev), &sm501_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, &sm501_ops, s);
} }

View File

@@ -299,7 +299,7 @@ static int ssd0303_init(I2CSlave *i2c)
{ {
ssd0303_state *s = SSD0303(i2c); ssd0303_state *s = SSD0303(i2c);
s->con = graphic_console_init(DEVICE(i2c), &ssd0303_ops, s); s->con = graphic_console_init(DEVICE(i2c), 0, &ssd0303_ops, s);
qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
return 0; return 0;
} }

View File

@@ -342,7 +342,7 @@ static int ssd0323_init(SSISlave *dev)
s->col_end = 63; s->col_end = 63;
s->row_end = 79; s->row_end = 79;
s->con = graphic_console_init(DEVICE(dev), &ssd0323_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, &ssd0323_ops, s);
qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);

View File

@@ -587,7 +587,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
memory_region_add_subregion(sysmem, base + 0x100000, &s->vram); memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
s->scr_width = 480; s->scr_width = 480;
s->scr_height = 640; s->scr_height = 640;
s->con = graphic_console_init(NULL, &tc6393xb_gfx_ops, s); s->con = graphic_console_init(NULL, 0, &tc6393xb_gfx_ops, s);
return s; return s;
} }

View File

@@ -602,14 +602,14 @@ static int tcx_init1(SysBusDevice *dev)
&s->vram_mem, vram_offset, size); &s->vram_mem, vram_offset, size);
sysbus_init_mmio(dev, &s->vram_cplane); sysbus_init_mmio(dev, &s->vram_cplane);
s->con = graphic_console_init(DEVICE(dev), &tcx24_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
} else { } else {
/* THC 8 bit (dummy) */ /* THC 8 bit (dummy) */
memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8", memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
TCX_THC_NREGS_8); TCX_THC_NREGS_8);
sysbus_init_mmio(dev, &s->thc8); sysbus_init_mmio(dev, &s->thc8);
s->con = graphic_console_init(DEVICE(dev), &tcx_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
} }
qemu_console_resize(s->con, s->width, s->height); qemu_console_resize(s->con, s->width, s->height);

View File

@@ -135,7 +135,7 @@ int isa_vga_mm_init(hwaddr vram_base,
vga_common_init(&s->vga, NULL); vga_common_init(&s->vga, NULL);
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
s->vga.con = graphic_console_init(NULL, s->vga.hw_ops, s); s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
vga_init_vbe(&s->vga, NULL, address_space); vga_init_vbe(&s->vga, NULL, address_space);
return 0; return 0;

View File

@@ -67,7 +67,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
isa_mem_base + 0x000a0000, isa_mem_base + 0x000a0000,
vga_io_memory, 1); vga_io_memory, 1);
memory_region_set_coalescing(vga_io_memory); memory_region_set_coalescing(vga_io_memory);
s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev)); vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev));
/* ROM BIOS */ /* ROM BIOS */

View File

@@ -151,7 +151,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev), vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
true); true);
s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
/* XXX: VGA_RAM_SIZE must be a power of two */ /* XXX: VGA_RAM_SIZE must be a power of two */
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);

View File

@@ -1199,7 +1199,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
s->scratch_size = SVGA_SCRATCH_SIZE; s->scratch_size = SVGA_SCRATCH_SIZE;
s->scratch = g_malloc(s->scratch_size * 4); s->scratch = g_malloc(s->scratch_size * 4);
s->vga.con = graphic_console_init(dev, &vmsvga_ops, s); s->vga.con = graphic_console_init(dev, 0, &vmsvga_ops, s);
s->fifo_size = SVGA_FIFO_SIZE; s->fifo_size = SVGA_FIFO_SIZE;
memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size); memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size);

View File

@@ -992,7 +992,7 @@ wait_more:
/* vfb */ /* vfb */
fb = container_of(xfb, struct XenFB, c.xendev); fb = container_of(xfb, struct XenFB, c.xendev);
fb->c.con = graphic_console_init(NULL, &xenfb_ops, fb); fb->c.con = graphic_console_init(NULL, 0, &xenfb_ops, fb);
fb->have_console = 1; fb->have_console = 1;
/* vkbd */ /* vkbd */

View File

@@ -227,7 +227,8 @@ static const VMStateDescription vmstate_pl330_queue = {
}; };
struct PL330State { struct PL330State {
SysBusDevice busdev; SysBusDevice parent_obj;
MemoryRegion iomem; MemoryRegion iomem;
qemu_irq irq_abort; qemu_irq irq_abort;
qemu_irq *irq; qemu_irq *irq;
@@ -577,7 +578,7 @@ static inline void pl330_queue_remove_tagged(PL330Queue *s, uint8_t tag)
static inline void pl330_fault(PL330Chan *ch, uint32_t flags) static inline void pl330_fault(PL330Chan *ch, uint32_t flags)
{ {
DB_PRINT("ch: %p, flags: %x\n", ch, flags); DB_PRINT("ch: %p, flags: %" PRIx32 "\n", ch, flags);
ch->fault_type |= flags; ch->fault_type |= flags;
if (ch->state == pl330_chan_fault) { if (ch->state == pl330_chan_fault) {
return; return;
@@ -600,10 +601,12 @@ static inline void pl330_fault(PL330Chan *ch, uint32_t flags)
* LEN - number of elements in ARGS array * LEN - number of elements in ARGS array
*/ */
static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) static void pl330_dmaadxh(PL330Chan *ch, uint8_t *args, bool ra, bool neg)
{ {
uint16_t im = (((uint16_t)args[1]) << 8) | ((uint16_t)args[0]); uint32_t im = (args[1] << 8) | args[0];
uint8_t ra = (opcode >> 1) & 1; if (neg) {
im |= 0xffffu << 16;
}
if (ch->is_manager) { if (ch->is_manager) {
pl330_fault(ch, PL330_FAULT_UNDEF_INSTR); pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
@@ -616,6 +619,16 @@ static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
} }
} }
static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
{
pl330_dmaadxh(ch, args, extract32(opcode, 1, 1), false);
}
static void pl330_dmaadnh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
{
pl330_dmaadxh(ch, args, extract32(opcode, 1, 1), true);
}
static void pl330_dmaend(PL330Chan *ch, uint8_t opcode, static void pl330_dmaend(PL330Chan *ch, uint8_t opcode,
uint8_t *args, int len) uint8_t *args, int len)
{ {
@@ -723,7 +736,8 @@ static void pl330_dmald(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
ch->stall = pl330_queue_put_insn(&ch->parent->read_queue, ch->src, ch->stall = pl330_queue_put_insn(&ch->parent->read_queue, ch->src,
size, num, inc, 0, ch->tag); size, num, inc, 0, ch->tag);
if (!ch->stall) { if (!ch->stall) {
DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n", DB_PRINT("channel:%" PRId8 " address:%08" PRIx32 " size:%" PRIx32
" num:%" PRId32 " %c\n",
ch->tag, ch->src, size, num, inc ? 'Y' : 'N'); ch->tag, ch->src, size, num, inc ? 'Y' : 'N');
ch->src += inc ? size * num - (ch->src & (size - 1)) : 0; ch->src += inc ? size * num - (ch->src & (size - 1)) : 0;
} }
@@ -868,9 +882,10 @@ static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
} }
if (ch->parent->inten & (1 << ev_id)) { if (ch->parent->inten & (1 << ev_id)) {
ch->parent->int_status |= (1 << ev_id); ch->parent->int_status |= (1 << ev_id);
DB_PRINT("event interrupt raised %d\n", ev_id); DB_PRINT("event interrupt raised %" PRId8 "\n", ev_id);
qemu_irq_raise(ch->parent->irq[ev_id]); qemu_irq_raise(ch->parent->irq[ev_id]);
} }
DB_PRINT("event raised %" PRId8 "\n", ev_id);
ch->parent->ev_status |= (1 << ev_id); ch->parent->ev_status |= (1 << ev_id);
} }
@@ -895,7 +910,8 @@ static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst, ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst,
size, num, inc, 0, ch->tag); size, num, inc, 0, ch->tag);
if (!ch->stall) { if (!ch->stall) {
DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n", DB_PRINT("channel:%" PRId8 " address:%08" PRIx32 " size:%" PRIx32
" num:%" PRId32 " %c\n",
ch->tag, ch->dst, size, num, inc ? 'Y' : 'N'); ch->tag, ch->dst, size, num, inc ? 'Y' : 'N');
ch->dst += inc ? size * num - (ch->dst & (size - 1)) : 0; ch->dst += inc ? size * num - (ch->dst & (size - 1)) : 0;
} }
@@ -972,6 +988,7 @@ static void pl330_dmawfe(PL330Chan *ch, uint8_t opcode,
} }
} }
ch->parent->ev_status &= ~(1 << ev_id); ch->parent->ev_status &= ~(1 << ev_id);
DB_PRINT("event lowered %" PRIx8 "\n", ev_id);
} else { } else {
ch->stall = 1; ch->stall = 1;
} }
@@ -1037,6 +1054,7 @@ static void pl330_dmawmb(PL330Chan *ch, uint8_t opcode,
/* NULL terminated array of the instruction descriptions. */ /* NULL terminated array of the instruction descriptions. */
static const PL330InsnDesc insn_desc[] = { static const PL330InsnDesc insn_desc[] = {
{ .opcode = 0x54, .opmask = 0xFD, .size = 3, .exec = pl330_dmaaddh, }, { .opcode = 0x54, .opmask = 0xFD, .size = 3, .exec = pl330_dmaaddh, },
{ .opcode = 0x5c, .opmask = 0xFD, .size = 3, .exec = pl330_dmaadnh, },
{ .opcode = 0x00, .opmask = 0xFF, .size = 1, .exec = pl330_dmaend, }, { .opcode = 0x00, .opmask = 0xFF, .size = 1, .exec = pl330_dmaend, },
{ .opcode = 0x35, .opmask = 0xFF, .size = 2, .exec = pl330_dmaflushp, }, { .opcode = 0x35, .opmask = 0xFF, .size = 2, .exec = pl330_dmaflushp, },
{ .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, }, { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, },
@@ -1108,7 +1126,6 @@ static int pl330_chan_exec(PL330Chan *ch)
ch->state != pl330_chan_waiting_periph && ch->state != pl330_chan_waiting_periph &&
ch->state != pl330_chan_at_barrier && ch->state != pl330_chan_at_barrier &&
ch->state != pl330_chan_waiting_event) { ch->state != pl330_chan_waiting_event) {
DB_PRINT("%d\n", ch->state);
return 0; return 0;
} }
ch->stall = 0; ch->stall = 0;
@@ -1155,7 +1172,7 @@ static int pl330_exec_cycle(PL330Chan *channel)
dma_memory_read(&address_space_memory, q->addr, buf, len); dma_memory_read(&address_space_memory, q->addr, buf, len);
if (PL330_ERR_DEBUG > 1) { if (PL330_ERR_DEBUG > 1) {
DB_PRINT("PL330 read from memory @%08x (size = %08x):\n", DB_PRINT("PL330 read from memory @%08" PRIx32 " (size = %08x):\n",
q->addr, len); q->addr, len);
qemu_hexdump((char *)buf, stderr, "", len); qemu_hexdump((char *)buf, stderr, "", len);
} }
@@ -1187,8 +1204,8 @@ static int pl330_exec_cycle(PL330Chan *channel)
if (fifo_res == PL330_FIFO_OK || q->z) { if (fifo_res == PL330_FIFO_OK || q->z) {
dma_memory_write(&address_space_memory, q->addr, buf, len); dma_memory_write(&address_space_memory, q->addr, buf, len);
if (PL330_ERR_DEBUG > 1) { if (PL330_ERR_DEBUG > 1) {
DB_PRINT("PL330 read from memory @%08x (size = %08x):\n", DB_PRINT("PL330 read from memory @%08" PRIx32
q->addr, len); " (size = %08x):\n", q->addr, len);
qemu_hexdump((char *)buf, stderr, "", len); qemu_hexdump((char *)buf, stderr, "", len);
} }
if (q->inc) { if (q->inc) {
@@ -1277,7 +1294,7 @@ static void pl330_debug_exec(PL330State *s)
args[2] = (s->dbg[1] >> 8) & 0xff; args[2] = (s->dbg[1] >> 8) & 0xff;
args[3] = (s->dbg[1] >> 16) & 0xff; args[3] = (s->dbg[1] >> 16) & 0xff;
args[4] = (s->dbg[1] >> 24) & 0xff; args[4] = (s->dbg[1] >> 24) & 0xff;
DB_PRINT("chan id: %d\n", chan_id); DB_PRINT("chan id: %" PRIx8 "\n", chan_id);
if (s->dbg[0] & 1) { if (s->dbg[0] & 1) {
ch = &s->chan[chan_id]; ch = &s->chan[chan_id];
} else { } else {
@@ -1311,7 +1328,7 @@ static void pl330_iomem_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size) uint64_t value, unsigned size)
{ {
PL330State *s = (PL330State *) opaque; PL330State *s = (PL330State *) opaque;
uint32_t i; int i;
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)value); DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)value);
@@ -1467,8 +1484,8 @@ static inline uint32_t pl330_iomem_read_imp(void *opaque,
static uint64_t pl330_iomem_read(void *opaque, hwaddr offset, static uint64_t pl330_iomem_read(void *opaque, hwaddr offset,
unsigned size) unsigned size)
{ {
int ret = pl330_iomem_read_imp(opaque, offset); uint32_t ret = pl330_iomem_read_imp(opaque, offset);
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, ret); DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset, ret);
return ret; return ret;
} }
@@ -1554,7 +1571,7 @@ static void pl330_realize(DeviceState *dev, Error **errp)
s->cfg[1] |= 5; s->cfg[1] |= 5;
break; break;
default: default:
error_setg(errp, "Bad value for i-cache_len property: %d\n", error_setg(errp, "Bad value for i-cache_len property: %" PRIx8 "\n",
s->i_cache_len); s->i_cache_len);
return; return;
} }
@@ -1589,7 +1606,7 @@ static void pl330_realize(DeviceState *dev, Error **errp)
s->cfg[CFG_CRD] |= 0x4; s->cfg[CFG_CRD] |= 0x4;
break; break;
default: default:
error_setg(errp, "Bad value for data_width property: %d\n", error_setg(errp, "Bad value for data_width property: %" PRIx8 "\n",
s->data_width); s->data_width);
return; return;
} }
@@ -1602,7 +1619,7 @@ static void pl330_realize(DeviceState *dev, Error **errp)
pl330_queue_init(&s->read_queue, s->rd_q_dep, s); pl330_queue_init(&s->read_queue, s->rd_q_dep, s);
pl330_queue_init(&s->write_queue, s->wr_q_dep, s); pl330_queue_init(&s->write_queue, s->wr_q_dep, s);
pl330_fifo_init(&s->fifo, s->data_buffer_dep); pl330_fifo_init(&s->fifo, s->data_width / 4 * s->data_buffer_dep);
} }
static Property pl330_properties[] = { static Property pl330_properties[] = {

View File

@@ -743,6 +743,7 @@ static void assign_failed_examine(AssignedDevice *dev)
goto fail; goto fail;
} }
driver[r] = 0;
ns = strrchr(driver, '/'); ns = strrchr(driver, '/');
if (!ns) { if (!ns) {
goto fail; goto fail;

View File

@@ -221,10 +221,16 @@ static void pc_init1(QEMUMachineInitArgs *args,
} else { } else {
for(i = 0; i < MAX_IDE_BUS; i++) { for(i = 0; i < MAX_IDE_BUS; i++) {
ISADevice *dev; ISADevice *dev;
char busname[] = "ide.0";
dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
ide_irq[i], ide_irq[i],
hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
idebus[i] = qdev_get_child_bus(DEVICE(dev), "ide.0"); /*
* The ide bus name is ide.0 for the first bus and ide.1 for the
* second one.
*/
busname[4] = '0' + i;
idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
} }
} }

View File

@@ -40,7 +40,7 @@
#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ #define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
AHCI_RX_FIS_SZ) AHCI_RX_FIS_SZ)
#define AHCI_IRQ_ON_SG (1 << 31) #define AHCI_IRQ_ON_SG (1U << 31)
#define AHCI_CMD_ATAPI (1 << 5) #define AHCI_CMD_ATAPI (1 << 5)
#define AHCI_CMD_WRITE (1 << 6) #define AHCI_CMD_WRITE (1 << 6)
#define AHCI_CMD_PREFETCH (1 << 7) #define AHCI_CMD_PREFETCH (1 << 7)
@@ -61,7 +61,7 @@
/* HOST_CTL bits */ /* HOST_CTL bits */
#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ #define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */
#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ #define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */
#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ #define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */
/* HOST_CAP bits */ /* HOST_CAP bits */
#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ #define HOST_CAP_SSC (1 << 14) /* Slumber capable */
@@ -69,7 +69,7 @@
#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ #define HOST_CAP_CLO (1 << 24) /* Command List Override support */
#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ #define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */
#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ #define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */
#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */ #define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */
/* registers for each SATA port */ /* registers for each SATA port */
#define PORT_LST_ADDR 0x00 /* command list DMA addr */ #define PORT_LST_ADDR 0x00 /* command list DMA addr */
@@ -89,7 +89,7 @@
#define PORT_RESERVED 0x3c /* reserved */ #define PORT_RESERVED 0x3c /* reserved */
/* PORT_IRQ_{STAT,MASK} bits */ /* PORT_IRQ_{STAT,MASK} bits */
#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ #define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */
#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ #define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ #define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ #define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
@@ -151,7 +151,7 @@
#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ #define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */
#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ #define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */
#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ #define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */
#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */ #define PORT_IRQ_STAT_CPDS (1U << 31) /* Code Port Detect Status */
/* ap->flags bits */ /* ap->flags bits */
#define AHCI_FLAG_NO_NCQ (1 << 24) #define AHCI_FLAG_NO_NCQ (1 << 24)

View File

@@ -167,7 +167,7 @@ static int pci_piix_ide_initfn(PCIDevice *dev)
return 0; return 0;
} }
static int pci_piix3_xen_ide_unplug(DeviceState *dev) int pci_piix3_xen_ide_unplug(DeviceState *dev)
{ {
PCIIDEState *pci_ide; PCIIDEState *pci_ide;
DriveInfo *di; DriveInfo *di;
@@ -266,7 +266,6 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data)
k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
k->class_id = PCI_CLASS_STORAGE_IDE; k->class_id = PCI_CLASS_STORAGE_IDE;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->unplug = pci_piix3_xen_ide_unplug;
} }
static const TypeInfo piix3_ide_xen_info = { static const TypeInfo piix3_ide_xen_info = {

View File

@@ -25,3 +25,4 @@ obj-$(CONFIG_SH4) += sh_intc.o
obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_XICS_KVM) += xics_kvm.o obj-$(CONFIG_XICS_KVM) += xics_kvm.o
obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
obj-$(CONFIG_S390_FLIC) += s390_flic.o

View File

@@ -3,6 +3,7 @@
* *
* Copyright (c) 2012 Linaro Limited * Copyright (c) 2012 Linaro Limited
* Written by Peter Maydell * Written by Peter Maydell
* Save/Restore logic added by Christoffer Dall.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -23,6 +24,20 @@
#include "kvm_arm.h" #include "kvm_arm.h"
#include "gic_internal.h" #include "gic_internal.h"
//#define DEBUG_GIC_KVM
#ifdef DEBUG_GIC_KVM
static const int debug_gic_kvm = 1;
#else
static const int debug_gic_kvm = 0;
#endif
#define DPRINTF(fmt, ...) do { \
if (debug_gic_kvm) { \
printf("arm_gic: " fmt , ## __VA_ARGS__); \
} \
} while (0)
#define TYPE_KVM_ARM_GIC "kvm-arm-gic" #define TYPE_KVM_ARM_GIC "kvm-arm-gic"
#define KVM_ARM_GIC(obj) \ #define KVM_ARM_GIC(obj) \
OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC) OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
@@ -72,14 +87,419 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
kvm_set_irq(kvm_state, kvm_irq, !!level); kvm_set_irq(kvm_state, kvm_irq, !!level);
} }
static bool kvm_arm_gic_can_save_restore(GICState *s)
{
return s->dev_fd >= 0;
}
static void kvm_gic_access(GICState *s, int group, int offset,
int cpu, uint32_t *val, bool write)
{
struct kvm_device_attr attr;
int type;
int err;
cpu = cpu & 0xff;
attr.flags = 0;
attr.group = group;
attr.attr = (((uint64_t)cpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) &
KVM_DEV_ARM_VGIC_CPUID_MASK) |
(((uint64_t)offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) &
KVM_DEV_ARM_VGIC_OFFSET_MASK);
attr.addr = (uintptr_t)val;
if (write) {
type = KVM_SET_DEVICE_ATTR;
} else {
type = KVM_GET_DEVICE_ATTR;
}
err = kvm_device_ioctl(s->dev_fd, type, &attr);
if (err < 0) {
fprintf(stderr, "KVM_{SET/GET}_DEVICE_ATTR failed: %s\n",
strerror(-err));
abort();
}
}
static void kvm_gicd_access(GICState *s, int offset, int cpu,
uint32_t *val, bool write)
{
kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
offset, cpu, val, write);
}
static void kvm_gicc_access(GICState *s, int offset, int cpu,
uint32_t *val, bool write)
{
kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
offset, cpu, val, write);
}
#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
/*
* Translate from the in-kernel field for an IRQ value to/from the qemu
* representation.
*/
typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel);
/* synthetic translate function used for clear/set registers to completely
* clear a setting using a clear-register before setting the remaing bits
* using a set-register */
static void translate_clear(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = ~0;
} else {
/* does not make sense: qemu model doesn't use set/clear regs */
abort();
}
}
static void translate_enabled(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (to_kernel) {
*field = GIC_TEST_ENABLED(irq, cm);
} else {
if (*field & 1) {
GIC_SET_ENABLED(irq, cm);
}
}
}
static void translate_pending(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (to_kernel) {
*field = gic_test_pending(s, irq, cm);
} else {
if (*field & 1) {
GIC_SET_PENDING(irq, cm);
/* TODO: Capture is level-line is held high in the kernel */
}
}
}
static void translate_active(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (to_kernel) {
*field = GIC_TEST_ACTIVE(irq, cm);
} else {
if (*field & 1) {
GIC_SET_ACTIVE(irq, cm);
}
}
}
static void translate_trigger(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = (GIC_TEST_EDGE_TRIGGER(irq)) ? 0x2 : 0x0;
} else {
if (*field & 0x2) {
GIC_SET_EDGE_TRIGGER(irq);
}
}
}
static void translate_priority(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = GIC_GET_PRIORITY(irq, cpu) & 0xff;
} else {
gic_set_priority(s, cpu, irq, *field & 0xff);
}
}
static void translate_targets(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = s->irq_target[irq] & 0xff;
} else {
s->irq_target[irq] = *field & 0xff;
}
}
static void translate_sgisource(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = s->sgi_pending[irq][cpu] & 0xff;
} else {
s->sgi_pending[irq][cpu] = *field & 0xff;
}
}
/* Read a register group from the kernel VGIC */
static void kvm_dist_get(GICState *s, uint32_t offset, int width,
int maxirq, vgic_translate_fn translate_fn)
{
uint32_t reg;
int i;
int j;
int irq;
int cpu;
int regsz = 32 / width; /* irqs per kernel register */
uint32_t field;
for_each_irq_reg(i, maxirq, width) {
irq = i * regsz;
cpu = 0;
while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
kvm_gicd_access(s, offset, cpu, &reg, false);
for (j = 0; j < regsz; j++) {
field = extract32(reg, j * width, width);
translate_fn(s, irq + j, cpu, &field, false);
}
cpu++;
}
offset += 4;
}
}
/* Write a register group to the kernel VGIC */
static void kvm_dist_put(GICState *s, uint32_t offset, int width,
int maxirq, vgic_translate_fn translate_fn)
{
uint32_t reg;
int i;
int j;
int irq;
int cpu;
int regsz = 32 / width; /* irqs per kernel register */
uint32_t field;
for_each_irq_reg(i, maxirq, width) {
irq = i * regsz;
cpu = 0;
while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
reg = 0;
for (j = 0; j < regsz; j++) {
translate_fn(s, irq + j, cpu, &field, true);
reg = deposit32(reg, j * width, width, field);
}
kvm_gicd_access(s, offset, cpu, &reg, true);
cpu++;
}
offset += 4;
}
}
static void kvm_arm_gic_put(GICState *s) static void kvm_arm_gic_put(GICState *s)
{ {
/* TODO: there isn't currently a kernel interface to set the GIC state */ uint32_t reg;
int i;
int cpu;
int num_cpu;
int num_irq;
if (!kvm_arm_gic_can_save_restore(s)) {
DPRINTF("Cannot put kernel gic state, no kernel interface");
return;
}
/* Note: We do the restore in a slightly different order than the save
* (where the order doesn't matter and is simply ordered according to the
* register offset values */
/*****************************************************************
* Distributor State
*/
/* s->enabled -> GICD_CTLR */
reg = s->enabled;
kvm_gicd_access(s, 0x0, 0, &reg, true);
/* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */
kvm_gicd_access(s, 0x4, 0, &reg, false);
num_irq = ((reg & 0x1f) + 1) * 32;
num_cpu = ((reg & 0xe0) >> 5) + 1;
if (num_irq < s->num_irq) {
fprintf(stderr, "Restoring %u IRQs, but kernel supports max %d\n",
s->num_irq, num_irq);
abort();
} else if (num_cpu != s->num_cpu) {
fprintf(stderr, "Restoring %u CPU interfaces, kernel only has %d\n",
s->num_cpu, num_cpu);
/* Did we not create the VCPUs in the kernel yet? */
abort();
}
/* TODO: Consider checking compatibility with the IIDR ? */
/* irq_state[n].enabled -> GICD_ISENABLERn */
kvm_dist_put(s, 0x180, 1, s->num_irq, translate_clear);
kvm_dist_put(s, 0x100, 1, s->num_irq, translate_enabled);
/* s->irq_target[irq] -> GICD_ITARGETSRn
* (restore targets before pending to ensure the pending state is set on
* the appropriate CPU interfaces in the kernel) */
kvm_dist_put(s, 0x800, 8, s->num_irq, translate_targets);
/* irq_state[n].pending + irq_state[n].level -> GICD_ISPENDRn */
kvm_dist_put(s, 0x280, 1, s->num_irq, translate_clear);
kvm_dist_put(s, 0x200, 1, s->num_irq, translate_pending);
/* irq_state[n].active -> GICD_ISACTIVERn */
kvm_dist_put(s, 0x380, 1, s->num_irq, translate_clear);
kvm_dist_put(s, 0x300, 1, s->num_irq, translate_active);
/* irq_state[n].trigger -> GICD_ICFRn */
kvm_dist_put(s, 0xc00, 2, s->num_irq, translate_trigger);
/* s->priorityX[irq] -> ICD_IPRIORITYRn */
kvm_dist_put(s, 0x400, 8, s->num_irq, translate_priority);
/* s->sgi_pending -> ICD_CPENDSGIRn */
kvm_dist_put(s, 0xf10, 8, GIC_NR_SGIS, translate_clear);
kvm_dist_put(s, 0xf20, 8, GIC_NR_SGIS, translate_sgisource);
/*****************************************************************
* CPU Interface(s) State
*/
for (cpu = 0; cpu < s->num_cpu; cpu++) {
/* s->cpu_enabled[cpu] -> GICC_CTLR */
reg = s->cpu_enabled[cpu];
kvm_gicc_access(s, 0x00, cpu, &reg, true);
/* s->priority_mask[cpu] -> GICC_PMR */
reg = (s->priority_mask[cpu] & 0xff);
kvm_gicc_access(s, 0x04, cpu, &reg, true);
/* s->bpr[cpu] -> GICC_BPR */
reg = (s->bpr[cpu] & 0x7);
kvm_gicc_access(s, 0x08, cpu, &reg, true);
/* s->abpr[cpu] -> GICC_ABPR */
reg = (s->abpr[cpu] & 0x7);
kvm_gicc_access(s, 0x1c, cpu, &reg, true);
/* s->apr[n][cpu] -> GICC_APRn */
for (i = 0; i < 4; i++) {
reg = s->apr[i][cpu];
kvm_gicc_access(s, 0xd0 + i * 4, cpu, &reg, true);
}
}
} }
static void kvm_arm_gic_get(GICState *s) static void kvm_arm_gic_get(GICState *s)
{ {
/* TODO: there isn't currently a kernel interface to get the GIC state */ uint32_t reg;
int i;
int cpu;
if (!kvm_arm_gic_can_save_restore(s)) {
DPRINTF("Cannot get kernel gic state, no kernel interface");
return;
}
/*****************************************************************
* Distributor State
*/
/* GICD_CTLR -> s->enabled */
kvm_gicd_access(s, 0x0, 0, &reg, false);
s->enabled = reg & 1;
/* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */
kvm_gicd_access(s, 0x4, 0, &reg, false);
s->num_irq = ((reg & 0x1f) + 1) * 32;
s->num_cpu = ((reg & 0xe0) >> 5) + 1;
if (s->num_irq > GIC_MAXIRQ) {
fprintf(stderr, "Too many IRQs reported from the kernel: %d\n",
s->num_irq);
abort();
}
/* GICD_IIDR -> ? */
kvm_gicd_access(s, 0x8, 0, &reg, false);
/* Verify no GROUP 1 interrupts configured in the kernel */
for_each_irq_reg(i, s->num_irq, 1) {
kvm_gicd_access(s, 0x80 + (i * 4), 0, &reg, false);
if (reg != 0) {
fprintf(stderr, "Unsupported GICD_IGROUPRn value: %08x\n",
reg);
abort();
}
}
/* Clear all the IRQ settings */
for (i = 0; i < s->num_irq; i++) {
memset(&s->irq_state[i], 0, sizeof(s->irq_state[0]));
}
/* GICD_ISENABLERn -> irq_state[n].enabled */
kvm_dist_get(s, 0x100, 1, s->num_irq, translate_enabled);
/* GICD_ISPENDRn -> irq_state[n].pending + irq_state[n].level */
kvm_dist_get(s, 0x200, 1, s->num_irq, translate_pending);
/* GICD_ISACTIVERn -> irq_state[n].active */
kvm_dist_get(s, 0x300, 1, s->num_irq, translate_active);
/* GICD_ICFRn -> irq_state[n].trigger */
kvm_dist_get(s, 0xc00, 2, s->num_irq, translate_trigger);
/* GICD_IPRIORITYRn -> s->priorityX[irq] */
kvm_dist_get(s, 0x400, 8, s->num_irq, translate_priority);
/* GICD_ITARGETSRn -> s->irq_target[irq] */
kvm_dist_get(s, 0x800, 8, s->num_irq, translate_targets);
/* GICD_CPENDSGIRn -> s->sgi_pending */
kvm_dist_get(s, 0xf10, 8, GIC_NR_SGIS, translate_sgisource);
/*****************************************************************
* CPU Interface(s) State
*/
for (cpu = 0; cpu < s->num_cpu; cpu++) {
/* GICC_CTLR -> s->cpu_enabled[cpu] */
kvm_gicc_access(s, 0x00, cpu, &reg, false);
s->cpu_enabled[cpu] = (reg & 1);
/* GICC_PMR -> s->priority_mask[cpu] */
kvm_gicc_access(s, 0x04, cpu, &reg, false);
s->priority_mask[cpu] = (reg & 0xff);
/* GICC_BPR -> s->bpr[cpu] */
kvm_gicc_access(s, 0x08, cpu, &reg, false);
s->bpr[cpu] = (reg & 0x7);
/* GICC_ABPR -> s->abpr[cpu] */
kvm_gicc_access(s, 0x1c, cpu, &reg, false);
s->abpr[cpu] = (reg & 0x7);
/* GICC_APRn -> s->apr[n][cpu] */
for (i = 0; i < 4; i++) {
kvm_gicc_access(s, 0xd0 + i * 4, cpu, &reg, false);
s->apr[i][cpu] = reg;
}
}
} }
static void kvm_arm_gic_reset(DeviceState *dev) static void kvm_arm_gic_reset(DeviceState *dev)
@@ -97,6 +517,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
GICState *s = KVM_ARM_GIC(dev); GICState *s = KVM_ARM_GIC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s); KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
int ret;
kgc->parent_realize(dev, errp); kgc->parent_realize(dev, errp);
if (error_is_set(errp)) { if (error_is_set(errp)) {
@@ -119,13 +540,27 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->num_cpu; i++) { for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_irq[i]); sysbus_init_irq(sbd, &s->parent_irq[i]);
} }
/* Try to create the device via the device control API */
s->dev_fd = -1;
ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
if (ret >= 0) {
s->dev_fd = ret;
} else if (ret != -ENODEV && ret != -ENOTSUP) {
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
return;
}
/* Distributor */ /* Distributor */
memory_region_init_reservation(&s->iomem, OBJECT(s), memory_region_init_reservation(&s->iomem, OBJECT(s),
"kvm-gic_dist", 0x1000); "kvm-gic_dist", 0x1000);
sysbus_init_mmio(sbd, &s->iomem); sysbus_init_mmio(sbd, &s->iomem);
kvm_arm_register_device(&s->iomem, kvm_arm_register_device(&s->iomem,
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
| KVM_VGIC_V2_ADDR_TYPE_DIST); | KVM_VGIC_V2_ADDR_TYPE_DIST,
KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V2_ADDR_TYPE_DIST,
s->dev_fd);
/* CPU interface for current core. Unlike arm_gic, we don't /* CPU interface for current core. Unlike arm_gic, we don't
* provide the "interface for core #N" memory regions, because * provide the "interface for core #N" memory regions, because
* cores with a VGIC don't have those. * cores with a VGIC don't have those.
@@ -135,7 +570,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->cpuiomem[0]); sysbus_init_mmio(sbd, &s->cpuiomem[0]);
kvm_arm_register_device(&s->cpuiomem[0], kvm_arm_register_device(&s->cpuiomem[0],
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
| KVM_VGIC_V2_ADDR_TYPE_CPU); | KVM_VGIC_V2_ADDR_TYPE_CPU,
KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V2_ADDR_TYPE_CPU,
s->dev_fd);
} }
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)

View File

@@ -418,7 +418,7 @@ static int exynos4210_combiner_init(SysBusDevice *sbd)
qdev_init_gpio_in(dev, exynos4210_combiner_handler, IIC_NIRQ); qdev_init_gpio_in(dev, exynos4210_combiner_handler, IIC_NIRQ);
/* Connect SysBusDev irqs to device specific irqs */ /* Connect SysBusDev irqs to device specific irqs */
for (i = 0; i < IIC_NIRQ; i++) { for (i = 0; i < IIC_NGRP; i++) {
sysbus_init_irq(sbd, &s->output_irq[i]); sysbus_init_irq(sbd, &s->output_irq[i]);
} }

View File

@@ -40,7 +40,7 @@
#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true #define GIC_SET_MODEL(irq) s->irq_state[irq].model = true
#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false
#define GIC_TEST_MODEL(irq) s->irq_state[irq].model #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm) #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level |= (cm)
#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm) #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0) #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true #define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true

View File

@@ -228,7 +228,7 @@ int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
encap.cap = KVM_CAP_IRQ_MPIC; encap.cap = KVM_CAP_IRQ_MPIC;
encap.args[0] = opp->fd; encap.args[0] = opp->fd;
encap.args[1] = cs->cpu_index; encap.args[1] = kvm_arch_vcpu_id(cs);
return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap); return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
} }

322
hw/intc/s390_flic.c Normal file
View File

@@ -0,0 +1,322 @@
/*
* QEMU S390x KVM floating interrupt controller (flic)
*
* Copyright 2014 IBM Corp.
* Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
* your option) any later version. See the COPYING file in the top-level
* directory.
*/
#include <sys/ioctl.h>
#include "qemu/error-report.h"
#include "hw/sysbus.h"
#include "sysemu/kvm.h"
#include "migration/qemu-file.h"
#include "hw/s390x/s390_flic.h"
#include "trace.h"
#define FLIC_SAVE_INITIAL_SIZE getpagesize()
#define FLIC_FAILED (-1UL)
#define FLIC_SAVEVM_VERSION 1
void s390_flic_init(void)
{
DeviceState *dev;
int r;
if (kvm_enabled()) {
dev = qdev_create(NULL, "s390-flic");
object_property_add_child(qdev_get_machine(), "s390-flic",
OBJECT(dev), NULL);
r = qdev_init(dev);
if (r) {
error_report("flic: couldn't create qdev");
}
}
}
/**
* flic_get_all_irqs - store all pending irqs in buffer
* @buf: pointer to buffer which is passed to kernel
* @len: length of buffer
* @flic: pointer to flic device state
*
* Returns: -ENOMEM if buffer is too small,
* -EINVAL if attr.group is invalid,
* -EFAULT if copying to userspace failed,
* on success return number of stored interrupts
*/
static int flic_get_all_irqs(KVMS390FLICState *flic,
void *buf, int len)
{
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_GET_ALL_IRQS,
.addr = (uint64_t) buf,
.attr = len,
};
int rc;
rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
return rc == -1 ? -errno : rc;
}
static void flic_enable_pfault(KVMS390FLICState *flic)
{
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_APF_ENABLE,
};
int rc;
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
if (rc) {
fprintf(stderr, "flic: couldn't enable pfault\n");
}
}
static void flic_disable_wait_pfault(KVMS390FLICState *flic)
{
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
};
int rc;
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
if (rc) {
fprintf(stderr, "flic: couldn't disable pfault\n");
}
}
/** flic_enqueue_irqs - returns 0 on success
* @buf: pointer to buffer which is passed to kernel
* @len: length of buffer
* @flic: pointer to flic device state
*
* Returns: -EINVAL if attr.group is unknown
*/
static int flic_enqueue_irqs(void *buf, uint64_t len,
KVMS390FLICState *flic)
{
int rc;
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_ENQUEUE,
.addr = (uint64_t) buf,
.attr = len,
};
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
return rc ? -errno : 0;
}
/**
* __get_all_irqs - store all pending irqs in buffer
* @flic: pointer to flic device state
* @buf: pointer to pointer to a buffer
* @len: length of buffer
*
* Returns: return value of flic_get_all_irqs
* Note: Retry and increase buffer size until flic_get_all_irqs
* either returns a value >= 0 or a negative error code.
* -ENOMEM is an exception, which means the buffer is too small
* and we should try again. Other negative error codes can be
* -EFAULT and -EINVAL which we ignore at this point
*/
static int __get_all_irqs(KVMS390FLICState *flic,
void **buf, int len)
{
int r;
do {
/* returns -ENOMEM if buffer is too small and number
* of queued interrupts on success */
r = flic_get_all_irqs(flic, *buf, len);
if (r >= 0) {
break;
}
len *= 2;
*buf = g_try_realloc(*buf, len);
if (!buf) {
return -ENOMEM;
}
} while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
return r;
}
/**
* kvm_flic_save - Save pending floating interrupts
* @f: QEMUFile containing migration state
* @opaque: pointer to flic device state
*
* Note: Pass buf and len to kernel. Start with one page and
* increase until buffer is sufficient or maxium size is
* reached
*/
static void kvm_flic_save(QEMUFile *f, void *opaque)
{
KVMS390FLICState *flic = opaque;
int len = FLIC_SAVE_INITIAL_SIZE;
void *buf;
int count;
flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
buf = g_try_malloc0(len);
if (!buf) {
/* Storing FLIC_FAILED into the count field here will cause the
* target system to fail when attempting to load irqs from the
* migration state */
error_report("flic: couldn't allocate memory");
qemu_put_be64(f, FLIC_FAILED);
return;
}
count = __get_all_irqs(flic, &buf, len);
if (count < 0) {
error_report("flic: couldn't retrieve irqs from kernel, rc %d",
count);
/* Storing FLIC_FAILED into the count field here will cause the
* target system to fail when attempting to load irqs from the
* migration state */
qemu_put_be64(f, FLIC_FAILED);
} else {
qemu_put_be64(f, count);
qemu_put_buffer(f, (uint8_t *) buf,
count * sizeof(struct kvm_s390_irq));
}
g_free(buf);
}
/**
* kvm_flic_load - Load pending floating interrupts
* @f: QEMUFile containing migration state
* @opaque: pointer to flic device state
* @version_id: version id for migration
*
* Returns: value of flic_enqueue_irqs, -EINVAL on error
* Note: Do nothing when no interrupts where stored
* in QEMUFile
*/
static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
{
uint64_t len = 0;
uint64_t count = 0;
void *buf = NULL;
int r = 0;
if (version_id != FLIC_SAVEVM_VERSION) {
r = -EINVAL;
goto out;
}
flic_enable_pfault((struct KVMS390FLICState *) opaque);
count = qemu_get_be64(f);
len = count * sizeof(struct kvm_s390_irq);
if (count == FLIC_FAILED) {
r = -EINVAL;
goto out;
}
if (count == 0) {
r = 0;
goto out;
}
buf = g_try_malloc0(len);
if (!buf) {
r = -ENOMEM;
goto out;
}
if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
r = -EINVAL;
goto out_free;
}
r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
out_free:
g_free(buf);
out:
return r;
}
static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
{
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
struct kvm_create_device cd = {0};
int ret;
flic_state->fd = -1;
if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) {
trace_flic_no_device_api(errno);
return;
}
cd.type = KVM_DEV_TYPE_FLIC;
ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
if (ret < 0) {
trace_flic_create_device(errno);
return;
}
flic_state->fd = cd.fd;
/* Register savevm handler for floating interrupts */
register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
kvm_flic_load, (void *) flic_state);
}
static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp)
{
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
unregister_savevm(DEVICE(flic_state), "s390-flic", flic_state);
}
static void kvm_s390_flic_reset(DeviceState *dev)
{
KVMS390FLICState *flic = KVM_S390_FLIC(dev);
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_CLEAR_IRQS,
};
int rc = 0;
if (flic->fd == -1) {
return;
}
flic_disable_wait_pfault(flic);
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
if (rc) {
trace_flic_reset_failed(errno);
}
flic_enable_pfault(flic);
}
static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = kvm_s390_flic_realize;
dc->unrealize = kvm_s390_flic_unrealize;
dc->reset = kvm_s390_flic_reset;
}
static const TypeInfo kvm_s390_flic_info = {
.name = TYPE_KVM_S390_FLIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(KVMS390FLICState),
.class_init = kvm_s390_flic_class_init,
};
static void kvm_s390_flic_register_types(void)
{
type_register_static(&kvm_s390_flic_info);
}
type_init(kvm_s390_flic_register_types)

View File

@@ -33,6 +33,17 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qapi/visitor.h" #include "qapi/visitor.h"
static int get_cpu_index_by_dt_id(int cpu_dt_id)
{
PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id);
if (cpu) {
return cpu->parent_obj.cpu_index;
}
return -1;
}
void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu) void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
{ {
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
@@ -659,7 +670,7 @@ static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args) target_ulong opcode, target_ulong *args)
{ {
target_ulong server = args[0]; target_ulong server = get_cpu_index_by_dt_id(args[0]);
target_ulong mfrr = args[1]; target_ulong mfrr = args[1];
if (server >= spapr->icp->nr_servers) { if (server >= spapr->icp->nr_servers) {
@@ -728,7 +739,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
} }
nr = rtas_ld(args, 0); nr = rtas_ld(args, 0);
server = rtas_ld(args, 1); server = get_cpu_index_by_dt_id(rtas_ld(args, 1));
priority = rtas_ld(args, 2); priority = rtas_ld(args, 2);
if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers) if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)

View File

@@ -65,7 +65,7 @@ static void icp_get_kvm_state(ICPState *ss)
ret = kvm_vcpu_ioctl(ss->cs, KVM_GET_ONE_REG, &reg); ret = kvm_vcpu_ioctl(ss->cs, KVM_GET_ONE_REG, &reg);
if (ret != 0) { if (ret != 0) {
error_report("Unable to retrieve KVM interrupt controller state" error_report("Unable to retrieve KVM interrupt controller state"
" for CPU %d: %s", ss->cs->cpu_index, strerror(errno)); " for CPU %ld: %s", kvm_arch_vcpu_id(ss->cs), strerror(errno));
exit(1); exit(1);
} }
@@ -97,7 +97,7 @@ static int icp_set_kvm_state(ICPState *ss, int version_id)
ret = kvm_vcpu_ioctl(ss->cs, KVM_SET_ONE_REG, &reg); ret = kvm_vcpu_ioctl(ss->cs, KVM_SET_ONE_REG, &reg);
if (ret != 0) { if (ret != 0) {
error_report("Unable to restore KVM interrupt controller state (0x%" error_report("Unable to restore KVM interrupt controller state (0x%"
PRIx64 ") for CPU %d: %s", state, ss->cs->cpu_index, PRIx64 ") for CPU %ld: %s", state, kvm_arch_vcpu_id(ss->cs),
strerror(errno)); strerror(errno));
return ret; return ret;
} }
@@ -325,15 +325,15 @@ static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
struct kvm_enable_cap xics_enable_cap = { struct kvm_enable_cap xics_enable_cap = {
.cap = KVM_CAP_IRQ_XICS, .cap = KVM_CAP_IRQ_XICS,
.flags = 0, .flags = 0,
.args = {icpkvm->kernel_xics_fd, cs->cpu_index, 0, 0}, .args = {icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs), 0, 0},
}; };
ss->cs = cs; ss->cs = cs;
ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap); ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
if (ret < 0) { if (ret < 0) {
error_report("Unable to connect CPU%d to kernel XICS: %s", error_report("Unable to connect CPU%ld to kernel XICS: %s",
cs->cpu_index, strerror(errno)); kvm_arch_vcpu_id(cs), strerror(errno));
exit(1); exit(1);
} }
} }

View File

@@ -32,7 +32,6 @@
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "hw/devices.h" #include "hw/devices.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/xilinx.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "hw/char/serial.h" #include "hw/char/serial.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
@@ -49,6 +48,7 @@
#define NUM_SPI_FLASHES 4 #define NUM_SPI_FLASHES 4
#define SPI_BASEADDR 0x40a00000
#define MEMORY_BASEADDR 0x50000000 #define MEMORY_BASEADDR 0x50000000
#define FLASH_BASEADDR 0x86000000 #define FLASH_BASEADDR 0x86000000
#define INTC_BASEADDR 0x81800000 #define INTC_BASEADDR 0x81800000
@@ -57,6 +57,13 @@
#define AXIENET_BASEADDR 0x82780000 #define AXIENET_BASEADDR 0x82780000
#define AXIDMA_BASEADDR 0x84600000 #define AXIDMA_BASEADDR 0x84600000
#define AXIDMA_IRQ1 0
#define AXIDMA_IRQ0 1
#define TIMER_IRQ 2
#define AXIENET_IRQ 3
#define SPI_IRQ 4
#define UART16550_IRQ 5
static void machine_cpu_reset(MicroBlazeCPU *cpu) static void machine_cpu_reset(MicroBlazeCPU *cpu)
{ {
CPUMBState *env = &cpu->env; CPUMBState *env = &cpu->env;
@@ -111,17 +118,27 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
2, 0x89, 0x18, 0x0000, 0x0, 0); 2, 0x89, 0x18, 0x0000, 0x0, 0);
dev = xilinx_intc_create(INTC_BASEADDR, qdev_get_gpio_in(DEVICE(cpu), dev = qdev_create(NULL, "xlnx.xps-intc");
MB_CPU_IRQ), 4); qdev_prop_set_uint32(dev, "kind-of-intr", 1 << TIMER_IRQ);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ));
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
irq[i] = qdev_get_gpio_in(dev, i); irq[i] = qdev_get_gpio_in(dev, i);
} }
serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2, serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN); irq[UART16550_IRQ], 115200, serial_hds[0],
DEVICE_LITTLE_ENDIAN);
/* 2 timers at irq 2 @ 100 Mhz. */ /* 2 timers at irq 2 @ 100 Mhz. */
xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000); dev = qdev_create(NULL, "xlnx.xps-timer");
qdev_prop_set_uint32(dev, "one-timer-only", 0);
qdev_prop_set_uint32(dev, "clock-frequency", 100 * 1000000);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);
/* axi ethernet and dma initialization. */ /* axi ethernet and dma initialization. */
qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet"); qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet");
@@ -138,16 +155,30 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
"axistream-connected-target", NULL); "axistream-connected-target", NULL);
cs = object_property_get_link(OBJECT(dma), cs = object_property_get_link(OBJECT(dma),
"axistream-control-connected-target", NULL); "axistream-control-connected-target", NULL);
xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(ds), qdev_set_nic_properties(eth0, &nd_table[0]);
STREAM_SLAVE(cs), 0x82780000, irq[3], 0x1000, qdev_prop_set_uint32(eth0, "rxmem", 0x1000);
0x1000); qdev_prop_set_uint32(eth0, "txmem", 0x1000);
object_property_set_link(OBJECT(eth0), OBJECT(ds),
"axistream-connected", &error_abort);
object_property_set_link(OBJECT(eth0), OBJECT(cs),
"axistream-control-connected", &error_abort);
qdev_init_nofail(eth0);
sysbus_mmio_map(SYS_BUS_DEVICE(eth0), 0, AXIENET_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(eth0), 0, irq[AXIENET_IRQ]);
ds = object_property_get_link(OBJECT(eth0), ds = object_property_get_link(OBJECT(eth0),
"axistream-connected-target", NULL); "axistream-connected-target", NULL);
cs = object_property_get_link(OBJECT(eth0), cs = object_property_get_link(OBJECT(eth0),
"axistream-control-connected-target", NULL); "axistream-control-connected-target", NULL);
xilinx_axidma_init(dma, STREAM_SLAVE(ds), STREAM_SLAVE(cs), 0x84600000, qdev_prop_set_uint32(dma, "freqhz", 100 * 1000000);
irq[1], irq[0], 100 * 1000000); object_property_set_link(OBJECT(dma), OBJECT(ds),
"axistream-connected", &error_abort);
object_property_set_link(OBJECT(dma), OBJECT(cs),
"axistream-control-connected", &error_abort);
qdev_init_nofail(dma);
sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, AXIDMA_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(dma), 0, irq[AXIDMA_IRQ0]);
sysbus_connect_irq(SYS_BUS_DEVICE(dma), 1, irq[AXIDMA_IRQ1]);
{ {
SSIBus *spi; SSIBus *spi;
@@ -156,8 +187,8 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES); qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
qdev_init_nofail(dev); qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev); busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0x40a00000); sysbus_mmio_map(busdev, 0, SPI_BASEADDR);
sysbus_connect_irq(busdev, 0, irq[4]); sysbus_connect_irq(busdev, 0, irq[SPI_IRQ]);
spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); spi = (SSIBus *)qdev_get_child_bus(dev, "spi");

View File

@@ -30,7 +30,6 @@
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "hw/devices.h" #include "hw/devices.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/xilinx.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
@@ -48,6 +47,10 @@
#define UARTLITE_BASEADDR 0x84000000 #define UARTLITE_BASEADDR 0x84000000
#define ETHLITE_BASEADDR 0x81000000 #define ETHLITE_BASEADDR 0x81000000
#define TIMER_IRQ 0
#define ETHLITE_IRQ 1
#define UARTLITE_IRQ 3
static void machine_cpu_reset(MicroBlazeCPU *cpu) static void machine_cpu_reset(MicroBlazeCPU *cpu)
{ {
CPUMBState *env = &cpu->env; CPUMBState *env = &cpu->env;
@@ -93,16 +96,36 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
FLASH_SIZE >> 16, FLASH_SIZE >> 16,
1, 0x89, 0x18, 0x0000, 0x0, 1); 1, 0x89, 0x18, 0x0000, 0x0, 1);
dev = xilinx_intc_create(INTC_BASEADDR, qdev_get_gpio_in(DEVICE(cpu), dev = qdev_create(NULL, "xlnx.xps-intc");
MB_CPU_IRQ), 0xA); qdev_prop_set_uint32(dev, "kind-of-intr",
1 << ETHLITE_IRQ | 1 << UARTLITE_IRQ);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, INTC_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
qdev_get_gpio_in(DEVICE(cpu), MB_CPU_IRQ));
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
irq[i] = qdev_get_gpio_in(dev, i); irq[i] = qdev_get_gpio_in(dev, i);
} }
sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR, irq[3]); sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR,
irq[UARTLITE_IRQ]);
/* 2 timers at irq 2 @ 62 Mhz. */ /* 2 timers at irq 2 @ 62 Mhz. */
xilinx_timer_create(TIMER_BASEADDR, irq[0], 0, 62 * 1000000); dev = qdev_create(NULL, "xlnx.xps-timer");
xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0); qdev_prop_set_uint32(dev, "one-timer-only", 0);
qdev_prop_set_uint32(dev, "clock-frequency", 62 * 1000000);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);
qemu_check_nic_model(&nd_table[0], "xlnx.xps-ethernetlite");
dev = qdev_create(NULL, "xlnx.xps-ethernetlite");
qdev_set_nic_properties(dev, &nd_table[0]);
qdev_prop_set_uint32(dev, "tx-ping-pong", 0);
qdev_prop_set_uint32(dev, "rx-ping-pong", 0);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ETHLITE_BASEADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[ETHLITE_IRQ]);
microblaze_load_kernel(cpu, ddr_base, ram_size, microblaze_load_kernel(cpu, ddr_base, ram_size,
args->initrd_filename, args->initrd_filename,

View File

@@ -276,7 +276,7 @@ static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
} }
break; break;
case SYS_CFG_OSC: case SYS_CFG_OSC:
if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) { if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
/* motherboard clock */ /* motherboard clock */
*val = s->mb_clock[device]; *val = s->mb_clock[device];
return true; return true;
@@ -324,7 +324,7 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
switch (function) { switch (function) {
case SYS_CFG_OSC: case SYS_CFG_OSC:
if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) { if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
/* motherboard clock */ /* motherboard clock */
s->mb_clock[device] = val; s->mb_clock[device] = val;
return true; return true;

View File

@@ -209,6 +209,29 @@ typedef struct VFIOGroup {
QLIST_ENTRY(VFIOGroup) container_next; QLIST_ENTRY(VFIOGroup) container_next;
} VFIOGroup; } VFIOGroup;
typedef struct VFIORomBlacklistEntry {
uint16_t vendor_id;
uint16_t device_id;
} VFIORomBlacklistEntry;
/*
* List of device ids/vendor ids for which to disable
* option rom loading. This avoids the guest hangs during rom
* execution as noticed with the BCM 57810 card for lack of a
* more better way to handle such issues.
* The user can still override by specifying a romfile or
* rombar=1.
* Please see https://bugs.launchpad.net/qemu/+bug/1284874
* for an analysis of the 57810 card hang. When adding
* a new vendor id/device id combination below, please also add
* your card/environment details and information that could
* help in debugging to the bug tracking this issue
*/
static const VFIORomBlacklistEntry romblacklist[] = {
/* Broadcom BCM 57810 */
{ 0x14e4, 0x168e }
};
#define MSIX_CAP_LENGTH 12 #define MSIX_CAP_LENGTH 12
static QLIST_HEAD(, VFIOContainer) static QLIST_HEAD(, VFIOContainer)
@@ -1197,13 +1220,43 @@ static const MemoryRegionOps vfio_rom_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
static bool vfio_blacklist_opt_rom(VFIODevice *vdev)
{
PCIDevice *pdev = &vdev->pdev;
uint16_t vendor_id, device_id;
int count = 0;
vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
while (count < ARRAY_SIZE(romblacklist)) {
if (romblacklist[count].vendor_id == vendor_id &&
romblacklist[count].device_id == device_id) {
return true;
}
count++;
}
return false;
}
static void vfio_pci_size_rom(VFIODevice *vdev) static void vfio_pci_size_rom(VFIODevice *vdev)
{ {
uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK); uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK);
off_t offset = vdev->config_offset + PCI_ROM_ADDRESS; off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
DeviceState *dev = DEVICE(vdev);
char name[32]; char name[32];
if (vdev->pdev.romfile || !vdev->pdev.rom_bar) { if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
/* Since pci handles romfile, just print a message and return */
if (vfio_blacklist_opt_rom(vdev) && vdev->pdev.romfile) {
error_printf("Warning : Device at %04x:%02x:%02x.%x "
"is known to cause system instability issues during "
"option rom execution. "
"Proceeding anyway since user specified romfile\n",
vdev->host.domain, vdev->host.bus, vdev->host.slot,
vdev->host.function);
}
return; return;
} }
@@ -1227,6 +1280,26 @@ static void vfio_pci_size_rom(VFIODevice *vdev)
return; return;
} }
if (vfio_blacklist_opt_rom(vdev)) {
if (dev->opts && qemu_opt_get(dev->opts, "rombar")) {
error_printf("Warning : Device at %04x:%02x:%02x.%x "
"is known to cause system instability issues during "
"option rom execution. "
"Proceeding anyway since user specified non zero value for "
"rombar\n",
vdev->host.domain, vdev->host.bus, vdev->host.slot,
vdev->host.function);
} else {
error_printf("Warning : Rom loading for device at "
"%04x:%02x:%02x.%x has been disabled due to "
"system instability issues. "
"Specify rombar=1 or romfile to force\n",
vdev->host.domain, vdev->host.bus, vdev->host.slot,
vdev->host.function);
return;
}
}
DPRINTF("%04x:%02x:%02x.%x ROM size 0x%x\n", vdev->host.domain, DPRINTF("%04x:%02x:%02x.%x ROM size 0x%x\n", vdev->host.domain,
vdev->host.bus, vdev->host.slot, vdev->host.function, size); vdev->host.bus, vdev->host.slot, vdev->host.function, size);
@@ -3681,10 +3754,10 @@ static int vfio_initfn(PCIDevice *pdev)
strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1); strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1);
len = readlink(path, iommu_group_path, PATH_MAX); len = readlink(path, iommu_group_path, sizeof(path));
if (len <= 0) { if (len <= 0 || len >= sizeof(path)) {
error_report("vfio: error no iommu_group for device"); error_report("vfio: error no iommu_group for device");
return -errno; return len < 0 ? -errno : ENAMETOOLONG;
} }
iommu_group_path[len] = 0; iommu_group_path[len] = 0;

View File

@@ -55,7 +55,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
&entry, &kernel_low, &kernel_high, 1, &entry, &kernel_low, &kernel_high, 1,
ELF_MACHINE, 0); ELF_MACHINE, 0);
if (!kernel_size) { if (kernel_size <= 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n", fprintf(stderr, "qemu: could not load kernel '%s'\n",
loader_params->kernel_filename); loader_params->kernel_filename);
exit(1); exit(1);

View File

@@ -32,3 +32,6 @@ obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
obj-$(CONFIG_VIRTIO) += virtio-net.o obj-$(CONFIG_VIRTIO) += virtio-net.o
obj-y += vhost_net.o obj-y += vhost_net.o
obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
fsl_etsec/rings.o fsl_etsec/miim.o

Some files were not shown because too many files have changed in this diff Show More