Compare commits

..
242 Commits
Author SHA1 Message Date
Michael Roth f4c53d94d2 update VERSION for v1.2.1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:47:44 -05:00
David Gibson 159fe82dea pseries: Don't test for MSR_PR for hypercalls under KVM
PAPR hypercalls should only be invoked from the guest kernel, not guest
user programs, that is, with MSR[PR]=0.  Currently we check this in
spapr_hypercall, returning H_PRIVILEGE if MSR[PR]=1.

However, under KVM the state of MSR[PR] is already checked by the host
kernel before passing the hypercall to qemu, making this check redundant.
Worse, however, we don't generally synchronize KVM and qemu state on the
hypercall path, meaning that qemu could incorrectly reject a hypercall
because it has a stale MSR value.

This patch fixes the problem by moving the privilege test exclusively to
the TCG hypercall path.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
CC: qemu-stable@nongnu.org
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit efcb9383b9)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Peter Maydell a8f2299d1b fpu/softfloat.c: Return correctly signed values from uint64_to_float32
The uint64_to_float32() conversion function was incorrectly always
returning numbers with the sign bit set (ie negative numbers). Correct
this so we return positive numbers instead.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Eduardo Habkost 68fc5d1d27 i386: kvm: bit 10 of CPUID[8000_0001].EDX is reserved
Bit 10 of CPUID[8000_0001].EDX is not defined as an alias of
CPUID[1].EDX[10], so do not duplicate it on
kvm_arch_get_supported_cpuid().

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-By: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Don Slutz <Don@CloudSwitch.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit b1f4679392)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Francesco Lavra 3e1954cb4a Versatile Express: Fix NOR flash 0 address and remove flash alias
In the A series memory map (implemented in the Cortex A15 CoreTile), the
first NOR flash bank (flash 0) is mapped to address 0x08000000, while
address 0x00000000 can be configured as alias to either the first or the
second flash bank. This patch fixes the definition of flash 0 address,
and for simplicity removes the alias definition.

Signed-off-by: Francesco Lavra <francescolavra.fl@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 661bafb3e1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Meador Inge 14bdf978ef hw/armv7m_nvic: Correctly register GIC region when setting up NVIC
When setting up the NVIC memory regions the memory range
0x100..0xcff is aliased to an IO memory region that belongs
to the ARM GIC.  This aliased region should be added to the
NVIC memory container, but the actual GIC IO memory region
was being added instead.  This mixup was causing the wrong
IO memory access functions to be called when accessing parts
of the NVIC memory.

Signed-off-by: Meador Inge <meadori@codesourcery.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 9892cae395)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Brendan Fennell 806d996789 pl190: fix read of VECTADDR
Reading VECTADDR was causing us to set the current priority to
the wrong value, the most obvious effect of which was that we
would return the vector for the wrong interrupt as the result
of the read.

Signed-off-by: Brendan Fennell <bfennell@skynet.ie>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 14c126baf1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Orit Wasserman d893e56f72 Clear handler only for valid fd
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 3202becaa2)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Orit Wasserman 240f68ce5b Fix address handling in inet_nonblocking_connect
getaddrinfo can give us a list of addresses, but we only try to
connect to the first one. If that fails we never proceed to
the next one.  This is common on desktop setups that often have ipv6
configured but not actually working.

To fix this make inet_connect_nonblocking retry connection with a different
address.
callers on inet_nonblocking_connect register a callback function that will
be called when connect opertion completes, in case of failure the fd will have
a negative value

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 233aa5c2d1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Orit Wasserman ee0999b16a Separate inet_connect into inet_connect (blocking) and inet_nonblocking_connect
No need to add non blocking parameters to the blocking inet_connect
add block parameter for inet_connect_opts instead of using QemuOpt "block".

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 5db5f44cb4)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Michael S. Tsirkin 57f8a4c507 Refactor inet_connect_opts function
refactor address resolution code to fix nonblocking connect
remove getnameinfo call

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 05bc1d8a4b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Stefan Weil b83465006d configure: Allow builds without any system or user emulation
The old code aborted configure when no emulation target was selected.
Even after removing the 'exit 1', it tried to read from STDIN
when QEMU was configured with

    configure' '--disable-user' '--disable-system'

This is fixed here.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 8bdd3d499f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:21 -05:00
Jeff Cody d80210efbc block: correctly set the keep_read_only flag
I believe the bs->keep_read_only flag is supposed to reflect
the initial open state of the device. If the device is initially
opened R/O, then commit operations, or reopen operations changing
to R/W, are prohibited.

Currently, the keep_read_only flag is only accurate for the active
layer, and its backing file. Subsequent images end up always having
the keep_read_only flag set.

For instance, what happens now:

[  base  ]  kro = 1, ro = 1
    |
    v
[ snap-1 ]  kro = 1, ro = 1
    |
    v
[ snap-2 ]  kro = 0, ro = 1
    |
    v
[ active ]  kro = 0, ro = 0

What we want:

[  base  ]  kro = 0, ro = 1
    |
    v
[ snap-1 ]  kro = 0, ro = 1
    |
    v
[ snap-2 ]  kro = 0, ro = 1
    |
    v
[ active ]  kro = 0, ro = 0

Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit be028adced)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Kevin Shanahan 513cdda198 blockdev: preserve readonly and snapshot states across media changes
If readonly=on is given at device creation time, the ->readonly flag
needs to be set in the block driver state for this device so that
readonly-ness is preserved across media changes (qmp change command).
Similarly, to preserve the snapshot property requires ->open_flags to
be correct.

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 80dd1aae36)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil eea54caab0 w32: Add implementation of gmtime_r, localtime_r
Those functions are missing in MinGW.

Some versions of MinGW-w64 include defines for gmtime_r and localtime_r.
Older versions of these macros are buggy (they return a pointer to a
static variable), therefore we don't want them. Newer versions are
similar to the code used here, but without the memset.

The implementation which is used here is not strictly reentrant,
but sufficiently good for QEMU on w32 or w64.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
[blauwirbel@gmail.com: added comment about locking]
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit d3e8f95753)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 78fd27b3b6 w32: Always use standard instead of native format strings
GLib 2.0 include files use __printf__ for the format attribute
which resolves to native format strings on w32 hosts.

QEMU wants standard format strings instead of native format
strings, so we simply change any declaration with __printf__
to use __gnu_printf__.

This works because all basic printf functions support both
kinds of format strings.

This fixes a compiler warning:

qapi/string-output-visitor.c: In function ‘print_type_int’:
qapi/string-output-visitor.c:34:5: warning: unknown conversion type character ‘l’ in format [-Wformat]
qapi/string-output-visitor.c:34:5: warning: too many arguments for format [-Wformat-extra-args]

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 95df51a4a0)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil d4413913e1 net/socket: Fix compiler warning (regression for MinGW)
Commit 213fd5087e removed a type cast
which is needed for MinGW:

net/socket.c:136: warning:
 pointer targets in passing argument 2 of ‘sendto’ differ in signedness
/usr/lib/gcc/amd64-mingw32msvc/4.4.4/../../../../amd64-mingw32msvc/include/winsock2.h:1313: note:
 expected ‘const char *’ but argument is of type ‘const uint8_t *’

Add a 'qemu_sendto' macro which provides that type cast where needed
and use the new macro instead of 'sendto'.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 73062dfe6b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 61dea8e914 linux-user: Remove redundant null check and replace free by g_free
Report from smatch:

linux-user/syscall.c:3632 do_ioctl_dm(220) info:
 redundant null check on big_buf calling free()

'big_buf' was allocated by g_malloc0, therefore free was also
replaced by g_free.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit ad11ad7774)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Laszlo Ersek a2aad5fdc4 TextConsole: saturate escape parameter in TTY_STATE_CSI
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit c10600af60)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Hitoshi Mitake 5730401442 curses: don't initialize curses when qemu is daemonized
Current qemu initializes curses even if -daemonize option is
passed. This cause problem because shell prompt appears without
calling endwin().

This patch adds new function, is_daemonized(), to OS dependent
code. With this function, curses_display_init() can check that qemu is
daemonized or not. If daemonized, curses_display_init() isn't called
and the problem is avoided.

Of course, -daemonize && -curses doesn't make sense. Users shouldn't
pass the arguments at the same time. But the problem is very painful
because Ctrl-C cannot be delivered to the terminal.

Cc: Andrzej Zaborowski  <balrog@zabor.org>
Cc: Stefan Hajnoczi <stefanha@gmail.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Hitoshi Mitake <h.mitake@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 995ee2bf46)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil f3e9893078 pflash_cfi01: Fix warning caused by unreachable code
Report from smatch:
hw/pflash_cfi01.c:431 pflash_write(180) info: ignoring unreachable code.

Instead of removing the return statement after the switch statement,
the patch replaces the return statements in the switch statement by
break statements. Other switch statements in the same code do it also
like that.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 12dabc79f9)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 4d0fcc1968 ioh3420: Remove unreachable code
Report from smatch:
hw/ioh3420.c:128 ioh3420_initfn(35) info: ignoring unreachable code.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 997f15672a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 2b9a5aca51 lm4549: Fix buffer overflow
Report from smatch:
lm4549.c:234 lm4549_write_samples(14) error:
 buffer overflow 's->buffer' 1024 <= 1024

There must be enough space to add two entries starting with index
s->buffer_level, therefore the old check was wrong.

[Peter Maydell <peter.maydell@linaro.org> clarifies the nature of the
analyser warning:

I don't object to making the change to placate the analyser,
but I don't think this is actually a buffer overrun. We always
add and remove samples from the buffer two at a time, so it's
not possible to get here with s->buffer_level == BUFFER_SIZE-1
(which is the only case where the old and new conditions
give different answers).]

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 8139626643)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 96d90d32ac cadence_uart: Fix buffer overflow
Report from smatch:
hw/cadence_uart.c:413 uart_read(13) error: buffer overflow 's->r' 18 <= 18

This fixes read access to s->r[R_MAX] which is behind the limits of s->r.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 5d40097fc0)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 3c980e22ac qemu-sockets: Fix potential memory leak
The old code leaks variable 'peer'.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 39b384591f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil 907a34c9d7 qemu-ga: Remove unreachable code after g_error
Report from smatch:
qemu-ga.c:117 register_signal_handlers(11) info: ignoring unreachable code.
qemu-ga.c:122 register_signal_handlers(16) info: ignoring unreachable code.

g_error calls abort which terminates the program.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit b548828862)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Stefan Weil b79ba45af1 audio: Fix warning from static code analysis
smatch report:
audio/audio_template.h:416 AUD_open_out(18) warn:
 variable dereferenced before check 'as' (see line 414)

Moving the ldebug statement after the statement which checks 'as'
fixes that warning.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 93b6599734)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Ronnie Sahlberg 75a44ae297 SCSI: Standard INQUIRY data should report HiSup flag as set.
QEMU as far as I know only reports LUN numbers using the modes that
are described in SAM4.
As such, since all LUN numbers generated by the SCSI emulation in QEMU
follow SAM4, we should set the HiSup bit in the standard INQUIRY data
to indicate such.

From SAM4:
  4.6.3 LUNs overview
  All LUN formats described in this standard are hierarchical in
  structure even when only a single level in that hierarchy is used.
  The HISUP bit shall be set to one in the standard INQUIRY data
  (see SPC-4) when any LUN format described in this standard is used.
  Non-hierarchical formats are outside the scope of this standard.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
(cherry picked from commit 1109c89405)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:20 -05:00
Paolo Bonzini ff498e4a0d scsi-disk: fix check for out-of-range LBA
This fix is needed to correctly handle 0-block read and writes.
Without it, a 0-block access at LBA 0 would underflow.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Paolo Bonzini 394a2f28cb scsi-disk: introduce check_lba_range
Abstract the test for an out-of-range (starting block, block count)
pair.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Ronnie Sahlberg 60088e5b83 iSCSI: We dont need to explicitely call qemu_notify_event() any more
We no longer need to explicitely call qemu_notify_event() any more
since this is now done automatically any time the filehandles we listen
to change.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 40a13ca8d2)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Ronnie Sahlberg ae06193d73 iSCSI: We need to support SG_IO also from iscsi_ioctl()
We need to support SG_IO from the synchronous iscsi_ioctl() since
scsi-block uses this to do an INQ to the device to discover its properties
This patch makes scsi-block work with iscsi.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit f1a12821d7)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Andreas Färber e8ca4a8ac7 MAINTAINERS: Add entry for QOM CPU
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit f2ca052414)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Aurelien Jarno 68958c31b5 pflash_cfi01: fix vendor specific extended query
pflash_cfi01 announces a version number of 1.1, which implies
"Protection Register Information" and "Burst Read information"
sections, which are not provided.

Decrease the version number to 1.0 so that only the "Protection
Register Information" section is needed.

Set the number of protection fields (0x3f) to 0x01, as 0x00 means 256
protections field, which makes the CFI table bigger than the current
implementation, causing some kernels to fail to read it.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Chris Wulff 584717a39a xilinx_timer: Fix a compile error if debug enabled
There was a missing include of qemu-log and a variable name in a printf was out
of date.

Signed-off-by: Chris Wulff <crwulff@gmail.com>
Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
(cherry picked from commit 8354cd722e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Peter A. G. Crosthwaite 85368b79a0 xilinx.h: Error check when setting links
Assert that the ethernet and dma controller are sucessfully linked to their
peers.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
(cherry picked from commit 4b5e52101f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Peter A. G. Crosthwaite 36d7fb299a xilinx_timer: Send dbg msgs to stderr not stdout
Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
(cherry picked from commit e03377ae75)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Peter A. G. Crosthwaite 3412955066 xilinx_timer: Removed comma in device name
Fixes an error in a61e4b07a3

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
(cherry picked from commit c0a1dcb9f0)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Peter Maydell b52c8f78f2 arch_init.c: Improve '-soundhw help' for non-HAS_AUDIO_CHOICE archs
For architectures which don't set HAS_AUDIO_CHOICE, improve the
'-soundhw help' message so that it doesn't simply print an empty
list, implying no sound support at all.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 55d4fd3c24)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
David Gibson 668194d5a5 cpu_physical_memory_write_rom() needs to do TB invalidates
cpu_physical_memory_write_rom(), despite the name, can also be used to
write images into RAM - and will often be used that way if the machine
uses load_image_targphys() into RAM addresses.

However, cpu_physical_memory_write_rom(), unlike cpu_physical_memory_rw()
doesn't invalidate any cached TBs which might be affected by the region
written.

This was breaking reset (under full emu) on the pseries machine - we loaded
our firmware image into RAM, and while executing it rewrite the code at
the entry point (correctly causing a TB invalidate/refresh).  When we
reset the firmware image was reloaded, but the TB from the rewrite was
still active and caused us to get an illegal instruction trap.

This patch fixes the bug by duplicating the tb invalidate code from
cpu_physical_memory_rw() in cpu_physical_memory_write_rom().

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 0b57e28713)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
David Gibson 8484fead29 qemu-char: BUGFIX, don't call FD_ISSET with negative fd
tcp_chr_connect(), unlike for example udp_chr_update_read_handler() does
not check if the fd it is using is valid (>= 0) before passing it to
qemu_set_fd_handler2().  If using e.g. a TCP serial port, which is not
initially connected, this can result in -1 being passed to FD_ISSET, which
has undefined behaviour.  On x86 it seems to harmlessly return 0, but on
PowerPC, it causes a fortify buffer overflow error to be thrown.

This patch fixes this by putting an extra test in tcp_chr_connect(), and
also adds an assert qemu_set_fd_handler2() to catch other such errors on
all platforms, rather than just some.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bbdd2ad081)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Anthony Liguori 57683d6354 Revert 455aa1e08 and c3767ed0eb
commit c3767ed0eb
    qemu-char: (Re-)connect for tcp_chr_write() unconnected writing

Has no hope of working because tcp_chr_connect() does not actually connect.

455aa1e08 just fixes the SEGV with server() but the attempt to connect a client
socket is still completely broken.

This patch reverts both.

Reported-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6db0fdce02)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:19 -05:00
Natanael Copa 5d6ad6262b configure: properly check if -lrt and -lm is needed
Fixes build against uClibc.

uClibc provides 2 versions of clock_gettime(), one with realtime
support and one without (this is so you can avoid linking in -lrt
unless actually needed). This means that the clock_gettime() don't
need -lrt. We still need it for timer_create() so we check for this
function in addition.

We also need check if -lm is needed for isnan().

Both -lm and -lrt are needed for libs_qga.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 8bacde8d86)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Yann E. MORIN a63eb7a227 configure: fix seccomp check
Currently, if libseccomp is missing but the user explicitly requested
seccomp support using --enable-seccomp, configure silently ignores the
situation and disables seccomp support.

This is unlike all other tests that explicitly fail in such situation.

Fix that.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit e84d5956cc)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi a638498f51 net: EAGAIN handling for net/socket.c TCP
Replace spinning send_all() with a proper non-blocking send.  When the
socket write buffer limit is reached, we should stop trying to send and
wait for the socket to become writable again.

Non-blocking TCP sockets can return in two different ways when the write
buffer limit is reached:

1. ret = -1 and errno = EAGAIN/EWOULDBLOCK.  No data has been written.

2. ret < total_size.  Short write, only part of the message was
   transmitted.

Handle both cases and keep track of how many bytes have been written in
s->send_index.  (This includes the 'length' header before the actual
payload buffer.)

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 45a7f54a8b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi 9d72a090b2 net: EAGAIN handling for net/socket.c UDP
Implement asynchronous send for UDP (or other SOCK_DGRAM) sockets.  If
send fails with EAGAIN we wait for the socket to become writable again.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 213fd5087e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi ab52df7712 net: asynchronous send/receive infrastructure for net/socket.c
The net/socket.c net client is not truly asynchronous.  This patch
borrows the qemu_set_fd_handler2() code from net/tap.c as the basis for
proper asynchronous send/receive.

Only read packets from the socket when the peer is able to receive.
This avoids needless queuing.

Later patches implement asynchronous send.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 863f678fba)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi 5c8240c09c net: broadcast hub packets if at least one port can receive
In commit 60c07d933c ("net: fix
qemu_can_send_packet logic") the "VLAN" broadcast behavior was changed
to queue packets if any net client cannot receive.  It turns out that
this was not actually the right fix and just hides the real bug that
hw/usb/dev-network.c:usbnet_receive() clobbers its receive buffer when
called multiple times in a row.  The commit also introduced a new bug
that "VLAN" packets would not be sent if one of multiple net clients was
down.

The hw/usb/dev-network.c bug has since been fixed, so this patch reverts
broadcast behavior to send packets as long as one net client can
receive.  Packets simply get queued for the net clients that are
temporarily unable to receive.

Reported-by: Roy.Li <rongqing.li@windriver.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 61518a74ca)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi d8f4811880 net: fix usbnet_receive() packet drops
The USB network interface has a single buffer which the guest reads
from.  This patch prevents multiple calls to usbnet_receive() from
clobbering the input buffer.  Instead we queue packets until buffer
space becomes available again.

This is inspired by virtio-net and e1000 rxbuf handling.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 190563f9a9)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi 2747a3eee3 net: clean up usbnet_receive()
The USB network interface has two code paths depending on whether or not
RNDIS mode is enabled.  Refactor usbnet_receive() so that there is a
common path throughout the function instead of duplicating everything
across if (is_rndis(s)) ... else ... code paths.

Clean up coding style and 80 character line wrap along the way.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit f237ddbb89)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi aa69dd05ce net: add -netdev options to man page
Document the -netdev syntax which supercedes the older -net syntax.
This patch is a first step to making -netdev prominent in the QEMU
manual.

Reported-by: Anatoly Techtonik <techtonik@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 08d12022c7)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi a9d8f7b1c4 net: do not report queued packets as sent
Net send functions have a return value where 0 means the packet has not
been sent and will be queued.  A non-zero value means the packet was
sent or an error caused the packet to be dropped.

This patch fixes two instances where packets are queued but we return
their size.  This causes callers to believe the packets were sent.  When
the caller uses the async send interface this creates a real problem
because the callback will be invoked for a packet that the caller
believed to be already sent.  This bug can cause double-frees in the
caller.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 06b5f36d05)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Stefan Hajnoczi 0d91cd5aa7 net: add receive_disabled logic to iov delivery path
This patch adds the missing NetClient->receive_disabled logic in the
sendv delivery code path.  It seems that commit
893379efd0 ("net: disable receiving if
client returns zero") only added the logic to qemu_deliver_packet() and
not qemu_deliver_packet_iov().

The receive_disabled flag should be automatically set when .receive(),
.receive_raw(), or .receive_iov() return 0.  No further packets will be
delivered to the NetClient until the receive_disabled flag is cleared
again by calling qemu_flush_queued_packets().

Typically the NetClient will wait until its file descriptor becomes
writable and then invoke qemu_flush_queued_packets() to resume
transmission.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit c67f5dc105)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Bo Yang bfa23099aa eepro100: Fix network hang when rx buffers run out
This is reported by QA. When installing os with pxe, after the initial
kernel and initrd are loaded, the procedure tries to copy files from install
server to local harddisk, the network becomes stall because of running out of
receive descriptor.

[Whitespace fixes and removed qemu_notify_event() because Paolo's
earlier net patches have moved it into qemu_flush_queued_packets().

Additional info:

I can reproduce the network hang with a tap device doing a iPXE HTTP
boot as follows:

  $ qemu -enable-kvm -m 1024 \
    -netdev tap,id=netdev0,script=no,downscript=no \
    -device i82559er,netdev=netdev0,romfile=80861209.rom \
    -drive if=virtio,cache=none,file=test.img
  iPXE> ifopen net0
  iPXE> config # set static network configuration
  iPXE> kernel http://mirror.bytemark.co.uk/fedora/linux/releases/17/Fedora/x86_64/os/images/pxeboot/vmlinuz

I needed a vanilla iPXE ROM to get to the iPXE prompt.  I think the boot
prompt has been disabled in the ROMs that ship with QEMU to reduce boot
time.

During the vmlinuz HTTP download there is a network hang.  hw/eepro100.c
has reached the end of the rx descriptor list.  When the iPXE driver
replenishes the rx descriptor list we don't kick the QEMU net subsystem
and event loop, thereby leaving the tap netdev without its file
descriptor in select(2).

Stefan Hajnoczi <stefanha@gmail.com>]

Signed-off-by: Bo Yang <boyang@suse.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 1069985fb1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Paolo Bonzini 65a2f8e27c xen: flush queue when getting an event
xen does not have a register that, when written, will cause can_receive
to go from false to true.  However, flushing the queue can be attempted
whenever the front-end raises its side of the Xen event channel.  There
is a single event channel for tx and rx.

Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Amos Kong <akong@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit a98b140223)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Paolo Bonzini 7575a6d2f2 e1000: flush queue whenever can_receive can go from false to true
When the guests replenish the receive ring buffer, the network device
should flush its queue of pending packets.  This is done with
qemu_flush_queued_packets.

e1000's can_receive can go from false to true when RCTL or RDT are
modified.

Reported-by: Luigi Rizzo <rizzo@iet.unipi.it>
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Cc: Jan Kiszka <jan.kiszka@siemens.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Amos Kong <akong@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit e8b4c680b4)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:18 -05:00
Paolo Bonzini 8e9fdc4a88 net: notify iothread after flushing queue
virtio-net has code to flush the queue and notify the iothread
whenever new receive buffers are added by the guest.  That is
fine, and indeed we need to do the same in all other drivers.
However, notifying the iothread should be work for the network
subsystem.  And since we are at it we can add a little smartness:
if some of the queued packets already could not be delivered,
there is no need to notify the iothread.

Reported-by: Luigi Rizzo <rizzo@iet.unipi.it>
Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Cc: Jan Kiszka <jan.kiszka@siemens.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Amos Kong <akong@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit 987a9b4800)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Igor Mitsyanko ca54dc1e75 arch_init.c: add missing '%' symbols before PRIu64 in debug printfs
'%' symbols were missing in front of PRIu64 macros in DPRINTF() messages in
arch_init.c, this caused compilation warnings when compiled with DEBUG_ARCH_INIT defined.

Signed-off-by: Igor Mitsyanko <i.mitsyanko@samsung.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit ef37a699a0)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Stefan Weil a78cedc09e kvm: Fix warning from static code analysis
Report from smatch:

kvm-all.c:1373 kvm_init(135) warn:
 variable dereferenced before check 's' (see line 1360)

's' cannot by NULL (it was alloced using g_malloc0), so there is no need
to check it here.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 6d1cc3210c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Lei Li 59a01f73c3 qapi: Fix enumeration typo error
Signed-off-by: Lei Li <lilei@linux.vnet.ibm.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
(cherry picked from commit 6932a69b20)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
BALATON Zoltan c6553fee81 console: Clean up bytes per pixel calculation
Division with round up is the correct way to compute this even if the
only case where division with round down gives incorrect result is
probably 15 bpp. This case was explicitely patched up in one of these
functions but was unhandled in the other. (I'm not sure about setting
16 bpp for the 15bpp case either but I left that there for now.)

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
(cherry picked from commit feadf1a4de)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Stefan Weil a0d718a395 Spelling fixes in comments and documentation
These wrong spellings were detected by codespell:

* successully -> successfully

* alot -> a lot

* wanna -> want to

* infomation -> information

* occured -> occurred

["also is" -> "is also" and "ressources" -> "resources" suggested by
Peter Maydell <peter.maydell@linaro.org>]

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Stefan Weil 34173da021 srp: Don't use QEMU_PACKED for single elements of a structured type
QEMU_PACKED results in a MinGW compiler warning when it is
used for single structure elements:

warning: 'gcc_struct' attribute ignored

Using QEMU_PACKED for the whole structure avoids the compiler warning
without changing the memory layout.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hervé Poussineau c23314334d slirp: Implement TFTP Blocksize option
This option is described in RFC 1783. As this is only an optional field,
we may ignore it in some situations and handle it in some others.

However, MS Windows 2003 PXE boot client requests a block size of the MTU
(most of the times 1472 bytes), and doesn't work if the option is not
acknowledged (with whatever value).

According to the RFC 1783, we cannot acknowledge the option with a bigger
value than the requested one.

As current implementation is using 512 bytes by block, accept the option
with a value of 512 if the option was specified, and don't acknowledge it
if it is not present or less than 512 bytes.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 95b1ad7ad8)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hervé Poussineau b83f395ba1 slirp: Handle more than 65535 blocks in TFTP transfers
RFC 1350 does not mention block count roll-over. However, a lot of TFTP servers
implement it to be able to transmit big files, so do it also.

Current block size is 512 bytes, so TFTP files were limited to 32 MB.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 4aa401f39e)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hervé Poussineau 34f7e690c3 slirp: improve TFTP performance
When transferring a file, keep it open during the whole transfer,
instead of opening/closing it for each block.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 78be056628)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Stefan Weil 6116adbc0e slirp: Fix error reported by static code analysis
Report from smatch:

slirp/tcp_subr.c:127 tcp_respond(17) error:
 we previously assumed 'tp' could be null (see line 124)

Return if 'tp' is NULL.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit e56afbc54a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Stefan Weil 3ed791b42d slirp: Remove wrong type casts ins debug statements
The type casts of pointers to long are not allowed
when sizeof(pointer) != sizeof(long).

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit c4d12a743c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hans de Goede 2ee160f8e1 uhci: Don't queue up packets after one with the SPD flag set
Don't queue up packets after a packet with the SPD (short packet detect)
flag set. Since we won't know if the packet will actually be short until it
has completed, and if it is short we should stop the queue.

This fixes a miniature photoframe emulating a USB cdrom with the windows
software for it not working.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hans de Goede 981e213cf7 usb-redir: Revert usb-redir part of commit 93bfef4c
Commit 93bfef4c6e makes qemu-devices
which report the qemu version string to the guest in some way use a
qemu_get_version function which reports a machine-specific version string.

However usb-redir does not expose the qemu version to the guest, only to
the usbredir-host as part of the initial handshake. This can then be logged
on the usbredir-host side for debugging purposes and is otherwise completely
unused! For debugging purposes it is important to have the real qemu version
in there, rather then the machine-specific version.

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

Conflicts:

	hw/usb/redirect.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hans de Goede d56d7e6ef8 ehci: Walk async schedule before and after migration
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit ceab6f9645)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Hans de Goede ad2cea3878 ehci: Don't set seen to 0 when removing unseen queue-heads
When removing unseen queue-heads from the async queue list, we should not
set the seen flag to 0, as this may cause them to be removed by
ehci_queues_rip_unused() during the next call to ehci_advance_async_state()
if the timer is late or running at a low frequency.

Note:
1) This *may* have caused the instant unlink / relinks described in commit
   9bc3a3a216

2) Rather then putting more if-s inside ehci_queues_rip_unused, this patch
   instead introduces a new ehci_queues_rip_unseen function.

3) This patch also makes it save to call ehci_queues_rip_unseen() multiple
   times, which gets used in the folluw up patch titled:
   "ehci: Walk async schedule before and after migration"

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:17 -05:00
Aurelien Jarno d28ed2ffbb configure: usbredir fixes
usbredir is only used by system emulation, so add the libraries to
libs_softmmu instead of LIBS.

Cc: Michael Tokarev <mjt@tls.msk.ru>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 56ab2ad177)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Alon Levy bffb221775 hw/qxl: tracing fixes
Add two new trace events:
qxl_send_events(int qid, uint32_t events) "%d %d"
qxl_set_guest_bug(int qid) "%d"

Change qxl_io_unexpected_vga_mode parameters to be equivalent to those
of qxl_io_write for easier grouping under a single systemtap probe.

Change d to qxl in one place.

Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 917ae08ca1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Dunrong Huang 9cf4af689b block: Don't forget to delete temporary file
The caller would not delete temporary file after failed get_tmp_filename().

Signed-off-by: Dunrong Huang <riegamaths@gmail.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit fe235a06e1)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Daniel P. Berrange f9f552e80b Don't require encryption password for 'qemu-img info' command
The encryption password is only required if I/O is going to be
performed on a disk image. The 'qemu-img info' command merely
reports metadata, so it should not ask for a decryption password

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit f0536bb848)

Conflicts:

	qemu-img.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Jason Baron 7cf7e305cc ahci: properly reset PxCMD on HBA reset
While testing q35, I found that windows 7 (specifically, windows 7 ultimate
with sp1 x64), wouldn't install because it can't find the cdrom or disk drive.
The failure message is: 'A required cd/dvd device driver is missing. If you
have a driver floppy disk, CD, DVD, or USB flash drive, please insert it now.'
This can also be reproduced on piix by adding an ahci controller, and
observing that windows 7 does not see any devices behind it.

The problem is that when windows issues a HBA reset, qemu does not reset the
individual ports' PxCMD register. Windows 7 then reads back the PxCMD register
and presumably assumes that the ahci controller has already been initialized.
Windows then never sets up the PxIE register to enable interrupts, and thus it
never gets irqs back when it sends ata device inquiry commands.

This change brings qemu into ahci 1.3 specification compliance.

Section 10.4.3 HBA Reset:

"
When GHC.HR is set to '1', GHC.AE, GHC.IE, the IS register, and all port
register fields (except PxFB/PxFBU/PxCLB/PxCLBU) that are not HwInit in the
HBA's register memory space are reset.
"

I've also re-tested Fedora 16 and 17 to verify that they continue to work with
this change.

Signed-off-by: Jason Baron <jbaron@redhat.com>
Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 2a4f4f34e6)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Pavel Hrdina 84a2ca9f90 block: fix block tray status
The tray status should change also if you eject empty block device.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Stefan Weil 1c224f0ab3 vdi: Fix warning from clang
ccc-analyzer reports these warnings:

block/vdi.c:704:13: warning: Dereference of null pointer
            bmap[i] = VDI_UNALLOCATED;
            ^
block/vdi.c:702:13: warning: Dereference of null pointer
            bmap[i] = i;
            ^

Moving some code into the if block fixes this.
It also avoids calling function write with 0 bytes of data.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Stefan Weil 1e32a1651a block/curl: Fix wrong free statement
Report from smatch:
block/curl.c:546 curl_close(21) info: redundant null check on s->url calling free()

The check was redundant, and free was also wrong because the memory
was allocated using g_strdup.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Stefan Weil 3900d1d992 ide: Fix error messages from static code analysis (no real error)
Report from smatch:
hw/ide/core.c:1472 ide_exec_cmd(423) error: buffer overflow 'smart_attributes' 8 <= 29
hw/ide/core.c:1474 ide_exec_cmd(425) error: buffer overflow 'smart_attributes' 8 <= 29
hw/ide/core.c:1475 ide_exec_cmd(426) error: buffer overflow 'smart_attributes' 8 <= 29
...

The upper limit of 30 was never reached because both for loops terminated
when 'smart_attributes' reached end of list, so there was no real buffer
overflow.

Nevertheless, changing the code not only fixes the error report, but also
reduces the size of smart_attributes and simplifies the for loops.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
MORITA Kazutaka 1fce4135f3 sheepdog: fix savevm and loadvm
This patch sets data to be sent to Sheepdog correctly and fixes savevm
and loadvm operations on a Sheepdog image.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Hans de Goede 349b4e9070 ehci: Don't process too much frames in 1 timer tick (v2)
The Linux ehci isoc scheduling code fills the entire schedule ahead of
time minus 80 frames. If we make a large jump in where we are in the
schedule, ie 40 frames, then the scheduler all of a sudden will only have
40 frames left to work in, causing it to fail packet submissions
with error -27 (-EFBIG).

Changes in v2:
-Don't hardcode a maximum number of frames to process in one tick, instead:
 -Process a minimum number of frames to ensure we do eventually catch up
 -Stop (after the minimum number) when the guest has requested an irq

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Hans de Goede 29ecaa26a8 ehci: Fix interrupts stopping when Interrupt Threshold Control is 8
If Interrupt Threshold Control is 8 or a multiple of 8, then
s->usbsts_frindex can become exactly 0x4000, at which point
(s->usbsts_frindex > s->frindex) will never become true, as
s->usbsts_frindex will not be lowered / reset in this case.

This patch fixes this.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Gerd Hoffmann 1f97f6c9fe ehci: switch to new-style memory ops
Also register different memory regions for capabilities,
operational registers and port status registers.  Create
separate tracepoints for operational regs and port status
regs.  Ditch a bunch of sanity checks because the memory
core will do this for us now.

Offloading the byte, word and dword access handling to the
memory core also has the side effect of fixing ehci register
access on bigendian hosts.

Cc: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 3e4f910c8d)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:16 -05:00
Uri Lublin 9a5a94de58 qxl: better cleanup for surface destroy
Add back a call to qxl_spice_destroy_surface_wait_complete() in qxl_spice_destroy_surface_wait(),
that was removed by commit c480bb7da4

It is needed to complete surface-removal cleanup, for non async.
For async, qxl_spice_destroy_surface_wait_complete is called upon operation completion.

Signed-off-by: Uri Lublin <uril@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 753b8b0d77)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Gerd Hoffmann 462ff6fda1 usb-host: allow emulated (non-async) control requests without USBPacket
xhci needs this for USB_REQ_SET_ADDRESS due to the way
usb addressing is handled by the xhci hardware.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Dunrong Huang b26859ab18 qxl: dont update invalid area
This patch fixes the following error:

$ ~/usr/bin/qemu-system-x86_64 -enable-kvm -m 1024 -spice port=5900,disable-ticketing -vga qxl -cdrom ~/Images/linuxmint-13-mate-dvd-32bit.iso
(/home/mathslinux/usr/bin/qemu-system-x86_64:10068): SpiceWorker-CRITICAL **: red_worker.c:4599:red_update_area: condition `area->left >= 0 && area->top >= 0 && area->left < area->right && area->top < area->bottom' failed
Aborted

spice server terminates QEMU process if we pass invalid area to it,
so dont update those invalid areas.

Signed-off-by: Dunrong Huang <riegamaths@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit ccc2960d65)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Gerd Hoffmann 03c0342cb8 xhci: allow bytewise capability register reads
Some guests need this according to
Alejandro Martinez Ruiz <alex@securiforest.com>

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

Conflicts:

	hw/usb/hcd-xhci.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Gerd Hoffmann 23ba9d4838 xhci: fix runtime write tracepoint
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 8e9f18b6db)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Gerd Hoffmann 640bda8df5 xhci: drop buffering
This patch splits the xhci_xfer_data function into three.
The xhci_xfer_data function used to do does two things:

  (1) copy transfer data between guest memory and a temporary buffer.
  (2) report transfer results to the guest using events.

Now we three functions to handle this:

  (1) xhci_xfer_map creates a scatter list for the transfer and
      uses that (instead of the temporary buffer) to build a
      USBPacket.
  (2) xhci_xfer_unmap undoes the mapping.
  (3) xhci_xfer_report sends out events.

The patch also fixes reporting of transaction errors which must be
reported unconditinally, not only in case the guest asks for it
using the ISP flag.

[ v2: fix warning ]

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Gerd Hoffmann 64022e9d58 xhci: rip out background transfer code
original xhci code (the one which used libusb directly) used to use
'background transfers' for iso streams.  In upstream qemu the iso
stream buffering is handled by usb-host & usb-redir, so we will
never ever need this.  It has been left in as reference, but is dead
code anyway.  Rip it out.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Gerd Hoffmann 3e3750e10a usb-audio: fix usb version
usb-audio is a full speed (1.1) device,
but bcdUSB claims it is usb 2.0.  Fix it.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Samuel Thibault fbcb89ddc9 Better name usb braille device
Windows users need to know that they have to use the Baum driver to make
the qemu braille device work.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 2964cd9bfa)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Hans de Goede 22ba7a7488 usb-redir: Return babble when getting more bulk data then requested
Babble is the appropriate error in this case (rather then signalling a stall).

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Hans de Goede 636071de92 usb-redir: Move to core packet id and queue handling
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit de550a6afb)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Hans de Goede 55a2f465b9 usb-redir: Get rid of unused async-struct dev member
This is a preparation patch for completely getting rid of the async-packet
struct in usb-redir, instead relying on the (new) per ep queues in the
qemu usb core.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Hans de Goede aa57b628e0 usb-redir: Get rid of local shadow copy of packet headers
The shadow copy only serves as an extra check (besides the packet-id) to
ensure the packet we get back is a reply to the packet we think it is.

This check has never triggered in all the time usb-redir is in use now,
and since the verified data in the returned packet-header is not used
otherwise, removing the check does not open any possibilities for the
usbredirhost to confuse us.

This is a preparation patch for completely getting rid of the async-packet
struct in usb-redir, instead relying on the (new) per ep queues in the
qemu usb core.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:15 -05:00
Hans de Goede 57eae744d4 usb-redir: Get rid of async-struct get member
This is a preparation patch for completely getting rid of the async-packet
struct in usb-redir, instead relying on the (new) per ep queues in the
qemu usb core.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 14ecfb09fa usb-redir: Don't delay handling of open events to a bottom half
There is no need for this, and doing so means that a backend trying to
write immediately after an open event will see qemu_chr_be_can_write
returning 0, which not all backends handle well as there is no wakeup
mechanism to detect when the frontend does become writable.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 1d5ba9a6a8 usb-redir: Never return USB_RET_NAK for async handled packets
USB_RET_NAK is not a valid response for async handled packets (and will
trigger an assert as such).

Also drop the warning when receiving a status of cancelled for packets not
cancelled by qemu itself, this can happen when a device gets unredirected
by the usbredir-host while transfers are pending.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 77c3d59256 ehci: Correct a comment in fetchqtd packet processing
Since my previous comment said "Should never happen", I tried changing the
next line to an assert(0), which did not go well, which as the new comments
explains is logical if you think about it for a moment.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede e2ab86fe2d ehci: Handle USB_RET_PROCERR in ehci_fill_queue
USB_RET_PROCERR can be triggered by the guest (by for example requesting more
then BUFFSIZE bytes), so don't assert on it.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 2f7ba4731b ehci: Fix memory leak in handling of NAK-ed packets
Currently each time we try to execute a NAK-ed packet we redo
ehci_init_transfer, and usb_packet_map, re-allocing (without freeing) the
sg list every time.

This patch fixes this, it does this by introducing another async state, so
that we also properly cleanup a NAK-ed packet on cancel.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 0154d330c7 ehci: Add some additional ehci_trace_guest_bug() calls
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 3a8ca08e01)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Gerd Hoffmann d294ad6323 ehci: add doorbell trace events
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 1defcbd1e8)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Gerd Hoffmann 62fc5e6983 ehci: trace guest bugs
make qemu_queue_{cancel,reset} return the number of packets released,
so the caller can figure whenever there have been active packets even
though there shouldn't have been any.  Add tracepoint to log this.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Gerd Hoffmann 4a6cdb4807 ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet
Otherwise we'll see the packet free twice in the trace log even though
it actually happens only once.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede a8cf10d5d6 ehci: Properly report completed but not yet processed packets to the guest
Reported packets which have completed before being cancelled as such to the
host. Note that the new code path this patch adds is untested since it I've
been unable to actually trigger the race which needs this code path.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 4b63a0df3b)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 307fea863a ehci: Properly cleanup packets on cancel
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 0e7953525f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede c15d61b252 ehci: Update copyright headers to reflect recent work
Update copyright headers to reflect all the work Gerd and I have been doing
on the EHCI emulation.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 522079dd44)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:14 -05:00
Hans de Goede 712fc762a6 ehci: Validate qh is not changed unexpectedly by the guest
-combine the qh check with the check for devaddr changes
-also ensure that p gets set to NULL when the queue gets cancelled on
 devaddr change, which was not done properly before this patch

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit dafe31fc2a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Hans de Goede a37d5e521a Revert "ehci: don't flush cache on doorbell rings."
This reverts commit 9bc3a3a216, which got
added to fix an issue where the real, underlying cause was not stopping
the ep queue on an error.

Now that the underlying cause is fixed by the "usb: Halt ep queue and
cancel pending packets on a packet error" patch, the "don't flush" fix
is no longer needed.

Not only is it not needed, it causes us to see cancellations (unlinks)
done by the Linux EHCI driver too late, which in combination with the new
usb-core packet-id generation where qtd addresses are used as ids, causes
duplicate ids for in flight packets.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 66f092d256)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Hans de Goede d6e508d3a5 usb-core: Allow the first packet of a pipelined ep to complete immediately
This can happen with usb-redir live-migration when the packet gets re-queued
after the migration and the original queuing from the migration source side
has already finished.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Hans de Goede d780116ab0 usb-core: Add a usb_ep_find_packet_by_id() helper function
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit c13a9e6136)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Hans de Goede 597330bd8d usb-core: Don't set packet state to complete on a nak
This way the hcd can re-use the same packet to retry without needing
to re-init it.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Hans de Goede 4ebbf3229a usb: controllers do not need to check for babble themselves
If an (emulated) usb-device tries to write more data to a packet then
its iov len, this will trigger an assert in usb_packet_copy(), and if
a driver somehow circumvents that check and writes more data to the
iov then there is space, we have a much bigger problem then not correctly
reporting babble to the guest.

In practice babble will only happen with (real) redirected devices, and there
both the usb-host os and the qemu usb-device code already check for it.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Daniel P. Berrange b5701820f8 Add ability to force enable/disable of tools build
The qemu-img, qemu-nbd and qemu-io tools are built conditionally
based on whether any softmmu target is enabled. These are useful
self-contained tools which can be used in many other scenarios.
Add new --enable-tools/--disable-tools args to configure to allow
the user to explicitly turn on / off their build. The default
behaviour is now to build these tools are all times, regardless
of whether any softmmu target is enabled

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-11 21:44:13 -05:00
Anthony Liguori 5af6b07ab0 socket: don't attempt to reconnect a TCP socket in server mode
Commit c3767ed0eb introduced a possible SEGV when
using a socket chardev with server=on because it assumes that all TCP sockets
are in client mode.

This patch adds a check to only reconnect when in client mode.

Cc: Lei Li <lilei@linux.vnet.ibm.com>
Reported-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 455aa1e081)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Michael Tokarev 82645b9e93 use --libexecdir instead of ignoring it first and reinventing it later
Commit 7b93fadf3a "Add basic version
of bridge helper" put the bridge helper executable into a fixed
${prefix}/libexec/ location, instead of using ${libexecdir} for
this.  At the same time, --libexecdir is being happily ignored
by ./configure.  Even more, the same patch sets unused $libexecdir
variable in the generated config-host.mak, and uses fixed string
(\${prefix}/libexecdir) for the bridge helper binary.

Fix this braindamage by introducing $libexecdir variable, using
it for the bridge helper binary, and recognizing --libexecdir.

This patch is applicable to stable-1.1.

Reviewed-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Cc: Corey Bryant <coreyb@linux.vnet.ibm.com>
Cc: Richa Marwaha <rmarwah@linux.vnet.ibm.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 8bf188aa18)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Stefan Weil b750d22466 hw/mcf5206: Fix buffer overflow for MBAR read / write
Report from smatch:

mcf5206.c:384 m5206_mbar_readb(7) error: buffer overflow 'm5206_mbar_width' 128 <= 128
mcf5206.c:403 m5206_mbar_readw(8) error: buffer overflow 'm5206_mbar_width' 128 <= 128
mcf5206.c:427 m5206_mbar_readl(8) error: buffer overflow 'm5206_mbar_width' 128 <= 128
mcf5206.c:451 m5206_mbar_writeb(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128
mcf5206.c:475 m5206_mbar_writew(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128
mcf5206.c:503 m5206_mbar_writel(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128

m5206_mbar_width has 0x80 elements and supports 0 <= offset < 0x200.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit a32354e206)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Stefan Weil bd4dba6658 hw/wm8750: Fix potential buffer overflow
Report from smatch:

hw/wm8750.c:369 wm8750_tx(12) error: buffer overflow 's->i2c_data' 2 <= 2

It looks like the preprocessor statements were simply misplaced.

Replace also __FUNCTION__ by __func__ to please checkpatch.pl.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 149eeb5fe5)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Christian Borntraeger 7566759fd5 qemu: Use valgrind annotations to mark kvm guest memory as defined
valgrind with kvm produces a big amount of false positives regarding
"Conditional jump or move depends on uninitialised value(s)". This
happens because the guest memory is allocated with qemu_vmalloc which
boils down posix_memalign etc. This function is (correctly) considered
by valgrind as returning undefined memory.

Since valgrind is based on jitting code, it will not be able to see
changes made by the guest to guest memory if this is done by KVM_RUN,
thus keeping most of the guest memory undefined.

Now lots of places in qemu will then use guest memory to change behaviour.
To avoid the flood of these messages, lets declare the whole guest
memory as defined. This will reduce the noise and allows us to see real
problems.

In the future we might want to make this conditional, since there
is actually something that we can use those false positives for:
These messages will point to code that depends on guest memory, so
we can use these backtraces to actually make an audit that is focussed
only at those code places. For normal development we dont want to
see those messages, though.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 62fe83318d)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Jan Kiszka 47b11da1e9 musicpal: Fix flash mapping
The old arithmetic assumed 32 physical address bits which is no longer
true for ARM since 3cc0cd61f4.

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 0c267217ca)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Fabien Chouteau 2ecd8831e0 Add MAINTAINERS entry for leon3
Signed-off-by: Fabien Chouteau <chouteau@adacore.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit ce6c760c37)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Maciej W. Rozycki 27aae39fa0 MIPS/user: Fix reset CPU state initialization
This change updates the CPU reset sequence to use a common piece of code
that figures out CPU state flags, fixing the problem with MIPS_HFLAG_COP1X
not being set where applicable that causes floating-point MADD family
instructions (and other instructions from the MIPS IV FP subset) to trap.

 As compute_hflags is now shared between op_helper.c and translate.c, the
function is now moved to a common header.  There are no changes to this
function.

 The problem was seen with the 24Kf MIPS32r2 processor in user emulation.
The new approach prevents system and user emulation from diverging -- all
the hflags state is initialized in one place now.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 03e6e50177)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Aurelien Jarno 635cc81bf9 lan9118: fix multicast filtering
The lan9118 emulation tries to compute the multicast index by calling
directly the crc32() function from zlib, but fails to get the correct
result.

Use the common compute_mcast_idx() function instead, which gives the
correct result. This fixes IPv6 support.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:30 -05:00
Henning Schild 4de6467cbc fix entry pointer for ELF kernels loaded with -kernel option
Find a hopefully proper patch attached. Take it or leave it.

Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Henning Schild <henning@hennsch.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 7e9c7ffe9f)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Jason Baron 4382057785 pcie_aer: clear cmask for Advanced Error Interrupt Message Number
The Advanced Error Interrupt Message Number (bits 31:27 of the Root
Error Status Register) is updated when the number of msi messages assigned to a
device changes. Migration of windows 7 on q35 chipset failed because the check
in get_pci_config_device() fails due to cmask being set on these bits. Its valid
to update these bits and we must restore this state across migration.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Jason Baron 6ac46e3216 pcie: drop version_id field for live migration
While testing q35 live migration, I found that the migration would abort with
the following error: "Unknown savevm section type 76".

The error is due to this check failing in 'vmstate_load_state()':

    while(field->name) {
        if ((field->field_exists &&
             field->field_exists(opaque, version_id)) ||
            (!field->field_exists &&
             field->version_id <= version_id)) {

The VMSTATE_PCIE_DEVICE() currently has a 'version_id' set to 2. However,
'version_id' in the above check is 1. And thus we fail to load the pcie device
field. Further the code returns to 'qemu_loadvm_state()' which produces the
error that I saw.

I'm proposing to fix this by simply dropping the 'version_id' field from
VMSTATE_PCIE_DEVICE(). VMSTATE_PCI_DEVICE() defines no such field and further
the vmstate_pcie_device that VMSTATE_PCI_DEVICE() refers to is already
versioned. Thus, any versioning issues could be detected at the vmsd level.

Taking a step back, I think that the 'field->version_id' should be compared
against a saved version number for the field not the 'version_id'. Futhermore,
once vmstate_load_state() is called recursively on another vmsd, the check of:

    if (version_id > vmsd->version_id) {
        return -EINVAL;
    }

Will never fail since version_id is always equal to vmsd->version_id. So I'm
wondering why we aren't storing the vmsd version id of the source in the
migration stream?

This patch also renames the 'name' field of vmstate_pcie_device from:
PCIDevice -> PCIEDevice to differentiate it from vmstate_pci_device.

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Stefan Weil 3aec24d195 json-parser: Fix potential NULL pointer segfault
Report from smatch:
json-parser.c:474 parse_object(62) error: potential null derefence 'dict'.
json-parser.c:553 parse_array(75) error: potential null derefence 'list'.

Label 'out' in json-parser.c can be called with list == NULL
which is passed to QDECREF.

Modify QDECREF to handle a NULL argument (inline function qobject_decref
already handles them, too).

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 149474c934)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Stefan Weil 122b92d90a qapi: Fix potential NULL pointer segfault
Report from smatch:

qapi-visit.c:1640 visit_type_BlockdevAction(8) error:
 we previously assumed 'obj' could be null (see line 1639)
qapi-visit.c:2432 visit_type_NetClientOptions(8) error:
 we previously assumed 'obj' could be null (see line 2431)

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 227ccf6bff)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Amos Kong 23086b2054 fix doc of using raw values with sendkey
(qemu) sendkey a
(qemu) sendkey 0x1e
(qemu) sendkey #0x1e
 unknown key: '#0x1e'

The last command doesn't work, '#' is not requested before
raw values, and the raw value in decimal format is not supported.

Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 886cc706ce)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Alon Levy ea4c86551d configure: print spice-protocol and spice-server versions
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 2e0e3c399a)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Alon Levy b75c710575 qxl: add QXL_IO_MONITORS_CONFIG_ASYNC
Revision bumped to 4 for new IO support, enabled for spice-server >=
0.11.1. New io enabled if revision is 4. Revision can be set to 4.

[ kraxel: 3 continues to be the default revision.  Once we have a new
          stable spice-server release and the qemu patches to enable
          the new bits merged we'll go flip the switch and make rev4
          the default ]

This io calls the corresponding new spice api
spice_qxl_monitors_config_async to let spice-server read a new guest set
monitors config and notify the client.

On migration reissue spice_qxl_monitors_config_async.

RHBZ: 770842

Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

fixup

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

Conflicts:

	hw/qxl.c

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Alon Levy 5b7582af06 qxl/update_area_io: guest_bug on invalid parameters
Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 511b13e2c9)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Yonit Halperin 615198836c spice: increase the verbosity of spice section in "qemu --help"
Added all spice options to the help string. This can be used by libvirt
to determine which spice related features are supported by qemu.

Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 27af778828)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Yonit Halperin 7908e4a388 spice: adding seamless-migration option to the command line
The seamless-migration flag is required in order to identify
whether libvirt supports the new QEVENT_SPICE_MIGRATE_COMPLETED or not
(by default the flag is off).
New libvirt versions that wait for QEVENT_SPICE_MIGRATE_COMPLETED should turn on this flag.
When this flag is off, spice fallbacks to its old migration method, which
can result in data loss.

Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 8c9570530c)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Yonit Halperin 38a01d68c6 spice: add 'migrated' flag to spice info
The flag is 'true' when spice migration has completed on the src side.
It is needed for a case where libvirt dies before migration completes
and it misses the event QEVENT_SPICE_MIGRATE_COMPLETED.
When libvirt is restored and queries the migration status, it also needs
to query spice and check if its migration has completed.

Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 61c4efe2cb)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:29 -05:00
Yonit Halperin 986b9a1a2a spice migration: add QEVENT_SPICE_MIGRATE_COMPLETED
When migrating, libvirt queries the migration status, and upon migration
completions, it closes the migration src. On the other hand, when
migration is completed, spice transfers data from the src to destination
via the client. This data is required for keeping the spice session
after migration, without suffering from data loss and inconsistencies.
In order to allow this data transfer, we add QEVENT for signaling
libvirt that spice migration has completed, and libvirt needs to wait
for this event before quitting the src process.

Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 2fdd16e239)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:28 -05:00
Yonit Halperin 25bc2251eb spice: notify on vm state change only via spice_server_vm_start/stop
QXLWorker->start/stop are deprecated since spice-server 0.11.2

Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 71d388d420)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:28 -05:00
Yonit Halperin fc24f3bd2e spice: notify spice server on vm start/stop
Spice server needs to know about the vm state in order to prevent
attempts to write to devices when they are stopped, mainly during
the non-live stage of migration.
Instead, spice will take care of restoring this writes, on the migration
target side, after migration completes.

Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit f5bb039c6d)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:28 -05:00
Christophe Fergeau 3c82758f04 spice: abort on invalid streaming cmdline params
When parsing its command line parameters, spice aborts when it
finds unexpected values, except for the 'streaming-video' option.
This happens because the parsing of the parameters for this option
is done using the 'name2enum' helper, which does not error out
on unknown values. Using the 'parse_name' helper makes sure we
error out in this case. Looking at git history, the use of
'name2enum' instead of 'parse_name' seems to have been an oversight,
so let's change to that now.

Fixes rhbz#831708

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

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:58:28 -05:00
Stefan Weil 7fd494086b tci: Fix for AREG0 free mode
Support for helper functions with 5 arguments was missing
in the code generator and in the interpreter.

There is no need to pass the constant TCG_AREG0 from the
code generator to the interpreter. Remove that code for
the INDEX_op_qemu_st* opcodes.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Stefan Weil e46258fb50 tcg: Fix MAX_OPC_PARAM_IARGS
DEF_HELPER_FLAGS_5 was added some time ago without adjusting
MAX_OPC_PARAM_IARGS.

Fixing the definition becomes more important as QEMU is using
an increasing number of helper functions called with 5 arguments.

Add also a comment to avoid future problems when DEF_HELPER_FLAGS_6
will be added.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Aurelien Jarno c90a8840b4 tcg/i386: fix build with -march < i686
The movcond_i32 op has to be protected with TCG_TARGET_HAS_movcond_i32
to fix the build with -march < i686.

Thanks to Richard Henderson for the hint.

Reported-by: Alex Barcelo <abarcelo@ac.upc.edu>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Richard Henderson e1312991ed tcg: Adjust descriptions of *cond opcodes
The README file documented the operand ordering of the tcg_gen_*
functions.  Since we're documenting opcodes here, use the true
operand ordering.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Cc: malc <av1474@comtv.ru>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Aurelien Jarno 6c975d03a2 tcg/mips: fix MIPS32(R2) detection
Fix the MIPS32(R2) cpu detection so that it also works with
-march=octeon. Thanks to Andrew Pinski for the hint.

Cc: Andrew Pinski <apinski@cavium.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Richard Henderson df6502fac5 target-alpha: Initialize env->cpu_model_str
Save the cpu_model_str so that we have a non-null value when
creating a new cpu during clone.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Richard Henderson fef28a4336 tcg-sparc: Preserve branch destinations during retranslation
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:11 -05:00
Richard Henderson 38df9027ce tcg-sparc: Fix and enable direct TB chaining.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson ba8b16fac5 tcg-sparc: Add %g/%o registers to alloc_order
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson 39cbcb4b45 tcg-sparc: Use defines for temporaries.
And change from %i4/%i5 to %g1/%o7 to remove a v8plus fixme.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson db0cfd14ba tcg-sparc: Mask shift immediates to avoid illegal insns.
The xtensa-test image generates a sra_i32 with count 0x40.
Whether this is accident of tcg constant propagation or
originating directly from the instruction stream is immaterial.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson 5c7199f164 tcg-sparc: Clean up cruft stemming from attempts to use global registers.
Don't use -ffixed-gN.  Don't link statically.  Don't save/restore
AREG0 around calls.  Don't allocate space on the stack for AREG0 save.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson 60db655378 tcg-sparc: Change AREG0 in generated code to %i0.
We can now move the TCG variable from %g[56] to a call-preserved
windowed register.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson 757ee3f9e2 tcg-sparc: Support GUEST_BASE.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson e85ec822e9 tcg-sparc: Fix qemu_ld/st to handle 32-bit host.
At the same time, split out the tlb load logic to a new function.
Fixes the cases of two data registers and two address registers.
Fixes the signature of, and adds missing, qemu_ld/st opcodes.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson 181dd0b27c tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
Current code doesn't actually work in 32-bit mode at all.  Since
no one really noticed, drop the complication of v7 and v8 cpus.
Eliminate the --sparc_cpu configure option and standardize macro
testing on TCG_TARGET_REG_BITS / HOST_LONG_BITS

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson e1784a4cbd tcg-sparc: Don't MAP_FIXED on top of the program
The address we pick in sparc64.ld is also 0x60000000, so doing a fixed map
on top of that is guaranteed to blow up.  Choosing 0x40000000 is exactly
right for the max of code_gen_buffer_size set below.

No need to ever use MAP_FIXED.  While getting our desired address helps
optimize the generated code, we won't fail if we don't get it.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson e183eb99fa tcg-sparc: Fix ADDX opcode.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Richard Henderson ee13de2853 tcg-sparc: Hack in qemu_ld/st64 for 32-bit.
Not actually implemented, but at least we avoid the tcg assert at startup.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
malc 6164c1274e tcg/ppc32: Implement movcond32
Thanks to Richard Henderson

Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Stefan Weil a48028b8e9 w64: Fix TCG helper functions with 5 arguments
TCG uses 6 registers for function arguments on 64 bit Linux hosts,
but only 4 registers on W64 hosts.

Commit 2999a0b200 increased the number
of arguments for some important helper functions from 4 to 5
which triggered a bug for W64 hosts: QEMU aborts when executing
helper_lcall_real in the guest's BIOS because function
tcg_target_get_call_iarg_regs_count always returned 6.

As W64 has only 4 registers for arguments, the 5th argument must be
passed on the stack using a correct stack offset.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Max Filippov 5096a7c7d8 tcg/README: document tcg_gen_goto_tb restrictions
See
http://lists.nongnu.org/archive/html/qemu-devel/2012-09/msg03196.html
for the whole story.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Aurelien Jarno 2e1d09263b tcg/optimize: add constant folding for deposit
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Aurelien Jarno ffc1c56815 tcg: remove #ifdef #endif around TCGOpcode tests
Commit 25c4d9cc changed all TCGOpcode enums to be available, so we don't
need to #ifdef #endif the one that are available only on some targets.
This makes the code easier to read.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Aurelien Jarno cfca711212 tcg/optimize: prefer the "op a, a, b" form for commutative ops
The "op a, a, b" form is better handled on non-RISC host than the "op
a, b, a" form, so swap the arguments to this form when possible, and
when b is not a constant.

This reduces the number of generated instructions by a tiny bit.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Aurelien Jarno 26adaf07da tcg/optimize: further optimize brcond/movcond/setcond
When both argument of brcond/movcond/setcond are the same or when one
of the two values is a constant equal to zero, it's possible to do
further optimizations.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:10 -05:00
Aurelien Jarno f4643451e9 tcg/optimize: optimize "op r, a, a => movi r, 0"
Now that it's possible to detect copies, we can optimize the case
the "op r, a, a => movi r, 0". This helps in the computation of
overflow flags when one of the two args is 0.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno d3b9fb75c6 tcg/optimize: optimize "op r, a, a => mov r, a"
Now that we can easily detect all copies, we can optimize the
"op r, a, a => mov r, a" case a bit more.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 6599e3faae tcg/optimize: do copy propagation for all operations
It is possible to due copy propagation for all operations, even the one
that have side effects or clobber arguments (it only concerns input
arguments). That said, the call operation should be handled differently
due to the variable number of arguments.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno a17f24e08d tcg/optimize: rework copy progagation
The copy propagation pass tries to keep track what is a copy of what
and what has copy of what, and in addition it keep a circular list of
of all the copies. Unfortunately this doesn't fully work: a mov from
a temp which has a state "COPY" changed it into a state "HAS_COPY".
Later when this temp is used again, it is considered has not having
copy and thus no propagation is done.

This patch fixes that by removing the hiearchy between copies, and thus
only keeping a "COPY" state both meaning "is a copy" and "has a copy".
The decision of which copy to use is deferred to the actual temp
replacement. At this stage there is not one best choice to do, but only
better choices than others. For doing the best choice the operation
would have to be parsed in reversed to know if a temp is going to be
used later or not. That what is done by the liveness analysis. At this
stage it is known that globals will be always live, that local temps
will be dead at the end of the translation block, and that the temps
will be dead at the end of the basic block. This means that this stage
should try to replace temps by local temps or globals and local temps
by globals.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno a4c701ee76 tcg/optimize: check types in copy propagation
The copy propagation doesn't check the types of the temps during copy
propagation. However TCG is using the mov_i32 for the i64 to i32
conversion and thus the two are not equivalent.

With this patch tcg_opt_gen_mov() doesn't consider two temps of
different type as copies anymore.

So far it seems the optimization was not aggressive enough to trigger
this bug, but it will be triggered later in this series once the copy
propagation is improved.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno ad797145ae tcg/optimize: remove TCG_TEMP_ANY
TCG_TEMP_ANY has no different meaning than TCG_TEMP_UNDEF, so use
the later instead.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 7ef9bee924 tcg/mips: implement movcond op on MIPS32R2
movcond operation can be implemented on MIPS32 Release 2 using the MOVN,
MOVZ, SLT and SLTU instructions.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 6d82e71b6a tcg/mips: implement deposit op on MIPS32R2
deposit operations can be optimized on MIPS32 Release 2 using the INS
instruction.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno a8067da5d1 tcg/mips: implement rotl/rotr ops on MIPS32R2
rotr operations can be optimized on MIPS32 Release 2 using the ROTR and
ROTRV instructions. Also implemented rotl operations by subtracting the
shift from 32.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 3b63392482 tcg/mips: optimize bswap{16,16s,32} on MIPS32R2
bswap operations can be optimized on MIPS32 Release 2 using the ROTR,
WSBH and SEH instructions. We can't use the non-R2 code to implement the
ops due to registers constraints, so don't define the corresponding
TCG_TARGET_HAS_bswap* values.

Also bswap16* operations are supposed to be called with the 16 high bits
zeroed. This is the case everywhere (including for TCG by definition)
except when called from the store helper. Remove the AND instructions from
bswap16* and move it there.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 86b4f7ca05 tcg/mips: optimize brcond arg, 0
MIPS has some conditional branch instructions when comparing with zero.
Use them.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno adf89e7483 tcg/mips: use stack for TCG temps
Use stack instead of temp_buf array in CPUState for TCG
temps.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 8193cdd0d0 tcg/mips: don't use global pointer
Don't use the global pointer in TCG, in case helpers try access global
variables.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno f25f0d7751 tcg/mips: use TCGArg or TCGReg instead of int
Instead of int, use the correct TCGArg and TCGReg type: TCGReg when
representing a TCG target register, TCGArg when representing the latter
or a constant.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno b7505cfd52 tcg/mips: kill warnings in user mode
Recent versions of GCC emit warnings when compiling user mode targets.
Kill them by reordering a bit the #ifdef.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno df3e097e21 tcg-mips: fix wrong usage of 'Z' constraint
The 'Z' constraint has been introduced to map the zero register. However
when the op also accept a constant, there is no point to accept the zero
register in addition.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Richard Henderson 707eee12fd tcg-hppa: Fix broken load/store helpers
The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers
was not respecting the ABI requirement for 64-bit values
being aligned in registers.

Mirror the ARM port in use of helper functions to marshal
arguments into the correct registers.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Richard Henderson fb1d48edb6 tcg-hppa: Fix brcond2 and setcond2
Neither of these functions were performing double-word
compares properly.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Richard Henderson 4c8f62d388 tcg: Fix !USE_DIRECT_JUMP
Commit 6375e09e changed the type of TranslationBlock.tb_next,
but failed to change the type of TCGContext.tb_next.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Aurelien Jarno 15658ad01b gdbstub/sh4: fix build with USE_SOFTFLOAT_STRUCT_TYPES
We have to use different type to access float values when
USE_SOFTFLOAT_STRUCT_TYPES is defined.

Rework SH4 version of cpu_gdb_{read,write}_register() using
a single case, and fixing the coding style. Use ldll_p() and
stfl_p() to access float values.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Richard Henderson 1d465a94ad tcg: Optimize two-address commutative operations
While swapping constants to the second operand, swap
sources matching destinations to the first operand.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Richard Henderson b5b6bb16b9 tcg: Optimize movcond for constant comparisons
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:09 -05:00
Richard Henderson 52080f688b tcg-i386: Implement movcond
Signed-off-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Richard Henderson 72bdbb7f46 target-alpha: Use movcond
For proper cmov insns, as well as the non-goto-tb case
of conditional branch.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Richard Henderson 6314cc0c73 tcg: Introduce movcond
Implemented with setcond if the target does not provide
the optional opcode.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Max Filippov cc10061717 target-xtensa: don't emit extra tcg_gen_goto_tb
Unconditional gen_check_loop_end at the end of disas_xtensa_insn
can emit tcg_gen_goto_tb with slot id already used in the TB (e.g. when
TB ends at LEND with a branch).

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Max Filippov 44219e7df2 target-xtensa: fix extui shift amount
extui opcode only uses lowermost op1 bit for sa4.

Reported-by: malc <av1474@comtv.ru>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Aurelien Jarno 5b681fffe4 tcg/optimize: fix end of basic block detection
Commit e31b0a7c05 fixed copy propagation on
32-bit host by restricting the copy between different types. This was the
wrong fix.

The real problem is that the all temps states should be reset at the end
of a basic block. This was done by adding such operations in the switch,
but brcond2 was forgotten (that's why the crash was only observed on 32-bit
hosts).

Fix that by looking at the TCG_OPF_BB_END instead. We need to keep the case
for op_set_label as temps might be modified through another path.

Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Richard Henderson 447f11b945 target-mips: Always evaluate debugging macro arguments
this will prevent some of the compilation errors with debugging
enabled from creeping back in.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Richard Henderson fe07dcf262 target-mips: Fix MIPS_DEBUG.
The macro uses the DisasContext.  Pass it around as needed.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Richard Henderson d25c2359de target-mips: Set opn in gen_ldst_multiple.
Used by MIPS_DEBUG, when enabled.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Aurelien Jarno 4f17bc1e89 revert "TCG: fix copy propagation"
Given the copy propagation breakage on 32-bit hosts has been fixed
commit e31b0a7c05 can be reverted.

Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Aurelien Jarno d39d648846 tcg: mark set_label with TCG_OPF_BB_END flag
set_label is effectively the end of a basic block, as no optimization
can be made accross it. It was treated as such in the liveness analysis
code, but as a special case.

Mark it with TCG_OPF_BB_END flag so that this information can be used
by other parts of the TCG code, and remove the special case in the liveness
analysis code.

Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Aurelien Jarno ea15fd7c1a tcg/i386: allow constants in load/store ops
On x86, it is possible to move a constant value to memory. Add code to
handle a constant argument to load/store ops.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Blue Swirl a0969d7a46 Remove unused CONFIG_TCG_PASS_AREG0 and dead code
Now that CONFIG_TCG_PASS_AREG0 is enabled for all targets,
remove dead code and support for !CONFIG_TCG_PASS_AREG0 case.

Remove dyngen-exec.h and all references to it. Although included by
hw/spapr_hcall.c, it does not seem to use it.

Remove unused HELPER_CFLAGS.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Blue Swirl 0c4b3c0198 target-mips: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Blue Swirl ca75e56821 target-sh4: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.

Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Aurelien Jarno c383331e9d target-cris: Switch to AREG0 free mode
Add an explicit CPUCRISState parameter instead of relying on AREG0, and
use cpu_ld* in translation and interrupt handling. Remove AREG0 swapping
in tlb_fill(). Switch to AREG0 free mode

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:08 -05:00
Aurelien Jarno d36ae16dd4 target-cris: Avoid AREG0 for helpers
Add an explicit CPUCRISState parameter instead of relying on AREG0.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl c9b89e8224 target-microblaze: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl 40b1f8a804 target-arm: final conversion to AREG0 free mode
Convert code load functions and switch to AREG0 free mode.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl 883864650e target-arm: convert remaining helpers
Convert remaining helpers to AREG0 free mode: add an explicit
CPUState parameter instead of relying on AREG0.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl 6178b83f35 target-arm: convert void helpers
Add an explicit CPUState parameter instead of relying on AREG0.

For easier review, convert only op helpers which don't return any value.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl af411212ce target-unicore32: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.

Tested-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl e67d4921fd target-m68k: avoid using cpu_single_env
Pass around CPUState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl 3654ef451e target-m68k: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl 7a5311f64f target-lm32: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Blue Swirl 1ada516f0e target-s390x: avoid cpu_single_env
Pass around CPUState instead of using global cpu_single_env.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno 578c758200 tcg/optimize: fix if/else/break coding style
optimizer.c contains some cases were the break is appearing in both the
if and the else parts. Fix that by moving it to the outer part. Also
move some common code there.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno 97c012c76a tcg/optimize: add constant folding for brcond
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno 2108a786ba tcg/optimize: add constant folding for setcond
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno decddd9021 tcg/optimize: swap brcond/setcond arguments when possible
brcond and setcond ops are not commutative, but it's easy to compute the
new condition after swapping the arguments. Try to always put the constant
argument in second position like for commutative ops, to help backends to
generate better code.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno 52173babad tcg/optimize: simplify shift/rot r, 0, a => movi r, 0 cases
shift/rot r, 0, a is equivalent to movi r, 0.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno f66f1dab29 tcg/optimize: simplify and r, a, 0 cases
and r, a, 0 is equivalent to a movi r, 0.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno 6c9785fb4b tcg/optimize: simplify or/xor r, a, 0 cases
or/xor r, a, 0 is equivalent to a mov r, a.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Aurelien Jarno d969307261 tcg/optimize: split expression simplification
Split expression simplification in multiple parts so that a given op
can appear multiple times. This patch should not change anything.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:07 -05:00
Stefan Weil 62cdb0fdd3 target-arm: Fix potential buffer overflow
Report from smatch:

target-arm/helper.c:651 arm946_prbs_read(6) error:
 buffer overflow 'env->cp15.c6_region' 8 <= 8
target-arm/helper.c:661 arm946_prbs_write(6) error:
 buffer overflow 'env->cp15.c6_region' 8 <= 8

c7_region is an array with 8 elements, so the index must be less than 8.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Aurelien Jarno 3bc7da7cd7 tcg/s390: fix ld/st with CONFIG_TCG_PASS_AREG0
The load/store slow path has been broken in e141ab52d:
- We need to move 4 registers for store functions and 3 registers for
  load functions and not the reverse.
- According to the s390x calling convention the arguments of a function
  should be zero extended. This means that the register shift should be
  done with TCG_TYPE_I64 to ensure the higher word is correctly zero
  extended when needed.

I am aware that CONFIG_TCG_PASS_AREG0 is being removed and thus that
this patch can be improved, but doing so means it can also be applied to
the 1.1 and 1.2 stable branches.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 265434460e target-s390x: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0.

Remove temporary wrappers and switch to AREG0 free mode.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
[agraf: fix conflicts]
Signed-off-by: Alexander Graf <agraf@suse.de>

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 71742e6c68 target-s390x: avoid AREG0 for misc helpers
Make misc helpers take a parameter for CPUState instead
of relying on global env.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
[agraf: fix conflict]
Signed-off-by: Alexander Graf <agraf@suse.de>

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 719a60ddb3 target-s390x: avoid AREG0 for condition code helpers
Make condition code helpers take a parameter for CPUState instead
of relying on global env.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 1f983b49f7 target-s390x: avoid AREG0 for integer helpers
Make integer helpers take a parameter for CPUState instead
of relying on global env.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 313e38b4a1 target-s390x: avoid AREG0 for FPU helpers
Make FPU helpers take a parameter for CPUState instead
of relying on global env.

Introduce temporary wrappers for FPU load and store ops.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 1a392c8957 target-s390x: rename op_helper.c to misc_helper.c
Now op_helper.c contains miscellaneous helpers, rename
it to misc_helper.c.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
[agraf: fix conflict]
Signed-off-by: Alexander Graf <agraf@suse.de>

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 84dde20eea target-s390x: split memory access helpers
Move memory access helpers to mem_helper.c.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
[agraf: fold softmmu include ifdefs together]
Signed-off-by: Alexander Graf <agraf@suse.de>

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 7dc581be44 target-s390x: split integer helpers
Move integer helpers to int_helper.c.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl f7c50726dd target-s390x: split condition code helpers
Move condition code helpers to cc_helper.c.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl 4bae8a0a90 target-s390x: split FPU ops
Move floating point instructions to fpu_helper.c.

While exporting some condition code helpers,
avoid duplicate identifier conflict with translate.c.

Remove unused set_cc_nz_f64() in translate.c.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Blue Swirl b05900a761 target-s390x: fix style
Before splitting op_helper.c and helper.c in the next patches,
fix style issues. No functional changes.

Replace also GCC specific __FUNCTION__ with
standard __func__.

Don't init static variable (cpu_s390x_init:inited) with 0.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Aurelien Jarno b16148e1c6 target-sparc: fix fcmp{s,d,q} instructions wrt exception
fcmp{s,d,q} instructions are supposed to ignore quiet NaN (contrary to
the fcmpe{s,d,q} instructions), but the current code is wrongly setting
the NV exception in that case. Moreover the current code is duplicated:
first the arguments are checked for NaN to generate an exception, and
later in case the comparison is unordered (which can only happens if one
of the argument is a NaN), the same check is done to generate an
exception.

Fix that by calling clear_float_exceptions() followed by
check_ieee_exceptions() as for the other floating point instructions.
Use the _compare_quiet functions for fcmp{s,d,q} and the _compare ones
for fcmpe{s,d,q}. Simplify the flag setting by not clearing a flag that
is set the line just below.

This fix allows the math glibc testsuite to pass.

Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Max Filippov dafd8866be target-xtensa: fix missing errno codes for mingw32
Put the following errno value mappings under #ifdef:

xtensa-semi.c: In function 'errno_h2g':
xtensa-semi.c:113: error: 'ENOTBLK' undeclared (first use in this function)
xtensa-semi.c:113: error: (Each undeclared identifier is reported only once
xtensa-semi.c:113: error: for each function it appears in.)
xtensa-semi.c:113: error: array index in initializer not of integer type
xtensa-semi.c:113: error: (near initialization for 'guest_errno')
xtensa-semi.c:124: error: 'ETXTBSY' undeclared (first use in this function)
xtensa-semi.c:124: error: array index in initializer not of integer type
xtensa-semi.c:124: error: (near initialization for 'guest_errno')
xtensa-semi.c:134: error: 'ELOOP' undeclared (first use in this function)
xtensa-semi.c:134: error: array index in initializer not of integer type
xtensa-semi.c:134: error: (near initialization for 'guest_errno')

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Stefan Weil 631287933e target-cris: Fix buffer overflow
Report from smatch:

target-cris/translate.c:3464 cpu_dump_state(32) error:
 buffer overflow 'env->sregs' 4 <= 255

sregs is declared 'uint32_t sregs[4][16]', so the first index must be
less than 4 or ARRAY_SIZE(env->sregs).

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
Max Filippov 814395979e target-xtensa: convert host errno values to guest
Guest errno values are taken from the newlib. Convert only those errno
values that can be returned from used system calls.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2012-10-09 01:42:06 -05:00
1436 changed files with 23585 additions and 81087 deletions

No files matched your search

-7
View File
@@ -1,7 +0,0 @@
"VIM settings to match QEMU coding style. They are activated by adding the
"following settings (without the " symbol) as last two lines in $HOME/.vimrc:
"set secure
"set exrc
set expandtab
set shiftwidth=4
set smarttab
+2
View File
@@ -12,6 +12,8 @@ trace-dtrace.dtrace
*-linux-user
*-bsd-user
libdis*
libhw32
libhw64
libuser
linux-headers/asm
qapi-generated
-3
View File
@@ -19,6 +19,3 @@
[submodule "roms/sgabios"]
path = roms/sgabios
url = git://git.qemu.org/sgabios.git
[submodule "pixman"]
path = pixman
url = git://anongit.freedesktop.org/pixman
+5 -6
View File
@@ -32,7 +32,7 @@ mandatory for VMState fields.
Don't use Linux kernel internal types like u32, __u32 or __le32.
Use hwaddr for guest physical addresses except pcibus_t
Use target_phys_addr_t for guest physical addresses except pcibus_t
for PCI addresses. In addition, ram_addr_t is a QEMU internal address
space that maps guest RAM physical addresses into an intermediate
address space that can map to host virtual address spaces. Generally
@@ -91,11 +91,10 @@ emulators.
4. String manipulation
Do not use the strncpy function. As mentioned in the man page, it does *not*
guarantee a NULL-terminated buffer, which makes it extremely dangerous to use.
It also zeros trailing destination bytes out to the specified length. Instead,
use this similar function when possible, but note its different signature:
void pstrcpy(char *dest, int dest_buf_size, const char *src)
Do not use the strncpy function. According to the man page, it does
*not* guarantee a NULL-terminated buffer, which makes it extremely dangerous
to use. Instead, use functionally equivalent function:
void pstrcpy(char *buf, int buf_size, const char *str)
Don't use strcat because it can't check for buffer overflows, but:
char *pstrcat(char *buf, int buf_size, const char *s)
+3 -66
View File
@@ -268,7 +268,6 @@ S: Maintained
F: hw/xilinx_zynq.c
F: hw/zynq_slcr.c
F: hw/cadence_*
F: hw/xilinx_spips.c
CRIS Machines
-------------
@@ -350,31 +349,9 @@ PowerPC Machines
405
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Odd Fixes
S: Maintained
F: hw/ppc405_boards.c
Bamboo
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc440_bamboo.c
e500
M: Alexander Graf <agraf@suse.de>
M: Scott Wood <scottwood@freescale.com>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/ppc/e500.[hc]
F: hw/ppc/e500plat.c
mpc8544ds
M: Alexander Graf <agraf@suse.de>
M: Scott Wood <scottwood@freescale.com>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/ppc/mpc8544ds.c
F: hw/mpc8544_guts.c
New World
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
@@ -397,19 +374,6 @@ S: Odd Fixes
F: hw/ppc_prep.c
F: hw/prep_pci.[hc]
sPAPR
M: David Gibson <david@gibson.dropbear.id.au>
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/spapr*
virtex_ml507
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/virtex_ml507.c
SH4 Machines
------------
R2D
@@ -493,19 +457,6 @@ S: Supported
F: hw/pci*
F: hw/piix*
ppc4xx
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc4xx*.[hc]
ppce500
M: Alexander Graf <agraf@suse.de>
M: Scott Wood <scottwood@freescale.com>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/ppce500_*
SCSI
M: Paolo Bonzini <pbonzini@redhat.com>
S: Supported
@@ -518,22 +469,11 @@ M: Paul Brook <paul@codesourcery.com>
S: Odd Fixes
F: hw/lsi53c895a.c
SSI
M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
S: Maintained
F: hw/ssi.*
F: hw/m25p80.c
USB
M: Gerd Hoffmann <kraxel@redhat.com>
S: Maintained
F: hw/usb*
VFIO
M: Alex Williamson <alex.williamson@redhat.com>
S: Supported
F: hw/vfio*
vhost
M: Michael S. Tsirkin <mst@redhat.com>
S: Supported
@@ -553,7 +493,6 @@ T: git git://github.com/kvaneesh/QEMU.git
virtio-blk
M: Kevin Wolf <kwolf@redhat.com>
M: Stefan Hajnoczi <stefanha@redhat.com>
S: Supported
F: hw/virtio-blk*
@@ -573,7 +512,6 @@ F: hw/xilinx_intc.c
F: hw/xilinx_ethlite.c
F: hw/xilinx_timer.c
F: hw/xilinx.h
F: hw/xilinx_spi.c
Subsystems
----------
@@ -584,7 +522,6 @@ F: audio/
Block
M: Kevin Wolf <kwolf@redhat.com>
M: Stefan Hajnoczi <stefanha@redhat.com>
S: Supported
F: block*
F: block/
@@ -643,7 +580,7 @@ F: monitor.c
Network device layer
M: Anthony Liguori <aliguori@us.ibm.com>
M: Stefan Hajnoczi <stefanha@redhat.com>
M: Stefan Hajnoczi <stefanha@gmail.com>
S: Maintained
F: net/
T: git git://github.com/stefanha/qemu.git net
@@ -663,7 +600,7 @@ F: slirp/
T: git git://git.kiszka.org/qemu.git queues/slirp
Tracing
M: Stefan Hajnoczi <stefanha@redhat.com>
M: Stefan Hajnoczi <stefanha@gmail.com>
S: Maintained
F: trace/
F: scripts/tracetool.py
+9 -40
View File
@@ -8,28 +8,15 @@ ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
all:
include config-host.mak
# Check that we're not trying to do an out-of-tree build from
# a tree that's been used for an in-tree build.
ifneq ($(realpath $(SRC_PATH)),$(realpath .))
ifneq ($(wildcard $(SRC_PATH)/config-host.mak),)
$(error This is an out of tree build but your source tree ($(SRC_PATH)) \
seems to have been used for an in-tree build. You can fix this by running \
"make distclean && rm -rf *-linux-user *-softmmu" in your source tree)
endif
endif
include $(SRC_PATH)/rules.mak
config-host.mak: $(SRC_PATH)/configure
@echo $@ is out-of-date, running configure
@sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh
else
config-host.mak:
ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
@echo "Please call configure before running make!"
@exit 1
endif
endif
GENERATED_HEADERS = config-host.h trace.h qemu-options.def
ifeq ($(TRACE_BACKEND),dtrace)
@@ -118,17 +105,6 @@ endif
subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
subdir-pixman: pixman/Makefile
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)
pixman/Makefile: $(SRC_PATH)/pixman/configure
(cd pixman; CFLAGS="$(CFLAGS) -fPIC" $(SRC_PATH)/pixman/configure $(AUTOCONF_HOST) --disable-gtk --disable-shared --enable-static)
$(SRC_PATH)/pixman/configure:
(cd $(SRC_PATH)/pixman; autoreconf -v --install)
$(SUBDIR_RULES): libqemustub.a
$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis
$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
@@ -159,12 +135,6 @@ version.o: $(SRC_PATH)/version.rc config-host.h
$(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@")
version-obj-$(CONFIG_WIN32) += version.o
######################################################################
# Build library with stubs
libqemustub.a: $(stub-obj-y)
######################################################################
# Support building shared library libcacard
@@ -188,16 +158,17 @@ endif
qemu-img.o: qemu-img-cmds.h
tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
main-loop.o iohandler.o error.o
qemu-timer-common.o main-loop.o notify.o \
iohandler.o cutils.o iov.o async.o
tools-obj-$(CONFIG_POSIX) += compatfd.o
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) libqemustub.a
qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o libqemustub.a
vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o
$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@")
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
@@ -240,9 +211,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y) libqemustub.a
qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y)
QEMULIBS=libuser libdis libdis-user
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
clean:
# avoid old build problems by removing potentially incorrect old files
@@ -286,7 +257,6 @@ distclean: clean
for d in $(TARGET_DIRS) $(QEMULIBS); do \
rm -rf $$d || exit 1 ; \
done
if test -f pixman/config.log; then make -C pixman distclean; fi
KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \
ar de en-us fi fr-be hr it lv nl pl ru th \
@@ -332,6 +302,7 @@ install-confdir:
install-sysconfig: install-datadir install-confdir
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)"
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/cpus-x86_64.conf "$(DESTDIR)$(qemu_datadir)"
install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir
$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
@@ -432,9 +403,7 @@ qemu-doc.dvi qemu-doc.html qemu-doc.info qemu-doc.pdf: \
# Add a dependency on the generated files, so that they are always
# rebuilt before other object files
ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
Makefile: $(GENERATED_HEADERS)
endif
# Include automatically generated dependency files
# Dependencies in Makefile.objs files come from our recursive subdir rules
+23
View File
@@ -0,0 +1,23 @@
# Makefile for qemu target independent devices.
include ../config-host.mak
include ../config-all-devices.mak
include config.mak
include $(SRC_PATH)/rules.mak
.PHONY: all
$(call set-vpath, $(SRC_PATH))
QEMU_CFLAGS+=-I..
QEMU_CFLAGS += -I$(SRC_PATH)/include
include $(SRC_PATH)/Makefile.objs
all: $(hw-obj-y)
# Dummy command so that make thinks it has done something
@true
clean:
rm -f $(addsuffix *.o, $(sort $(dir $(hw-obj-y))))
rm -f $(addsuffix *.d, $(sort $(dir $(hw-obj-y))))
+20 -24
View File
@@ -1,7 +1,3 @@
#######################################################################
# Stub library, linked in tools
stub-obj-y = stubs/
#######################################################################
# Target-independent parts used in system and user emulation
universal-obj-y =
@@ -23,7 +19,7 @@ universal-obj-y += $(qom-obj-y)
#######################################################################
# oslib-obj-y is code depending on the OS (win32 vs posix)
oslib-obj-y = osdep.o cutils.o qemu-timer-common.o
oslib-obj-y = osdep.o
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
@@ -45,14 +41,12 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o
block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o
block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o
block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o
block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
block-obj-y += block/
block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
@@ -65,11 +59,10 @@ endif
# suppress *all* target specific code in case of system emulation, i.e. a
# single QEMU executable should support all CPUs and machines.
common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
common-obj-y = $(block-obj-y) blockdev.o
common-obj-y += net.o net/
common-obj-y += qom/
common-obj-y += readline.o console.o cursor.o
common-obj-y += qemu-pixman.o
common-obj-y += $(oslib-obj-y)
common-obj-$(CONFIG_WIN32) += os-win32.o
common-obj-$(CONFIG_POSIX) += os-posix.o
@@ -82,6 +75,7 @@ common-obj-y += input.o
common-obj-y += buffered_file.o migration.o migration-tcp.o
common-obj-y += qemu-char.o #aio.o
common-obj-y += block-migration.o iohandler.o
common-obj-y += pflib.o
common-obj-y += bitmap.o bitops.o
common-obj-y += page_cache.o
@@ -95,17 +89,13 @@ common-obj-y += hw/
common-obj-y += ui/
common-obj-y += bt-host.o bt-vhci.o
common-obj-y += dma-helpers.o
common-obj-y += acl.o
common-obj-y += iov.o acl.o
common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += notify.o event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
common-obj-y += qtest.o
common-obj-y += vl.o
common-obj-$(CONFIG_SLIRP) += slirp/
common-obj-y += backends/
######################################################################
# libseccomp
ifeq ($(CONFIG_SECCOMP),y)
@@ -118,12 +108,17 @@ endif
user-obj-y =
user-obj-y += envlist.o path.o
user-obj-y += tcg-runtime.o host-utils.o
user-obj-y += cache-utils.o
user-obj-y += cutils.o iov.o cache-utils.o
user-obj-y += module.o
user-obj-y += qemu-user.o
user-obj-y += $(trace-obj-y)
user-obj-y += qom/
######################################################################
# libhw
hw-obj-y = vl.o dma-helpers.o qtest.o hw/
######################################################################
# libdis
# NOTE: the disassembler code is only needed for debugging
@@ -233,8 +228,9 @@ universal-obj-y += $(qapi-obj-y)
######################################################################
# guest agent
qga-obj-y = qga/ qemu-ga.o module.o qemu-tool.o
qga-obj-$(CONFIG_POSIX) += qemu-sockets.o qemu-option.o
qga-obj-y = qga/ qemu-ga.o module.o
qga-obj-$(CONFIG_WIN32) += oslib-win32.o
qga-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-sockets.o qemu-option.o
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
@@ -243,11 +239,11 @@ vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
QEMU_CFLAGS+=$(GLIB_CFLAGS)
nested-vars += \
stub-obj-y \
hw-obj-y \
qga-obj-y \
block-obj-y \
qom-obj-y \
qapi-obj-y \
block-obj-y \
user-obj-y \
common-obj-y \
extra-obj-y
+6 -5
View File
@@ -4,6 +4,9 @@ include ../config-host.mak
include config-devices.mak
include config-target.mak
include $(SRC_PATH)/rules.mak
ifneq ($(HWDIR),)
include $(HWDIR)/config.mak
endif
$(call set-vpath, $(SRC_PATH))
ifdef CONFIG_LINUX
@@ -143,9 +146,6 @@ GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
endif # CONFIG_SOFTMMU
# Workaround for http://gcc.gnu.org/PR55489, see configure.
%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
nested-vars += obj-y
# This resolves all nested paths, so it must come last
@@ -157,6 +157,7 @@ all-obj-y += $(addprefix ../, $(universal-obj-y))
ifdef CONFIG_SOFTMMU
all-obj-y += $(addprefix ../, $(common-obj-y))
all-obj-y += $(addprefix ../libdis/, $(libdis-y))
all-obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
all-obj-y += $(addprefix ../, $(trace-obj-y))
else
all-obj-y += $(addprefix ../libuser/, $(user-obj-y))
@@ -165,12 +166,12 @@ endif #CONFIG_LINUX_USER
ifdef QEMU_PROGW
# The linker builds a windows executable. Make also a console executable.
$(QEMU_PROGW): $(all-obj-y) ../libqemustub.a
$(QEMU_PROGW): $(all-obj-y)
$(call LINK,$^)
$(QEMU_PROG): $(QEMU_PROGW)
$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
else
$(QEMU_PROG): $(all-obj-y) ../libqemustub.a
$(QEMU_PROG): $(all-obj-y)
$(call LINK,$^)
endif
-299
View File
@@ -1,299 +0,0 @@
#!/usr/bin/python
# QEMU Guest Agent Client
#
# Copyright (C) 2012 Ryota Ozaki <ozaki.ryota@gmail.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
# Usage:
#
# Start QEMU with:
#
# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
# -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
#
# Run the script:
#
# $ qemu-ga-client --address=/tmp/qga.sock <command> [args...]
#
# or
#
# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock
# $ qemu-ga-client <command> [args...]
#
# For example:
#
# $ qemu-ga-client cat /etc/resolv.conf
# # Generated by NetworkManager
# nameserver 10.0.2.3
# $ qemu-ga-client fsfreeze status
# thawed
# $ qemu-ga-client fsfreeze freeze
# 2 filesystems frozen
#
# See also: http://wiki.qemu.org/Features/QAPI/GuestAgent
#
import base64
import random
import qmp
class QemuGuestAgent(qmp.QEMUMonitorProtocol):
def __getattr__(self, name):
def wrapper(**kwds):
return self.command('guest-' + name.replace('_', '-'), **kwds)
return wrapper
class QemuGuestAgentClient:
error = QemuGuestAgent.error
def __init__(self, address):
self.qga = QemuGuestAgent(address)
self.qga.connect(negotiate=False)
def sync(self, timeout=3):
# Avoid being blocked forever
if not self.ping(timeout):
raise EnvironmentError('Agent seems not alive')
uid = random.randint(0, (1 << 32) - 1)
while True:
ret = self.qga.sync(id=uid)
if isinstance(ret, int) and int(ret) == uid:
break
def __file_read_all(self, handle):
eof = False
data = ''
while not eof:
ret = self.qga.file_read(handle=handle, count=1024)
_data = base64.b64decode(ret['buf-b64'])
data += _data
eof = ret['eof']
return data
def read(self, path):
handle = self.qga.file_open(path=path)
try:
data = self.__file_read_all(handle)
finally:
self.qga.file_close(handle=handle)
return data
def info(self):
info = self.qga.info()
msgs = []
msgs.append('version: ' + info['version'])
msgs.append('supported_commands:')
enabled = [c['name'] for c in info['supported_commands'] if c['enabled']]
msgs.append('\tenabled: ' + ', '.join(enabled))
disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']]
msgs.append('\tdisabled: ' + ', '.join(disabled))
return '\n'.join(msgs)
def __gen_ipv4_netmask(self, prefixlen):
mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2)
return '.'.join([str(mask >> 24),
str((mask >> 16) & 0xff),
str((mask >> 8) & 0xff),
str(mask & 0xff)])
def ifconfig(self):
nifs = self.qga.network_get_interfaces()
msgs = []
for nif in nifs:
msgs.append(nif['name'] + ':')
if 'ip-addresses' in nif:
for ipaddr in nif['ip-addresses']:
if ipaddr['ip-address-type'] == 'ipv4':
addr = ipaddr['ip-address']
mask = self.__gen_ipv4_netmask(int(ipaddr['prefix']))
msgs.append("\tinet %s netmask %s" % (addr, mask))
elif ipaddr['ip-address-type'] == 'ipv6':
addr = ipaddr['ip-address']
prefix = ipaddr['prefix']
msgs.append("\tinet6 %s prefixlen %s" % (addr, prefix))
if nif['hardware-address'] != '00:00:00:00:00:00':
msgs.append("\tether " + nif['hardware-address'])
return '\n'.join(msgs)
def ping(self, timeout):
self.qga.settimeout(timeout)
try:
self.qga.ping()
except self.qga.timeout:
return False
return True
def fsfreeze(self, cmd):
if cmd not in ['status', 'freeze', 'thaw']:
raise StandardError('Invalid command: ' + cmd)
return getattr(self.qga, 'fsfreeze' + '_' + cmd)()
def fstrim(self, minimum=0):
return getattr(self.qga, 'fstrim')(minimum=minimum)
def suspend(self, mode):
if mode not in ['disk', 'ram', 'hybrid']:
raise StandardError('Invalid mode: ' + mode)
try:
getattr(self.qga, 'suspend' + '_' + mode)()
# On error exception will raise
except self.qga.timeout:
# On success command will timed out
return
def shutdown(self, mode='powerdown'):
if mode not in ['powerdown', 'halt', 'reboot']:
raise StandardError('Invalid mode: ' + mode)
try:
self.qga.shutdown(mode=mode)
except self.qga.timeout:
return
def _cmd_cat(client, args):
if len(args) != 1:
print('Invalid argument')
print('Usage: cat <file>')
sys.exit(1)
print(client.read(args[0]))
def _cmd_fsfreeze(client, args):
usage = 'Usage: fsfreeze status|freeze|thaw'
if len(args) != 1:
print('Invalid argument')
print(usage)
sys.exit(1)
if args[0] not in ['status', 'freeze', 'thaw']:
print('Invalid command: ' + args[0])
print(usage)
sys.exit(1)
cmd = args[0]
ret = client.fsfreeze(cmd)
if cmd == 'status':
print(ret)
elif cmd == 'freeze':
print("%d filesystems frozen" % ret)
else:
print("%d filesystems thawed" % ret)
def _cmd_fstrim(client, args):
if len(args) == 0:
minimum = 0
else:
minimum = int(args[0])
print(client.fstrim(minimum))
def _cmd_ifconfig(client, args):
print(client.ifconfig())
def _cmd_info(client, args):
print(client.info())
def _cmd_ping(client, args):
if len(args) == 0:
timeout = 3
else:
timeout = float(args[0])
alive = client.ping(timeout)
if not alive:
print("Not responded in %s sec" % args[0])
sys.exit(1)
def _cmd_suspend(client, args):
usage = 'Usage: suspend disk|ram|hybrid'
if len(args) != 1:
print('Less argument')
print(usage)
sys.exit(1)
if args[0] not in ['disk', 'ram', 'hybrid']:
print('Invalid command: ' + args[0])
print(usage)
sys.exit(1)
client.suspend(args[0])
def _cmd_shutdown(client, args):
client.shutdown()
_cmd_powerdown = _cmd_shutdown
def _cmd_halt(client, args):
client.shutdown('halt')
def _cmd_reboot(client, args):
client.shutdown('reboot')
commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m]
def main(address, cmd, args):
if not os.path.exists(address):
print('%s not found' % address)
sys.exit(1)
if cmd not in commands:
print('Invalid command: ' + cmd)
print('Available commands: ' + ', '.join(commands))
sys.exit(1)
try:
client = QemuGuestAgentClient(address)
except QemuGuestAgent.error, e:
import errno
print(e)
if e.errno == errno.ECONNREFUSED:
print('Hint: qemu is not running?')
sys.exit(1)
if cmd != 'ping':
client.sync()
globals()['_cmd_' + cmd](client, args)
if __name__ == '__main__':
import sys
import os
import optparse
address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None
usage = "%prog [--address=<unix_path>|<ipv4_address>] <command> [args...]\n"
usage += '<command>: ' + ', '.join(commands)
parser = optparse.OptionParser(usage=usage)
parser.add_option('--address', action='store', type='string',
default=address, help='Specify a ip:port pair or a unix socket path')
options, args = parser.parse_args()
address = options.address
if address is None:
parser.error('address is not specified')
sys.exit(1)
if len(args) == 0:
parser.error('Less argument')
sys.exit(1)
main(address, args[0], args[1:])
+2 -44
View File
@@ -50,8 +50,7 @@ Emitted when a block job has been cancelled.
Data:
- "type": Job type (json-string; "stream" for image streaming
"commit" for block commit)
- "type": Job type ("stream" for image streaming, json-string)
- "device": Device name (json-string)
- "len": Maximum progress value (json-int)
- "offset": Current progress value (json-int)
@@ -74,8 +73,7 @@ Emitted when a block job has completed.
Data:
- "type": Job type (json-string; "stream" for image streaming
"commit" for block commit)
- "type": Job type ("stream" for image streaming, json-string)
- "device": Device name (json-string)
- "len": Maximum progress value (json-int)
- "offset": Current progress value (json-int)
@@ -96,46 +94,6 @@ Example:
"speed": 0 },
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
BLOCK_JOB_ERROR
---------------
Emitted when a block job encounters an error.
Data:
- "device": device name (json-string)
- "operation": I/O operation (json-string, "read" or "write")
- "action": action that has been taken, it's one of the following (json-string):
"ignore": error has been ignored, the job may fail later
"report": error will be reported and the job canceled
"stop": error caused job to be paused
Example:
{ "event": "BLOCK_JOB_ERROR",
"data": { "device": "ide0-hd1",
"operation": "write",
"action": "stop" },
"timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
BLOCK_JOB_READY
---------------
Emitted when a block job is ready to complete.
Data:
- "device": device name (json-string)
Example:
{ "event": "BLOCK_JOB_READY",
"data": { "device": "ide0-hd1" },
"timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
event.
DEVICE_TRAY_MOVED
-----------------
+13 -33
View File
@@ -33,7 +33,6 @@
import qmp
import readline
import sys
import pprint
class QMPCompleter(list):
def complete(self, text, state):
@@ -53,11 +52,10 @@ class QMPShellBadPort(QMPShellError):
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
# _execute_cmd()). Let's design a better one.
class QMPShell(qmp.QEMUMonitorProtocol):
def __init__(self, address, pp=None):
def __init__(self, address):
qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
self._greeting = None
self._completer = None
self._pp = pp
def __get_address(self, arg):
"""
@@ -116,11 +114,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
if resp is None:
print 'Disconnected'
return False
if self._pp is not None:
self._pp.pprint(resp)
else:
print resp
print resp
return True
def connect(self):
@@ -228,36 +222,22 @@ def die(msg):
def fail_cmdline(option=None):
if option:
sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
sys.stderr.write('qemu-shell [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
sys.stderr.write('qemu-shell [ -H ] < UNIX socket path> | < TCP address:port >\n')
sys.exit(1)
def main():
addr = ''
qemu = None
hmp = False
pp = None
try:
for arg in sys.argv[1:]:
if arg == "-H":
if qemu is not None:
fail_cmdline(arg)
hmp = True
elif arg == "-p":
if pp is not None:
fail_cmdline(arg)
pp = pprint.PrettyPrinter(indent=4)
else:
if qemu is not None:
fail_cmdline(arg)
if hmp:
qemu = HMPShell(arg)
else:
qemu = QMPShell(arg, pp)
addr = arg
if qemu is None:
fail_cmdline()
if len(sys.argv) == 2:
qemu = QMPShell(sys.argv[1])
addr = sys.argv[1]
elif len(sys.argv) == 3:
if sys.argv[1] != '-H':
fail_cmdline(sys.argv[1])
qemu = HMPShell(sys.argv[2])
addr = sys.argv[2]
else:
fail_cmdline()
except QMPShellBadPort:
die('bad port number in command-line')
+3 -30
View File
@@ -49,6 +49,7 @@ class QEMUMonitorProtocol:
return socket.socket(family, socket.SOCK_STREAM)
def __negotiate_capabilities(self):
self.__sockfile = self.__sock.makefile()
greeting = self.__json_read()
if greeting is None or not greeting.has_key('QMP'):
raise QMPConnectError
@@ -72,7 +73,7 @@ class QEMUMonitorProtocol:
error = socket.error
def connect(self, negotiate=True):
def connect(self):
"""
Connect to the QMP Monitor and perform capabilities negotiation.
@@ -82,9 +83,7 @@ class QEMUMonitorProtocol:
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
self.__sockfile = self.__sock.makefile()
if negotiate:
return self.__negotiate_capabilities()
return self.__negotiate_capabilities()
def accept(self):
"""
@@ -96,7 +95,6 @@ class QEMUMonitorProtocol:
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock, _ = self.__sock.accept()
self.__sockfile = self.__sock.makefile()
return self.__negotiate_capabilities()
def cmd_obj(self, qmp_cmd):
@@ -136,26 +134,6 @@ class QEMUMonitorProtocol:
raise Exception(ret['error']['desc'])
return ret['return']
def pull_event(self, wait=False):
"""
Get and delete the first available QMP event.
@param wait: block until an event is available (bool)
"""
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
if not self.__events and wait:
self.__json_read(only_event=True)
event = self.__events[0]
del self.__events[0]
return event
def get_events(self, wait=False):
"""
Get a list of available QMP events.
@@ -183,8 +161,3 @@ class QEMUMonitorProtocol:
def close(self):
self.__sock.close()
self.__sockfile.close()
timeout = socket.timeout
def settimeout(self, timeout):
self.__sock.settimeout(timeout)
+1 -1
View File
@@ -1 +1 @@
1.3.1
1.2.1
-269
View File
@@ -1,269 +0,0 @@
/*
* QEMU aio implementation
*
* Copyright IBM, Corp. 2008
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.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 "qemu-common.h"
#include "block.h"
#include "qemu-queue.h"
#include "qemu_socket.h"
struct AioHandler
{
GPollFD pfd;
IOHandler *io_read;
IOHandler *io_write;
AioFlushHandler *io_flush;
int deleted;
void *opaque;
QLIST_ENTRY(AioHandler) node;
};
static AioHandler *find_aio_handler(AioContext *ctx, int fd)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->pfd.fd == fd)
if (!node->deleted)
return node;
}
return NULL;
}
void aio_set_fd_handler(AioContext *ctx,
int fd,
IOHandler *io_read,
IOHandler *io_write,
AioFlushHandler *io_flush,
void *opaque)
{
AioHandler *node;
node = find_aio_handler(ctx, fd);
/* Are we deleting the fd handler? */
if (!io_read && !io_write) {
if (node) {
g_source_remove_poll(&ctx->source, &node->pfd);
/* If the lock is held, just mark the node as deleted */
if (ctx->walking_handlers) {
node->deleted = 1;
node->pfd.revents = 0;
} else {
/* Otherwise, delete it for real. We can't just mark it as
* deleted because deleted nodes are only cleaned up after
* releasing the walking_handlers lock.
*/
QLIST_REMOVE(node, node);
g_free(node);
}
}
} else {
if (node == NULL) {
/* Alloc and insert if it's not already there */
node = g_malloc0(sizeof(AioHandler));
node->pfd.fd = fd;
QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
g_source_add_poll(&ctx->source, &node->pfd);
}
/* Update handler with latest information */
node->io_read = io_read;
node->io_write = io_write;
node->io_flush = io_flush;
node->opaque = opaque;
node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0);
node->pfd.events |= (io_write ? G_IO_OUT : 0);
}
aio_notify(ctx);
}
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
EventNotifierHandler *io_read,
AioFlushEventNotifierHandler *io_flush)
{
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
(IOHandler *)io_read, NULL,
(AioFlushHandler *)io_flush, notifier);
}
bool aio_pending(AioContext *ctx)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
int revents;
/*
* FIXME: right now we cannot get G_IO_HUP and G_IO_ERR because
* main-loop.c is still select based (due to the slirp legacy).
* If main-loop.c ever switches to poll, G_IO_ERR should be
* tested too. Dispatching G_IO_ERR to both handlers should be
* okay, since handlers need to be ready for spurious wakeups.
*/
revents = node->pfd.revents & node->pfd.events;
if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
return true;
}
if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
return true;
}
}
return false;
}
bool aio_poll(AioContext *ctx, bool blocking)
{
static struct timeval tv0;
AioHandler *node;
fd_set rdfds, wrfds;
int max_fd = -1;
int ret;
bool busy, progress;
progress = false;
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
/*
* Then dispatch any pending callbacks from the GSource.
*
* We have to walk very carefully in case qemu_aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
int revents;
ctx->walking_handlers++;
revents = node->pfd.revents & node->pfd.events;
node->pfd.revents = 0;
/* See comment in aio_pending. */
if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
node->io_read(node->opaque);
progress = true;
}
if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
node->io_write(node->opaque);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
if (progress && !blocking) {
return true;
}
ctx->walking_handlers++;
FD_ZERO(&rdfds);
FD_ZERO(&wrfds);
/* fill fd sets */
busy = false;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
*/
if (!node->deleted && node->io_flush) {
if (node->io_flush(node->opaque) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_read) {
FD_SET(node->pfd.fd, &rdfds);
max_fd = MAX(max_fd, node->pfd.fd + 1);
}
if (!node->deleted && node->io_write) {
FD_SET(node->pfd.fd, &wrfds);
max_fd = MAX(max_fd, node->pfd.fd + 1);
}
}
ctx->walking_handlers--;
/* No AIO operations? Get us out of here */
if (!busy) {
return progress;
}
/* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0);
/* if we have any readable fds, dispatch event */
if (ret > 0) {
/* we have to walk very carefully in case
* qemu_aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
ctx->walking_handlers++;
if (!node->deleted &&
FD_ISSET(node->pfd.fd, &rdfds) &&
node->io_read) {
node->io_read(node->opaque);
progress = true;
}
if (!node->deleted &&
FD_ISSET(node->pfd.fd, &wrfds) &&
node->io_write) {
node->io_write(node->opaque);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
}
assert(progress || busy);
return true;
}
-219
View File
@@ -1,219 +0,0 @@
/*
* QEMU aio implementation
*
* Copyright IBM Corp., 2008
* Copyright Red Hat Inc., 2012
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
* Paolo Bonzini <pbonzini@redhat.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 "qemu-common.h"
#include "block.h"
#include "qemu-queue.h"
#include "qemu_socket.h"
struct AioHandler {
EventNotifier *e;
EventNotifierHandler *io_notify;
AioFlushEventNotifierHandler *io_flush;
GPollFD pfd;
int deleted;
QLIST_ENTRY(AioHandler) node;
};
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *e,
EventNotifierHandler *io_notify,
AioFlushEventNotifierHandler *io_flush)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->e == e && !node->deleted) {
break;
}
}
/* Are we deleting the fd handler? */
if (!io_notify) {
if (node) {
g_source_remove_poll(&ctx->source, &node->pfd);
/* If the lock is held, just mark the node as deleted */
if (ctx->walking_handlers) {
node->deleted = 1;
node->pfd.revents = 0;
} else {
/* Otherwise, delete it for real. We can't just mark it as
* deleted because deleted nodes are only cleaned up after
* releasing the walking_handlers lock.
*/
QLIST_REMOVE(node, node);
g_free(node);
}
}
} else {
if (node == NULL) {
/* Alloc and insert if it's not already there */
node = g_malloc0(sizeof(AioHandler));
node->e = e;
node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
node->pfd.events = G_IO_IN;
QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
g_source_add_poll(&ctx->source, &node->pfd);
}
/* Update handler with latest information */
node->io_notify = io_notify;
node->io_flush = io_flush;
}
aio_notify(ctx);
}
bool aio_pending(AioContext *ctx)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->pfd.revents && node->io_notify) {
return true;
}
}
return false;
}
bool aio_poll(AioContext *ctx, bool blocking)
{
AioHandler *node;
HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
bool busy, progress;
int count;
progress = false;
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
/*
* Then dispatch any pending callbacks from the GSource.
*
* We have to walk very carefully in case qemu_aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
ctx->walking_handlers++;
if (node->pfd.revents && node->io_notify) {
node->pfd.revents = 0;
node->io_notify(node->e);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
if (progress && !blocking) {
return true;
}
ctx->walking_handlers++;
/* fill fd sets */
busy = false;
count = 0;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
*/
if (!node->deleted && node->io_flush) {
if (node->io_flush(node->e) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_notify) {
events[count++] = event_notifier_get_handle(node->e);
}
}
ctx->walking_handlers--;
/* No AIO operations? Get us out of here */
if (!busy) {
return progress;
}
/* wait until next event */
while (count > 0) {
int timeout = blocking ? INFINITE : 0;
int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
/* if we have any signaled events, dispatch event */
if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
break;
}
blocking = false;
/* we have to walk very carefully in case
* qemu_aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
ctx->walking_handlers++;
if (!node->deleted &&
event_notifier_get_handle(node->e) == events[ret - WAIT_OBJECT_0] &&
node->io_notify) {
node->io_notify(node->e);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
/* Try again, but only call each handler once. */
events[ret - WAIT_OBJECT_0] = events[--count];
}
assert(progress || busy);
return true;
}
+194
View File
@@ -0,0 +1,194 @@
/*
* QEMU aio implementation
*
* Copyright IBM, Corp. 2008
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.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 "qemu-common.h"
#include "block.h"
#include "qemu-queue.h"
#include "qemu_socket.h"
typedef struct AioHandler AioHandler;
/* The list of registered AIO handlers */
static QLIST_HEAD(, AioHandler) aio_handlers;
/* This is a simple lock used to protect the aio_handlers list. Specifically,
* it's used to ensure that no callbacks are removed while we're walking and
* dispatching callbacks.
*/
static int walking_handlers;
struct AioHandler
{
int fd;
IOHandler *io_read;
IOHandler *io_write;
AioFlushHandler *io_flush;
int deleted;
void *opaque;
QLIST_ENTRY(AioHandler) node;
};
static AioHandler *find_aio_handler(int fd)
{
AioHandler *node;
QLIST_FOREACH(node, &aio_handlers, node) {
if (node->fd == fd)
if (!node->deleted)
return node;
}
return NULL;
}
int qemu_aio_set_fd_handler(int fd,
IOHandler *io_read,
IOHandler *io_write,
AioFlushHandler *io_flush,
void *opaque)
{
AioHandler *node;
node = find_aio_handler(fd);
/* Are we deleting the fd handler? */
if (!io_read && !io_write) {
if (node) {
/* If the lock is held, just mark the node as deleted */
if (walking_handlers)
node->deleted = 1;
else {
/* Otherwise, delete it for real. We can't just mark it as
* deleted because deleted nodes are only cleaned up after
* releasing the walking_handlers lock.
*/
QLIST_REMOVE(node, node);
g_free(node);
}
}
} else {
if (node == NULL) {
/* Alloc and insert if it's not already there */
node = g_malloc0(sizeof(AioHandler));
node->fd = fd;
QLIST_INSERT_HEAD(&aio_handlers, node, node);
}
/* Update handler with latest information */
node->io_read = io_read;
node->io_write = io_write;
node->io_flush = io_flush;
node->opaque = opaque;
}
qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
return 0;
}
void qemu_aio_flush(void)
{
while (qemu_aio_wait());
}
bool qemu_aio_wait(void)
{
AioHandler *node;
fd_set rdfds, wrfds;
int max_fd = -1;
int ret;
bool busy;
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/
if (qemu_bh_poll()) {
return true;
}
walking_handlers = 1;
FD_ZERO(&rdfds);
FD_ZERO(&wrfds);
/* fill fd sets */
busy = false;
QLIST_FOREACH(node, &aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
*/
if (node->io_flush) {
if (node->io_flush(node->opaque) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_read) {
FD_SET(node->fd, &rdfds);
max_fd = MAX(max_fd, node->fd + 1);
}
if (!node->deleted && node->io_write) {
FD_SET(node->fd, &wrfds);
max_fd = MAX(max_fd, node->fd + 1);
}
}
walking_handlers = 0;
/* No AIO operations? Get us out of here */
if (!busy) {
return false;
}
/* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
/* if we have any readable fds, dispatch event */
if (ret > 0) {
walking_handlers = 1;
/* we have to walk very carefully in case
* qemu_aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&aio_handlers);
while (node) {
AioHandler *tmp;
if (!node->deleted &&
FD_ISSET(node->fd, &rdfds) &&
node->io_read) {
node->io_read(node->opaque);
}
if (!node->deleted &&
FD_ISSET(node->fd, &wrfds) &&
node->io_write) {
node->io_write(node->opaque);
}
tmp = node;
node = QLIST_NEXT(node, node);
if (tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
walking_handlers = 0;
}
return true;
}
+37 -115
View File
@@ -31,8 +31,6 @@
#include "config.h"
#include "monitor.h"
#include "sysemu.h"
#include "bitops.h"
#include "bitmap.h"
#include "arch_init.h"
#include "audio/audio.h"
#include "hw/pc.h"
@@ -47,7 +45,6 @@
#include "hw/pcspk.h"
#include "qemu/page_cache.h"
#include "qmp-commands.h"
#include "trace.h"
#ifdef DEBUG_ARCH_INIT
#define DPRINTF(fmt, ...) \
@@ -139,6 +136,7 @@ static struct defconfig_file {
/* Indicates it is an user config file (disabled by -no-user-config) */
bool userconfig;
} default_config_files[] = {
{ CONFIG_QEMU_DATADIR "/cpus-" TARGET_ARCH ".conf", false },
{ CONFIG_QEMU_CONFDIR "/qemu.conf", true },
{ CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf", true },
{ NULL }, /* end of list */
@@ -333,78 +331,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
static RAMBlock *last_block;
static ram_addr_t last_offset;
static unsigned long *migration_bitmap;
static uint64_t migration_dirty_pages;
static inline bool migration_bitmap_test_and_reset_dirty(MemoryRegion *mr,
ram_addr_t offset)
{
bool ret;
int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS;
ret = test_and_clear_bit(nr, migration_bitmap);
if (ret) {
migration_dirty_pages--;
}
return ret;
}
static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
ram_addr_t offset)
{
bool ret;
int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS;
ret = test_and_set_bit(nr, migration_bitmap);
if (!ret) {
migration_dirty_pages++;
}
return ret;
}
static void migration_bitmap_sync(void)
{
RAMBlock *block;
ram_addr_t addr;
uint64_t num_dirty_pages_init = migration_dirty_pages;
MigrationState *s = migrate_get_current();
static int64_t start_time;
static int64_t num_dirty_pages_period;
int64_t end_time;
if (!start_time) {
start_time = qemu_get_clock_ms(rt_clock);
}
trace_migration_bitmap_sync_start();
memory_global_sync_dirty_bitmap(get_system_memory());
QLIST_FOREACH(block, &ram_list.blocks, next) {
for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
migration_bitmap_set_dirty(block->mr, addr);
}
}
memory_region_reset_dirty(block->mr, 0, block->length,
DIRTY_MEMORY_MIGRATION);
}
trace_migration_bitmap_sync_end(migration_dirty_pages
- num_dirty_pages_init);
num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
end_time = qemu_get_clock_ms(rt_clock);
/* more than 1 second = 1000 millisecons */
if (end_time > start_time + 1000) {
s->dirty_pages_rate = num_dirty_pages_period * 1000
/ (end_time - start_time);
start_time = end_time;
num_dirty_pages_period = 0;
}
}
/*
* ram_save_block: Writes a page of memory to the stream f
@@ -427,10 +353,14 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
do {
mr = block->mr;
if (migration_bitmap_test_and_reset_dirty(mr, offset)) {
if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
uint8_t *p;
int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION);
p = memory_region_get_ram_ptr(mr) + offset;
if (is_dup_page(p)) {
@@ -480,7 +410,7 @@ static uint64_t bytes_transferred;
static ram_addr_t ram_save_remaining(void)
{
return migration_dirty_pages;
return ram_list.dirty_pages;
}
uint64_t ram_bytes_remaining(void)
@@ -535,13 +465,9 @@ static void sort_ram_list(void)
static void migration_end(void)
{
if (migration_bitmap) {
memory_global_dirty_log_stop();
g_free(migration_bitmap);
migration_bitmap = NULL;
}
memory_global_dirty_log_stop();
if (XBZRLE.cache) {
if (migrate_use_xbzrle()) {
cache_fini(XBZRLE.cache);
g_free(XBZRLE.cache);
g_free(XBZRLE.encoded_buf);
@@ -556,27 +482,17 @@ static void ram_migration_cancel(void *opaque)
migration_end();
}
static void reset_ram_globals(void)
{
last_block = NULL;
last_offset = 0;
sort_ram_list();
}
#define MAX_WAIT 50 /* ms, half buffered_file limit */
static int ram_save_setup(QEMUFile *f, void *opaque)
{
ram_addr_t addr;
RAMBlock *block;
int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
migration_bitmap = bitmap_new(ram_pages);
bitmap_set(migration_bitmap, 0, ram_pages);
migration_dirty_pages = ram_pages;
bytes_transferred = 0;
reset_ram_globals();
last_block = NULL;
last_offset = 0;
sort_ram_list();
if (migrate_use_xbzrle()) {
XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
@@ -591,8 +507,17 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
acct_clear();
}
/* Make sure all dirty bits are set */
QLIST_FOREACH(block, &ram_list.blocks, next) {
for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE);
}
}
}
memory_global_dirty_log_start();
migration_bitmap_sync();
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
@@ -613,8 +538,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
double bwidth = 0;
int ret;
int i;
uint64_t expected_downtime;
MigrationState *s = migrate_get_current();
uint64_t expected_time;
bytes_transferred_last = bytes_transferred;
bwidth = qemu_get_clock_ns(rt_clock);
@@ -653,32 +577,31 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
/* if we haven't transferred anything this round, force
* expected_downtime to a very high value, but without
* crashing */
/* if we haven't transferred anything this round, force expected_time to a
* a very high value, but without crashing */
if (bwidth == 0) {
bwidth = 0.000001;
}
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
DPRINTF("ram_save_live: expected(%" PRIu64 ") <= max(" PRIu64 ")?\n",
expected_downtime, migrate_max_downtime());
expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
if (expected_downtime <= migrate_max_downtime()) {
migration_bitmap_sync();
expected_downtime = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
s->expected_downtime = expected_downtime / 1000000; /* ns -> ms */
DPRINTF("ram_save_live: expected(%" PRIu64 ") <= max(%" PRIu64 ")?\n",
expected_time, migrate_max_downtime());
return expected_downtime <= migrate_max_downtime();
if (expected_time <= migrate_max_downtime()) {
memory_global_sync_dirty_bitmap(get_system_memory());
expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
return expected_time <= migrate_max_downtime();
}
return 0;
}
static int ram_save_complete(QEMUFile *f, void *opaque)
{
migration_bitmap_sync();
memory_global_sync_dirty_bitmap(get_system_memory());
/* try transferring iterative blocks of memory */
@@ -693,7 +616,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
}
bytes_transferred += bytes_sent;
}
migration_end();
memory_global_dirty_log_stop();
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
@@ -841,8 +764,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
memset(host, ch, TARGET_PAGE_SIZE);
#ifndef _WIN32
if (ch == 0 &&
(!kvm_enabled() || kvm_has_sync_mmu()) &&
getpagesize() <= TARGET_PAGE_SIZE) {
(!kvm_enabled() || kvm_has_sync_mmu())) {
qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
}
#endif
+1 -1
View File
@@ -34,6 +34,6 @@ int tcg_available(void);
int kvm_available(void);
int xen_available(void);
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
CpuDefinitionInfoList GCC_WEAK_DECL *arch_query_cpu_definitions(Error **errp);
#endif
+19 -99
View File
@@ -26,11 +26,13 @@
#include "qemu-aio.h"
#include "main-loop.h"
/* Anchor of the list of Bottom Halves belonging to the context */
static struct QEMUBH *first_bh;
/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
struct QEMUBH {
AioContext *ctx;
QEMUBHFunc *cb;
void *opaque;
QEMUBH *next;
@@ -39,27 +41,27 @@ struct QEMUBH {
bool deleted;
};
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
{
QEMUBH *bh;
bh = g_malloc0(sizeof(QEMUBH));
bh->ctx = ctx;
bh->cb = cb;
bh->opaque = opaque;
bh->next = ctx->first_bh;
ctx->first_bh = bh;
bh->next = first_bh;
first_bh = bh;
return bh;
}
int aio_bh_poll(AioContext *ctx)
int qemu_bh_poll(void)
{
QEMUBH *bh, **bhp, *next;
int ret;
static int nesting = 0;
ctx->walking_bh++;
nesting++;
ret = 0;
for (bh = ctx->first_bh; bh; bh = next) {
for (bh = first_bh; bh; bh = next) {
next = bh->next;
if (!bh->deleted && bh->scheduled) {
bh->scheduled = 0;
@@ -70,11 +72,11 @@ int aio_bh_poll(AioContext *ctx)
}
}
ctx->walking_bh--;
nesting--;
/* remove deleted bhs */
if (!ctx->walking_bh) {
bhp = &ctx->first_bh;
if (!nesting) {
bhp = &first_bh;
while (*bhp) {
bh = *bhp;
if (bh->deleted) {
@@ -103,7 +105,8 @@ void qemu_bh_schedule(QEMUBH *bh)
return;
bh->scheduled = 1;
bh->idle = 0;
aio_notify(bh->ctx);
/* stop the currently executing CPU to execute the BH ASAP */
qemu_notify_event();
}
void qemu_bh_cancel(QEMUBH *bh)
@@ -117,106 +120,23 @@ void qemu_bh_delete(QEMUBH *bh)
bh->deleted = 1;
}
static gboolean
aio_ctx_prepare(GSource *source, gint *timeout)
void qemu_bh_update_timeout(uint32_t *timeout)
{
AioContext *ctx = (AioContext *) source;
QEMUBH *bh;
for (bh = ctx->first_bh; bh; bh = bh->next) {
for (bh = first_bh; bh; bh = bh->next) {
if (!bh->deleted && bh->scheduled) {
if (bh->idle) {
/* idle bottom halves will be polled at least
* every 10ms */
*timeout = 10;
*timeout = MIN(10, *timeout);
} else {
/* non-idle bottom halves will be executed
* immediately */
*timeout = 0;
return true;
break;
}
}
}
return false;
}
static gboolean
aio_ctx_check(GSource *source)
{
AioContext *ctx = (AioContext *) source;
QEMUBH *bh;
for (bh = ctx->first_bh; bh; bh = bh->next) {
if (!bh->deleted && bh->scheduled) {
return true;
}
}
return aio_pending(ctx);
}
static gboolean
aio_ctx_dispatch(GSource *source,
GSourceFunc callback,
gpointer user_data)
{
AioContext *ctx = (AioContext *) source;
assert(callback == NULL);
aio_poll(ctx, false);
return true;
}
static void
aio_ctx_finalize(GSource *source)
{
AioContext *ctx = (AioContext *) source;
aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
event_notifier_cleanup(&ctx->notifier);
}
static GSourceFuncs aio_source_funcs = {
aio_ctx_prepare,
aio_ctx_check,
aio_ctx_dispatch,
aio_ctx_finalize
};
GSource *aio_get_g_source(AioContext *ctx)
{
g_source_ref(&ctx->source);
return &ctx->source;
}
void aio_notify(AioContext *ctx)
{
event_notifier_set(&ctx->notifier);
}
AioContext *aio_context_new(void)
{
AioContext *ctx;
ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
event_notifier_init(&ctx->notifier, false);
aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *)
event_notifier_test_and_clear, NULL);
return ctx;
}
void aio_context_ref(AioContext *ctx)
{
g_source_ref(&ctx->source);
}
void aio_context_unref(AioContext *ctx)
{
g_source_unref(&ctx->source);
}
void aio_flush(AioContext *ctx)
{
while (aio_poll(ctx, true));
}
-2
View File
@@ -1,2 +0,0 @@
common-obj-y += rng.o rng-egd.o
common-obj-$(CONFIG_POSIX) += rng-random.o
-224
View File
@@ -1,224 +0,0 @@
/*
* QEMU Random Number Generator Backend
*
* Copyright IBM, Corp. 2012
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* 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 "qemu/rng.h"
#include "qemu-char.h"
#include "qerror.h"
#include "hw/qdev.h" /* just for DEFINE_PROP_CHR */
#define TYPE_RNG_EGD "rng-egd"
#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
typedef struct RngEgd
{
RngBackend parent;
CharDriverState *chr;
char *chr_name;
GSList *requests;
} RngEgd;
typedef struct RngRequest
{
EntropyReceiveFunc *receive_entropy;
uint8_t *data;
void *opaque;
size_t offset;
size_t size;
} RngRequest;
static void rng_egd_request_entropy(RngBackend *b, size_t size,
EntropyReceiveFunc *receive_entropy,
void *opaque)
{
RngEgd *s = RNG_EGD(b);
RngRequest *req;
req = g_malloc(sizeof(*req));
req->offset = 0;
req->size = size;
req->receive_entropy = receive_entropy;
req->opaque = opaque;
req->data = g_malloc(req->size);
while (size > 0) {
uint8_t header[2];
uint8_t len = MIN(size, 255);
/* synchronous entropy request */
header[0] = 0x02;
header[1] = len;
qemu_chr_fe_write(s->chr, header, sizeof(header));
size -= len;
}
s->requests = g_slist_append(s->requests, req);
}
static void rng_egd_free_request(RngRequest *req)
{
g_free(req->data);
g_free(req);
}
static int rng_egd_chr_can_read(void *opaque)
{
RngEgd *s = RNG_EGD(opaque);
GSList *i;
int size = 0;
for (i = s->requests; i; i = i->next) {
RngRequest *req = i->data;
size += req->size - req->offset;
}
return size;
}
static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
{
RngEgd *s = RNG_EGD(opaque);
while (size > 0 && s->requests) {
RngRequest *req = s->requests->data;
int len = MIN(size, req->size - req->offset);
memcpy(req->data + req->offset, buf, len);
req->offset += len;
size -= len;
if (req->offset == req->size) {
s->requests = g_slist_remove_link(s->requests, s->requests);
req->receive_entropy(req->opaque, req->data, req->size);
rng_egd_free_request(req);
}
}
}
static void rng_egd_free_requests(RngEgd *s)
{
GSList *i;
for (i = s->requests; i; i = i->next) {
rng_egd_free_request(i->data);
}
g_slist_free(s->requests);
s->requests = NULL;
}
static void rng_egd_cancel_requests(RngBackend *b)
{
RngEgd *s = RNG_EGD(b);
/* We simply delete the list of pending requests. If there is data in the
* queue waiting to be read, this is okay, because there will always be
* more data than we requested originally
*/
rng_egd_free_requests(s);
}
static void rng_egd_opened(RngBackend *b, Error **errp)
{
RngEgd *s = RNG_EGD(b);
if (s->chr_name == NULL) {
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
"chardev", "a valid character device");
return;
}
s->chr = qemu_chr_find(s->chr_name);
if (s->chr == NULL) {
error_set(errp, QERR_DEVICE_NOT_FOUND, s->chr_name);
return;
}
/* FIXME we should resubmit pending requests when the CDS reconnects. */
qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
NULL, s);
}
static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
{
RngBackend *b = RNG_BACKEND(obj);
RngEgd *s = RNG_EGD(b);
if (b->opened) {
error_set(errp, QERR_PERMISSION_DENIED);
} else {
g_free(s->chr_name);
s->chr_name = g_strdup(value);
}
}
static char *rng_egd_get_chardev(Object *obj, Error **errp)
{
RngEgd *s = RNG_EGD(obj);
if (s->chr && s->chr->label) {
return g_strdup(s->chr->label);
}
return NULL;
}
static void rng_egd_init(Object *obj)
{
object_property_add_str(obj, "chardev",
rng_egd_get_chardev, rng_egd_set_chardev,
NULL);
}
static void rng_egd_finalize(Object *obj)
{
RngEgd *s = RNG_EGD(obj);
if (s->chr) {
qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
}
g_free(s->chr_name);
rng_egd_free_requests(s);
}
static void rng_egd_class_init(ObjectClass *klass, void *data)
{
RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
rbc->request_entropy = rng_egd_request_entropy;
rbc->cancel_requests = rng_egd_cancel_requests;
rbc->opened = rng_egd_opened;
}
static TypeInfo rng_egd_info = {
.name = TYPE_RNG_EGD,
.parent = TYPE_RNG_BACKEND,
.instance_size = sizeof(RngEgd),
.class_init = rng_egd_class_init,
.instance_init = rng_egd_init,
.instance_finalize = rng_egd_finalize,
};
static void register_types(void)
{
type_register_static(&rng_egd_info);
}
type_init(register_types);
-161
View File
@@ -1,161 +0,0 @@
/*
* QEMU Random Number Generator Backend
*
* Copyright IBM, Corp. 2012
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* 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 "qemu/rng-random.h"
#include "qemu/rng.h"
#include "qerror.h"
#include "main-loop.h"
struct RndRandom
{
RngBackend parent;
int fd;
char *filename;
EntropyReceiveFunc *receive_func;
void *opaque;
size_t size;
};
/**
* A simple and incomplete backend to request entropy from /dev/random.
*
* This backend exposes an additional "filename" property that can be used to
* set the filename to use to open the backend.
*/
static void entropy_available(void *opaque)
{
RndRandom *s = RNG_RANDOM(opaque);
uint8_t buffer[s->size];
ssize_t len;
len = read(s->fd, buffer, s->size);
g_assert(len != -1);
s->receive_func(s->opaque, buffer, len);
s->receive_func = NULL;
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
}
static void rng_random_request_entropy(RngBackend *b, size_t size,
EntropyReceiveFunc *receive_entropy,
void *opaque)
{
RndRandom *s = RNG_RANDOM(b);
if (s->receive_func) {
s->receive_func(s->opaque, NULL, 0);
}
s->receive_func = receive_entropy;
s->opaque = opaque;
s->size = size;
qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
}
static void rng_random_opened(RngBackend *b, Error **errp)
{
RndRandom *s = RNG_RANDOM(b);
if (s->filename == NULL) {
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
"filename", "a valid filename");
} else {
s->fd = open(s->filename, O_RDONLY | O_NONBLOCK);
if (s->fd == -1) {
error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
}
}
}
static char *rng_random_get_filename(Object *obj, Error **errp)
{
RndRandom *s = RNG_RANDOM(obj);
if (s->filename) {
return g_strdup(s->filename);
}
return NULL;
}
static void rng_random_set_filename(Object *obj, const char *filename,
Error **errp)
{
RngBackend *b = RNG_BACKEND(obj);
RndRandom *s = RNG_RANDOM(obj);
if (b->opened) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
if (s->filename) {
g_free(s->filename);
}
s->filename = g_strdup(filename);
}
static void rng_random_init(Object *obj)
{
RndRandom *s = RNG_RANDOM(obj);
object_property_add_str(obj, "filename",
rng_random_get_filename,
rng_random_set_filename,
NULL);
s->filename = g_strdup("/dev/random");
}
static void rng_random_finalize(Object *obj)
{
RndRandom *s = RNG_RANDOM(obj);
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
if (s->fd != -1) {
close(s->fd);
}
g_free(s->filename);
}
static void rng_random_class_init(ObjectClass *klass, void *data)
{
RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
rbc->request_entropy = rng_random_request_entropy;
rbc->opened = rng_random_opened;
}
static TypeInfo rng_random_info = {
.name = TYPE_RNG_RANDOM,
.parent = TYPE_RNG_BACKEND,
.instance_size = sizeof(RndRandom),
.class_init = rng_random_class_init,
.instance_init = rng_random_init,
.instance_finalize = rng_random_finalize,
};
static void register_types(void)
{
type_register_static(&rng_random_info);
}
type_init(register_types);
-93
View File
@@ -1,93 +0,0 @@
/*
* QEMU Random Number Generator Backend
*
* Copyright IBM, Corp. 2012
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* 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 "qemu/rng.h"
#include "qerror.h"
void rng_backend_request_entropy(RngBackend *s, size_t size,
EntropyReceiveFunc *receive_entropy,
void *opaque)
{
RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
if (k->request_entropy) {
k->request_entropy(s, size, receive_entropy, opaque);
}
}
void rng_backend_cancel_requests(RngBackend *s)
{
RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
if (k->cancel_requests) {
k->cancel_requests(s);
}
}
static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
{
RngBackend *s = RNG_BACKEND(obj);
return s->opened;
}
void rng_backend_open(RngBackend *s, Error **errp)
{
object_property_set_bool(OBJECT(s), true, "opened", errp);
}
static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
{
RngBackend *s = RNG_BACKEND(obj);
RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
if (value == s->opened) {
return;
}
if (!value && s->opened) {
error_set(errp, QERR_PERMISSION_DENIED);
return;
}
if (k->opened) {
k->opened(s, errp);
}
if (!error_is_set(errp)) {
s->opened = value;
}
}
static void rng_backend_init(Object *obj)
{
object_property_add_bool(obj, "opened",
rng_backend_prop_get_opened,
rng_backend_prop_set_opened,
NULL);
}
static TypeInfo rng_backend_info = {
.name = TYPE_RNG_BACKEND,
.parent = TYPE_OBJECT,
.instance_size = sizeof(RngBackend),
.instance_init = rng_backend_init,
.class_size = sizeof(RngBackendClass),
.abstract = true,
};
static void register_types(void)
{
type_register_static(&rng_backend_info);
}
type_init(register_types);
+28 -30
View File
@@ -423,23 +423,20 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
error:
DPRINTF("Error reading sector %" PRId64 "\n", sector);
qemu_file_set_error(f, ret);
g_free(blk->buf);
g_free(blk);
return ret;
return 0;
}
/* return value:
* 0: too much data for max_downtime
* 1: few enough data for max_downtime
*/
static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
{
BlkMigDevState *bmds;
int ret = 1;
int ret = 0;
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
ret = mig_save_device_dirty(f, bmds, is_async);
if (ret <= 0) {
if (mig_save_device_dirty(f, bmds, is_async) == 0) {
ret = 1;
break;
}
}
@@ -447,10 +444,9 @@ static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
return ret;
}
static int flush_blks(QEMUFile *f)
static void flush_blks(QEMUFile* f)
{
BlkMigBlock *blk;
int ret = 0;
DPRINTF("%s Enter submitted %d read_done %d transferred %d\n",
__FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
@@ -461,7 +457,7 @@ static int flush_blks(QEMUFile *f)
break;
}
if (blk->ret < 0) {
ret = blk->ret;
qemu_file_set_error(f, blk->ret);
break;
}
blk_send(f, blk);
@@ -478,7 +474,6 @@ static int flush_blks(QEMUFile *f)
DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
block_mig_state.submitted, block_mig_state.read_done,
block_mig_state.transferred);
return ret;
}
static int64_t get_remaining_dirty(void)
@@ -524,8 +519,6 @@ static void blk_mig_cleanup(void)
BlkMigDevState *bmds;
BlkMigBlock *blk;
bdrv_drain_all();
set_dirty_tracking(0);
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
@@ -560,7 +553,9 @@ static int block_save_setup(QEMUFile *f, void *opaque)
/* start track dirty blocks */
set_dirty_tracking(1);
ret = flush_blks(f);
flush_blks(f);
ret = qemu_file_get_error(f);
if (ret) {
blk_mig_cleanup();
return ret;
@@ -580,7 +575,9 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
DPRINTF("Enter save live iterate submitted %d transferred %d\n",
block_mig_state.submitted, block_mig_state.transferred);
ret = flush_blks(f);
flush_blks(f);
ret = qemu_file_get_error(f);
if (ret) {
blk_mig_cleanup();
return ret;
@@ -599,19 +596,16 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
block_mig_state.bulk_completed = 1;
}
} else {
ret = blk_mig_save_dirty_block(f, 1);
if (ret != 0) {
if (blk_mig_save_dirty_block(f, 1) == 0) {
/* no more dirty blocks */
break;
}
}
}
if (ret) {
blk_mig_cleanup();
return ret;
}
ret = flush_blks(f);
flush_blks(f);
ret = qemu_file_get_error(f);
if (ret) {
blk_mig_cleanup();
return ret;
@@ -629,7 +623,9 @@ static int block_save_complete(QEMUFile *f, void *opaque)
DPRINTF("Enter save live complete submitted %d transferred %d\n",
block_mig_state.submitted, block_mig_state.transferred);
ret = flush_blks(f);
flush_blks(f);
ret = qemu_file_get_error(f);
if (ret) {
blk_mig_cleanup();
return ret;
@@ -641,16 +637,18 @@ static int block_save_complete(QEMUFile *f, void *opaque)
all async read completed */
assert(block_mig_state.submitted == 0);
do {
ret = blk_mig_save_dirty_block(f, 0);
} while (ret == 0);
while (blk_mig_save_dirty_block(f, 0) != 0) {
/* Do nothing */
}
blk_mig_cleanup();
/* report completion */
qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
ret = qemu_file_get_error(f);
if (ret) {
return ret;
}
/* report completion */
qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
DPRINTF("Block migration completed\n");
+313 -693
View File
File diff suppressed because it is too large. Load diff
+12 -37
View File
@@ -6,11 +6,9 @@
#include "qemu-option.h"
#include "qemu-coroutine.h"
#include "qobject.h"
#include "qapi-types.h"
/* block.c */
typedef struct BlockDriver BlockDriver;
typedef struct BlockJob BlockJob;
typedef struct BlockDriverInfo {
/* in bytes, 0 if irrelevant */
@@ -91,23 +89,21 @@ typedef struct BlockDevOps {
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1)
typedef enum {
BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
BLOCK_ERR_STOP_ANY
} BlockErrorAction;
typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
typedef struct BDRVReopenState {
BlockDriverState *bs;
int flags;
void *opaque;
} BDRVReopenState;
typedef enum {
BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
} BlockQMPEventAction;
void bdrv_iostatus_enable(BlockDriverState *bs);
void bdrv_iostatus_reset(BlockDriverState *bs);
void bdrv_iostatus_disable(BlockDriverState *bs);
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs);
void bdrv_iostatus_set_err(BlockDriverState *bs, int error);
void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
BlockQMPEventAction action, int is_read);
void bdrv_info_print(Monitor *mon, const QObject *data);
void bdrv_info(Monitor *mon, QObject **ret_data);
void bdrv_stats_print(Monitor *mon, const QObject *data);
@@ -133,19 +129,9 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
void bdrv_delete(BlockDriverState *bs);
int bdrv_parse_cache_flags(const char *mode, int *flags);
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
int bdrv_open_backing_file(BlockDriverState *bs);
int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv);
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
BlockDriverState *bs, int flags);
int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
BlockReopenQueue *queue, Error **errp);
void bdrv_reopen_commit(BDRVReopenState *reopen_state);
void bdrv_reopen_abort(BDRVReopenState *reopen_state);
void bdrv_close(BlockDriverState *bs);
void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify);
int bdrv_attach_dev(BlockDriverState *bs, void *dev);
void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev);
void bdrv_detach_dev(BlockDriverState *bs, void *dev);
@@ -200,11 +186,6 @@ int bdrv_commit_all(void);
int bdrv_change_backing_file(BlockDriverState *bs,
const char *backing_file, const char *backing_fmt);
void bdrv_register(BlockDriver *bdrv);
int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
BlockDriverState *base);
BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
BlockDriverState *bs);
BlockDriverState *bdrv_find_base(BlockDriverState *bs);
typedef struct BdrvCheckResult {
@@ -279,12 +260,9 @@ int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
int *pnum);
void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
BlockdevOnError on_write_error);
BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read);
BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error);
void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
bool is_read, int error);
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
BlockErrorAction on_write_error);
BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read);
int bdrv_is_read_only(BlockDriverState *bs);
int bdrv_is_sg(BlockDriverState *bs);
int bdrv_enable_write_cache(BlockDriverState *bs);
@@ -315,8 +293,6 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size);
void bdrv_get_full_backing_filename(BlockDriverState *bs,
char *dest, size_t sz);
BlockInfo *bdrv_query_info(BlockDriverState *s);
BlockStats *bdrv_query_stats(const BlockDriverState *bs);
int bdrv_can_snapshot(BlockDriverState *bs);
int bdrv_is_snapshot(BlockDriverState *bs);
BlockDriverState *bdrv_snapshots(void);
@@ -354,9 +330,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable);
int bdrv_get_dirty(BlockDriverState *bs, int64_t sector);
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector);
void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors);
int64_t bdrv_get_dirty_count(BlockDriverState *bs);
void bdrv_enable_copy_on_read(BlockDriverState *bs);
+3 -12
View File
@@ -2,19 +2,10 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.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 += parallels.o blkdebug.o blkverify.o
block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
block-obj-y += stream.o
block-obj-$(CONFIG_WIN32) += raw-win32.o
block-obj-$(CONFIG_POSIX) += raw-posix.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
ifeq ($(CONFIG_POSIX),y)
block-obj-y += nbd.o sheepdog.o
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
block-obj-$(CONFIG_CURL) += curl.o
block-obj-$(CONFIG_RBD) += rbd.o
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
endif
common-obj-y += stream.o
common-obj-y += commit.o
common-obj-y += mirror.o
+7 -9
View File
@@ -28,7 +28,6 @@
typedef struct BDRVBlkdebugState {
int state;
int new_state;
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
} BDRVBlkdebugState;
@@ -41,7 +40,7 @@ typedef struct BlkdebugAIOCB {
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
static const AIOCBInfo blkdebug_aiocb_info = {
static AIOPool blkdebug_aio_pool = {
.aiocb_size = sizeof(BlkdebugAIOCB),
.cancel = blkdebug_aio_cancel,
};
@@ -335,7 +334,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
return NULL;
}
acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&blkdebug_aio_pool, bs, cb, opaque);
acb->ret = -error;
bh = qemu_bh_new(error_callback_bh, acb);
@@ -404,12 +403,12 @@ static void blkdebug_close(BlockDriverState *bs)
}
static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
bool injected)
int old_state, bool injected)
{
BDRVBlkdebugState *s = bs->opaque;
/* Only process rules for the current state */
if (rule->state && rule->state != s->state) {
if (rule->state && rule->state != old_state) {
return injected;
}
@@ -424,7 +423,7 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
break;
case ACTION_SET_STATE:
s->new_state = rule->options.set_state.new_state;
s->state = rule->options.set_state.new_state;
break;
}
return injected;
@@ -434,16 +433,15 @@ static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
{
BDRVBlkdebugState *s = bs->opaque;
struct BlkdebugRule *rule;
int old_state = s->state;
bool injected;
assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
injected = false;
s->new_state = s->state;
QLIST_FOREACH(rule, &s->rules[event], next) {
injected = process_rule(bs, rule, injected);
injected = process_rule(bs, rule, old_state, injected);
}
s->state = s->new_state;
}
static int64_t blkdebug_getlength(BlockDriverState *bs)
+2 -2
View File
@@ -48,7 +48,7 @@ static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
}
}
static const AIOCBInfo blkverify_aiocb_info = {
static AIOPool blkverify_aio_pool = {
.aiocb_size = sizeof(BlkverifyAIOCB),
.cancel = blkverify_aio_cancel,
};
@@ -233,7 +233,7 @@ static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
BlockDriverCompletionFunc *cb,
void *opaque)
{
BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque);
BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aio_pool, bs, cb, opaque);
acb->bh = NULL;
acb->is_write = is_write;
-259
View File
@@ -1,259 +0,0 @@
/*
* Live block commit
*
* Copyright Red Hat, Inc. 2012
*
* Authors:
* Jeff Cody <jcody@redhat.com>
* Based on stream.c by Stefan Hajnoczi
*
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "trace.h"
#include "block_int.h"
#include "blockjob.h"
#include "qemu/ratelimit.h"
enum {
/*
* Size of data buffer for populating the image file. This should be large
* enough to process multiple clusters in a single call, so that populating
* contiguous regions of the image is efficient.
*/
COMMIT_BUFFER_SIZE = 512 * 1024, /* in bytes */
};
#define SLICE_TIME 100000000ULL /* ns */
typedef struct CommitBlockJob {
BlockJob common;
RateLimit limit;
BlockDriverState *active;
BlockDriverState *top;
BlockDriverState *base;
BlockdevOnError on_error;
int base_flags;
int orig_overlay_flags;
} CommitBlockJob;
static int coroutine_fn commit_populate(BlockDriverState *bs,
BlockDriverState *base,
int64_t sector_num, int nb_sectors,
void *buf)
{
int ret = 0;
ret = bdrv_read(bs, sector_num, buf, nb_sectors);
if (ret) {
return ret;
}
ret = bdrv_write(base, sector_num, buf, nb_sectors);
if (ret) {
return ret;
}
return 0;
}
static void coroutine_fn commit_run(void *opaque)
{
CommitBlockJob *s = opaque;
BlockDriverState *active = s->active;
BlockDriverState *top = s->top;
BlockDriverState *base = s->base;
BlockDriverState *overlay_bs = NULL;
int64_t sector_num, end;
int ret = 0;
int n = 0;
void *buf;
int bytes_written = 0;
int64_t base_len;
ret = s->common.len = bdrv_getlength(top);
if (s->common.len < 0) {
goto exit_restore_reopen;
}
ret = base_len = bdrv_getlength(base);
if (base_len < 0) {
goto exit_restore_reopen;
}
if (base_len < s->common.len) {
ret = bdrv_truncate(base, s->common.len);
if (ret) {
goto exit_restore_reopen;
}
}
overlay_bs = bdrv_find_overlay(active, top);
end = s->common.len >> BDRV_SECTOR_BITS;
buf = qemu_blockalign(top, COMMIT_BUFFER_SIZE);
for (sector_num = 0; sector_num < end; sector_num += n) {
uint64_t delay_ns = 0;
bool copy;
wait:
/* Note that even when no rate limit is applied we need to yield
* with no pending I/O here so that qemu_aio_flush() returns.
*/
block_job_sleep_ns(&s->common, rt_clock, delay_ns);
if (block_job_is_cancelled(&s->common)) {
break;
}
/* Copy if allocated above the base */
ret = bdrv_co_is_allocated_above(top, base, sector_num,
COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE,
&n);
copy = (ret == 1);
trace_commit_one_iteration(s, sector_num, n, ret);
if (copy) {
if (s->common.speed) {
delay_ns = ratelimit_calculate_delay(&s->limit, n);
if (delay_ns > 0) {
goto wait;
}
}
ret = commit_populate(top, base, sector_num, n, buf);
bytes_written += n * BDRV_SECTOR_SIZE;
}
if (ret < 0) {
if (s->on_error == BLOCKDEV_ON_ERROR_STOP ||
s->on_error == BLOCKDEV_ON_ERROR_REPORT||
(s->on_error == BLOCKDEV_ON_ERROR_ENOSPC && ret == -ENOSPC)) {
goto exit_free_buf;
} else {
n = 0;
continue;
}
}
/* Publish progress */
s->common.offset += n * BDRV_SECTOR_SIZE;
}
ret = 0;
if (!block_job_is_cancelled(&s->common) && sector_num == end) {
/* success */
ret = bdrv_drop_intermediate(active, top, base);
}
exit_free_buf:
qemu_vfree(buf);
exit_restore_reopen:
/* restore base open flags here if appropriate (e.g., change the base back
* to r/o). These reopens do not need to be atomic, since we won't abort
* even on failure here */
if (s->base_flags != bdrv_get_flags(base)) {
bdrv_reopen(base, s->base_flags, NULL);
}
if (s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) {
bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL);
}
block_job_completed(&s->common, ret);
}
static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
CommitBlockJob *s = container_of(job, CommitBlockJob, common);
if (speed < 0) {
error_set(errp, QERR_INVALID_PARAMETER, "speed");
return;
}
ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
}
static BlockJobType commit_job_type = {
.instance_size = sizeof(CommitBlockJob),
.job_type = "commit",
.set_speed = commit_set_speed,
};
void commit_start(BlockDriverState *bs, BlockDriverState *base,
BlockDriverState *top, int64_t speed,
BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
void *opaque, Error **errp)
{
CommitBlockJob *s;
BlockReopenQueue *reopen_queue = NULL;
int orig_overlay_flags;
int orig_base_flags;
BlockDriverState *overlay_bs;
Error *local_err = NULL;
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
error_set(errp, QERR_INVALID_PARAMETER_COMBINATION);
return;
}
/* Once we support top == active layer, remove this check */
if (top == bs) {
error_setg(errp,
"Top image as the active layer is currently unsupported");
return;
}
if (top == base) {
error_setg(errp, "Invalid files for merge: top and base are the same");
return;
}
overlay_bs = bdrv_find_overlay(bs, top);
if (overlay_bs == NULL) {
error_setg(errp, "Could not find overlay image for %s:", top->filename);
return;
}
orig_base_flags = bdrv_get_flags(base);
orig_overlay_flags = bdrv_get_flags(overlay_bs);
/* convert base & overlay_bs to r/w, if necessary */
if (!(orig_base_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, base,
orig_base_flags | BDRV_O_RDWR);
}
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs,
orig_overlay_flags | BDRV_O_RDWR);
}
if (reopen_queue) {
bdrv_reopen_multiple(reopen_queue, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
}
s = block_job_create(&commit_job_type, bs, speed, cb, opaque, errp);
if (!s) {
return;
}
s->base = base;
s->top = top;
s->active = bs;
s->base_flags = orig_base_flags;
s->orig_overlay_flags = orig_overlay_flags;
s->on_error = on_error;
s->common.co = qemu_coroutine_create(commit_run);
trace_commit_start(bs, base, top, s, s->common.co, opaque);
qemu_coroutine_enter(s->common.co, s);
}
+2 -2
View File
@@ -438,7 +438,7 @@ static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
// Do we have to implement canceling? Seems to work without...
}
static const AIOCBInfo curl_aiocb_info = {
static AIOPool curl_aio_pool = {
.aiocb_size = sizeof(CURLAIOCB),
.cancel = curl_aio_cancel,
};
@@ -505,7 +505,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
{
CURLAIOCB *acb;
acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
acb->qiov = qiov;
acb->sector_num = sector_num;
-624
View File
@@ -1,624 +0,0 @@
/*
* GlusterFS backend for QEMU
*
* Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
*
* Pipe handling mechanism in AIO implementation is derived from
* block/rbd.c. Hence,
*
* 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 "block_int.h"
#include "qemu_socket.h"
#include "uri.h"
typedef struct GlusterAIOCB {
BlockDriverAIOCB common;
int64_t size;
int ret;
bool *finished;
QEMUBH *bh;
} GlusterAIOCB;
typedef struct BDRVGlusterState {
struct glfs *glfs;
int fds[2];
struct glfs_fd *fd;
int qemu_aio_count;
int event_reader_pos;
GlusterAIOCB *event_acb;
} BDRVGlusterState;
#define GLUSTER_FD_READ 0
#define GLUSTER_FD_WRITE 1
typedef struct GlusterConf {
char *server;
int port;
char *volname;
char *image;
char *transport;
} GlusterConf;
static void qemu_gluster_gconf_free(GlusterConf *gconf)
{
g_free(gconf->server);
g_free(gconf->volname);
g_free(gconf->image);
g_free(gconf->transport);
g_free(gconf);
}
static int parse_volume_options(GlusterConf *gconf, char *path)
{
char *p, *q;
if (!path) {
return -EINVAL;
}
/* volume */
p = q = path + strspn(path, "/");
p += strcspn(p, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->volname = g_strndup(q, p - q);
/* image */
p += strspn(p, "/");
if (*p == '\0') {
return -EINVAL;
}
gconf->image = g_strdup(p);
return 0;
}
/*
* file=gluster[+transport]://[server[:port]]/volname/image[?socket=...]
*
* 'gluster' is the protocol.
*
* 'transport' specifies the transport type used to connect to gluster
* management daemon (glusterd). Valid transport types are
* tcp, unix and rdma. If a transport type isn't specified, then tcp
* type is assumed.
*
* 'server' specifies the server where the volume file specification for
* the given volume resides. This can be either hostname, ipv4 address
* or ipv6 address. ipv6 address needs to be within square brackets [ ].
* If transport type is 'unix', then 'server' field should not be specifed.
* The 'socket' field needs to be populated with the path to unix domain
* socket.
*
* 'port' is the port number on which glusterd is listening. This is optional
* and if not specified, QEMU will send 0 which will make gluster to use the
* default port. If the transport type is unix, then 'port' should not be
* specified.
*
* 'volname' is the name of the gluster volume which contains the VM image.
*
* 'image' is the path to the actual VM image that resides on gluster volume.
*
* Examples:
*
* file=gluster://1.2.3.4/testvol/a.img
* file=gluster+tcp://1.2.3.4/testvol/a.img
* file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
* file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
* file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
* file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
* file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
* file=gluster+rdma://1.2.3.4:24007/testvol/a.img
*/
static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
{
URI *uri;
QueryParams *qp = NULL;
bool is_unix = false;
int ret = 0;
uri = uri_parse(filename);
if (!uri) {
return -EINVAL;
}
/* transport */
if (!strcmp(uri->scheme, "gluster")) {
gconf->transport = g_strdup("tcp");
} else if (!strcmp(uri->scheme, "gluster+tcp")) {
gconf->transport = g_strdup("tcp");
} else if (!strcmp(uri->scheme, "gluster+unix")) {
gconf->transport = g_strdup("unix");
is_unix = true;
} else if (!strcmp(uri->scheme, "gluster+rdma")) {
gconf->transport = g_strdup("rdma");
} else {
ret = -EINVAL;
goto out;
}
ret = parse_volume_options(gconf, uri->path);
if (ret < 0) {
goto out;
}
qp = query_params_parse(uri->query);
if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
ret = -EINVAL;
goto out;
}
if (is_unix) {
if (uri->server || uri->port) {
ret = -EINVAL;
goto out;
}
if (strcmp(qp->p[0].name, "socket")) {
ret = -EINVAL;
goto out;
}
gconf->server = g_strdup(qp->p[0].value);
} else {
gconf->server = g_strdup(uri->server);
gconf->port = uri->port;
}
out:
if (qp) {
query_params_free(qp);
}
uri_free(uri);
return ret;
}
static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename)
{
struct glfs *glfs = NULL;
int ret;
int old_errno;
ret = qemu_gluster_parseuri(gconf, filename);
if (ret < 0) {
error_report("Usage: file=gluster[+transport]://[server[:port]]/"
"volname/image[?socket=...]");
errno = -ret;
goto out;
}
glfs = glfs_new(gconf->volname);
if (!glfs) {
goto out;
}
ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->server,
gconf->port);
if (ret < 0) {
goto out;
}
/*
* TODO: Use GF_LOG_ERROR instead of hard code value of 4 here when
* GlusterFS makes GF_LOG_* macros available to libgfapi users.
*/
ret = glfs_set_logging(glfs, "-", 4);
if (ret < 0) {
goto out;
}
ret = glfs_init(glfs);
if (ret) {
error_report("Gluster connection failed for server=%s port=%d "
"volume=%s image=%s transport=%s\n", gconf->server, gconf->port,
gconf->volname, gconf->image, gconf->transport);
goto out;
}
return glfs;
out:
if (glfs) {
old_errno = errno;
glfs_fini(glfs);
errno = old_errno;
}
return NULL;
}
static void qemu_gluster_complete_aio(GlusterAIOCB *acb, BDRVGlusterState *s)
{
int ret;
bool *finished = acb->finished;
BlockDriverCompletionFunc *cb = acb->common.cb;
void *opaque = acb->common.opaque;
if (!acb->ret || acb->ret == acb->size) {
ret = 0; /* Success */
} else if (acb->ret < 0) {
ret = acb->ret; /* Read/Write failed */
} else {
ret = -EIO; /* Partial read/write - fail it */
}
s->qemu_aio_count--;
qemu_aio_release(acb);
cb(opaque, ret);
if (finished) {
*finished = true;
}
}
static void qemu_gluster_aio_event_reader(void *opaque)
{
BDRVGlusterState *s = opaque;
ssize_t ret;
do {
char *p = (char *)&s->event_acb;
ret = read(s->fds[GLUSTER_FD_READ], p + s->event_reader_pos,
sizeof(s->event_acb) - s->event_reader_pos);
if (ret > 0) {
s->event_reader_pos += ret;
if (s->event_reader_pos == sizeof(s->event_acb)) {
s->event_reader_pos = 0;
qemu_gluster_complete_aio(s->event_acb, s);
}
}
} while (ret < 0 && errno == EINTR);
}
static int qemu_gluster_aio_flush_cb(void *opaque)
{
BDRVGlusterState *s = opaque;
return (s->qemu_aio_count > 0);
}
static int qemu_gluster_open(BlockDriverState *bs, const char *filename,
int bdrv_flags)
{
BDRVGlusterState *s = bs->opaque;
int open_flags = O_BINARY;
int ret = 0;
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
s->glfs = qemu_gluster_init(gconf, filename);
if (!s->glfs) {
ret = -errno;
goto out;
}
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;
}
s->fd = glfs_open(s->glfs, gconf->image, open_flags);
if (!s->fd) {
ret = -errno;
goto out;
}
ret = qemu_pipe(s->fds);
if (ret < 0) {
ret = -errno;
goto out;
}
fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK);
qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ],
qemu_gluster_aio_event_reader, NULL, qemu_gluster_aio_flush_cb, s);
out:
qemu_gluster_gconf_free(gconf);
if (!ret) {
return ret;
}
if (s->fd) {
glfs_close(s->fd);
}
if (s->glfs) {
glfs_fini(s->glfs);
}
return ret;
}
static int qemu_gluster_create(const char *filename,
QEMUOptionParameter *options)
{
struct glfs *glfs;
struct glfs_fd *fd;
int ret = 0;
int64_t total_size = 0;
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
glfs = qemu_gluster_init(gconf, filename);
if (!glfs) {
ret = -errno;
goto out;
}
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
fd = glfs_creat(glfs, gconf->image,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
if (!fd) {
ret = -errno;
} else {
if (glfs_ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
ret = -errno;
}
if (glfs_close(fd) != 0) {
ret = -errno;
}
}
out:
qemu_gluster_gconf_free(gconf);
if (glfs) {
glfs_fini(glfs);
}
return ret;
}
static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb)
{
GlusterAIOCB *acb = (GlusterAIOCB *)blockacb;
bool finished = false;
acb->finished = &finished;
while (!finished) {
qemu_aio_wait();
}
}
static const AIOCBInfo gluster_aiocb_info = {
.aiocb_size = sizeof(GlusterAIOCB),
.cancel = qemu_gluster_aio_cancel,
};
static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
{
GlusterAIOCB *acb = (GlusterAIOCB *)arg;
BlockDriverState *bs = acb->common.bs;
BDRVGlusterState *s = bs->opaque;
int retval;
acb->ret = ret;
retval = qemu_write_full(s->fds[GLUSTER_FD_WRITE], &acb, sizeof(acb));
if (retval != sizeof(acb)) {
/*
* Gluster AIO callback thread failed to notify the waiting
* QEMU thread about IO completion.
*
* Complete this IO request and make the disk inaccessible for
* subsequent reads and writes.
*/
error_report("Gluster failed to notify QEMU about IO completion");
qemu_mutex_lock_iothread(); /* We are in gluster thread context */
acb->common.cb(acb->common.opaque, -EIO);
qemu_aio_release(acb);
s->qemu_aio_count--;
close(s->fds[GLUSTER_FD_READ]);
close(s->fds[GLUSTER_FD_WRITE]);
qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL,
NULL);
bs->drv = NULL; /* Make the disk inaccessible */
qemu_mutex_unlock_iothread();
}
}
static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int write)
{
int ret;
GlusterAIOCB *acb;
BDRVGlusterState *s = bs->opaque;
size_t size;
off_t offset;
offset = sector_num * BDRV_SECTOR_SIZE;
size = nb_sectors * BDRV_SECTOR_SIZE;
s->qemu_aio_count++;
acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
acb->size = size;
acb->ret = 0;
acb->finished = NULL;
if (write) {
ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
&gluster_finish_aiocb, acb);
} else {
ret = glfs_preadv_async(s->fd, qiov->iov, qiov->niov, offset, 0,
&gluster_finish_aiocb, acb);
}
if (ret < 0) {
goto out;
}
return &acb->common;
out:
s->qemu_aio_count--;
qemu_aio_release(acb);
return NULL;
}
static BlockDriverAIOCB *qemu_gluster_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
}
static BlockDriverAIOCB *qemu_gluster_aio_writev(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
}
static BlockDriverAIOCB *qemu_gluster_aio_flush(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque)
{
int ret;
GlusterAIOCB *acb;
BDRVGlusterState *s = bs->opaque;
acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
acb->size = 0;
acb->ret = 0;
acb->finished = NULL;
s->qemu_aio_count++;
ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
if (ret < 0) {
goto out;
}
return &acb->common;
out:
s->qemu_aio_count--;
qemu_aio_release(acb);
return NULL;
}
static int64_t qemu_gluster_getlength(BlockDriverState *bs)
{
BDRVGlusterState *s = bs->opaque;
int64_t ret;
ret = glfs_lseek(s->fd, 0, SEEK_END);
if (ret < 0) {
return -errno;
} else {
return ret;
}
}
static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs)
{
BDRVGlusterState *s = bs->opaque;
struct stat st;
int ret;
ret = glfs_fstat(s->fd, &st);
if (ret < 0) {
return -errno;
} else {
return st.st_blocks * 512;
}
}
static void qemu_gluster_close(BlockDriverState *bs)
{
BDRVGlusterState *s = bs->opaque;
close(s->fds[GLUSTER_FD_READ]);
close(s->fds[GLUSTER_FD_WRITE]);
qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL, NULL);
if (s->fd) {
glfs_close(s->fd);
s->fd = NULL;
}
glfs_fini(s->glfs);
}
static QEMUOptionParameter qemu_gluster_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
.type = OPT_SIZE,
.help = "Virtual disk size"
},
{ NULL }
};
static BlockDriver bdrv_gluster = {
.format_name = "gluster",
.protocol_name = "gluster",
.instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open,
.bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
.create_options = qemu_gluster_create_options,
};
static BlockDriver bdrv_gluster_tcp = {
.format_name = "gluster",
.protocol_name = "gluster+tcp",
.instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open,
.bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
.create_options = qemu_gluster_create_options,
};
static BlockDriver bdrv_gluster_unix = {
.format_name = "gluster",
.protocol_name = "gluster+unix",
.instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open,
.bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
.create_options = qemu_gluster_create_options,
};
static BlockDriver bdrv_gluster_rdma = {
.format_name = "gluster",
.protocol_name = "gluster+rdma",
.instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open,
.bdrv_close = qemu_gluster_close,
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
.create_options = qemu_gluster_create_options,
};
static void bdrv_gluster_init(void)
{
bdrv_register(&bdrv_gluster_rdma);
bdrv_register(&bdrv_gluster_unix);
bdrv_register(&bdrv_gluster_tcp);
bdrv_register(&bdrv_gluster);
}
block_init(bdrv_gluster_init);
+193 -83
View File
@@ -65,6 +65,13 @@ typedef struct IscsiAIOCB {
#endif
} IscsiAIOCB;
struct IscsiTask {
IscsiLun *iscsilun;
BlockDriverState *bs;
int status;
int complete;
};
static void
iscsi_bh_cb(void *p)
{
@@ -126,7 +133,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
}
}
static const AIOCBInfo iscsi_aiocb_info = {
static AIOPool iscsi_aio_pool = {
.aiocb_size = sizeof(IscsiAIOCB),
.cancel = iscsi_aio_cancel,
};
@@ -227,7 +234,7 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
uint64_t lba;
struct iscsi_data data;
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
acb->iscsilun = iscsilun;
@@ -255,6 +262,10 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
acb->task->xfer_dir = SCSI_XFER_WRITE;
acb->task->cdb_size = 16;
acb->task->cdb[0] = 0x8a;
if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
/* set FUA on writes when cache mode is write through */
acb->task->cdb[1] |= 0x04;
}
lba = sector_qemu2lun(sector_num, iscsilun);
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
@@ -318,7 +329,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
acb->iscsilun = iscsilun;
@@ -373,7 +384,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
*(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
break;
}
if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
iscsi_aio_read16_cb,
NULL,
@@ -423,7 +434,7 @@ iscsi_aio_flush(BlockDriverState *bs,
struct iscsi_context *iscsi = iscsilun->iscsi;
IscsiAIOCB *acb;
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
acb->iscsilun = iscsilun;
acb->canceled = 0;
@@ -476,7 +487,7 @@ iscsi_aio_discard(BlockDriverState *bs,
IscsiAIOCB *acb;
struct unmap_list list[1];
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
acb->iscsilun = iscsilun;
acb->canceled = 0;
@@ -551,7 +562,7 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
assert(req == SG_IO);
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
acb->iscsilun = iscsilun;
acb->canceled = 0;
@@ -658,6 +669,163 @@ iscsi_getlength(BlockDriverState *bs)
return len;
}
static void
iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
struct IscsiTask *itask = opaque;
struct scsi_readcapacity16 *rc16;
struct scsi_task *task = command_data;
if (status != 0) {
error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
iscsi_get_error(iscsi));
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
rc16 = scsi_datain_unmarshall(task);
if (rc16 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
itask->iscsilun->block_size = rc16->block_length;
itask->iscsilun->num_blocks = rc16->returned_lba + 1;
itask->bs->total_sectors = itask->iscsilun->num_blocks *
itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
itask->status = 0;
itask->complete = 1;
scsi_free_scsi_task(task);
}
static void
iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
struct IscsiTask *itask = opaque;
struct scsi_readcapacity10 *rc10;
struct scsi_task *task = command_data;
if (status != 0) {
error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
iscsi_get_error(iscsi));
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
rc10 = scsi_datain_unmarshall(task);
if (rc10 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
itask->iscsilun->block_size = rc10->block_size;
if (rc10->lba == 0) {
/* blank disk loaded */
itask->iscsilun->num_blocks = 0;
} else {
itask->iscsilun->num_blocks = rc10->lba + 1;
}
itask->bs->total_sectors = itask->iscsilun->num_blocks *
itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
itask->status = 0;
itask->complete = 1;
scsi_free_scsi_task(task);
}
static void
iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
void *opaque)
{
struct IscsiTask *itask = opaque;
struct scsi_task *task = command_data;
struct scsi_inquiry_standard *inq;
if (status != 0) {
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
inq = scsi_datain_unmarshall(task);
if (inq == NULL) {
error_report("iSCSI: Failed to unmarshall inquiry data.");
itask->status = 1;
itask->complete = 1;
scsi_free_scsi_task(task);
return;
}
itask->iscsilun->type = inq->periperal_device_type;
scsi_free_scsi_task(task);
switch (itask->iscsilun->type) {
case TYPE_DISK:
task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
iscsi_readcapacity16_cb, opaque);
if (task == NULL) {
error_report("iSCSI: failed to send readcapacity16 command.");
itask->status = 1;
itask->complete = 1;
return;
}
break;
case TYPE_ROM:
task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
0, 0,
iscsi_readcapacity10_cb, opaque);
if (task == NULL) {
error_report("iSCSI: failed to send readcapacity16 command.");
itask->status = 1;
itask->complete = 1;
return;
}
break;
default:
itask->status = 0;
itask->complete = 1;
}
}
static void
iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
void *opaque)
{
struct IscsiTask *itask = opaque;
struct scsi_task *task;
if (status != 0) {
itask->status = 1;
itask->complete = 1;
return;
}
task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
0, 0, 36,
iscsi_inquiry_cb, opaque);
if (task == NULL) {
error_report("iSCSI: failed to send inquiry command.");
itask->status = 1;
itask->complete = 1;
return;
}
}
static int parse_chap(struct iscsi_context *iscsi, const char *target)
{
QemuOptsList *list;
@@ -770,10 +938,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
IscsiLun *iscsilun = bs->opaque;
struct iscsi_context *iscsi = NULL;
struct iscsi_url *iscsi_url = NULL;
struct scsi_task *task = NULL;
struct scsi_inquiry_standard *inq = NULL;
struct scsi_readcapacity10 *rc10 = NULL;
struct scsi_readcapacity16 *rc16 = NULL;
struct IscsiTask task;
char *initiator_name = NULL;
int ret;
@@ -786,7 +951,8 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
iscsi_url = iscsi_parse_full_url(iscsi, filename);
if (iscsi_url == NULL) {
error_report("Failed to parse URL : %s", filename);
error_report("Failed to parse URL : %s %s", filename,
iscsi_get_error(iscsi));
ret = -EINVAL;
goto out;
}
@@ -836,80 +1002,33 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
/* check if we got HEADER_DIGEST via the options */
parse_header_digest(iscsi, iscsi_url->target);
if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
error_report("iSCSI: Failed to connect to LUN : %s",
iscsi_get_error(iscsi));
ret = -EINVAL;
goto out;
}
task.iscsilun = iscsilun;
task.status = 0;
task.complete = 0;
task.bs = bs;
iscsilun->iscsi = iscsi;
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.");
if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
iscsi_connect_cb, &task)
!= 0) {
error_report("iSCSI: Failed to start async connect.");
ret = -EINVAL;
goto out;
}
inq = scsi_datain_unmarshall(task);
if (inq == NULL) {
error_report("iSCSI: Failed to unmarshall inquiry data.");
while (!task.complete) {
iscsi_set_events(iscsilun);
qemu_aio_wait();
}
if (task.status != 0) {
error_report("iSCSI: Failed to connect to LUN : %s",
iscsi_get_error(iscsi));
ret = -EINVAL;
goto out;
}
iscsilun->type = inq->periperal_device_type;
scsi_free_scsi_task(task);
switch (iscsilun->type) {
case TYPE_DISK:
task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_report("iSCSI: failed to send readcapacity16 command.");
ret = -EINVAL;
goto out;
}
rc16 = scsi_datain_unmarshall(task);
if (rc16 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
ret = -EINVAL;
goto out;
}
iscsilun->block_size = rc16->block_length;
iscsilun->num_blocks = rc16->returned_lba + 1;
break;
case TYPE_ROM:
task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_report("iSCSI: failed to send readcapacity10 command.");
ret = -EINVAL;
goto out;
}
rc10 = scsi_datain_unmarshall(task);
if (rc10 == NULL) {
error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
ret = -EINVAL;
goto out;
}
iscsilun->block_size = rc10->block_size;
if (rc10->lba == 0) {
/* blank disk loaded */
iscsilun->num_blocks = 0;
} else {
iscsilun->num_blocks = rc10->lba + 1;
}
break;
default:
break;
}
bs->total_sectors = iscsilun->num_blocks *
iscsilun->block_size / BDRV_SECTOR_SIZE ;
/* Medium changer or tape. We dont have any emulation for this so this must
* be sg ioctl compatible. We force it to be sg, otherwise qemu will try
* to read from the device to guess the image format.
@@ -928,9 +1047,6 @@ out:
if (iscsi_url != NULL) {
iscsi_destroy_url(iscsi_url);
}
if (task != NULL) {
scsi_free_scsi_task(task);
}
if (ret) {
if (iscsi != NULL) {
@@ -951,11 +1067,6 @@ static void iscsi_close(BlockDriverState *bs)
memset(iscsilun, 0, sizeof(IscsiLun));
}
static int iscsi_has_zero_init(BlockDriverState *bs)
{
return 0;
}
static BlockDriver bdrv_iscsi = {
.format_name = "iscsi",
.protocol_name = "iscsi",
@@ -971,7 +1082,6 @@ static BlockDriver bdrv_iscsi = {
.bdrv_aio_flush = iscsi_aio_flush,
.bdrv_aio_discard = iscsi_aio_discard,
.bdrv_has_zero_init = iscsi_has_zero_init,
#ifdef __linux__
.bdrv_ioctl = iscsi_ioctl,
-322
View File
@@ -1,322 +0,0 @@
/*
* Image mirroring
*
* Copyright Red Hat, Inc. 2012
*
* Authors:
* Paolo Bonzini <pbonzini@redhat.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "trace.h"
#include "blockjob.h"
#include "block_int.h"
#include "qemu/ratelimit.h"
enum {
/*
* Size of data buffer for populating the image file. This should be large
* enough to process multiple clusters in a single call, so that populating
* contiguous regions of the image is efficient.
*/
BLOCK_SIZE = 512 * BDRV_SECTORS_PER_DIRTY_CHUNK, /* in bytes */
};
#define SLICE_TIME 100000000ULL /* ns */
typedef struct MirrorBlockJob {
BlockJob common;
RateLimit limit;
BlockDriverState *target;
MirrorSyncMode mode;
BlockdevOnError on_source_error, on_target_error;
bool synced;
bool should_complete;
int64_t sector_num;
uint8_t *buf;
} MirrorBlockJob;
static BlockErrorAction mirror_error_action(MirrorBlockJob *s, bool read,
int error)
{
s->synced = false;
if (read) {
return block_job_error_action(&s->common, s->common.bs,
s->on_source_error, true, error);
} else {
return block_job_error_action(&s->common, s->target,
s->on_target_error, false, error);
}
}
static int coroutine_fn mirror_iteration(MirrorBlockJob *s,
BlockErrorAction *p_action)
{
BlockDriverState *source = s->common.bs;
BlockDriverState *target = s->target;
QEMUIOVector qiov;
int ret, nb_sectors;
int64_t end;
struct iovec iov;
end = s->common.len >> BDRV_SECTOR_BITS;
s->sector_num = bdrv_get_next_dirty(source, s->sector_num);
nb_sectors = MIN(BDRV_SECTORS_PER_DIRTY_CHUNK, end - s->sector_num);
bdrv_reset_dirty(source, s->sector_num, nb_sectors);
/* Copy the dirty cluster. */
iov.iov_base = s->buf;
iov.iov_len = nb_sectors * 512;
qemu_iovec_init_external(&qiov, &iov, 1);
trace_mirror_one_iteration(s, s->sector_num, nb_sectors);
ret = bdrv_co_readv(source, s->sector_num, nb_sectors, &qiov);
if (ret < 0) {
*p_action = mirror_error_action(s, true, -ret);
goto fail;
}
ret = bdrv_co_writev(target, s->sector_num, nb_sectors, &qiov);
if (ret < 0) {
*p_action = mirror_error_action(s, false, -ret);
s->synced = false;
goto fail;
}
return 0;
fail:
/* Try again later. */
bdrv_set_dirty(source, s->sector_num, nb_sectors);
return ret;
}
static void coroutine_fn mirror_run(void *opaque)
{
MirrorBlockJob *s = opaque;
BlockDriverState *bs = s->common.bs;
int64_t sector_num, end;
int ret = 0;
int n;
if (block_job_is_cancelled(&s->common)) {
goto immediate_exit;
}
s->common.len = bdrv_getlength(bs);
if (s->common.len < 0) {
block_job_completed(&s->common, s->common.len);
return;
}
end = s->common.len >> BDRV_SECTOR_BITS;
s->buf = qemu_blockalign(bs, BLOCK_SIZE);
if (s->mode != MIRROR_SYNC_MODE_NONE) {
/* First part, loop on the sectors and initialize the dirty bitmap. */
BlockDriverState *base;
base = s->mode == MIRROR_SYNC_MODE_FULL ? NULL : bs->backing_hd;
for (sector_num = 0; sector_num < end; ) {
int64_t next = (sector_num | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1;
ret = bdrv_co_is_allocated_above(bs, base,
sector_num, next - sector_num, &n);
if (ret < 0) {
goto immediate_exit;
}
assert(n > 0);
if (ret == 1) {
bdrv_set_dirty(bs, sector_num, n);
sector_num = next;
} else {
sector_num += n;
}
}
}
s->sector_num = -1;
for (;;) {
uint64_t delay_ns;
int64_t cnt;
bool should_complete;
cnt = bdrv_get_dirty_count(bs);
if (cnt != 0) {
BlockErrorAction action = BDRV_ACTION_REPORT;
ret = mirror_iteration(s, &action);
if (ret < 0 && action == BDRV_ACTION_REPORT) {
goto immediate_exit;
}
cnt = bdrv_get_dirty_count(bs);
}
should_complete = false;
if (cnt == 0) {
trace_mirror_before_flush(s);
ret = bdrv_flush(s->target);
if (ret < 0) {
if (mirror_error_action(s, false, -ret) == BDRV_ACTION_REPORT) {
goto immediate_exit;
}
} else {
/* We're out of the streaming phase. From now on, if the job
* is cancelled we will actually complete all pending I/O and
* report completion. This way, block-job-cancel will leave
* the target in a consistent state.
*/
s->common.offset = end * BDRV_SECTOR_SIZE;
if (!s->synced) {
block_job_ready(&s->common);
s->synced = true;
}
should_complete = s->should_complete ||
block_job_is_cancelled(&s->common);
cnt = bdrv_get_dirty_count(bs);
}
}
if (cnt == 0 && should_complete) {
/* The dirty bitmap is not updated while operations are pending.
* If we're about to exit, wait for pending operations before
* calling bdrv_get_dirty_count(bs), or we may exit while the
* source has dirty data to copy!
*
* Note that I/O can be submitted by the guest while
* mirror_populate runs.
*/
trace_mirror_before_drain(s, cnt);
bdrv_drain_all();
cnt = bdrv_get_dirty_count(bs);
}
ret = 0;
trace_mirror_before_sleep(s, cnt, s->synced);
if (!s->synced) {
/* Publish progress */
s->common.offset = end * BDRV_SECTOR_SIZE - cnt * BLOCK_SIZE;
if (s->common.speed) {
delay_ns = ratelimit_calculate_delay(&s->limit, BDRV_SECTORS_PER_DIRTY_CHUNK);
} else {
delay_ns = 0;
}
/* Note that even when no rate limit is applied we need to yield
* with no pending I/O here so that qemu_aio_flush() returns.
*/
block_job_sleep_ns(&s->common, rt_clock, delay_ns);
if (block_job_is_cancelled(&s->common)) {
break;
}
} else if (!should_complete) {
delay_ns = (cnt == 0 ? SLICE_TIME : 0);
block_job_sleep_ns(&s->common, rt_clock, delay_ns);
} else if (cnt == 0) {
/* The two disks are in sync. Exit and report successful
* completion.
*/
assert(QLIST_EMPTY(&bs->tracked_requests));
s->common.cancelled = false;
break;
}
}
immediate_exit:
g_free(s->buf);
bdrv_set_dirty_tracking(bs, false);
bdrv_iostatus_disable(s->target);
if (s->should_complete && ret == 0) {
if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) {
bdrv_reopen(s->target, bdrv_get_flags(s->common.bs), NULL);
}
bdrv_swap(s->target, s->common.bs);
}
bdrv_close(s->target);
bdrv_delete(s->target);
block_job_completed(&s->common, ret);
}
static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
if (speed < 0) {
error_set(errp, QERR_INVALID_PARAMETER, "speed");
return;
}
ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
}
static void mirror_iostatus_reset(BlockJob *job)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
bdrv_iostatus_reset(s->target);
}
static void mirror_complete(BlockJob *job, Error **errp)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
int ret;
ret = bdrv_open_backing_file(s->target);
if (ret < 0) {
char backing_filename[PATH_MAX];
bdrv_get_full_backing_filename(s->target, backing_filename,
sizeof(backing_filename));
error_set(errp, QERR_OPEN_FILE_FAILED, backing_filename);
return;
}
if (!s->synced) {
error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
return;
}
s->should_complete = true;
block_job_resume(job);
}
static BlockJobType mirror_job_type = {
.instance_size = sizeof(MirrorBlockJob),
.job_type = "mirror",
.set_speed = mirror_set_speed,
.iostatus_reset= mirror_iostatus_reset,
.complete = mirror_complete,
};
void mirror_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, MirrorSyncMode mode,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockDriverCompletionFunc *cb,
void *opaque, Error **errp)
{
MirrorBlockJob *s;
if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
error_set(errp, QERR_INVALID_PARAMETER, "on-source-error");
return;
}
s = block_job_create(&mirror_job_type, bs, speed, cb, opaque, errp);
if (!s) {
return;
}
s->on_source_error = on_source_error;
s->on_target_error = on_target_error;
s->target = target;
s->mode = mode;
bdrv_set_dirty_tracking(bs, true);
bdrv_set_enable_write_cache(s->target, true);
bdrv_set_on_error(s->target, on_target_error, on_target_error);
bdrv_iostatus_enable(s->target);
s->common.co = qemu_coroutine_create(mirror_run);
trace_mirror_start(bs, s, s->common.co, opaque);
qemu_coroutine_enter(s->common.co, s);
}
+18 -111
View File
@@ -28,7 +28,6 @@
#include "qemu-common.h"
#include "nbd.h"
#include "uri.h"
#include "block_int.h"
#include "module.h"
#include "qemu_socket.h"
@@ -56,6 +55,7 @@ typedef struct BDRVNBDState {
uint32_t nbdflags;
off_t size;
size_t blocksize;
char *export_name; /* An NBD server may export several devices */
CoMutex send_mutex;
CoMutex free_sema;
@@ -65,75 +65,13 @@ typedef struct BDRVNBDState {
Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
struct nbd_reply reply;
int is_unix;
/* If it begins with '/', this is a UNIX domain socket. Otherwise,
* it's a string of the form <hostname|ip4|\[ip6\]>:port
*/
char *host_spec;
char *export_name; /* An NBD server may export several devices */
} BDRVNBDState;
static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
{
URI *uri;
const char *p;
QueryParams *qp = NULL;
int ret = 0;
uri = uri_parse(filename);
if (!uri) {
return -EINVAL;
}
/* transport */
if (!strcmp(uri->scheme, "nbd")) {
s->is_unix = false;
} else if (!strcmp(uri->scheme, "nbd+tcp")) {
s->is_unix = false;
} else if (!strcmp(uri->scheme, "nbd+unix")) {
s->is_unix = true;
} else {
ret = -EINVAL;
goto out;
}
p = uri->path ? uri->path : "/";
p += strspn(p, "/");
if (p[0]) {
s->export_name = g_strdup(p);
}
qp = query_params_parse(uri->query);
if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
ret = -EINVAL;
goto out;
}
if (s->is_unix) {
/* nbd+unix:///export?socket=path */
if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
ret = -EINVAL;
goto out;
}
s->host_spec = g_strdup(qp->p[0].value);
} else {
/* nbd[+tcp]://host:port/export */
if (!uri->server) {
ret = -EINVAL;
goto out;
}
if (!uri->port) {
uri->port = NBD_DEFAULT_PORT;
}
s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
}
out:
if (qp) {
query_params_free(qp);
}
uri_free(uri);
return ret;
}
static int nbd_config(BDRVNBDState *s, const char *filename)
static int nbd_config(BDRVNBDState *s, const char *filename, int flags)
{
char *file;
char *export_name;
@@ -141,10 +79,6 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
const char *unixpath;
int err = -EINVAL;
if (strstr(filename, "://")) {
return nbd_parse_uri(s, filename);
}
file = g_strdup(filename);
export_name = strstr(file, EN_OPTSTR);
@@ -164,10 +98,11 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
/* are we a UNIX or TCP socket? */
if (strstart(host_spec, "unix:", &unixpath)) {
s->is_unix = true;
if (unixpath[0] != '/') { /* We demand an absolute path*/
goto out;
}
s->host_spec = g_strdup(unixpath);
} else {
s->is_unix = false;
s->host_spec = g_strdup(host_spec);
}
@@ -327,7 +262,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
off_t size;
size_t blocksize;
if (s->is_unix) {
if (s->host_spec[0] == '/') {
sock = unix_socket_outgoing(s->host_spec);
} else {
sock = tcp_socket_outgoing_spec(s->host_spec);
@@ -385,7 +320,7 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
qemu_co_mutex_init(&s->free_sema);
/* Pop the config into our state object. Exit if invalid. */
result = nbd_config(s, filename);
result = nbd_config(s, filename, flags);
if (result != 0) {
return result;
}
@@ -563,48 +498,20 @@ static int64_t nbd_getlength(BlockDriverState *bs)
static BlockDriver bdrv_nbd = {
.format_name = "nbd",
.instance_size = sizeof(BDRVNBDState),
.bdrv_file_open = nbd_open,
.bdrv_co_readv = nbd_co_readv,
.bdrv_co_writev = nbd_co_writev,
.bdrv_close = nbd_close,
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
.protocol_name = "nbd",
.instance_size = sizeof(BDRVNBDState),
.bdrv_file_open = nbd_open,
.bdrv_co_readv = nbd_co_readv,
.bdrv_co_writev = nbd_co_writev,
.bdrv_close = nbd_close,
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
};
static BlockDriver bdrv_nbd_tcp = {
.format_name = "nbd",
.protocol_name = "nbd+tcp",
.instance_size = sizeof(BDRVNBDState),
.bdrv_file_open = nbd_open,
.bdrv_co_readv = nbd_co_readv,
.bdrv_co_writev = nbd_co_writev,
.bdrv_close = nbd_close,
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
};
static BlockDriver bdrv_nbd_unix = {
.format_name = "nbd",
.protocol_name = "nbd+unix",
.instance_size = sizeof(BDRVNBDState),
.bdrv_file_open = nbd_open,
.bdrv_co_readv = nbd_co_readv,
.bdrv_co_writev = nbd_co_writev,
.bdrv_close = nbd_close,
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
};
static void bdrv_nbd_init(void)
{
bdrv_register(&bdrv_nbd);
bdrv_register(&bdrv_nbd_tcp);
bdrv_register(&bdrv_nbd_unix);
}
block_init(bdrv_nbd_init);
-10
View File
@@ -197,15 +197,6 @@ static int qcow_open(BlockDriverState *bs, int flags)
return ret;
}
/* We have nothing to do for QCOW reopen, stubs just return
* success */
static int qcow_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
return 0;
}
static int qcow_set_key(BlockDriverState *bs, const char *key)
{
BDRVQcowState *s = bs->opaque;
@@ -877,7 +868,6 @@ static BlockDriver bdrv_qcow = {
.bdrv_probe = qcow_probe,
.bdrv_open = qcow_open,
.bdrv_close = qcow_close,
.bdrv_reopen_prepare = qcow_reopen_prepare,
.bdrv_create = qcow_create,
.bdrv_co_readv = qcow_co_readv,
+1 -2
View File
@@ -301,8 +301,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
uint64_t last_table_size;
uint64_t blocks_clusters;
do {
uint64_t table_clusters =
size_to_clusters(s, table_size * sizeof(uint64_t));
uint64_t table_clusters = size_to_clusters(s, table_size);
blocks_clusters = 1 +
((table_clusters + refcount_block_clusters - 1)
/ refcount_block_clusters);
-11
View File
@@ -52,7 +52,6 @@ typedef struct {
uint32_t magic;
uint32_t len;
} QCowExtension;
#define QCOW2_EXT_MAGIC_END 0
#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
#define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857
@@ -559,14 +558,6 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
return 0;
}
/* We have nothing to do for QCOW2 reopen, stubs just return
* success */
static int qcow2_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
return 0;
}
static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int *pnum)
{
@@ -1096,7 +1087,6 @@ int qcow2_update_header(BlockDriverState *bs)
goto fail;
}
/* Using strncpy is ok here, since buf is not NUL-terminated. */
strncpy(buf, bs->backing_file, buflen);
header->backing_file_offset = cpu_to_be64(buf - ((char*) header));
@@ -1689,7 +1679,6 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_probe = qcow2_probe,
.bdrv_open = qcow2_open,
.bdrv_close = qcow2_close,
.bdrv_reopen_prepare = qcow2_reopen_prepare,
.bdrv_create = qcow2_create,
.bdrv_co_is_allocated = qcow2_co_is_allocated,
.bdrv_set_key = qcow2_set_key,
+1
View File
@@ -103,6 +103,7 @@ static void qed_write_table_cb(void *opaque, int ret)
out:
qemu_vfree(write_table_cb->table);
gencb_complete(&write_table_cb->gencb, ret);
return;
}
/**
+2 -11
View File
@@ -30,7 +30,7 @@ static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
}
}
static const AIOCBInfo qed_aiocb_info = {
static AIOPool qed_aio_pool = {
.aiocb_size = sizeof(QEDAIOCB),
.cancel = qed_aio_cancel,
};
@@ -505,14 +505,6 @@ out:
return ret;
}
/* We have nothing to do for QED reopen, stubs just return
* success */
static int bdrv_qed_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
return 0;
}
static void bdrv_qed_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
@@ -1311,7 +1303,7 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
BlockDriverCompletionFunc *cb,
void *opaque, int flags)
{
QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque);
QEDAIOCB *acb = qemu_aio_get(&qed_aio_pool, bs, cb, opaque);
trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors,
opaque, flags);
@@ -1572,7 +1564,6 @@ static BlockDriver bdrv_qed = {
.bdrv_rebind = bdrv_qed_rebind,
.bdrv_open = bdrv_qed_open,
.bdrv_close = bdrv_qed_close,
.bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
.bdrv_create = bdrv_qed_create,
.bdrv_co_is_allocated = bdrv_qed_co_is_allocated,
.bdrv_make_empty = bdrv_qed_make_empty,
+13 -16
View File
@@ -1,5 +1,5 @@
/*
* Declarations for AIO in the raw protocol
* QEMU Posix block I/O backend AIO support
*
* Copyright IBM, Corp. 2008
*
@@ -12,8 +12,8 @@
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#ifndef QEMU_RAW_AIO_H
#define QEMU_RAW_AIO_H
#ifndef QEMU_RAW_POSIX_AIO_H
#define QEMU_RAW_POSIX_AIO_H
/* AIO request types */
#define QEMU_AIO_READ 0x0001
@@ -27,22 +27,19 @@
#define QEMU_AIO_MISALIGNED 0x1000
/* posix-aio-compat.c - thread pool based implementation */
int paio_init(void);
BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type);
BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque);
/* linux-aio.c - Linux native implementation */
#ifdef CONFIG_LINUX_AIO
void *laio_init(void);
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type);
#endif
#ifdef _WIN32
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
QEMUWin32AIOState *win32_aio_init(void);
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
QEMUWin32AIOState *aio, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type);
#endif
#endif /* QEMU_RAW_AIO_H */
#endif /* QEMU_RAW_POSIX_AIO_H */
+62 -475
View File
@@ -27,10 +27,7 @@
#include "qemu-log.h"
#include "block_int.h"
#include "module.h"
#include "trace.h"
#include "thread-pool.h"
#include "iov.h"
#include "raw-aio.h"
#include "block/raw-posix-aio.h"
#if defined(__APPLE__) && (__MACH__)
#include <paths.h>
@@ -136,36 +133,16 @@ typedef struct BDRVRawState {
int use_aio;
void *aio_ctx;
#endif
uint8_t *aligned_buf;
unsigned aligned_buf_size;
#ifdef CONFIG_XFS
bool is_xfs : 1;
#endif
} BDRVRawState;
typedef struct BDRVRawReopenState {
int fd;
int open_flags;
#ifdef CONFIG_LINUX_AIO
int use_aio;
#endif
} BDRVRawReopenState;
static int fd_open(BlockDriverState *bs);
static int64_t raw_getlength(BlockDriverState *bs);
typedef struct RawPosixAIOData {
BlockDriverState *bs;
int aio_fildes;
union {
struct iovec *aio_iov;
void *aio_ioctl_buf;
};
int aio_niov;
size_t aio_nbytes;
#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */
off_t aio_offset;
int aio_type;
} RawPosixAIOData;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int cdrom_reopen(BlockDriverState *bs);
#endif
@@ -208,57 +185,6 @@ static int raw_normalize_devicepath(const char **filename)
}
#endif
static void raw_parse_flags(int bdrv_flags, int *open_flags)
{
assert(open_flags != NULL);
*open_flags |= O_BINARY;
*open_flags &= ~O_ACCMODE;
if (bdrv_flags & BDRV_O_RDWR) {
*open_flags |= O_RDWR;
} else {
*open_flags |= O_RDONLY;
}
/* Use O_DSYNC for write-through caching, no flags for write-back caching,
* and O_DIRECT for no caching. */
if ((bdrv_flags & BDRV_O_NOCACHE)) {
*open_flags |= O_DIRECT;
}
}
#ifdef CONFIG_LINUX_AIO
static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
{
int ret = -1;
assert(aio_ctx != NULL);
assert(use_aio != NULL);
/*
* Currently Linux do AIO only for files opened with O_DIRECT
* specified so check NOCACHE flag too
*/
if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
(BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
/* if non-NULL, laio_init() has already been run */
if (*aio_ctx == NULL) {
*aio_ctx = laio_init();
if (!*aio_ctx) {
goto error;
}
}
*use_aio = 1;
} else {
*use_aio = 0;
}
ret = 0;
error:
return ret;
}
#endif
static int raw_open_common(BlockDriverState *bs, const char *filename,
int bdrv_flags, int open_flags)
{
@@ -270,8 +196,20 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
return ret;
}
s->open_flags = open_flags;
raw_parse_flags(bdrv_flags, &s->open_flags);
s->open_flags = open_flags | O_BINARY;
s->open_flags &= ~O_ACCMODE;
if (bdrv_flags & BDRV_O_RDWR) {
s->open_flags |= O_RDWR;
} else {
s->open_flags |= O_RDONLY;
}
/* Use O_DSYNC for write-through caching, no flags for write-back caching,
* and O_DIRECT for no caching. */
if ((bdrv_flags & BDRV_O_NOCACHE))
s->open_flags |= O_DIRECT;
if (!(bdrv_flags & BDRV_O_CACHE_WB))
s->open_flags |= O_DSYNC;
s->fd = -1;
fd = qemu_open(filename, s->open_flags, 0644);
@@ -282,13 +220,45 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
return ret;
}
s->fd = fd;
s->aligned_buf = NULL;
if ((bdrv_flags & BDRV_O_NOCACHE)) {
/*
* Allocate a buffer for read/modify/write cycles. Chose the size
* pessimistically as we don't know the block size yet.
*/
s->aligned_buf_size = 32 * MAX_BLOCKSIZE;
s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, s->aligned_buf_size);
if (s->aligned_buf == NULL) {
goto out_close;
}
}
/* We're falling back to POSIX AIO in some cases so init always */
if (paio_init() < 0) {
goto out_free_buf;
}
#ifdef CONFIG_LINUX_AIO
if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
qemu_close(fd);
return -errno;
}
/*
* Currently Linux do AIO only for files opened with O_DIRECT
* specified so check NOCACHE flag too
*/
if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
(BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
s->aio_ctx = laio_init();
if (!s->aio_ctx) {
goto out_free_buf;
}
s->use_aio = 1;
} else
#endif
{
#ifdef CONFIG_LINUX_AIO
s->use_aio = 0;
#endif
}
#ifdef CONFIG_XFS
if (platform_test_xfs_fd(s->fd)) {
@@ -297,6 +267,12 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
#endif
return 0;
out_free_buf:
qemu_vfree(s->aligned_buf);
out_close:
qemu_close(fd);
return -errno;
}
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
@@ -307,113 +283,6 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
return raw_open_common(bs, filename, flags, 0);
}
static int raw_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
BDRVRawState *s;
BDRVRawReopenState *raw_s;
int ret = 0;
assert(state != NULL);
assert(state->bs != NULL);
s = state->bs->opaque;
state->opaque = g_malloc0(sizeof(BDRVRawReopenState));
raw_s = state->opaque;
#ifdef CONFIG_LINUX_AIO
raw_s->use_aio = s->use_aio;
/* we can use s->aio_ctx instead of a copy, because the use_aio flag is
* valid in the 'false' condition even if aio_ctx is set, and raw_set_aio()
* won't override aio_ctx if aio_ctx is non-NULL */
if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) {
return -1;
}
#endif
if (s->type == FTYPE_FD || s->type == FTYPE_CD) {
raw_s->open_flags |= O_NONBLOCK;
}
raw_parse_flags(state->flags, &raw_s->open_flags);
raw_s->fd = -1;
int fcntl_flags = O_APPEND | O_ASYNC | O_NONBLOCK;
#ifdef O_NOATIME
fcntl_flags |= O_NOATIME;
#endif
if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
/* dup the original fd */
/* TODO: use qemu fcntl wrapper */
#ifdef F_DUPFD_CLOEXEC
raw_s->fd = fcntl(s->fd, F_DUPFD_CLOEXEC, 0);
#else
raw_s->fd = dup(s->fd);
if (raw_s->fd != -1) {
qemu_set_cloexec(raw_s->fd);
}
#endif
if (raw_s->fd >= 0) {
ret = fcntl_setfl(raw_s->fd, raw_s->open_flags);
if (ret) {
qemu_close(raw_s->fd);
raw_s->fd = -1;
}
}
}
/* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */
if (raw_s->fd == -1) {
assert(!(raw_s->open_flags & O_CREAT));
raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags);
if (raw_s->fd == -1) {
ret = -1;
}
}
return ret;
}
static void raw_reopen_commit(BDRVReopenState *state)
{
BDRVRawReopenState *raw_s = state->opaque;
BDRVRawState *s = state->bs->opaque;
s->open_flags = raw_s->open_flags;
qemu_close(s->fd);
s->fd = raw_s->fd;
#ifdef CONFIG_LINUX_AIO
s->use_aio = raw_s->use_aio;
#endif
g_free(state->opaque);
state->opaque = NULL;
}
static void raw_reopen_abort(BDRVReopenState *state)
{
BDRVRawReopenState *raw_s = state->opaque;
/* nothing to do if NULL, we didn't get far enough */
if (raw_s == NULL) {
return;
}
if (raw_s->fd >= 0) {
qemu_close(raw_s->fd);
raw_s->fd = -1;
}
g_free(state->opaque);
state->opaque = NULL;
}
/* XXX: use host sector size if necessary with:
#ifdef DIOCGSECTORSIZE
{
@@ -447,275 +316,6 @@ static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
return 1;
}
static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
{
int ret;
ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
if (ret == -1) {
return -errno;
}
return 0;
}
static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb)
{
int ret;
ret = qemu_fdatasync(aiocb->aio_fildes);
if (ret == -1) {
return -errno;
}
return 0;
}
#ifdef CONFIG_PREADV
static bool preadv_present = true;
static ssize_t
qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return preadv(fd, iov, nr_iov, offset);
}
static ssize_t
qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return pwritev(fd, iov, nr_iov, offset);
}
#else
static bool preadv_present = false;
static ssize_t
qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return -ENOSYS;
}
static ssize_t
qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return -ENOSYS;
}
#endif
static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
{
ssize_t len;
do {
if (aiocb->aio_type & QEMU_AIO_WRITE)
len = qemu_pwritev(aiocb->aio_fildes,
aiocb->aio_iov,
aiocb->aio_niov,
aiocb->aio_offset);
else
len = qemu_preadv(aiocb->aio_fildes,
aiocb->aio_iov,
aiocb->aio_niov,
aiocb->aio_offset);
} while (len == -1 && errno == EINTR);
if (len == -1) {
return -errno;
}
return len;
}
/*
* Read/writes the data to/from a given linear buffer.
*
* Returns the number of bytes handles or -errno in case of an error. Short
* reads are only returned if the end of the file is reached.
*/
static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
{
ssize_t offset = 0;
ssize_t len;
while (offset < aiocb->aio_nbytes) {
if (aiocb->aio_type & QEMU_AIO_WRITE) {
len = pwrite(aiocb->aio_fildes,
(const char *)buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
} else {
len = pread(aiocb->aio_fildes,
buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
}
if (len == -1 && errno == EINTR) {
continue;
} else if (len == -1) {
offset = -errno;
break;
} else if (len == 0) {
break;
}
offset += len;
}
return offset;
}
static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
{
ssize_t nbytes;
char *buf;
if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
/*
* If there is just a single buffer, and it is properly aligned
* we can just use plain pread/pwrite without any problems.
*/
if (aiocb->aio_niov == 1) {
return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
}
/*
* We have more than one iovec, and all are properly aligned.
*
* Try preadv/pwritev first and fall back to linearizing the
* buffer if it's not supported.
*/
if (preadv_present) {
nbytes = handle_aiocb_rw_vector(aiocb);
if (nbytes == aiocb->aio_nbytes ||
(nbytes < 0 && nbytes != -ENOSYS)) {
return nbytes;
}
preadv_present = false;
}
/*
* XXX(hch): short read/write. no easy way to handle the reminder
* using these interfaces. For now retry using plain
* pread/pwrite?
*/
}
/*
* Ok, we have to do it the hard way, copy all segments into
* a single aligned buffer.
*/
buf = qemu_blockalign(aiocb->bs, aiocb->aio_nbytes);
if (aiocb->aio_type & QEMU_AIO_WRITE) {
char *p = buf;
int i;
for (i = 0; i < aiocb->aio_niov; ++i) {
memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
p += aiocb->aio_iov[i].iov_len;
}
}
nbytes = handle_aiocb_rw_linear(aiocb, buf);
if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
char *p = buf;
size_t count = aiocb->aio_nbytes, copy;
int i;
for (i = 0; i < aiocb->aio_niov && count; ++i) {
copy = count;
if (copy > aiocb->aio_iov[i].iov_len) {
copy = aiocb->aio_iov[i].iov_len;
}
memcpy(aiocb->aio_iov[i].iov_base, p, copy);
p += copy;
count -= copy;
}
}
qemu_vfree(buf);
return nbytes;
}
static int aio_worker(void *arg)
{
RawPosixAIOData *aiocb = arg;
ssize_t ret = 0;
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
case QEMU_AIO_READ:
ret = handle_aiocb_rw(aiocb);
if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->bs->growable) {
iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
0, aiocb->aio_nbytes - ret);
ret = aiocb->aio_nbytes;
}
if (ret == aiocb->aio_nbytes) {
ret = 0;
} else if (ret >= 0 && ret < aiocb->aio_nbytes) {
ret = -EINVAL;
}
break;
case QEMU_AIO_WRITE:
ret = handle_aiocb_rw(aiocb);
if (ret == aiocb->aio_nbytes) {
ret = 0;
} else if (ret >= 0 && ret < aiocb->aio_nbytes) {
ret = -EINVAL;
}
break;
case QEMU_AIO_FLUSH:
ret = handle_aiocb_flush(aiocb);
break;
case QEMU_AIO_IOCTL:
ret = handle_aiocb_ioctl(aiocb);
break;
default:
fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
ret = -EINVAL;
break;
}
g_slice_free(RawPosixAIOData, aiocb);
return ret;
}
static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
{
RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
acb->bs = bs;
acb->aio_type = type;
acb->aio_fildes = fd;
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
}
acb->aio_nbytes = nb_sectors * 512;
acb->aio_offset = sector_num * 512;
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
}
static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque)
{
RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
acb->bs = bs;
acb->aio_type = QEMU_AIO_IOCTL;
acb->aio_fildes = fd;
acb->aio_offset = 0;
acb->aio_ioctl_buf = buf;
acb->aio_ioctl_cmd = req;
return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
}
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
@@ -730,7 +330,7 @@ static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
* boundary. Check if this is the case or tell the low-level
* driver that it needs to copy the buffer.
*/
if ((bs->open_flags & BDRV_O_NOCACHE)) {
if (s->aligned_buf) {
if (!qiov_is_aligned(bs, qiov)) {
type |= QEMU_AIO_MISALIGNED;
#ifdef CONFIG_LINUX_AIO
@@ -778,6 +378,8 @@ static void raw_close(BlockDriverState *bs)
if (s->fd >= 0) {
qemu_close(s->fd);
s->fd = -1;
if (s->aligned_buf != NULL)
qemu_vfree(s->aligned_buf);
}
}
@@ -1133,9 +735,6 @@ static BlockDriver bdrv_file = {
.instance_size = sizeof(BDRVRawState),
.bdrv_probe = NULL, /* no probe for protocols */
.bdrv_file_open = raw_open,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_close = raw_close,
.bdrv_create = raw_create,
.bdrv_co_discard = raw_co_discard,
@@ -1405,9 +1004,6 @@ static BlockDriver bdrv_host_device = {
.bdrv_probe_device = hdev_probe_device,
.bdrv_file_open = hdev_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
.bdrv_has_zero_init = hdev_has_zero_init,
@@ -1529,9 +1125,6 @@ static BlockDriver bdrv_host_floppy = {
.bdrv_probe_device = floppy_probe_device,
.bdrv_file_open = floppy_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
.bdrv_has_zero_init = hdev_has_zero_init,
@@ -1631,9 +1224,6 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_probe_device = cdrom_probe_device,
.bdrv_file_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
.bdrv_has_zero_init = hdev_has_zero_init,
@@ -1753,9 +1343,6 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_probe_device = cdrom_probe_device,
.bdrv_file_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
.bdrv_has_zero_init = hdev_has_zero_init,
+69 -190
View File
@@ -25,10 +25,6 @@
#include "qemu-timer.h"
#include "block_int.h"
#include "module.h"
#include "raw-aio.h"
#include "trace.h"
#include "thread-pool.h"
#include "iov.h"
#include <windows.h>
#include <winioctl.h>
@@ -36,130 +32,12 @@
#define FTYPE_CD 1
#define FTYPE_HARDDISK 2
static QEMUWin32AIOState *aio;
typedef struct RawWin32AIOData {
BlockDriverState *bs;
HANDLE hfile;
struct iovec *aio_iov;
int aio_niov;
size_t aio_nbytes;
off64_t aio_offset;
int aio_type;
} RawWin32AIOData;
typedef struct BDRVRawState {
HANDLE hfile;
int type;
char drive_path[16]; /* format: "d:\" */
QEMUWin32AIOState *aio;
} BDRVRawState;
/*
* Read/writes the data to/from a given linear buffer.
*
* Returns the number of bytes handles or -errno in case of an error. Short
* reads are only returned if the end of the file is reached.
*/
static size_t handle_aiocb_rw(RawWin32AIOData *aiocb)
{
size_t offset = 0;
int i;
for (i = 0; i < aiocb->aio_niov; i++) {
OVERLAPPED ov;
DWORD ret, ret_count, len;
memset(&ov, 0, sizeof(ov));
ov.Offset = (aiocb->aio_offset + offset);
ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32;
len = aiocb->aio_iov[i].iov_len;
if (aiocb->aio_type & QEMU_AIO_WRITE) {
ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
len, &ret_count, &ov);
} else {
ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
len, &ret_count, &ov);
}
if (!ret) {
ret_count = 0;
}
if (ret_count != len) {
break;
}
offset += len;
}
return offset;
}
static int aio_worker(void *arg)
{
RawWin32AIOData *aiocb = arg;
ssize_t ret = 0;
size_t count;
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
case QEMU_AIO_READ:
count = handle_aiocb_rw(aiocb);
if (count < aiocb->aio_nbytes && aiocb->bs->growable) {
/* A short read means that we have reached EOF. Pad the buffer
* with zeros for bytes after EOF. */
iov_memset(aiocb->aio_iov, aiocb->aio_niov, count,
0, aiocb->aio_nbytes - count);
count = aiocb->aio_nbytes;
}
if (count == aiocb->aio_nbytes) {
ret = 0;
} else {
ret = -EINVAL;
}
break;
case QEMU_AIO_WRITE:
count = handle_aiocb_rw(aiocb);
if (count == aiocb->aio_nbytes) {
count = 0;
} else {
count = -EINVAL;
}
break;
case QEMU_AIO_FLUSH:
if (!FlushFileBuffers(aiocb->hfile)) {
return -EIO;
}
break;
default:
fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
ret = -EINVAL;
break;
}
g_slice_free(RawWin32AIOData, aiocb);
return ret;
}
static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
{
RawWin32AIOData *acb = g_slice_new(RawWin32AIOData);
acb->bs = bs;
acb->hfile = hfile;
acb->aio_type = type;
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
}
acb->aio_nbytes = nb_sectors * 512;
acb->aio_offset = sector_num * 512;
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
}
int qemu_ftruncate64(int fd, int64_t length)
{
LARGE_INTEGER li;
@@ -199,26 +77,6 @@ static int set_sparse(int fd)
NULL, 0, NULL, 0, &returned, NULL);
}
static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
{
assert(access_flags != NULL);
assert(overlapped != NULL);
if (flags & BDRV_O_RDWR) {
*access_flags = GENERIC_READ | GENERIC_WRITE;
} else {
*access_flags = GENERIC_READ;
}
*overlapped = FILE_ATTRIBUTE_NORMAL;
if (flags & BDRV_O_NATIVE_AIO) {
*overlapped |= FILE_FLAG_OVERLAPPED;
}
if (flags & BDRV_O_NOCACHE) {
*overlapped |= FILE_FLAG_NO_BUFFERING;
}
}
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
@@ -227,15 +85,17 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
s->type = FTYPE_FILE;
raw_parse_flags(flags, &access_flags, &overlapped);
if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
aio = win32_aio_init();
if (aio == NULL) {
return -EINVAL;
}
if (flags & BDRV_O_RDWR) {
access_flags = GENERIC_READ | GENERIC_WRITE;
} else {
access_flags = GENERIC_READ;
}
overlapped = FILE_ATTRIBUTE_NORMAL;
if (flags & BDRV_O_NOCACHE)
overlapped |= FILE_FLAG_NO_BUFFERING;
if (!(flags & BDRV_O_CACHE_WB))
overlapped |= FILE_FLAG_WRITE_THROUGH;
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
OPEN_EXISTING, overlapped, NULL);
@@ -244,53 +104,64 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
if (err == ERROR_ACCESS_DENIED)
return -EACCES;
return -EINVAL;
}
if (flags & BDRV_O_NATIVE_AIO) {
int ret = win32_aio_attach(aio, s->hfile);
if (ret < 0) {
CloseHandle(s->hfile);
return ret;
}
s->aio = aio;
return -1;
}
return 0;
}
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
static int raw_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVRawState *s = bs->opaque;
if (s->aio) {
return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
nb_sectors, cb, opaque, QEMU_AIO_READ);
} else {
return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
cb, opaque, QEMU_AIO_READ);
}
OVERLAPPED ov;
DWORD ret_count;
int ret;
int64_t offset = sector_num * 512;
int count = nb_sectors * 512;
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
if (!ret)
return ret_count;
if (ret_count == count)
ret_count = 0;
return ret_count;
}
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVRawState *s = bs->opaque;
if (s->aio) {
return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
nb_sectors, cb, opaque, QEMU_AIO_WRITE);
} else {
return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
cb, opaque, QEMU_AIO_WRITE);
}
OVERLAPPED ov;
DWORD ret_count;
int ret;
int64_t offset = sector_num * 512;
int count = nb_sectors * 512;
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
if (!ret)
return ret_count;
if (ret_count == count)
ret_count = 0;
return ret_count;
}
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque)
static int raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
int ret;
ret = FlushFileBuffers(s->hfile);
if (ret == 0) {
return -EIO;
}
return 0;
}
static void raw_close(BlockDriverState *bs)
@@ -411,9 +282,9 @@ static BlockDriver bdrv_file = {
.bdrv_close = raw_close,
.bdrv_create = raw_create,
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_co_flush_to_disk = raw_flush,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
@@ -503,10 +374,18 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
}
s->type = find_device_type(bs, filename);
raw_parse_flags(flags, &access_flags, &overlapped);
if (flags & BDRV_O_RDWR) {
access_flags = GENERIC_READ | GENERIC_WRITE;
} else {
access_flags = GENERIC_READ;
}
create_flags = OPEN_EXISTING;
overlapped = FILE_ATTRIBUTE_NORMAL;
if (flags & BDRV_O_NOCACHE)
overlapped |= FILE_FLAG_NO_BUFFERING;
if (!(flags & BDRV_O_CACHE_WB))
overlapped |= FILE_FLAG_WRITE_THROUGH;
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
create_flags, overlapped, NULL);
@@ -534,9 +413,9 @@ static BlockDriver bdrv_host_device = {
.bdrv_close = raw_close,
.bdrv_has_zero_init = hdev_has_zero_init,
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_co_flush_to_disk = raw_flush,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size
-10
View File
@@ -9,14 +9,6 @@ static int raw_open(BlockDriverState *bs, int flags)
return 0;
}
/* We have nothing to do for raw reopen, stubs just return
* success */
static int raw_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
return 0;
}
static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, QEMUIOVector *qiov)
{
@@ -123,8 +115,6 @@ static BlockDriver bdrv_raw = {
.bdrv_open = raw_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_co_readv = raw_co_readv,
.bdrv_co_writev = raw_co_writev,
.bdrv_co_is_allocated = raw_co_is_allocated,
+10 -4
View File
@@ -69,7 +69,7 @@ typedef enum {
typedef struct RBDAIOCB {
BlockDriverAIOCB common;
QEMUBH *bh;
int64_t ret;
int ret;
QEMUIOVector *qiov;
char *bounce;
RBDAIOCmd cmd;
@@ -86,7 +86,7 @@ typedef struct RADOSCB {
int done;
int64_t size;
char *buf;
int64_t ret;
int ret;
} RADOSCB;
#define RBD_FD_READ 0
@@ -487,6 +487,12 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags)
rados_conf_set(s->cluster, "rbd_cache", "false");
} else {
rados_conf_set(s->cluster, "rbd_cache", "true");
if (!(flags & BDRV_O_CACHE_WB)) {
r = rados_conf_set(s->cluster, "rbd_cache_max_dirty", "0");
if (r < 0) {
rados_conf_set(s->cluster, "rbd_cache", "false");
}
}
}
if (strstr(conf, "conf=") == NULL) {
@@ -570,7 +576,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
acb->cancelled = 1;
}
static const AIOCBInfo rbd_aiocb_info = {
static AIOPool rbd_aio_pool = {
.aiocb_size = sizeof(RBDAIOCB),
.cancel = qemu_rbd_aio_cancel,
};
@@ -672,7 +678,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
BDRVRBDState *s = bs->opaque;
acb = qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
acb->cmd = cmd;
acb->qiov = qiov;
if (cmd == RBD_AIO_DISCARD) {
+56 -64
View File
@@ -201,12 +201,12 @@ static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return hval;
}
static inline bool is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
{
return inode->vdi_id == inode->data_vdi_id[idx];
}
static inline bool is_data_obj(uint64_t oid)
static inline int is_data_obj(uint64_t oid)
{
return !(VDI_BIT & oid);
}
@@ -231,7 +231,7 @@ static inline uint64_t vid_to_data_oid(uint32_t vid, uint32_t idx)
return ((uint64_t)vid << VDI_SPACE_SHIFT) | idx;
}
static inline bool is_snapshot(struct SheepdogInode *inode)
static inline int is_snapshot(struct SheepdogInode *inode)
{
return !!inode->snap_ctime;
}
@@ -281,7 +281,7 @@ struct SheepdogAIOCB {
Coroutine *coroutine;
void (*aio_done_func)(SheepdogAIOCB *);
bool canceled;
int canceled;
int nr_pending;
};
@@ -292,8 +292,8 @@ typedef struct BDRVSheepdogState {
uint32_t max_dirty_data_idx;
char name[SD_MAX_VDI_LEN];
bool is_snapshot;
bool cache_enabled;
int is_snapshot;
uint8_t cache_enabled;
char *addr;
char *port;
@@ -417,10 +417,10 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
*/
acb->ret = -EIO;
qemu_coroutine_enter(acb->coroutine, NULL);
acb->canceled = true;
acb->canceled = 1;
}
static const AIOCBInfo sd_aiocb_info = {
static AIOPool sd_aio_pool = {
.aiocb_size = sizeof(SheepdogAIOCB),
.cancel = sd_aio_cancel,
};
@@ -431,7 +431,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
{
SheepdogAIOCB *acb;
acb = qemu_aio_get(&sd_aiocb_info, bs, cb, opaque);
acb = qemu_aio_get(&sd_aio_pool, bs, cb, opaque);
acb->qiov = qiov;
@@ -439,7 +439,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
acb->nb_sectors = nb_sectors;
acb->aio_done_func = NULL;
acb->canceled = false;
acb->canceled = 0;
acb->coroutine = qemu_coroutine_self();
acb->ret = 0;
acb->nr_pending = 0;
@@ -613,7 +613,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
}
static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
struct iovec *iov, int niov, bool create,
struct iovec *iov, int niov, int create,
enum AIOCBState aiocb_type);
@@ -646,7 +646,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
QLIST_REMOVE(aio_req, aio_siblings);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
ret = add_aio_request(s, aio_req, acb->qiov->iov,
acb->qiov->niov, false, acb->aiocb_type);
acb->qiov->niov, 0, acb->aiocb_type);
if (ret < 0) {
error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
@@ -866,14 +866,14 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
s->port = 0;
}
pstrcpy(vdi, SD_MAX_VDI_LEN, p);
strncpy(vdi, p, SD_MAX_VDI_LEN);
p = strchr(vdi, ':');
if (p) {
*p++ = '\0';
*snapid = strtoul(p, NULL, 10);
if (*snapid == 0) {
pstrcpy(tag, SD_MAX_VDI_TAG_LEN, p);
strncpy(tag, p, SD_MAX_VDI_TAG_LEN);
}
} else {
*snapid = CURRENT_VDI_ID; /* search current vdi */
@@ -900,10 +900,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
return fd;
}
/* This pair of strncpy calls ensures that the buffer is zero-filled,
* which is desirable since we'll soon be sending those bytes, and
* don't want the send_req to read uninitialized data.
*/
memset(buf, 0, sizeof(buf));
strncpy(buf, filename, SD_MAX_VDI_LEN);
strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN);
@@ -943,7 +940,7 @@ out:
}
static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
struct iovec *iov, int niov, bool create,
struct iovec *iov, int niov, int create,
enum AIOCBState aiocb_type)
{
int nr_copies = s->inode.nr_copies;
@@ -1022,7 +1019,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
unsigned int datalen, uint64_t offset,
bool write, bool create, bool cache)
int write, int create, uint8_t cache)
{
SheepdogObjReq hdr;
SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr;
@@ -1071,18 +1068,18 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
}
static int read_object(int fd, char *buf, uint64_t oid, int copies,
unsigned int datalen, uint64_t offset, bool cache)
unsigned int datalen, uint64_t offset, uint8_t cache)
{
return read_write_object(fd, buf, oid, copies, datalen, offset, false,
false, cache);
return read_write_object(fd, buf, oid, copies, datalen, offset, 0, 0,
cache);
}
static int write_object(int fd, char *buf, uint64_t oid, int copies,
unsigned int datalen, uint64_t offset, bool create,
bool cache)
unsigned int datalen, uint64_t offset, int create,
uint8_t cache)
{
return read_write_object(fd, buf, oid, copies, datalen, offset, true,
create, cache);
return read_write_object(fd, buf, oid, copies, datalen, offset, 1, create,
cache);
}
static int sd_open(BlockDriverState *bs, const char *filename, int flags)
@@ -1117,17 +1114,19 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
goto out;
}
s->cache_enabled = true;
s->flush_fd = connect_to_sdog(s->addr, s->port);
if (s->flush_fd < 0) {
error_report("failed to connect");
ret = s->flush_fd;
goto out;
if (flags & BDRV_O_CACHE_WB) {
s->cache_enabled = 1;
s->flush_fd = connect_to_sdog(s->addr, s->port);
if (s->flush_fd < 0) {
error_report("failed to connect");
ret = s->flush_fd;
goto out;
}
}
if (snapid || tag[0] != '\0') {
dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
s->is_snapshot = true;
s->is_snapshot = 1;
}
fd = connect_to_sdog(s->addr, s->port);
@@ -1152,7 +1151,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
s->max_dirty_data_idx = 0;
bs->total_sectors = s->inode.vdi_size / SECTOR_SIZE;
pstrcpy(s->name, sizeof(s->name), vdi);
strncpy(s->name, vdi, sizeof(s->name));
qemu_co_mutex_init(&s->lock);
g_free(buf);
return 0;
@@ -1180,11 +1179,8 @@ static int do_sd_create(char *filename, int64_t vdi_size,
return fd;
}
/* FIXME: would it be better to fail (e.g., return -EIO) when filename
* does not fit in buf? For now, just truncate and avoid buffer overrun.
*/
memset(buf, 0, sizeof(buf));
pstrcpy(buf, sizeof(buf), filename);
strncpy(buf, filename, SD_MAX_VDI_LEN);
memset(&hdr, 0, sizeof(hdr));
hdr.opcode = SD_OP_NEW_VDI;
@@ -1270,7 +1266,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
BDRVSheepdogState *s;
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
uint32_t snapid;
bool prealloc = false;
int prealloc = 0;
const char *vdiname;
s = g_malloc0(sizeof(BDRVSheepdogState));
@@ -1292,9 +1288,9 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
backing_file = options->value.s;
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
if (!options->value.s || !strcmp(options->value.s, "off")) {
prealloc = false;
prealloc = 0;
} else if (!strcmp(options->value.s, "full")) {
prealloc = true;
prealloc = 1;
} else {
error_report("Invalid preallocation mode: '%s'",
options->value.s);
@@ -1422,7 +1418,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
s->inode.vdi_size = offset;
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
s->inode.nr_copies, datalen, 0, false, s->cache_enabled);
s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
close(fd);
if (ret < 0) {
@@ -1461,7 +1457,7 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
data_len, offset, 0, 0, offset);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
ret = add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
ret = add_aio_request(s, aio_req, &iov, 1, 0, AIOCB_WRITE_UDATA);
if (ret) {
free_aio_req(s, aio_req);
acb->ret = -EIO;
@@ -1515,7 +1511,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
memcpy(&s->inode, buf, sizeof(s->inode));
s->is_snapshot = false;
s->is_snapshot = 0;
ret = 0;
dprintf("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
@@ -1570,7 +1566,7 @@ static int coroutine_fn sd_co_rw_vector(void *p)
while (done != total) {
uint8_t flags = 0;
uint64_t old_oid = 0;
bool create = false;
int create = 0;
oid = vid_to_data_oid(inode->data_vdi_id[idx], idx);
@@ -1585,10 +1581,10 @@ static int coroutine_fn sd_co_rw_vector(void *p)
break;
case AIOCB_WRITE_UDATA:
if (!inode->data_vdi_id[idx]) {
create = true;
create = 1;
} else if (!is_data_obj_writable(inode, idx)) {
/* Copy-On-Write */
create = true;
create = 1;
old_oid = oid;
flags = SD_FLAG_CMD_COW;
}
@@ -1722,7 +1718,7 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
if (rsp->result == SD_RES_INVALID_PARMS) {
dprintf("disable write cache since the server doesn't support it\n");
s->cache_enabled = false;
s->cache_enabled = 0;
closesocket(s->flush_fd);
return 0;
}
@@ -1758,9 +1754,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
s->inode.vm_state_size = sn_info->vm_state_size;
s->inode.vm_clock_nsec = sn_info->vm_clock_nsec;
/* It appears that inode.tag does not require a NUL terminator,
* which means this use of strncpy is ok.
*/
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
/* we don't need to update entire object */
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
@@ -1773,7 +1766,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
}
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
s->inode.nr_copies, datalen, 0, false, s->cache_enabled);
s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
if (ret < 0) {
error_report("failed to write snapshot's inode.");
goto cleanup;
@@ -1820,13 +1813,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
memcpy(old_s, s, sizeof(BDRVSheepdogState));
pstrcpy(vdi, sizeof(vdi), s->name);
memset(vdi, 0, sizeof(vdi));
strncpy(vdi, s->name, sizeof(vdi));
memset(tag, 0, sizeof(tag));
snapid = strtoul(snapshot_id, NULL, 10);
if (snapid) {
tag[0] = 0;
} else {
pstrcpy(tag, sizeof(tag), s->name);
if (!snapid) {
strncpy(tag, s->name, sizeof(tag));
}
ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
@@ -1860,7 +1853,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
goto out;
}
s->is_snapshot = true;
s->is_snapshot = 1;
g_free(buf);
g_free(old_s);
@@ -1955,9 +1948,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), "%u",
inode.snap_id);
pstrcpy(sn_tab[found].name,
MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)),
inode.tag);
strncpy(sn_tab[found].name, inode.tag,
MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)));
found++;
}
}
@@ -1978,8 +1970,8 @@ out:
static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
int64_t pos, int size, int load)
{
bool create;
int fd, ret = 0, remaining = size;
int fd, create;
int ret = 0, remaining = size;
unsigned int data_len;
uint64_t vmstate_oid;
uint32_t vdi_index;
+3 -30
View File
@@ -13,7 +13,6 @@
#include "trace.h"
#include "block_int.h"
#include "blockjob.h"
#include "qemu/ratelimit.h"
enum {
@@ -31,7 +30,6 @@ typedef struct StreamBlockJob {
BlockJob common;
RateLimit limit;
BlockDriverState *base;
BlockdevOnError on_error;
char backing_file_id[1024];
} StreamBlockJob;
@@ -79,14 +77,13 @@ static void coroutine_fn stream_run(void *opaque)
BlockDriverState *bs = s->common.bs;
BlockDriverState *base = s->base;
int64_t sector_num, end;
int error = 0;
int ret = 0;
int n = 0;
void *buf;
s->common.len = bdrv_getlength(bs);
if (s->common.len < 0) {
block_job_completed(&s->common, s->common.len);
block_job_complete(&s->common, s->common.len);
return;
}
@@ -144,19 +141,7 @@ wait:
ret = stream_populate(bs, sector_num, n, buf);
}
if (ret < 0) {
BlockErrorAction action =
block_job_error_action(&s->common, s->common.bs, s->on_error,
true, -ret);
if (action == BDRV_ACTION_STOP) {
n = 0;
continue;
}
if (error == 0) {
error = ret;
}
if (action == BDRV_ACTION_REPORT) {
break;
}
break;
}
ret = 0;
@@ -168,9 +153,6 @@ wait:
bdrv_disable_copy_on_read(bs);
}
/* Do not remove the backing file if an error was there but ignored. */
ret = error;
if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) {
const char *base_id = NULL, *base_fmt = NULL;
if (base) {
@@ -184,7 +166,7 @@ wait:
}
qemu_vfree(buf);
block_job_completed(&s->common, ret);
block_job_complete(&s->common, ret);
}
static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
@@ -206,19 +188,11 @@ static BlockJobType stream_job_type = {
void stream_start(BlockDriverState *bs, BlockDriverState *base,
const char *base_id, int64_t speed,
BlockdevOnError on_error,
BlockDriverCompletionFunc *cb,
void *opaque, Error **errp)
{
StreamBlockJob *s;
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
error_set(errp, QERR_INVALID_PARAMETER, "on-error");
return;
}
s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp);
if (!s) {
return;
@@ -229,7 +203,6 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id);
}
s->on_error = on_error;
s->common.co = qemu_coroutine_create(stream_run);
trace_stream_start(bs, base, s, s->common.co, opaque);
qemu_coroutine_enter(s->common.co, s);
+6 -10
View File
@@ -60,6 +60,9 @@
/* TODO: move uuid emulation to some central place in QEMU. */
#include "sysemu.h" /* UUID_FMT */
typedef unsigned char uuid_t[16];
void uuid_generate(uuid_t out);
int uuid_is_null(const uuid_t uu);
void uuid_unparse(const uuid_t uu, char *out);
#endif
/* Code configuration options. */
@@ -121,18 +124,18 @@ typedef unsigned char uuid_t[16];
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
#if !defined(CONFIG_UUID)
static inline void uuid_generate(uuid_t out)
void uuid_generate(uuid_t out)
{
memset(out, 0, sizeof(uuid_t));
}
static inline int uuid_is_null(const uuid_t uu)
int uuid_is_null(const uuid_t uu)
{
uuid_t null_uuid = { 0 };
return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
}
static inline void uuid_unparse(const uuid_t uu, char *out)
void uuid_unparse(const uuid_t uu, char *out)
{
snprintf(out, 37, UUID_FMT,
uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
@@ -451,12 +454,6 @@ static int vdi_open(BlockDriverState *bs, int flags)
return -1;
}
static int vdi_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
return 0;
}
static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int *pnum)
{
@@ -764,7 +761,6 @@ static BlockDriver bdrv_vdi = {
.bdrv_probe = vdi_probe,
.bdrv_open = vdi_open,
.bdrv_close = vdi_close,
.bdrv_reopen_prepare = vdi_reopen_prepare,
.bdrv_create = vdi_create,
.bdrv_co_is_allocated = vdi_co_is_allocated,
.bdrv_make_empty = vdi_make_empty,
+4 -44
View File
@@ -300,40 +300,6 @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
return 1;
}
/* Queue extents, if any, for reopen() */
static int vmdk_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
BDRVVmdkState *s;
int ret = -1;
int i;
VmdkExtent *e;
assert(state != NULL);
assert(state->bs != NULL);
if (queue == NULL) {
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
"No reopen queue for VMDK extents");
goto exit;
}
s = state->bs->opaque;
assert(s != NULL);
for (i = 0; i < s->num_extents; i++) {
e = &s->extents[i];
if (e->file != state->bs->file) {
bdrv_reopen_queue(queue, e->file, state->flags);
}
}
ret = 0;
exit:
return ret;
}
static int vmdk_parent_open(BlockDriverState *bs)
{
char *p_name;
@@ -1092,7 +1058,6 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
BDRVVmdkState *s = bs->opaque;
int ret;
uint64_t n, index_in_cluster;
uint64_t extent_begin_sector, extent_relative_sector_num;
VmdkExtent *extent = NULL;
uint64_t cluster_offset;
@@ -1104,9 +1069,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
ret = get_cluster_offset(
bs, extent, NULL,
sector_num << 9, 0, &cluster_offset);
extent_begin_sector = extent->end_sector - extent->sectors;
extent_relative_sector_num = sector_num - extent_begin_sector;
index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
index_in_cluster = sector_num % extent->cluster_sectors;
n = extent->cluster_sectors - index_in_cluster;
if (n > nb_sectors) {
n = nb_sectors;
@@ -1157,7 +1120,6 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
VmdkExtent *extent = NULL;
int n, ret;
int64_t index_in_cluster;
uint64_t extent_begin_sector, extent_relative_sector_num;
uint64_t cluster_offset;
VmdkMetaData m_data;
@@ -1200,9 +1162,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
if (ret) {
return -EINVAL;
}
extent_begin_sector = extent->end_sector - extent->sectors;
extent_relative_sector_num = sector_num - extent_begin_sector;
index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
index_in_cluster = sector_num % extent->cluster_sectors;
n = extent->cluster_sectors - index_in_cluster;
if (n > nb_sectors) {
n = nb_sectors;
@@ -1414,7 +1374,8 @@ static int relative_path(char *dest, int dest_size,
return -1;
}
if (path_is_absolute(target)) {
pstrcpy(dest, dest_size, target);
dest[dest_size - 1] = '\0';
strncpy(dest, target, dest_size - 1);
return 0;
}
while (base[i] == target[i]) {
@@ -1685,7 +1646,6 @@ static BlockDriver bdrv_vmdk = {
.instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe,
.bdrv_open = vmdk_open,
.bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_read = vmdk_co_read,
.bdrv_write = vmdk_co_write,
.bdrv_close = vmdk_close,
-7
View File
@@ -265,12 +265,6 @@ static int vpc_open(BlockDriverState *bs, int flags)
return err;
}
static int vpc_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
return 0;
}
/*
* Returns the absolute byte offset of the given sector in the image file.
* If the sector is not allocated, -1 is returned instead.
@@ -789,7 +783,6 @@ static BlockDriver bdrv_vpc = {
.bdrv_probe = vpc_probe,
.bdrv_open = vpc_open,
.bdrv_close = vpc_close,
.bdrv_reopen_prepare = vpc_reopen_prepare,
.bdrv_create = vpc_create,
.bdrv_read = vpc_co_read,
-226
View File
@@ -1,226 +0,0 @@
/*
* Block driver for RAW files (win32)
*
* Copyright (c) 2006 Fabrice Bellard
*
* 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-timer.h"
#include "block_int.h"
#include "module.h"
#include "qemu-common.h"
#include "qemu-aio.h"
#include "raw-aio.h"
#include "event_notifier.h"
#include <windows.h>
#include <winioctl.h>
#define FTYPE_FILE 0
#define FTYPE_CD 1
#define FTYPE_HARDDISK 2
struct QEMUWin32AIOState {
HANDLE hIOCP;
EventNotifier e;
int count;
};
typedef struct QEMUWin32AIOCB {
BlockDriverAIOCB common;
struct QEMUWin32AIOState *ctx;
int nbytes;
OVERLAPPED ov;
QEMUIOVector *qiov;
void *buf;
bool is_read;
bool is_linear;
} QEMUWin32AIOCB;
/*
* Completes an AIO request (calls the callback and frees the ACB).
*/
static void win32_aio_process_completion(QEMUWin32AIOState *s,
QEMUWin32AIOCB *waiocb, DWORD count)
{
int ret;
s->count--;
if (waiocb->ov.Internal != 0) {
ret = -EIO;
} else {
ret = 0;
if (count < waiocb->nbytes) {
/* Short reads mean EOF, pad with zeros. */
if (waiocb->is_read) {
qemu_iovec_memset(waiocb->qiov, count, 0,
waiocb->qiov->size - count);
} else {
ret = -EINVAL;
}
}
}
if (!waiocb->is_linear) {
if (ret == 0 && waiocb->is_read) {
QEMUIOVector *qiov = waiocb->qiov;
char *p = waiocb->buf;
int i;
for (i = 0; i < qiov->niov; ++i) {
memcpy(qiov->iov[i].iov_base, p, qiov->iov[i].iov_len);
p += qiov->iov[i].iov_len;
}
}
qemu_vfree(waiocb->buf);
}
waiocb->common.cb(waiocb->common.opaque, ret);
qemu_aio_release(waiocb);
}
static void win32_aio_completion_cb(EventNotifier *e)
{
QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
DWORD count;
ULONG_PTR key;
OVERLAPPED *ov;
event_notifier_test_and_clear(&s->e);
while (GetQueuedCompletionStatus(s->hIOCP, &count, &key, &ov, 0)) {
QEMUWin32AIOCB *waiocb = container_of(ov, QEMUWin32AIOCB, ov);
win32_aio_process_completion(s, waiocb, count);
}
}
static int win32_aio_flush_cb(EventNotifier *e)
{
QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
return (s->count > 0) ? 1 : 0;
}
static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
{
QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;
/*
* CancelIoEx is only supported in Vista and newer. For now, just
* wait for completion.
*/
while (!HasOverlappedIoCompleted(&waiocb->ov)) {
qemu_aio_wait();
}
}
static const AIOCBInfo win32_aiocb_info = {
.aiocb_size = sizeof(QEMUWin32AIOCB),
.cancel = win32_aio_cancel,
};
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
QEMUWin32AIOState *aio, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
{
struct QEMUWin32AIOCB *waiocb;
uint64_t offset = sector_num * 512;
DWORD rc;
waiocb = qemu_aio_get(&win32_aiocb_info, bs, cb, opaque);
waiocb->nbytes = nb_sectors * 512;
waiocb->qiov = qiov;
waiocb->is_read = (type == QEMU_AIO_READ);
if (qiov->niov > 1) {
waiocb->buf = qemu_blockalign(bs, qiov->size);
if (type & QEMU_AIO_WRITE) {
char *p = waiocb->buf;
int i;
for (i = 0; i < qiov->niov; ++i) {
memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);
p += qiov->iov[i].iov_len;
}
}
waiocb->is_linear = false;
} else {
waiocb->buf = qiov->iov[0].iov_base;
waiocb->is_linear = true;
}
memset(&waiocb->ov, 0, sizeof(waiocb->ov));
waiocb->ov.Offset = (DWORD)offset;
waiocb->ov.OffsetHigh = (DWORD)(offset >> 32);
waiocb->ov.hEvent = event_notifier_get_handle(&aio->e);
aio->count++;
if (type & QEMU_AIO_READ) {
rc = ReadFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);
} else {
rc = WriteFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);
}
if(rc == 0 && GetLastError() != ERROR_IO_PENDING) {
goto out_dec_count;
}
return &waiocb->common;
out_dec_count:
aio->count--;
qemu_aio_release(waiocb);
return NULL;
}
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
{
if (CreateIoCompletionPort(hfile, aio->hIOCP, (ULONG_PTR) 0, 0) == NULL) {
return -EINVAL;
} else {
return 0;
}
}
QEMUWin32AIOState *win32_aio_init(void)
{
QEMUWin32AIOState *s;
s = g_malloc0(sizeof(*s));
if (event_notifier_init(&s->e, false) < 0) {
goto out_free_state;
}
s->hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (s->hIOCP == NULL) {
goto out_close_efd;
}
qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb,
win32_aio_flush_cb);
return s;
out_close_efd:
event_notifier_cleanup(&s->e);
out_free_state:
g_free(s);
return NULL;
}
+156 -57
View File
@@ -31,7 +31,6 @@
#include "qemu-timer.h"
#include "qapi-types.h"
#include "qerror.h"
#include "monitor.h"
#define BLOCK_FLAG_ENCRYPT 1
#define BLOCK_FLAG_COMPAT6 4
@@ -68,18 +67,78 @@ typedef struct BlockIOBaseValue {
uint64_t ios[2];
} BlockIOBaseValue;
typedef struct BlockJob BlockJob;
/**
* BlockJobType:
*
* A class type for block job objects.
*/
typedef struct BlockJobType {
/** Derived BlockJob struct size */
size_t instance_size;
/** String describing the operation, part of query-block-jobs QMP API */
const char *job_type;
/** Optional callback for job types that support setting a speed limit */
void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
} BlockJobType;
/**
* BlockJob:
*
* Long-running operation on a BlockDriverState.
*/
struct BlockJob {
/** The job type, including the job vtable. */
const BlockJobType *job_type;
/** The block device on which the job is operating. */
BlockDriverState *bs;
/**
* The coroutine that executes the job. If not NULL, it is
* reentered when busy is false and the job is cancelled.
*/
Coroutine *co;
/**
* Set to true if the job should cancel itself. The flag must
* always be tested just before toggling the busy flag from false
* to true. After a job has been cancelled, it should only yield
* if #qemu_aio_wait will ("sooner or later") reenter the coroutine.
*/
bool cancelled;
/**
* Set to false by the job while it is in a quiescent state, where
* no I/O is pending and the job has yielded on any condition
* that is not detected by #qemu_aio_wait, such as a timer.
*/
bool busy;
/** Offset that is published by the query-block-jobs QMP API */
int64_t offset;
/** Length that is published by the query-block-jobs QMP API */
int64_t len;
/** Speed that was set with @block_job_set_speed. */
int64_t speed;
/** The completion function that will be called when the job completes. */
BlockDriverCompletionFunc *cb;
/** The opaque value that is passed to the completion function. */
void *opaque;
};
struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_probe_device)(const char *filename);
/* For handling image reopen for split or non-split files */
int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
BlockReopenQueue *queue, Error **errp);
void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
int (*bdrv_open)(BlockDriverState *bs, int flags);
int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags);
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
@@ -209,6 +268,7 @@ struct BlockDriverState {
int64_t total_sectors; /* if we are reading a disk image, give its
size in sectors */
int read_only; /* if true, the media is read only */
int keep_read_only; /* if true, the media was requested to stay read only */
int open_flags; /* flags used to open the file, re-used for re-open */
int encrypted; /* if true, the media is encrypted */
int valid_key; /* if true, a valid encryption key has been set */
@@ -233,8 +293,6 @@ struct BlockDriverState {
BlockDriverState *backing_hd;
BlockDriverState *file;
NotifierList close_notifiers;
/* number of in-flight copy-on-read requests */
unsigned int copy_on_read_in_flight;
@@ -265,7 +323,7 @@ struct BlockDriverState {
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
BlockdevOnError on_read_error, on_write_error;
BlockErrorAction on_read_error, on_write_error;
bool iostatus_enabled;
BlockDeviceIoStatus iostatus;
char device_name[32];
@@ -278,7 +336,6 @@ struct BlockDriverState {
/* long-running background operation */
BlockJob *job;
};
int get_tmp_filename(char *filename, int size);
@@ -289,9 +346,92 @@ void bdrv_set_io_limits(BlockDriverState *bs,
#ifdef _WIN32
int is_windows_drive(const char *filename);
#endif
void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
enum MonitorEvent ev,
BlockErrorAction action, bool is_read);
/**
* block_job_create:
* @job_type: The class object for the newly-created job.
* @bs: The block
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
* @errp: Error object.
*
* Create a new long-running block device job and return it. The job
* will call @cb asynchronously when the job completes. Note that
* @bs may have been closed at the time the @cb it is called. If
* this is the case, the job may be reported as either cancelled or
* completed.
*
* This function is not part of the public job interface; it should be
* called from a wrapper that is specific to the job type.
*/
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
int64_t speed, BlockDriverCompletionFunc *cb,
void *opaque, Error **errp);
/**
* block_job_sleep_ns:
* @job: The job that calls the function.
* @clock: The clock to sleep on.
* @ns: How many nanoseconds to stop for.
*
* Put the job to sleep (assuming that it wasn't canceled) for @ns
* nanoseconds. Canceling the job will interrupt the wait immediately.
*/
void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns);
/**
* block_job_complete:
* @job: The job being completed.
* @ret: The status code.
*
* Call the completion function that was registered at creation time, and
* free @job.
*/
void block_job_complete(BlockJob *job, int ret);
/**
* block_job_set_speed:
* @job: The job to set the speed for.
* @speed: The new value
* @errp: Error object.
*
* Set a rate-limiting parameter for the job; the actual meaning may
* vary depending on the job type.
*/
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
/**
* block_job_cancel:
* @job: The job to be canceled.
*
* Asynchronously cancel the specified job.
*/
void block_job_cancel(BlockJob *job);
/**
* block_job_is_cancelled:
* @job: The job being queried.
*
* Returns whether the job is scheduled for cancellation.
*/
bool block_job_is_cancelled(BlockJob *job);
/**
* block_job_cancel:
* @job: The job to be canceled.
*
* Asynchronously cancel the job and wait for it to reach a quiescent
* state. Note that the completion callback will still be called
* asynchronously, hence it is *not* valid to call #bdrv_delete
* immediately after #block_job_cancel_sync. Users of block jobs
* will usually protect the BlockDriverState objects with a reference
* count, should this be a concern.
*
* Returns the return value from the job if the job actually completed
* during the call, or -ECANCELED if it was canceled.
*/
int block_job_cancel_sync(BlockJob *job);
/**
* stream_start:
@@ -301,7 +441,6 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
* @base_id: The file name that will be written to @bs as the new
* backing file if the job completes. Ignored if @base is %NULL.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @on_error: The action to take upon error.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
* @errp: Error object.
@@ -313,47 +452,7 @@ void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
* @base_id in the written image and to @base in the live BlockDriverState.
*/
void stream_start(BlockDriverState *bs, BlockDriverState *base,
const char *base_id, int64_t speed, BlockdevOnError on_error,
BlockDriverCompletionFunc *cb,
void *opaque, Error **errp);
/**
* commit_start:
* @bs: Top Block device
* @base: Block device that will be written into, and become the new top
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @on_error: The action to take upon error.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
* @errp: Error object.
*
*/
void commit_start(BlockDriverState *bs, BlockDriverState *base,
BlockDriverState *top, int64_t speed,
BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
void *opaque, Error **errp);
/*
* mirror_start:
* @bs: Block device to operate on.
* @target: Block device to write to.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @mode: Whether to collapse all images in the chain to the target.
* @on_source_error: The action to take upon error reading from the source.
* @on_target_error: The action to take upon error writing to the target.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
* @errp: Error object.
*
* Start a mirroring operation on @bs. Clusters that are allocated
* in @bs will be written to @bs until the job is cancelled or
* manually completed. At the end of a successful mirroring job,
* @bs will be switched to read from @target.
*/
void mirror_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, MirrorSyncMode mode,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
const char *base_id, int64_t speed,
BlockDriverCompletionFunc *cb,
void *opaque, Error **errp);
-133
View File
@@ -1,133 +0,0 @@
/*
* Serving QEMU block devices via NBD
*
* Copyright (c) 2012 Red Hat, Inc.
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
* 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 "blockdev.h"
#include "hw/block-common.h"
#include "monitor.h"
#include "qerror.h"
#include "sysemu.h"
#include "qmp-commands.h"
#include "trace.h"
#include "nbd.h"
#include "qemu_socket.h"
static int server_fd = -1;
static void nbd_accept(void *opaque)
{
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
if (fd >= 0) {
nbd_client_new(NULL, fd, nbd_client_put);
}
}
void qmp_nbd_server_start(SocketAddress *addr, Error **errp)
{
if (server_fd != -1) {
error_setg(errp, "NBD server already running");
return;
}
server_fd = socket_listen(addr, errp);
if (server_fd != -1) {
qemu_set_fd_handler2(server_fd, NULL, nbd_accept, NULL, NULL);
}
}
/* Hook into the BlockDriverState notifiers to close the export when
* the file is closed.
*/
typedef struct NBDCloseNotifier {
Notifier n;
NBDExport *exp;
QTAILQ_ENTRY(NBDCloseNotifier) next;
} NBDCloseNotifier;
static QTAILQ_HEAD(, NBDCloseNotifier) close_notifiers =
QTAILQ_HEAD_INITIALIZER(close_notifiers);
static void nbd_close_notifier(Notifier *n, void *data)
{
NBDCloseNotifier *cn = DO_UPCAST(NBDCloseNotifier, n, n);
notifier_remove(&cn->n);
QTAILQ_REMOVE(&close_notifiers, cn, next);
nbd_export_close(cn->exp);
nbd_export_put(cn->exp);
g_free(cn);
}
static void nbd_server_put_ref(NBDExport *exp)
{
BlockDriverState *bs = nbd_export_get_blockdev(exp);
drive_put_ref(drive_get_by_blockdev(bs));
}
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
Error **errp)
{
BlockDriverState *bs;
NBDExport *exp;
NBDCloseNotifier *n;
if (server_fd == -1) {
error_setg(errp, "NBD server not running");
return;
}
if (nbd_export_find(device)) {
error_setg(errp, "NBD server already exporting device '%s'", device);
return;
}
bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
}
if (!has_writable) {
writable = false;
}
if (bdrv_is_read_only(bs)) {
writable = false;
}
exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
nbd_server_put_ref);
nbd_export_set_name(exp, device);
drive_get_ref(drive_get_by_blockdev(bs));
n = g_malloc0(sizeof(NBDCloseNotifier));
n->n.notify = nbd_close_notifier;
n->exp = exp;
bdrv_add_close_notifier(bs, &n->n);
QTAILQ_INSERT_TAIL(&close_notifiers, n, next);
}
void qmp_nbd_server_stop(Error **errp)
{
while (!QTAILQ_EMPTY(&close_notifiers)) {
NBDCloseNotifier *cn = QTAILQ_FIRST(&close_notifiers);
nbd_close_notifier(&cn->n, nbd_export_get_blockdev(cn->exp));
}
if (server_fd != -1) {
qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
close(server_fd);
server_fd = -1;
}
}
+43 -275
View File
@@ -9,7 +9,6 @@
#include "blockdev.h"
#include "hw/block-common.h"
#include "blockjob.h"
#include "monitor.h"
#include "qerror.h"
#include "qemu-option.h"
@@ -238,16 +237,16 @@ static void drive_put_ref_bh_schedule(DriveInfo *dinfo)
qemu_bh_schedule(s->bh);
}
static int parse_block_error_action(const char *buf, bool is_read)
static int parse_block_error_action(const char *buf, int is_read)
{
if (!strcmp(buf, "ignore")) {
return BLOCKDEV_ON_ERROR_IGNORE;
return BLOCK_ERR_IGNORE;
} else if (!is_read && !strcmp(buf, "enospc")) {
return BLOCKDEV_ON_ERROR_ENOSPC;
return BLOCK_ERR_STOP_ENOSPC;
} else if (!strcmp(buf, "stop")) {
return BLOCKDEV_ON_ERROR_STOP;
return BLOCK_ERR_STOP_ANY;
} else if (!strcmp(buf, "report")) {
return BLOCKDEV_ON_ERROR_REPORT;
return BLOCK_ERR_REPORT;
} else {
error_report("'%s' invalid %s error action",
buf, is_read ? "read" : "write");
@@ -433,13 +432,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
return NULL;
}
if (qemu_opt_get(opts, "boot") != NULL) {
fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
"ignored. Future versions will reject this parameter. Please "
"update your scripts.\n");
}
on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
on_write_error = BLOCK_ERR_STOP_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
error_report("werror is not supported by this bus type");
@@ -452,7 +445,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
}
}
on_read_error = BLOCKDEV_ON_ERROR_REPORT;
on_read_error = BLOCK_ERR_REPORT;
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
error_report("rerror is not supported by this bus type");
@@ -812,11 +805,6 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {
/* This removes our old bs from the bdrv_states, and adds the new bs */
bdrv_append(states->new_bs, states->old_bs);
/* We don't need (or want) to use the transactional
* bdrv_reopen_multiple() across all the entries at once, because we
* don't want to abort all of them if one of them fails the reopen */
bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR,
NULL);
}
/* success */
@@ -836,6 +824,7 @@ exit:
QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) {
g_free(states);
}
return;
}
@@ -1062,12 +1051,26 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
}
}
static void block_job_cb(void *opaque, int ret)
static QObject *qobject_from_block_job(BlockJob *job)
{
return qobject_from_jsonf("{ 'type': %s,"
"'device': %s,"
"'len': %" PRId64 ","
"'offset': %" PRId64 ","
"'speed': %" PRId64 " }",
job->job_type->job_type,
bdrv_get_device_name(job->bs),
job->len,
job->offset,
job->speed);
}
static void block_stream_cb(void *opaque, int ret)
{
BlockDriverState *bs = opaque;
QObject *obj;
trace_block_job_cb(bs, bs->job, ret);
trace_block_stream_cb(bs, bs->job, ret);
assert(bs->job);
obj = qobject_from_block_job(bs->job);
@@ -1087,18 +1090,13 @@ static void block_job_cb(void *opaque, int ret)
}
void qmp_block_stream(const char *device, bool has_base,
const char *base, bool has_speed, int64_t speed,
bool has_on_error, BlockdevOnError on_error,
Error **errp)
const char *base, bool has_speed,
int64_t speed, Error **errp)
{
BlockDriverState *bs;
BlockDriverState *base_bs = NULL;
Error *local_err = NULL;
if (!has_on_error) {
on_error = BLOCKDEV_ON_ERROR_REPORT;
}
bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
@@ -1114,7 +1112,7 @@ void qmp_block_stream(const char *device, bool has_base,
}
stream_start(bs, base_bs, base, has_speed ? speed : 0,
on_error, block_job_cb, bs, &local_err);
block_stream_cb, bs, &local_err);
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
return;
@@ -1128,199 +1126,6 @@ void qmp_block_stream(const char *device, bool has_base,
trace_qmp_block_stream(bs, bs->job);
}
void qmp_block_commit(const char *device,
bool has_base, const char *base, const char *top,
bool has_speed, int64_t speed,
Error **errp)
{
BlockDriverState *bs;
BlockDriverState *base_bs, *top_bs;
Error *local_err = NULL;
/* This will be part of the QMP command, if/when the
* BlockdevOnError change for blkmirror makes it in
*/
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
/* drain all i/o before commits */
bdrv_drain_all();
bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
}
/* default top_bs is the active layer */
top_bs = bs;
if (top) {
if (strcmp(bs->filename, top) != 0) {
top_bs = bdrv_find_backing_image(bs, top);
}
}
if (top_bs == NULL) {
error_setg(errp, "Top image file %s not found", top ? top : "NULL");
return;
}
if (has_base && base) {
base_bs = bdrv_find_backing_image(top_bs, base);
} else {
base_bs = bdrv_find_base(top_bs);
}
if (base_bs == NULL) {
error_set(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL");
return;
}
commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs,
&local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
/* Grab a reference so hotplug does not delete the BlockDriverState from
* underneath us.
*/
drive_get_ref(drive_get_by_blockdev(bs));
}
void qmp_drive_mirror(const char *device, const char *target,
bool has_format, const char *format,
enum MirrorSyncMode sync,
bool has_mode, enum NewImageMode mode,
bool has_speed, int64_t speed,
bool has_on_source_error, BlockdevOnError on_source_error,
bool has_on_target_error, BlockdevOnError on_target_error,
Error **errp)
{
BlockDriverInfo bdi;
BlockDriverState *bs;
BlockDriverState *source, *target_bs;
BlockDriver *proto_drv;
BlockDriver *drv = NULL;
Error *local_err = NULL;
int flags;
uint64_t size;
int ret;
if (!has_speed) {
speed = 0;
}
if (!has_on_source_error) {
on_source_error = BLOCKDEV_ON_ERROR_REPORT;
}
if (!has_on_target_error) {
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
}
if (!has_mode) {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
}
bs = bdrv_find(device);
if (!bs) {
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
return;
}
if (!bdrv_is_inserted(bs)) {
error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
return;
}
if (!has_format) {
format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
}
if (format) {
drv = bdrv_find_format(format);
if (!drv) {
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
return;
}
}
if (bdrv_in_use(bs)) {
error_set(errp, QERR_DEVICE_IN_USE, device);
return;
}
flags = bs->open_flags | BDRV_O_RDWR;
source = bs->backing_hd;
if (!source && sync == MIRROR_SYNC_MODE_TOP) {
sync = MIRROR_SYNC_MODE_FULL;
}
proto_drv = bdrv_find_protocol(target);
if (!proto_drv) {
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
return;
}
if (sync == MIRROR_SYNC_MODE_FULL && mode != NEW_IMAGE_MODE_EXISTING) {
/* create new image w/o backing file */
assert(format && drv);
bdrv_get_geometry(bs, &size);
size *= 512;
ret = bdrv_img_create(target, format,
NULL, NULL, NULL, size, flags);
} else {
switch (mode) {
case NEW_IMAGE_MODE_EXISTING:
ret = 0;
break;
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
/* create new image with backing file */
ret = bdrv_img_create(target, format,
source->filename,
source->drv->format_name,
NULL, -1, flags);
break;
default:
abort();
}
}
if (ret) {
error_set(errp, QERR_OPEN_FILE_FAILED, target);
return;
}
target_bs = bdrv_new("");
ret = bdrv_open(target_bs, target, flags | BDRV_O_NO_BACKING, drv);
if (ret < 0) {
bdrv_delete(target_bs);
error_set(errp, QERR_OPEN_FILE_FAILED, target);
return;
}
/* We need a backing file if we will copy parts of a cluster. */
if (bdrv_get_info(target_bs, &bdi) >= 0 && bdi.cluster_size != 0 &&
bdi.cluster_size >= BDRV_SECTORS_PER_DIRTY_CHUNK * 512) {
ret = bdrv_open_backing_file(target_bs);
if (ret < 0) {
bdrv_delete(target_bs);
error_set(errp, QERR_OPEN_FILE_FAILED, target);
return;
}
}
mirror_start(bs, target_bs, speed, sync, on_source_error, on_target_error,
block_job_cb, bs, &local_err);
if (local_err != NULL) {
bdrv_delete(target_bs);
error_propagate(errp, local_err);
return;
}
/* Grab a reference so hotplug does not delete the BlockDriverState from
* underneath us.
*/
drive_get_ref(drive_get_by_blockdev(bs));
}
static BlockJob *find_block_job(const char *device)
{
BlockDriverState *bs;
@@ -1337,28 +1142,19 @@ void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
BlockJob *job = find_block_job(device);
if (!job) {
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
error_set(errp, QERR_DEVICE_NOT_ACTIVE, device);
return;
}
block_job_set_speed(job, speed, errp);
}
void qmp_block_job_cancel(const char *device,
bool has_force, bool force, Error **errp)
void qmp_block_job_cancel(const char *device, Error **errp)
{
BlockJob *job = find_block_job(device);
if (!has_force) {
force = false;
}
if (!job) {
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
return;
}
if (job->paused && !force) {
error_set(errp, QERR_BLOCK_JOB_PAUSED, device);
error_set(errp, QERR_DEVICE_NOT_ACTIVE, device);
return;
}
@@ -1366,53 +1162,25 @@ void qmp_block_job_cancel(const char *device,
block_job_cancel(job);
}
void qmp_block_job_pause(const char *device, Error **errp)
{
BlockJob *job = find_block_job(device);
if (!job) {
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
return;
}
trace_qmp_block_job_pause(job);
block_job_pause(job);
}
void qmp_block_job_resume(const char *device, Error **errp)
{
BlockJob *job = find_block_job(device);
if (!job) {
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
return;
}
trace_qmp_block_job_resume(job);
block_job_resume(job);
}
void qmp_block_job_complete(const char *device, Error **errp)
{
BlockJob *job = find_block_job(device);
if (!job) {
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
return;
}
trace_qmp_block_job_complete(job);
block_job_complete(job, errp);
}
static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
{
BlockJobInfoList **prev = opaque;
BlockJob *job = bs->job;
if (job) {
BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
elem->value = block_job_query(bs->job);
BlockJobInfoList *elem;
BlockJobInfo *info = g_new(BlockJobInfo, 1);
*info = (BlockJobInfo){
.type = g_strdup(job->job_type->job_type),
.device = g_strdup(bdrv_get_device_name(bs)),
.len = job->len,
.offset = job->offset,
.speed = job->speed,
};
elem = g_new0(BlockJobInfoList, 1);
elem->value = info;
(*prev)->next = elem;
*prev = elem;
}
-283
View File
@@ -1,283 +0,0 @@
/*
* QEMU System Emulator block driver
*
* Copyright (c) 2011 IBM Corp.
* Copyright (c) 2012 Red Hat, Inc.
*
* 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 "config-host.h"
#include "qemu-common.h"
#include "trace.h"
#include "monitor.h"
#include "block.h"
#include "blockjob.h"
#include "block_int.h"
#include "qjson.h"
#include "qemu-coroutine.h"
#include "qmp-commands.h"
#include "qemu-timer.h"
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
int64_t speed, BlockDriverCompletionFunc *cb,
void *opaque, Error **errp)
{
BlockJob *job;
if (bs->job || bdrv_in_use(bs)) {
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
return NULL;
}
bdrv_set_in_use(bs, 1);
job = g_malloc0(job_type->instance_size);
job->job_type = job_type;
job->bs = bs;
job->cb = cb;
job->opaque = opaque;
job->busy = true;
bs->job = job;
/* Only set speed when necessary to avoid NotSupported error */
if (speed != 0) {
Error *local_err = NULL;
block_job_set_speed(job, speed, &local_err);
if (error_is_set(&local_err)) {
bs->job = NULL;
g_free(job);
bdrv_set_in_use(bs, 0);
error_propagate(errp, local_err);
return NULL;
}
}
return job;
}
void block_job_completed(BlockJob *job, int ret)
{
BlockDriverState *bs = job->bs;
assert(bs->job == job);
job->cb(job->opaque, ret);
bs->job = NULL;
g_free(job);
bdrv_set_in_use(bs, 0);
}
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
Error *local_err = NULL;
if (!job->job_type->set_speed) {
error_set(errp, QERR_NOT_SUPPORTED);
return;
}
job->job_type->set_speed(job, speed, &local_err);
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
return;
}
job->speed = speed;
}
void block_job_complete(BlockJob *job, Error **errp)
{
if (job->paused || job->cancelled || !job->job_type->complete) {
error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
return;
}
job->job_type->complete(job, errp);
}
void block_job_pause(BlockJob *job)
{
job->paused = true;
}
bool block_job_is_paused(BlockJob *job)
{
return job->paused;
}
void block_job_resume(BlockJob *job)
{
job->paused = false;
block_job_iostatus_reset(job);
if (job->co && !job->busy) {
qemu_coroutine_enter(job->co, NULL);
}
}
void block_job_cancel(BlockJob *job)
{
job->cancelled = true;
block_job_resume(job);
}
bool block_job_is_cancelled(BlockJob *job)
{
return job->cancelled;
}
void block_job_iostatus_reset(BlockJob *job)
{
job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
if (job->job_type->iostatus_reset) {
job->job_type->iostatus_reset(job);
}
}
struct BlockCancelData {
BlockJob *job;
BlockDriverCompletionFunc *cb;
void *opaque;
bool cancelled;
int ret;
};
static void block_job_cancel_cb(void *opaque, int ret)
{
struct BlockCancelData *data = opaque;
data->cancelled = block_job_is_cancelled(data->job);
data->ret = ret;
data->cb(data->opaque, ret);
}
int block_job_cancel_sync(BlockJob *job)
{
struct BlockCancelData data;
BlockDriverState *bs = job->bs;
assert(bs->job == job);
/* Set up our own callback to store the result and chain to
* the original callback.
*/
data.job = job;
data.cb = job->cb;
data.opaque = job->opaque;
data.ret = -EINPROGRESS;
job->cb = block_job_cancel_cb;
job->opaque = &data;
block_job_cancel(job);
while (data.ret == -EINPROGRESS) {
qemu_aio_wait();
}
return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
}
void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns)
{
assert(job->busy);
/* Check cancellation *before* setting busy = false, too! */
if (block_job_is_cancelled(job)) {
return;
}
job->busy = false;
if (block_job_is_paused(job)) {
qemu_coroutine_yield();
} else {
co_sleep_ns(clock, ns);
}
job->busy = true;
}
BlockJobInfo *block_job_query(BlockJob *job)
{
BlockJobInfo *info = g_new0(BlockJobInfo, 1);
info->type = g_strdup(job->job_type->job_type);
info->device = g_strdup(bdrv_get_device_name(job->bs));
info->len = job->len;
info->busy = job->busy;
info->paused = job->paused;
info->offset = job->offset;
info->speed = job->speed;
info->io_status = job->iostatus;
return info;
}
static void block_job_iostatus_set_err(BlockJob *job, int error)
{
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
BLOCK_DEVICE_IO_STATUS_FAILED;
}
}
QObject *qobject_from_block_job(BlockJob *job)
{
return qobject_from_jsonf("{ 'type': %s,"
"'device': %s,"
"'len': %" PRId64 ","
"'offset': %" PRId64 ","
"'speed': %" PRId64 " }",
job->job_type->job_type,
bdrv_get_device_name(job->bs),
job->len,
job->offset,
job->speed);
}
void block_job_ready(BlockJob *job)
{
QObject *data = qobject_from_block_job(job);
monitor_protocol_event(QEVENT_BLOCK_JOB_READY, data);
qobject_decref(data);
}
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
BlockdevOnError on_err,
int is_read, int error)
{
BlockErrorAction action;
switch (on_err) {
case BLOCKDEV_ON_ERROR_ENOSPC:
action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
break;
case BLOCKDEV_ON_ERROR_STOP:
action = BDRV_ACTION_STOP;
break;
case BLOCKDEV_ON_ERROR_REPORT:
action = BDRV_ACTION_REPORT;
break;
case BLOCKDEV_ON_ERROR_IGNORE:
action = BDRV_ACTION_IGNORE;
break;
default:
abort();
}
bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read);
if (action == BDRV_ACTION_STOP) {
block_job_pause(job);
block_job_iostatus_set_err(job, error);
if (bs != job->bs) {
bdrv_iostatus_set_err(bs, error);
}
}
return action;
}
-278
View File
@@ -1,278 +0,0 @@
/*
* Declarations for long-running block device operations
*
* Copyright (c) 2011 IBM Corp.
* Copyright (c) 2012 Red Hat, Inc.
*
* 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.
*/
#ifndef BLOCKJOB_H
#define BLOCKJOB_H 1
#include "block.h"
/**
* BlockJobType:
*
* A class type for block job objects.
*/
typedef struct BlockJobType {
/** Derived BlockJob struct size */
size_t instance_size;
/** String describing the operation, part of query-block-jobs QMP API */
const char *job_type;
/** Optional callback for job types that support setting a speed limit */
void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
/** Optional callback for job types that need to forward I/O status reset */
void (*iostatus_reset)(BlockJob *job);
/**
* Optional callback for job types whose completion must be triggered
* manually.
*/
void (*complete)(BlockJob *job, Error **errp);
} BlockJobType;
/**
* BlockJob:
*
* Long-running operation on a BlockDriverState.
*/
struct BlockJob {
/** The job type, including the job vtable. */
const BlockJobType *job_type;
/** The block device on which the job is operating. */
BlockDriverState *bs;
/**
* The coroutine that executes the job. If not NULL, it is
* reentered when busy is false and the job is cancelled.
*/
Coroutine *co;
/**
* Set to true if the job should cancel itself. The flag must
* always be tested just before toggling the busy flag from false
* to true. After a job has been cancelled, it should only yield
* if #qemu_aio_wait will ("sooner or later") reenter the coroutine.
*/
bool cancelled;
/**
* Set to true if the job is either paused, or will pause itself
* as soon as possible (if busy == true).
*/
bool paused;
/**
* Set to false by the job while it is in a quiescent state, where
* no I/O is pending and the job has yielded on any condition
* that is not detected by #qemu_aio_wait, such as a timer.
*/
bool busy;
/** Status that is published by the query-block-jobs QMP API */
BlockDeviceIoStatus iostatus;
/** Offset that is published by the query-block-jobs QMP API */
int64_t offset;
/** Length that is published by the query-block-jobs QMP API */
int64_t len;
/** Speed that was set with @block_job_set_speed. */
int64_t speed;
/** The completion function that will be called when the job completes. */
BlockDriverCompletionFunc *cb;
/** The opaque value that is passed to the completion function. */
void *opaque;
};
/**
* block_job_create:
* @job_type: The class object for the newly-created job.
* @bs: The block
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
* @errp: Error object.
*
* Create a new long-running block device job and return it. The job
* will call @cb asynchronously when the job completes. Note that
* @bs may have been closed at the time the @cb it is called. If
* this is the case, the job may be reported as either cancelled or
* completed.
*
* This function is not part of the public job interface; it should be
* called from a wrapper that is specific to the job type.
*/
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
int64_t speed, BlockDriverCompletionFunc *cb,
void *opaque, Error **errp);
/**
* block_job_sleep_ns:
* @job: The job that calls the function.
* @clock: The clock to sleep on.
* @ns: How many nanoseconds to stop for.
*
* Put the job to sleep (assuming that it wasn't canceled) for @ns
* nanoseconds. Canceling the job will interrupt the wait immediately.
*/
void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns);
/**
* block_job_completed:
* @job: The job being completed.
* @ret: The status code.
*
* Call the completion function that was registered at creation time, and
* free @job.
*/
void block_job_completed(BlockJob *job, int ret);
/**
* block_job_set_speed:
* @job: The job to set the speed for.
* @speed: The new value
* @errp: Error object.
*
* Set a rate-limiting parameter for the job; the actual meaning may
* vary depending on the job type.
*/
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
/**
* block_job_cancel:
* @job: The job to be canceled.
*
* Asynchronously cancel the specified job.
*/
void block_job_cancel(BlockJob *job);
/**
* block_job_complete:
* @job: The job to be completed.
* @errp: Error object.
*
* Asynchronously complete the specified job.
*/
void block_job_complete(BlockJob *job, Error **errp);
/**
* block_job_is_cancelled:
* @job: The job being queried.
*
* Returns whether the job is scheduled for cancellation.
*/
bool block_job_is_cancelled(BlockJob *job);
/**
* block_job_query:
* @job: The job to get information about.
*
* Return information about a job.
*/
BlockJobInfo *block_job_query(BlockJob *job);
/**
* block_job_pause:
* @job: The job to be paused.
*
* Asynchronously pause the specified job.
*/
void block_job_pause(BlockJob *job);
/**
* block_job_resume:
* @job: The job to be resumed.
*
* Resume the specified job.
*/
void block_job_resume(BlockJob *job);
/**
* qobject_from_block_job:
* @job: The job whose information is requested.
*
* Return a QDict corresponding to @job's query-block-jobs entry.
*/
QObject *qobject_from_block_job(BlockJob *job);
/**
* block_job_ready:
* @job: The job which is now ready to complete.
*
* Send a BLOCK_JOB_READY event for the specified job.
*/
void block_job_ready(BlockJob *job);
/**
* block_job_is_paused:
* @job: The job being queried.
*
* Returns whether the job is currently paused, or will pause
* as soon as it reaches a sleeping point.
*/
bool block_job_is_paused(BlockJob *job);
/**
* block_job_cancel_sync:
* @job: The job to be canceled.
*
* Synchronously cancel the job. The completion callback is called
* before the function returns. The job may actually complete
* instead of canceling itself; the circumstances under which this
* happens depend on the kind of job that is active.
*
* Returns the return value from the job if the job actually completed
* during the call, or -ECANCELED if it was canceled.
*/
int block_job_cancel_sync(BlockJob *job);
/**
* block_job_iostatus_reset:
* @job: The job whose I/O status should be reset.
*
* Reset I/O status on @job and on BlockDriverState objects it uses,
* other than job->bs.
*/
void block_job_iostatus_reset(BlockJob *job);
/**
* block_job_error_action:
* @job: The job to signal an error for.
* @bs: The block device on which to set an I/O error.
* @on_err: The error action setting.
* @is_read: Whether the operation was a read.
* @error: The error that was reported.
*
* Report an I/O error for a block job and possibly stop the VM. Return the
* action that was selected based on @on_err and @error.
*/
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
BlockdevOnError on_err,
int is_read, int error);
#endif
+88 -64
View File
@@ -23,7 +23,11 @@
typedef struct QEMUFileBuffered
{
MigrationState *migration_state;
BufferedPutFunc *put_buffer;
BufferedPutReadyFunc *put_ready;
BufferedWaitForUnfreezeFunc *wait_for_unfreeze;
BufferedCloseFunc *close;
void *opaque;
QEMUFile *file;
int freeze_output;
size_t bytes_xfer;
@@ -46,60 +50,70 @@ static void buffered_append(QEMUFileBuffered *s,
const uint8_t *buf, size_t size)
{
if (size > (s->buffer_capacity - s->buffer_size)) {
void *tmp;
DPRINTF("increasing buffer capacity from %zu by %zu\n",
s->buffer_capacity, size + 1024);
s->buffer_capacity += size + 1024;
s->buffer = g_realloc(s->buffer, s->buffer_capacity);
tmp = g_realloc(s->buffer, s->buffer_capacity);
if (tmp == NULL) {
fprintf(stderr, "qemu file buffer expansion failed\n");
exit(1);
}
s->buffer = tmp;
}
memcpy(s->buffer + s->buffer_size, buf, size);
s->buffer_size += size;
}
static ssize_t buffered_flush(QEMUFileBuffered *s)
static void buffered_flush(QEMUFileBuffered *s)
{
size_t offset = 0;
ssize_t ret = 0;
int error;
error = qemu_file_get_error(s->file);
if (error != 0) {
DPRINTF("flush when error, bailing: %s\n", strerror(-error));
return;
}
DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset,
to_send);
while (offset < s->buffer_size) {
ssize_t ret;
ret = s->put_buffer(s->opaque, s->buffer + offset,
s->buffer_size - offset);
if (ret == -EAGAIN) {
DPRINTF("backend not ready, freezing\n");
ret = 0;
s->freeze_output = 1;
break;
}
if (ret <= 0) {
DPRINTF("error flushing data, %zd\n", ret);
qemu_file_set_error(s->file, ret);
break;
} else {
DPRINTF("flushed %zd byte(s)\n", ret);
offset += ret;
s->bytes_xfer += ret;
}
}
DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);
memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
s->buffer_size -= offset;
if (ret < 0) {
return ret;
}
return offset;
}
static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
{
QEMUFileBuffered *s = opaque;
ssize_t error;
int offset = 0, error;
ssize_t ret;
DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
@@ -112,54 +126,65 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
DPRINTF("unfreezing output\n");
s->freeze_output = 0;
if (size > 0) {
DPRINTF("buffering %d bytes\n", size - offset);
buffered_append(s, buf, size);
buffered_flush(s);
while (!s->freeze_output && offset < size) {
if (s->bytes_xfer > s->xfer_limit) {
DPRINTF("transfer limit exceeded when putting\n");
break;
}
ret = s->put_buffer(s->opaque, buf + offset, size - offset);
if (ret == -EAGAIN) {
DPRINTF("backend not ready, freezing\n");
s->freeze_output = 1;
break;
}
if (ret <= 0) {
DPRINTF("error putting\n");
qemu_file_set_error(s->file, ret);
offset = -EINVAL;
break;
}
DPRINTF("put %zd byte(s)\n", ret);
offset += ret;
s->bytes_xfer += ret;
}
error = buffered_flush(s);
if (error < 0) {
DPRINTF("buffered flush error. bailing: %s\n", strerror(-error));
return error;
if (offset >= 0) {
DPRINTF("buffering %d bytes\n", size - offset);
buffered_append(s, buf + offset, size - offset);
offset = size;
}
if (pos == 0 && size == 0) {
DPRINTF("file is ready\n");
if (!s->freeze_output && s->bytes_xfer < s->xfer_limit) {
if (s->bytes_xfer <= s->xfer_limit) {
DPRINTF("notifying client\n");
migrate_fd_put_ready(s->migration_state);
s->put_ready(s->opaque);
}
}
return size;
return offset;
}
static int buffered_close(void *opaque)
{
QEMUFileBuffered *s = opaque;
ssize_t ret = 0;
int ret2;
int ret;
DPRINTF("closing\n");
s->xfer_limit = INT_MAX;
while (!qemu_file_get_error(s->file) && s->buffer_size) {
ret = buffered_flush(s);
if (ret < 0) {
break;
}
if (s->freeze_output) {
ret = migrate_fd_wait_for_unfreeze(s->migration_state);
if (ret < 0) {
break;
}
}
buffered_flush(s);
if (s->freeze_output)
s->wait_for_unfreeze(s->opaque);
}
ret2 = migrate_fd_close(s->migration_state);
if (ret >= 0) {
ret = ret2;
}
ret = s->close(s->opaque);
qemu_del_timer(s->timer);
qemu_free_timer(s->timer);
g_free(s->buffer);
@@ -174,13 +199,6 @@ static int buffered_close(void *opaque)
* 1: Time to stop
* negative: There has been an error
*/
static int buffered_get_fd(void *opaque)
{
QEMUFileBuffered *s = opaque;
return qemu_get_fd(s->file);
}
static int buffered_rate_limit(void *opaque)
{
QEMUFileBuffered *s = opaque;
@@ -238,28 +256,34 @@ static void buffered_rate_tick(void *opaque)
s->bytes_xfer = 0;
buffered_put_buffer(s, NULL, 0, 0);
buffered_flush(s);
/* Add some checks around this */
s->put_ready(s->opaque);
}
static const QEMUFileOps buffered_file_ops = {
.get_fd = buffered_get_fd,
.put_buffer = buffered_put_buffer,
.close = buffered_close,
.rate_limit = buffered_rate_limit,
.get_rate_limit = buffered_get_rate_limit,
.set_rate_limit = buffered_set_rate_limit,
};
QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state)
QEMUFile *qemu_fopen_ops_buffered(void *opaque,
size_t bytes_per_sec,
BufferedPutFunc *put_buffer,
BufferedPutReadyFunc *put_ready,
BufferedWaitForUnfreezeFunc *wait_for_unfreeze,
BufferedCloseFunc *close)
{
QEMUFileBuffered *s;
s = g_malloc0(sizeof(*s));
s->migration_state = migration_state;
s->xfer_limit = migration_state->bandwidth_limit / 10;
s->opaque = opaque;
s->xfer_limit = bytes_per_sec / 10;
s->put_buffer = put_buffer;
s->put_ready = put_ready;
s->wait_for_unfreeze = wait_for_unfreeze;
s->close = close;
s->file = qemu_fopen_ops(s, &buffered_file_ops);
s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL,
buffered_close, buffered_rate_limit,
buffered_set_rate_limit,
buffered_get_rate_limit);
s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s);
+10 -2
View File
@@ -15,8 +15,16 @@
#define QEMU_BUFFERED_FILE_H
#include "hw/hw.h"
#include "migration.h"
QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state);
typedef ssize_t (BufferedPutFunc)(void *opaque, const void *data, size_t size);
typedef void (BufferedPutReadyFunc)(void *opaque);
typedef void (BufferedWaitForUnfreezeFunc)(void *opaque);
typedef int (BufferedCloseFunc)(void *opaque);
QEMUFile *qemu_fopen_ops_buffered(void *opaque, size_t xfer_limit,
BufferedPutFunc *put_buffer,
BufferedPutReadyFunc *put_ready,
BufferedWaitForUnfreezeFunc *wait_for_unfreeze,
BufferedCloseFunc *close);
#endif
+7
View File
@@ -50,6 +50,13 @@
# define __printf__ __gnu_printf__
# endif
# endif
#if defined(_WIN32)
#define GCC_WEAK __attribute__((weak))
#define GCC_WEAK_DECL GCC_WEAK
#else
#define GCC_WEAK __attribute__((weak))
#define GCC_WEAK_DECL
#endif
#else
#define GCC_ATTR /**/
#define GCC_FMT_ATTR(n, m)
Vendored
+84 -157
View File
@@ -125,8 +125,7 @@ cc_i386=i386-pc-linux-gnu-gcc
libs_qga=""
debug_info="yes"
# Don't accept a target_list environment variable.
unset target_list
target_list=""
# Default value for a variable defining feature "foo".
# * foo="no" feature will only be used if --enable-foo arg is given
@@ -147,7 +146,6 @@ curses=""
docs=""
fdt=""
nptl=""
pixman=""
sdl=""
virtfs=""
vnc="yes"
@@ -186,7 +184,6 @@ libdir="\${prefix}/lib"
libexecdir="\${prefix}/libexec"
includedir="\${prefix}/include"
sysconfdir="\${prefix}/etc"
local_statedir="\${prefix}/var"
confsuffix="/qemu"
slirp="yes"
fmod_lib=""
@@ -200,7 +197,7 @@ cocoa="no"
softmmu="yes"
linux_user="no"
bsd_user="no"
guest_base="yes"
guest_base=""
uname_release=""
mixemu="no"
aix="no"
@@ -222,7 +219,6 @@ want_tools="yes"
libiscsi=""
coroutine=""
seccomp=""
glusterfs=""
# parse CC options first
for opt do
@@ -556,7 +552,6 @@ EOF
qemu_docdir="\${prefix}"
bindir="\${prefix}"
sysconfdir="\${prefix}"
local_statedir="\${prefix}"
confsuffix=""
libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga"
fi
@@ -633,9 +628,7 @@ for opt do
;;
--sysconfdir=*) sysconfdir="$optarg"
;;
--localstatedir=*) local_statedir="$optarg"
;;
--sbindir=*|--sharedstatedir=*|\
--sbindir=*|--sharedstatedir=*|--localstatedir=*|\
--oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
--htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
# These switches are silently ignored, for compatibility with
@@ -643,10 +636,6 @@ for opt do
# configure to be used by RPM and similar macros that set
# lots of directory switches by default.
;;
--with-system-pixman) pixman="system"
;;
--without-system-pixman) pixman="internal"
;;
--disable-sdl) sdl="no"
;;
--enable-sdl) sdl="yes"
@@ -867,45 +856,68 @@ for opt do
;;
--disable-seccomp) seccomp="no"
;;
--disable-glusterfs) glusterfs="no"
;;
--enable-glusterfs) glusterfs="yes"
;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
done
host_guest_base="no"
case "$cpu" in
sparc)
LDFLAGS="-m32 $LDFLAGS"
QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS"
host_guest_base="yes"
;;
sparc64)
LDFLAGS="-m64 $LDFLAGS"
QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS"
host_guest_base="yes"
;;
s390)
QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
LDFLAGS="-m31 $LDFLAGS"
host_guest_base="yes"
;;
s390x)
QEMU_CFLAGS="-m64 -march=z990 $QEMU_CFLAGS"
LDFLAGS="-m64 $LDFLAGS"
host_guest_base="yes"
;;
i386)
QEMU_CFLAGS="-m32 $QEMU_CFLAGS"
LDFLAGS="-m32 $LDFLAGS"
cc_i386='$(CC) -m32'
host_guest_base="yes"
;;
x86_64)
QEMU_CFLAGS="-m64 $QEMU_CFLAGS"
LDFLAGS="-m64 $LDFLAGS"
cc_i386='$(CC) -m32'
host_guest_base="yes"
;;
arm*)
host_guest_base="yes"
;;
ppc*)
host_guest_base="yes"
;;
mips*)
host_guest_base="yes"
;;
ia64*)
host_guest_base="yes"
;;
hppa*)
host_guest_base="yes"
;;
unicore32*)
host_guest_base="yes"
;;
# No special flags required for other host CPUs
esac
[ -z "$guest_base" ] && guest_base="$host_guest_base"
default_target_list=""
# these targets are portable
@@ -1010,7 +1022,6 @@ echo " --datadir=PATH install firmware in PATH$confsuffix"
echo " --docdir=PATH install documentation in PATH$confsuffix"
echo " --bindir=PATH install binaries in PATH"
echo " --sysconfdir=PATH install config in PATH$confsuffix"
echo " --localstatedir=PATH install local state in PATH"
echo " --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]"
echo " --enable-debug-tcg enable TCG debugging"
echo " --disable-debug-tcg disable TCG debugging (default)"
@@ -1117,8 +1128,6 @@ echo " --disable-seccomp disable seccomp support"
echo " --enable-seccomp enables seccomp support"
echo " --with-coroutine=BACKEND coroutine backend. Supported options:"
echo " gthread, ucontext, sigaltstack, windows"
echo " --enable-glusterfs enable GlusterFS backend"
echo " --disable-glusterfs disable GlusterFS backend"
echo ""
echo "NOTE: The object files are built at the place where configure is launched"
exit 1
@@ -1165,7 +1174,6 @@ gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
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="-fstack-protector-all -Wendif-labels $gcc_flags"
gcc_flags="-Wno-initializer-overrides $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due
# to -Werror this would just silently disable some features,
@@ -1174,30 +1182,11 @@ cat > $TMPC << EOF
int main(void) { return 0; }
EOF
for flag in $gcc_flags; do
# Use the positive sense of the flag when testing for -Wno-wombat
# support (gcc will happily accept the -Wno- form of unknown
# warning options).
optflag="$(echo $flag | sed -e 's/^-Wno-/-W/')"
if compile_prog "-Werror $optflag" "" ; then
if compile_prog "-Werror $flag" "" ; then
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
fi
done
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
# large functions that use global variables. The bug is in all releases of
# GCC, but it became particularly acute in 4.6.x and 4.7.x. It is fixed in
# 4.7.3 and 4.8.0. We should be able to delete this at the end of 2013.
cat > $TMPC << EOF
#if __GNUC__ == 4 && (__GNUC_MINOR__ == 6 || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ <= 2))
int main(void) { return 0; }
#else
#error No bug in this compiler.
#endif
EOF
if compile_prog "-Werror -fno-gcse" "" ; then
TRANSLATE_OPT_CFLAGS=-fno-gcse
fi
if test "$static" = "yes" ; then
if test "$pie" = "yes" ; then
echo "static and pie are mutually incompatible"
@@ -1292,7 +1281,7 @@ if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_
exit 1
fi
if test -z "${target_list+xxx}" ; then
if test -z "$target_list" ; then
target_list="$default_target_list"
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
@@ -1321,7 +1310,7 @@ if test -z "$cross_prefix" ; then
# big/little endian test
cat > $TMPC << EOF
#include <inttypes.h>
int main(void) {
int main(int argc, char ** argv){
volatile uint32_t i=0x01234567;
return (*((uint8_t*)(&i))) == 0x67;
}
@@ -1398,7 +1387,7 @@ fi
# libseccomp check
if test "$seccomp" != "no" ; then
if $pkg_config --atleast-version=1.0.0 libseccomp --modversion >/dev/null 2>&1; then
if $pkg_config libseccomp --modversion >/dev/null 2>&1; then
LIBS=`$pkg_config --libs libseccomp`
seccomp="yes"
else
@@ -2114,33 +2103,6 @@ else
exit 1
fi
##########################################
# pixman support probe
if test "$pixman" = ""; then
if $pkg_config pixman-1 > /dev/null 2>&1; then
pixman="system"
else
pixman="internal"
fi
fi
if test "$pixman" = "system"; then
pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null`
pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
else
if test ! -d ${source_path}/pixman/pixman; then
echo "ERROR: pixman not present. Your options:"
echo " (1) Prefered: Install the pixman devel package (any recent"
echo " distro should have packages as Xorg needs pixman too)."
echo " (2) Fetch the pixman submodule, using:"
echo " git submodule update --init pixman"
exit 1
fi
mkdir -p pixman/pixman
pixman_cflags="-I\$(SRC_PATH)/pixman/pixman -I\$(BUILD_DIR)/pixman/pixman"
pixman_libs="-L\$(BUILD_DIR)/pixman/pixman/.libs -lpixman-1"
fi
##########################################
# libcap probe
@@ -2341,29 +2303,6 @@ EOF
fi
fi
##########################################
# glusterfs probe
if test "$glusterfs" != "no" ; then
cat > $TMPC <<EOF
#include <glusterfs/api/glfs.h>
int main(void) {
(void) glfs_new("volume");
return 0;
}
EOF
glusterfs_libs="-lgfapi -lgfrpc -lgfxdr"
if compile_prog "" "$glusterfs_libs" ; then
glusterfs=yes
libs_tools="$glusterfs_libs $libs_tools"
libs_softmmu="$glusterfs_libs $libs_softmmu"
else
if test "$glusterfs" = "yes" ; then
feature_not_found "GlusterFS backend support"
fi
glusterfs=no
fi
fi
#
# Check for xxxat() functions when we are building linux-user
# emulator. This is done because older glibc versions don't
@@ -2450,7 +2389,8 @@ cat > $TMPC << EOF
int main(void)
{
int pipefd[2];
return pipe2(pipefd, O_CLOEXEC);
pipe2(pipefd, O_CLOEXEC);
return 0;
}
EOF
if compile_prog "" "" ; then
@@ -2745,14 +2685,17 @@ int main(void) { spice_server_new(); return 0; }
EOF
spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \
$pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1 && \
if $pkg_config --atleast-version=0.8.2 spice-server >/dev/null 2>&1 && \
$pkg_config --atleast-version=0.8.1 spice-protocol > /dev/null 2>&1 && \
compile_prog "$spice_cflags" "$spice_libs" ; then
spice="yes"
libs_softmmu="$libs_softmmu $spice_libs"
QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
spice_protocol_version=$($pkg_config --modversion spice-protocol)
spice_server_version=$($pkg_config --modversion spice-server)
if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
spice_qxl_io_monitors_config_async="yes"
fi
else
if test "$spice" = "yes" ; then
feature_not_found "spice"
@@ -2802,10 +2745,10 @@ fi
# check for usbredirparser for usb network redirection support
if test "$usb_redir" != "no" ; then
if $pkg_config --atleast-version=0.5.3 libusbredirparser-0.5 >/dev/null 2>&1 ; then
if $pkg_config --atleast-version=0.3.4 libusbredirparser >/dev/null 2>&1 ; then
usb_redir="yes"
usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null)
usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null)
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
libs_softmmu="$libs_softmmu $usb_redir_libs"
else
@@ -2863,24 +2806,6 @@ if compile_prog "" "" ; then
posix_madvise=yes
fi
##########################################
# check if we have usable SIGEV_THREAD_ID
sigev_thread_id=no
cat > $TMPC << EOF
#include <signal.h>
int main(void) {
struct sigevent ev;
ev.sigev_notify = SIGEV_THREAD_ID;
ev._sigev_un._tid = 0;
asm volatile("" : : "g"(&ev));
return 0;
}
EOF
if compile_prog "" "" ; then
sigev_thread_id=yes
fi
##########################################
# check if trace backend exists
@@ -2938,7 +2863,7 @@ static int sfaa(int *ptr)
return __sync_fetch_and_and(ptr, 0);
}
int main(void)
int main(int argc, char **argv)
{
int val = 42;
sfaa(&val);
@@ -3151,10 +3076,6 @@ if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
roms="$roms spapr-rtas"
fi
# add pixman flags after all config tests are done
QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
libs_softmmu="$libs_softmmu $pixman_libs"
echo "Install prefix $prefix"
echo "BIOS directory `eval echo $qemu_datadir`"
echo "binary directory `eval echo $bindir`"
@@ -3162,7 +3083,6 @@ echo "library directory `eval echo $libdir`"
echo "libexec directory `eval echo $libexecdir`"
echo "include directory `eval echo $includedir`"
echo "config directory `eval echo $sysconfdir`"
echo "local state directory `eval echo $local_statedir`"
if test "$mingw32" = "no" ; then
echo "Manual directory `eval echo $mandir`"
echo "ELF interp prefix $interp_prefix"
@@ -3193,7 +3113,6 @@ echo "-Werror enabled $werror"
if test "$darwin" = "yes" ; then
echo "Cocoa support $cocoa"
fi
echo "pixman $pixman"
echo "SDL support $sdl"
echo "curses support $curses"
echo "curl support $curl"
@@ -3233,7 +3152,6 @@ echo "preadv support $preadv"
echo "fdatasync $fdatasync"
echo "madvise $madvise"
echo "posix_madvise $posix_madvise"
echo "sigev_thread_id $sigev_thread_id"
echo "uuid support $uuid"
echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net"
@@ -3249,7 +3167,6 @@ echo "libiscsi support $libiscsi"
echo "build guest agent $guest_agent"
echo "seccomp support $seccomp"
echo "coroutine backend $coroutine_backend"
echo "GlusterFS support $glusterfs"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -3274,8 +3191,7 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak
echo "qemu_confdir=$qemu_confdir" >> $config_host_mak
echo "qemu_datadir=$qemu_datadir" >> $config_host_mak
echo "qemu_docdir=$qemu_docdir" >> $config_host_mak
echo "qemu_localstatedir=$local_statedir" >> $config_host_mak
echo "qemu_helperdir=$libexecdir" >> $config_host_mak
echo "CONFIG_QEMU_HELPERDIR=\"$libexecdir\"" >> $config_host_mak
echo "ARCH=$ARCH" >> $config_host_mak
if test "$debug_tcg" = "yes" ; then
@@ -3518,14 +3434,15 @@ fi
if test "$posix_madvise" = "yes" ; then
echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak
fi
if test "$sigev_thread_id" = "yes" ; then
echo "CONFIG_SIGEV_THREAD_ID=y" >> $config_host_mak
fi
if test "$spice" = "yes" ; then
echo "CONFIG_SPICE=y" >> $config_host_mak
fi
if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
fi
if test "$smartcard" = "yes" ; then
echo "CONFIG_SMARTCARD=y" >> $config_host_mak
fi
@@ -3592,10 +3509,6 @@ if test "$has_environ" = "yes" ; then
echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
fi
if test "$glusterfs" = "yes" ; then
echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
fi
# USB host support
case "$usb" in
linux)
@@ -3664,11 +3577,6 @@ if test "$sparse" = "yes" ; then
echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak
echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
fi
if test "$cross_prefix" != ""; then
echo "AUTOCONF_HOST := --host=${cross_prefix%-}" >> $config_host_mak
else
echo "AUTOCONF_HOST := " >> $config_host_mak
fi
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
echo "ARLIBS_END=$arlibs_end" >> $config_host_mak
@@ -3677,7 +3585,6 @@ echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
echo "POD2MAN=$POD2MAN" >> $config_host_mak
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
# generate list of library paths for linker script
@@ -3780,12 +3687,15 @@ TARGET_ABI_DIR=""
case "$target_arch2" in
i386)
target_phys_bits=64
;;
x86_64)
TARGET_BASE_ARCH=i386
target_phys_bits=64
target_long_alignment=8
;;
alpha)
target_phys_bits=64
target_long_alignment=8
target_nptl="yes"
;;
@@ -3794,18 +3704,22 @@ case "$target_arch2" in
bflt="yes"
target_nptl="yes"
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
target_phys_bits=64
target_llong_alignment=4
target_libs_softmmu="$fdt_libs"
;;
cris)
target_nptl="yes"
target_phys_bits=32
;;
lm32)
target_phys_bits=32
target_libs_softmmu="$opengl_libs"
;;
m68k)
bflt="yes"
gdb_xml_files="cf-core.xml cf-fp.xml"
target_phys_bits=32
target_int_alignment=2
target_long_alignment=2
target_llong_alignment=2
@@ -3814,30 +3728,36 @@ case "$target_arch2" in
TARGET_ARCH=microblaze
bflt="yes"
target_nptl="yes"
target_phys_bits=32
target_libs_softmmu="$fdt_libs"
;;
mips|mipsel)
TARGET_ARCH=mips
echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
target_nptl="yes"
target_phys_bits=64
;;
mipsn32|mipsn32el)
TARGET_ARCH=mipsn32
TARGET_BASE_ARCH=mips
echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
target_phys_bits=64
;;
mips64|mips64el)
TARGET_ARCH=mips64
TARGET_BASE_ARCH=mips
echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
target_phys_bits=64
target_long_alignment=8
;;
or32)
TARGET_ARCH=openrisc
TARGET_BASE_ARCH=openrisc
target_phys_bits=32
;;
ppc)
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
target_nptl="yes"
target_libs_softmmu="$fdt_libs"
;;
@@ -3845,6 +3765,7 @@ case "$target_arch2" in
TARGET_BASE_ARCH=ppc
TARGET_ABI_DIR=ppc
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
target_nptl="yes"
target_libs_softmmu="$fdt_libs"
;;
@@ -3852,6 +3773,7 @@ case "$target_arch2" in
TARGET_BASE_ARCH=ppc
TARGET_ABI_DIR=ppc
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
target_long_alignment=8
target_libs_softmmu="$fdt_libs"
;;
@@ -3861,17 +3783,21 @@ case "$target_arch2" in
TARGET_ABI_DIR=ppc
echo "TARGET_ABI32=y" >> $config_target_mak
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
target_libs_softmmu="$fdt_libs"
;;
sh4|sh4eb)
TARGET_ARCH=sh4
bflt="yes"
target_nptl="yes"
target_phys_bits=32
;;
sparc)
target_phys_bits=64
;;
sparc64)
TARGET_BASE_ARCH=sparc
target_phys_bits=64
target_long_alignment=8
;;
sparc32plus)
@@ -3879,15 +3805,19 @@ case "$target_arch2" in
TARGET_BASE_ARCH=sparc
TARGET_ABI_DIR=sparc
echo "TARGET_ABI32=y" >> $config_target_mak
target_phys_bits=64
;;
s390x)
target_nptl="yes"
target_phys_bits=64
target_long_alignment=8
;;
unicore32)
target_phys_bits=32
;;
xtensa|xtensaeb)
TARGET_ARCH=xtensa
target_phys_bits=32
;;
*)
echo "Unsupported target CPU"
@@ -3905,15 +3835,6 @@ upper() {
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
}
case "$cpu" in
i386|x86_64|ppc)
# The TCG interpreter currently does not support ld/st optimization.
if test "$tcg_interpreter" = "no" ; then
echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak
fi
;;
esac
echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
@@ -3931,6 +3852,7 @@ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
case "$target_arch2" in
i386|x86_64)
if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
target_phys_bits=64
echo "CONFIG_XEN=y" >> $config_target_mak
if test "$xen_pci_passthrough" = yes; then
echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak"
@@ -3970,8 +3892,11 @@ if test "$target_bigendian" = "yes" ; then
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
fi
if test "$target_softmmu" = "yes" ; then
echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak
echo "CONFIG_SOFTMMU=y" >> $config_target_mak
echo "LIBS+=$libs_softmmu $target_libs_softmmu" >> $config_target_mak
echo "HWDIR=../libhw$target_phys_bits" >> $config_target_mak
echo "subdir-$target: subdir-libhw$target_phys_bits" >> $config_host_mak
if test "$smartcard_nss" = "yes" ; then
echo "subdir-$target: subdir-libcacard" >> $config_host_mak
fi
@@ -4172,10 +4097,6 @@ echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
done # for target in $targets
if [ "$pixman" = "internal" ]; then
echo "config-host.h: subdir-pixman" >> $config_host_mak
fi
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32"
DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
@@ -4217,6 +4138,12 @@ for rom in seabios vgabios ; do
echo "LD=$ld" >> $config_mak
done
for hwlib in 32 64; do
d=libhw$hwlib
symlink "$source_path/Makefile.hw" "$d/Makefile"
echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
done
d=libuser
symlink "$source_path/Makefile.user" "$d/Makefile"
+130 -119
View File
@@ -24,7 +24,6 @@
#include "qemu-common.h"
#include "console.h"
#include "qemu-timer.h"
#include "qmp-commands.h"
//#define DEBUG_CONSOLE
#define DEFAULT_BACKSCROLL 512
@@ -114,20 +113,20 @@ typedef enum {
TEXT_CONSOLE_FIXED_SIZE
} console_type_t;
struct QemuConsole {
/* ??? This is mis-named.
It is used for both text and graphical consoles. */
struct TextConsole {
int index;
console_type_t console_type;
DisplayState *ds;
/* Graphic console state. */
vga_hw_update_ptr hw_update;
vga_hw_invalidate_ptr hw_invalidate;
vga_hw_screen_dump_ptr hw_screen_dump;
vga_hw_text_update_ptr hw_text_update;
void *hw;
int g_width, g_height;
/* Text console state */
int g_width, g_height;
int width;
int height;
int total_height;
@@ -161,8 +160,8 @@ struct QemuConsole {
};
static DisplayState *display_state;
static QemuConsole *active_console;
static QemuConsole *consoles[MAX_CONSOLES];
static TextConsole *active_console;
static TextConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0;
void vga_hw_update(void)
@@ -177,9 +176,9 @@ void vga_hw_invalidate(void)
active_console->hw_invalidate(active_console->hw);
}
void qmp_screendump(const char *filename, Error **errp)
void vga_hw_screen_dump(const char *filename)
{
QemuConsole *previous_active_console;
TextConsole *previous_active_console;
bool cswitch;
previous_active_console = active_console;
@@ -191,9 +190,9 @@ void qmp_screendump(const char *filename, Error **errp)
console_select(0);
}
if (consoles[0] && consoles[0]->hw_screen_dump) {
consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp);
consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch);
} else {
error_setg(errp, "device doesn't support screendump\n");
error_report("screen dump not implemented");
}
if (cswitch) {
@@ -521,7 +520,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
}
}
static void text_console_resize(QemuConsole *s)
static void text_console_resize(TextConsole *s)
{
TextCell *cells, *c, *c1;
int w1, x, y, last_width;
@@ -553,7 +552,7 @@ static void text_console_resize(QemuConsole *s)
s->cells = cells;
}
static inline void text_update_xy(QemuConsole *s, int x, int y)
static inline void text_update_xy(TextConsole *s, int x, int y)
{
s->text_x[0] = MIN(s->text_x[0], x);
s->text_x[1] = MAX(s->text_x[1], x);
@@ -561,7 +560,7 @@ static inline void text_update_xy(QemuConsole *s, int x, int y)
s->text_y[1] = MAX(s->text_y[1], y);
}
static void invalidate_xy(QemuConsole *s, int x, int y)
static void invalidate_xy(TextConsole *s, int x, int y)
{
if (s->update_x0 > x * FONT_WIDTH)
s->update_x0 = x * FONT_WIDTH;
@@ -573,7 +572,7 @@ static void invalidate_xy(QemuConsole *s, int x, int y)
s->update_y1 = (y + 1) * FONT_HEIGHT;
}
static void update_xy(QemuConsole *s, int x, int y)
static void update_xy(TextConsole *s, int x, int y)
{
TextCell *c;
int y1, y2;
@@ -597,7 +596,7 @@ static void update_xy(QemuConsole *s, int x, int y)
}
}
static void console_show_cursor(QemuConsole *s, int show)
static void console_show_cursor(TextConsole *s, int show)
{
TextCell *c;
int y, y1;
@@ -631,45 +630,42 @@ static void console_show_cursor(QemuConsole *s, int show)
}
}
static void console_refresh(QemuConsole *s)
static void console_refresh(TextConsole *s)
{
TextCell *c;
int x, y, y1;
if (s != active_console)
return;
if (s->ds->have_text) {
if (!ds_get_bits_per_pixel(s->ds)) {
s->text_x[0] = 0;
s->text_y[0] = 0;
s->text_x[1] = s->width - 1;
s->text_y[1] = s->height - 1;
s->cursor_invalidate = 1;
return;
}
if (s->ds->have_gfx) {
vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
color_table[0][COLOR_BLACK]);
y1 = s->y_displayed;
for (y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for (x = 0; x < s->width; x++) {
vga_putcharxy(s->ds, x, y, c->ch,
&(c->t_attrib));
c++;
}
if (++y1 == s->total_height) {
y1 = 0;
}
vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
color_table[0][COLOR_BLACK]);
y1 = s->y_displayed;
for(y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for(x = 0; x < s->width; x++) {
vga_putcharxy(s->ds, x, y, c->ch,
&(c->t_attrib));
c++;
}
console_show_cursor(s, 1);
dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
if (++y1 == s->total_height)
y1 = 0;
}
console_show_cursor(s, 1);
dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
}
static void console_scroll(int ydelta)
{
QemuConsole *s;
TextConsole *s;
int i, y1;
s = active_console;
@@ -701,7 +697,7 @@ static void console_scroll(int ydelta)
console_refresh(s);
}
static void console_put_lf(QemuConsole *s)
static void console_put_lf(TextConsole *s)
{
TextCell *c;
int x, y1;
@@ -752,7 +748,7 @@ static void console_put_lf(QemuConsole *s)
* NOTE: I know this code is not very efficient (checking every color for it
* self) but it is more readable and better maintainable.
*/
static void console_handle_escape(QemuConsole *s)
static void console_handle_escape(TextConsole *s)
{
int i;
@@ -845,7 +841,7 @@ static void console_handle_escape(QemuConsole *s)
}
}
static void console_clear_xy(QemuConsole *s, int x, int y)
static void console_clear_xy(TextConsole *s, int x, int y)
{
int y1 = (s->y_base + y) % s->total_height;
TextCell *c = &s->cells[y1 * s->width + x];
@@ -855,7 +851,7 @@ static void console_clear_xy(QemuConsole *s, int x, int y)
}
/* set cursor, checking bounds */
static void set_cursor(QemuConsole *s, int x, int y)
static void set_cursor(TextConsole *s, int x, int y)
{
if (x < 0) {
x = 0;
@@ -874,7 +870,7 @@ static void set_cursor(QemuConsole *s, int x, int y)
s->y = y;
}
static void console_putchar(QemuConsole *s, int ch)
static void console_putchar(TextConsole *s, int ch)
{
TextCell *c;
int y1, i;
@@ -1081,7 +1077,7 @@ static void console_putchar(QemuConsole *s, int ch)
void console_select(unsigned int index)
{
QemuConsole *s;
TextConsole *s;
if (index >= MAX_CONSOLES)
return;
@@ -1097,24 +1093,24 @@ void console_select(unsigned int index)
qemu_del_timer(active_console->cursor_timer);
}
active_console = s;
if (ds->have_gfx) {
if (ds_get_bits_per_pixel(s->ds)) {
ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
dpy_gfx_resize(ds);
}
if (ds->have_text) {
dpy_text_resize(ds, s->width, s->height);
} else {
s->ds->surface->width = s->width;
s->ds->surface->height = s->height;
}
if (s->cursor_timer) {
qemu_mod_timer(s->cursor_timer,
qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
}
dpy_resize(s->ds);
vga_hw_invalidate();
}
}
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
{
QemuConsole *s = chr->opaque;
TextConsole *s = chr->opaque;
int i;
s->update_x0 = s->width * FONT_WIDTH;
@@ -1126,17 +1122,17 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
console_putchar(s, buf[i]);
}
console_show_cursor(s, 1);
if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0);
if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
dpy_update(s->ds, s->update_x0, s->update_y0,
s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0);
}
return len;
}
static void kbd_send_chars(void *opaque)
{
QemuConsole *s = opaque;
TextConsole *s = opaque;
int len;
uint8_t buf[16];
@@ -1159,7 +1155,7 @@ static void kbd_send_chars(void *opaque)
/* called when an ascii key is pressed */
void kbd_put_keysym(int keysym)
{
QemuConsole *s;
TextConsole *s;
uint8_t buf[16], *q;
int c;
@@ -1214,7 +1210,7 @@ void kbd_put_keysym(int keysym)
static void text_console_invalidate(void *opaque)
{
QemuConsole *s = (QemuConsole *) opaque;
TextConsole *s = (TextConsole *) opaque;
if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
s->g_width = ds_get_width(s->ds);
s->g_height = ds_get_height(s->ds);
@@ -1225,7 +1221,7 @@ static void text_console_invalidate(void *opaque)
static void text_console_update(void *opaque, console_ch_t *chardata)
{
QemuConsole *s = (QemuConsole *) opaque;
TextConsole *s = (TextConsole *) opaque;
int i, j, src;
if (s->text_x[0] <= s->text_x[1]) {
@@ -1237,23 +1233,23 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
(s->cells[src].t_attrib.fgcol << 12) |
(s->cells[src].t_attrib.bgcol << 8) |
(s->cells[src].t_attrib.bold << 21));
dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
s->text_x[1] - s->text_x[0], i - s->text_y[0]);
dpy_update(s->ds, s->text_x[0], s->text_y[0],
s->text_x[1] - s->text_x[0], i - s->text_y[0]);
s->text_x[0] = s->width;
s->text_y[0] = s->height;
s->text_x[1] = 0;
s->text_y[1] = 0;
}
if (s->cursor_invalidate) {
dpy_text_cursor(s->ds, s->x, s->y);
dpy_cursor(s->ds, s->x, s->y);
s->cursor_invalidate = 0;
}
}
static QemuConsole *get_graphic_console(DisplayState *ds)
static TextConsole *get_graphic_console(DisplayState *ds)
{
int i;
QemuConsole *s;
TextConsole *s;
for (i = 0; i < nb_consoles; i++) {
s = consoles[i];
if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
@@ -1262,14 +1258,14 @@ static QemuConsole *get_graphic_console(DisplayState *ds)
return NULL;
}
static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
{
QemuConsole *s;
TextConsole *s;
int i;
if (nb_consoles >= MAX_CONSOLES)
return NULL;
s = g_malloc0(sizeof(QemuConsole));
s = g_malloc0(sizeof(TextConsole));
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
(console_type == GRAPHIC_CONSOLE))) {
active_console = s;
@@ -1294,31 +1290,9 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
return s;
}
static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags)
static DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
{
surface->pf = pf;
qemu_pixman_image_unref(surface->image);
surface->image = NULL;
surface->format = qemu_pixman_get_format(&pf);
assert(surface->format != 0);
surface->image = pixman_image_create_bits(surface->format,
width, height,
NULL, linesize);
assert(surface->image != NULL);
surface->flags = newflags | QEMU_ALLOCATED_FLAG;
#ifdef HOST_WORDS_BIGENDIAN
surface->flags |= QEMU_BIG_ENDIAN_FLAG;
#endif
}
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
int width, int height)
{
DisplaySurface *surface = g_new0(DisplaySurface, 1);
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
@@ -1326,54 +1300,75 @@ DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
return surface;
}
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
int width, int height)
static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
int width, int height)
{
int linesize = width * 4;
trace_displaysurface_resize(ds, ds->surface, width, height);
qemu_alloc_display(ds->surface, width, height, linesize,
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return ds->surface;
return surface;
}
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data)
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags)
{
DisplaySurface *surface = g_new0(DisplaySurface, 1);
void *data;
surface->width = width;
surface->height = height;
surface->linesize = linesize;
surface->pf = pf;
if (surface->flags & QEMU_ALLOCATED_FLAG) {
data = g_realloc(surface->data,
surface->linesize * surface->height);
} else {
data = g_malloc(surface->linesize * surface->height);
}
surface->data = (uint8_t *)data;
surface->flags = newflags | QEMU_ALLOCATED_FLAG;
#ifdef HOST_WORDS_BIGENDIAN
surface->flags |= QEMU_BIG_ENDIAN_FLAG;
#endif
}
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data)
{
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
surface->width = width;
surface->height = height;
surface->linesize = linesize;
surface->pf = qemu_default_pixelformat(bpp);
surface->format = qemu_pixman_get_format(&surface->pf);
assert(surface->format != 0);
surface->image = pixman_image_create_bits(surface->format,
width, height,
(void *)data, linesize);
assert(surface->image != NULL);
#ifdef HOST_WORDS_BIGENDIAN
surface->flags = QEMU_BIG_ENDIAN_FLAG;
#endif
surface->data = data;
return surface;
}
void qemu_free_displaysurface(DisplayState *ds)
static void defaultallocator_free_displaysurface(DisplaySurface *surface)
{
trace_displaysurface_free(ds, ds->surface);
if (ds->surface == NULL) {
if (surface == NULL)
return;
}
qemu_pixman_image_unref(ds->surface->image);
g_free(ds->surface);
if (surface->flags & QEMU_ALLOCATED_FLAG)
g_free(surface->data);
g_free(surface);
}
static struct DisplayAllocator default_allocator = {
defaultallocator_create_displaysurface,
defaultallocator_resize_displaysurface,
defaultallocator_free_displaysurface
};
static void dumb_display_init(void)
{
DisplayState *ds = g_malloc0(sizeof(DisplayState));
int width = 640;
int height = 480;
ds->allocator = &default_allocator;
if (is_fixedsize_console()) {
width = active_console->g_width;
height = active_console->g_height;
@@ -1403,16 +1398,29 @@ DisplayState *get_displaystate(void)
return display_state;
}
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
{
if(ds->allocator == &default_allocator) {
DisplaySurface *surf;
surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds));
defaultallocator_free_displaysurface(ds->surface);
ds->surface = surf;
ds->allocator = da;
}
return ds->allocator;
}
DisplayState *graphic_console_init(vga_hw_update_ptr update,
vga_hw_invalidate_ptr invalidate,
vga_hw_screen_dump_ptr screen_dump,
vga_hw_text_update_ptr text_update,
void *opaque)
{
QemuConsole *s;
TextConsole *s;
DisplayState *ds;
ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
ds->allocator = &default_allocator;
ds->surface = qemu_create_displaysurface(ds, 640, 480);
s = new_console(ds, GRAPHIC_CONSOLE);
@@ -1454,14 +1462,14 @@ void console_color_init(DisplayState *ds)
static void text_console_set_echo(CharDriverState *chr, bool echo)
{
QemuConsole *s = chr->opaque;
TextConsole *s = chr->opaque;
s->echo = echo;
}
static void text_console_update_cursor(void *opaque)
{
QemuConsole *s = opaque;
TextConsole *s = opaque;
s->cursor_visible_phase = !s->cursor_visible_phase;
vga_hw_invalidate();
@@ -1471,7 +1479,7 @@ static void text_console_update_cursor(void *opaque)
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
QemuConsole *s;
TextConsole *s;
static int color_inited;
s = chr->opaque;
@@ -1534,7 +1542,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
CharDriverState *text_console_init(QemuOpts *opts)
{
CharDriverState *chr;
QemuConsole *s;
TextConsole *s;
unsigned width;
unsigned height;
@@ -1580,14 +1588,14 @@ void text_consoles_set_display(DisplayState *ds)
void qemu_console_resize(DisplayState *ds, int width, int height)
{
QemuConsole *s = get_graphic_console(ds);
TextConsole *s = get_graphic_console(ds);
if (!s) return;
s->g_width = width;
s->g_height = height;
if (is_graphic_console()) {
ds->surface = qemu_resize_displaysurface(ds, width, height);
dpy_gfx_resize(ds);
dpy_resize(ds);
}
}
@@ -1595,7 +1603,7 @@ void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
int dst_x, int dst_y, int w, int h)
{
if (is_graphic_console()) {
dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
}
}
@@ -1706,15 +1714,18 @@ PixelFormat qemu_default_pixelformat(int bpp)
pf.rmask = 0x00FF0000;
pf.gmask = 0x0000FF00;
pf.bmask = 0x000000FF;
pf.amax = 255;
pf.rmax = 255;
pf.gmax = 255;
pf.bmax = 255;
pf.ashift = 24;
pf.rshift = 16;
pf.gshift = 8;
pf.bshift = 0;
pf.rbits = 8;
pf.gbits = 8;
pf.bbits = 8;
pf.abits = 8;
break;
default:
break;
+100 -176
View File
@@ -2,13 +2,10 @@
#define CONSOLE_H
#include "qemu-char.h"
#include "qemu-pixman.h"
#include "qdict.h"
#include "notify.h"
#include "monitor.h"
#include "trace.h"
#include "qapi-types.h"
#include "error.h"
/* keyboard/mouse support */
@@ -108,6 +105,7 @@ void kbd_put_keysym(int keysym);
#define QEMU_BIG_ENDIAN_FLAG 0x01
#define QEMU_ALLOCATED_FLAG 0x02
#define QEMU_REALPIXELS_FLAG 0x04
struct PixelFormat {
uint8_t bits_per_pixel;
@@ -120,9 +118,11 @@ struct PixelFormat {
};
struct DisplaySurface {
pixman_format_code_t format;
pixman_image_t *image;
uint8_t flags;
int width;
int height;
int linesize; /* bytes per line */
uint8_t *data;
struct PixelFormat pf;
};
@@ -152,32 +152,35 @@ struct DisplayChangeListener {
int idle;
uint64_t gui_timer_interval;
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s);
void (*dpy_setdata)(struct DisplayState *s);
void (*dpy_refresh)(struct DisplayState *s);
void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_gfx_resize)(struct DisplayState *s);
void (*dpy_gfx_setdata)(struct DisplayState *s);
void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
void (*dpy_fill)(struct DisplayState *s, int x, int y,
int w, int h, uint32_t c);
void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
struct DisplayChangeListener *next;
};
QLIST_ENTRY(DisplayChangeListener) next;
struct DisplayAllocator {
DisplaySurface* (*create_displaysurface)(int width, int height);
DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
void (*free_displaysurface)(DisplaySurface *surface);
};
struct DisplayState {
struct DisplaySurface *surface;
void *opaque;
struct QEMUTimer *gui_timer;
bool have_gfx;
bool have_text;
QLIST_HEAD(, DisplayChangeListener) listeners;
struct DisplayAllocator* allocator;
struct DisplayChangeListener* listeners;
void (*mouse_set)(int x, int y, int on);
void (*cursor_define)(QEMUCursor *cursor);
struct DisplayState *next;
};
@@ -186,14 +189,29 @@ void register_displaystate(DisplayState *ds);
DisplayState *get_displaystate(void);
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data);
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags);
PixelFormat qemu_different_endianness_pixelformat(int bpp);
PixelFormat qemu_default_pixelformat(int bpp);
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
int width, int height);
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
int width, int height);
void qemu_free_displaysurface(DisplayState *ds);
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da);
static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height)
{
return ds->allocator->create_displaysurface(width, height);
}
static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
{
trace_displaysurface_resize(ds, ds->surface, width, height);
return ds->allocator->resize_displaysurface(ds->surface, width, height);
}
static inline void qemu_free_displaysurface(DisplayState *ds)
{
trace_displaysurface_free(ds, ds->surface);
ds->allocator->free_displaysurface(ds->surface);
}
static inline int is_surface_bgr(DisplaySurface *surface)
{
@@ -205,201 +223,109 @@ static inline int is_surface_bgr(DisplaySurface *surface)
static inline int is_buffer_shared(DisplaySurface *surface)
{
return !(surface->flags & QEMU_ALLOCATED_FLAG);
return (!(surface->flags & QEMU_ALLOCATED_FLAG) &&
!(surface->flags & QEMU_REALPIXELS_FLAG));
}
void gui_setup_refresh(DisplayState *ds);
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
{
QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
gui_setup_refresh(ds);
if (dcl->dpy_gfx_resize) {
dcl->dpy_gfx_resize(ds);
dcl->next = ds->listeners;
ds->listeners = dcl;
}
static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
dcl->dpy_update(s, x, y, w, h);
dcl = dcl->next;
}
}
static inline void unregister_displaychangelistener(DisplayState *ds,
DisplayChangeListener *dcl)
static inline void dpy_resize(DisplayState *s)
{
QLIST_REMOVE(dcl, next);
gui_setup_refresh(ds);
}
static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_update) {
dcl->dpy_gfx_update(s, x, y, w, h);
}
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
dcl->dpy_resize(s);
dcl = dcl->next;
}
}
static inline void dpy_gfx_resize(DisplayState *s)
static inline void dpy_setdata(DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_resize) {
dcl->dpy_gfx_resize(s);
}
}
}
static inline void dpy_gfx_setdata(DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_setdata) {
dcl->dpy_gfx_setdata(s);
}
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_setdata) dcl->dpy_setdata(s);
dcl = dcl->next;
}
}
static inline void dpy_refresh(DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_refresh) {
dcl->dpy_refresh(s);
}
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_refresh) dcl->dpy_refresh(s);
dcl = dcl->next;
}
}
static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_copy) {
dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
} else { /* TODO */
dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
}
static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h) {
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_copy)
dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
else /* TODO */
dcl->dpy_update(s, dst_x, dst_y, w, h);
dcl = dcl->next;
}
}
static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_cursor) {
dcl->dpy_text_cursor(s, x, y);
}
static inline void dpy_fill(struct DisplayState *s, int x, int y,
int w, int h, uint32_t c) {
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c);
dcl = dcl->next;
}
}
static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_update) {
dcl->dpy_text_update(s, x, y, w, h);
}
static inline void dpy_cursor(struct DisplayState *s, int x, int y) {
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y);
dcl = dcl->next;
}
}
static inline void dpy_text_resize(DisplayState *s, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_resize) {
dcl->dpy_text_resize(s, w, h);
}
}
}
static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_mouse_set) {
dcl->dpy_mouse_set(s, x, y, on);
}
}
}
static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_cursor_define) {
dcl->dpy_cursor_define(s, cursor);
}
}
}
static inline bool dpy_cursor_define_supported(struct DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_cursor_define) {
return true;
}
}
return false;
}
static inline int ds_get_linesize(DisplayState *ds)
{
return pixman_image_get_stride(ds->surface->image);
return ds->surface->linesize;
}
static inline uint8_t* ds_get_data(DisplayState *ds)
{
return (void *)pixman_image_get_data(ds->surface->image);
return ds->surface->data;
}
static inline int ds_get_width(DisplayState *ds)
{
return pixman_image_get_width(ds->surface->image);
return ds->surface->width;
}
static inline int ds_get_height(DisplayState *ds)
{
return pixman_image_get_height(ds->surface->image);
return ds->surface->height;
}
static inline int ds_get_bits_per_pixel(DisplayState *ds)
{
int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
return bits;
return ds->surface->pf.bits_per_pixel;
}
static inline int ds_get_bytes_per_pixel(DisplayState *ds)
{
int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
return (bits + 7) / 8;
}
static inline pixman_format_code_t ds_get_format(DisplayState *ds)
{
return ds->surface->format;
}
static inline pixman_image_t *ds_get_image(DisplayState *ds)
{
return ds->surface->image;
}
static inline int ds_get_depth(DisplayState *ds)
{
return ds->surface->pf.depth;
}
static inline int ds_get_rmask(DisplayState *ds)
{
return ds->surface->pf.rmask;
}
static inline int ds_get_gmask(DisplayState *ds)
{
return ds->surface->pf.gmask;
}
static inline int ds_get_bmask(DisplayState *ds)
{
return ds->surface->pf.bmask;
return ds->surface->pf.bytes_per_pixel;
}
#ifdef CONFIG_CURSES
@@ -417,8 +343,7 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
typedef void (*vga_hw_update_ptr)(void *);
typedef void (*vga_hw_invalidate_ptr)(void *);
typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
Error **errp);
typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch);
typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *);
DisplayState *graphic_console_init(vga_hw_update_ptr update,
@@ -429,6 +354,7 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
void vga_hw_update(void);
void vga_hw_invalidate(void);
void vga_hw_screen_dump(const char *filename);
void vga_hw_text_update(console_ch_t *chardata);
int is_graphic_console(void);
@@ -449,8 +375,10 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
/* vnc.c */
void vnc_display_init(DisplayState *ds);
void vnc_display_open(DisplayState *ds, const char *display, Error **errp);
void vnc_display_close(DisplayState *ds);
int vnc_display_open(DisplayState *ds, const char *display);
void vnc_display_add_client(DisplayState *ds, int csock, int skipauth);
int vnc_display_disable_login(DisplayState *ds);
char *vnc_display_local_addr(DisplayState *ds);
#ifdef CONFIG_VNC
int vnc_display_password(DisplayState *ds, const char *password);
@@ -469,8 +397,4 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
/* curses.c */
void curses_display_init(DisplayState *ds, int full_screen);
/* input.c */
int index_from_key(const char *key);
int index_from_keycode(int code);
#endif
+2 -2
View File
@@ -171,8 +171,8 @@ static Coroutine *coroutine_new(void)
CoroutineThreadState *coTS;
struct sigaction sa;
struct sigaction osa;
stack_t ss;
stack_t oss;
struct sigaltstack ss;
struct sigaltstack oss;
sigset_t sigs;
sigset_t osigs;
jmp_buf old_env;
+6 -5
View File
@@ -356,9 +356,6 @@ CPUArchState *cpu_copy(CPUArchState *env);
CPUArchState *qemu_get_cpu(int cpu);
#define CPU_DUMP_CODE 0x00010000
#define CPU_DUMP_FPU 0x00020000 /* dump FPU register state, not just integer */
/* dump info about TCG QEMU's condition code optimization state */
#define CPU_DUMP_CCOP 0x00040000
void cpu_dump_state(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf,
int flags);
@@ -438,6 +435,8 @@ void cpu_reset_interrupt(CPUArchState *env, int mask);
void cpu_exit(CPUArchState *s);
bool qemu_cpu_has_work(CPUArchState *env);
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ 0x01
#define BP_MEM_WRITE 0x02
@@ -464,13 +463,15 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
void cpu_single_step(CPUArchState *env, int enabled);
int cpu_is_stopped(CPUArchState *env);
void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data);
#if !defined(CONFIG_USER_ONLY)
/* Return the physical page corresponding to a virtual one. Use it
only for debugging because no protection checks are done. Return -1
if no page found. */
hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
target_phys_addr_t cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
/* memory API */
@@ -496,6 +497,7 @@ typedef struct RAMBlock {
typedef struct RAMList {
uint8_t *phys_dirty;
QLIST_HEAD(, RAMBlock) blocks;
uint64_t dirty_pages;
} RAMList;
extern RAMList ram_list;
@@ -513,7 +515,6 @@ extern int mem_prealloc;
#define TLB_MMIO (1 << 5)
void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
ram_addr_t last_ram_offset(void);
#endif /* !CONFIG_USER_ONLY */
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
+40 -35
View File
@@ -3,7 +3,7 @@
/* CPU interfaces that are target independent. */
#include "hwaddr.h"
#include "targphys.h"
#ifndef NEED_CPU_H
#include "poison.h"
@@ -21,7 +21,7 @@ enum device_endian {
};
/* address in the RAM (different from a physical address) */
#if defined(CONFIG_XEN_BACKEND)
#if defined(CONFIG_XEN_BACKEND) && TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t ram_addr_t;
# define RAM_ADDR_MAX UINT64_MAX
# define RAM_ADDR_FMT "%" PRIx64
@@ -33,38 +33,43 @@ typedef uintptr_t ram_addr_t;
/* memory API */
typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size);
/* Same but slower, to use for migration, where the order of
* RAMBlocks must not change. */
void *qemu_safe_ram_ptr(ram_addr_t addr);
void qemu_put_ram_ptr(void *addr);
/* This should not be used by devices. */
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev);
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void cpu_physical_memory_read(hwaddr addr,
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
void *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(hwaddr addr,
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
const void *buf, int len)
{
cpu_physical_memory_rw(addr, (void *)buf, len, 1);
}
void *cpu_physical_memory_map(hwaddr addr,
hwaddr *plen,
void *cpu_physical_memory_map(target_phys_addr_t addr,
target_phys_addr_t *plen,
int is_write);
void cpu_physical_memory_unmap(void *buffer, hwaddr len,
int is_write, hwaddr access_len);
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len);
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
void cpu_unregister_map_client(void *cookie);
bool cpu_physical_memory_is_io(hwaddr phys_addr);
bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr);
/* Coalesced MMIO regions are areas where write operations can be reordered.
* This usually implies that write operations are side-effect free. This allows
@@ -73,33 +78,33 @@ bool cpu_physical_memory_is_io(hwaddr phys_addr);
*/
void qemu_flush_coalesced_mmio_buffer(void);
uint32_t ldub_phys(hwaddr addr);
uint32_t lduw_le_phys(hwaddr addr);
uint32_t lduw_be_phys(hwaddr addr);
uint32_t ldl_le_phys(hwaddr addr);
uint32_t ldl_be_phys(hwaddr addr);
uint64_t ldq_le_phys(hwaddr addr);
uint64_t ldq_be_phys(hwaddr addr);
void stb_phys(hwaddr addr, uint32_t val);
void stw_le_phys(hwaddr addr, uint32_t val);
void stw_be_phys(hwaddr addr, uint32_t val);
void stl_le_phys(hwaddr addr, uint32_t val);
void stl_be_phys(hwaddr addr, uint32_t val);
void stq_le_phys(hwaddr addr, uint64_t val);
void stq_be_phys(hwaddr addr, uint64_t val);
uint32_t ldub_phys(target_phys_addr_t addr);
uint32_t lduw_le_phys(target_phys_addr_t addr);
uint32_t lduw_be_phys(target_phys_addr_t addr);
uint32_t ldl_le_phys(target_phys_addr_t addr);
uint32_t ldl_be_phys(target_phys_addr_t addr);
uint64_t ldq_le_phys(target_phys_addr_t addr);
uint64_t ldq_be_phys(target_phys_addr_t addr);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_le_phys(target_phys_addr_t addr, uint32_t val);
void stw_be_phys(target_phys_addr_t addr, uint32_t val);
void stl_le_phys(target_phys_addr_t addr, uint32_t val);
void stl_be_phys(target_phys_addr_t addr, uint32_t val);
void stq_le_phys(target_phys_addr_t addr, uint64_t val);
void stq_be_phys(target_phys_addr_t addr, uint64_t val);
#ifdef NEED_CPU_H
uint32_t lduw_phys(hwaddr addr);
uint32_t ldl_phys(hwaddr addr);
uint64_t ldq_phys(hwaddr addr);
void stl_phys_notdirty(hwaddr addr, uint32_t val);
void stq_phys_notdirty(hwaddr addr, uint64_t val);
void stw_phys(hwaddr addr, uint32_t val);
void stl_phys(hwaddr addr, uint32_t val);
void stq_phys(hwaddr addr, uint64_t val);
uint32_t lduw_phys(target_phys_addr_t addr);
uint32_t ldl_phys(target_phys_addr_t addr);
uint64_t ldq_phys(target_phys_addr_t addr);
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
void stl_phys(target_phys_addr_t addr, uint32_t val);
void stq_phys(target_phys_addr_t addr, uint64_t val);
#endif
void cpu_physical_memory_write_rom(hwaddr addr,
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len);
extern struct MemoryRegion io_mem_ram;
+8 -2
View File
@@ -29,7 +29,7 @@
#include <signal.h>
#include "osdep.h"
#include "qemu-queue.h"
#include "hwaddr.h"
#include "targphys.h"
#ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header
@@ -111,7 +111,7 @@ extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BIT
#define CPU_COMMON_TLB \
/* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
target_ulong tlb_flush_addr; \
target_ulong tlb_flush_mask;
@@ -201,9 +201,15 @@ typedef struct CPUWatchpoint {
int nr_cores; /* number of cores within this CPU package */ \
int nr_threads;/* number of threads within this CPU */ \
int running; /* Nonzero if cpu is currently running(usermode). */ \
int thread_id; \
/* user data */ \
void *opaque; \
\
uint32_t created; \
uint32_t stop; /* Stop request */ \
uint32_t stopped; /* Artificially stopped */ \
struct QemuCond *halt_cond; \
struct qemu_work_item *queued_work_first, *queued_work_last; \
const char *cpu_model_str; \
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \
+6 -4
View File
@@ -27,9 +27,9 @@ int tb_invalidated_flag;
//#define CONFIG_DEBUG_EXEC
bool qemu_cpu_has_work(CPUState *cpu)
bool qemu_cpu_has_work(CPUArchState *env)
{
return cpu_has_work(cpu);
return cpu_has_work(env);
}
void cpu_loop_exit(CPUArchState *env)
@@ -181,14 +181,16 @@ volatile sig_atomic_t exit_request;
int cpu_exec(CPUArchState *env)
{
#ifdef TARGET_PPC
CPUState *cpu = ENV_GET_CPU(env);
#endif
int ret, interrupt_request;
TranslationBlock *tb;
uint8_t *tc_ptr;
tcg_target_ulong next_tb;
if (env->halted) {
if (!cpu_has_work(cpu)) {
if (!cpu_has_work(env)) {
return EXCP_HALTED;
}
@@ -550,7 +552,7 @@ int cpu_exec(CPUArchState *env)
#if defined(TARGET_I386)
env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
| (DF & DF_MASK);
log_cpu_state(env, CPU_DUMP_CCOP);
log_cpu_state(env, X86_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_M68K)
cpu_m68k_flush_flags(env, env->cc_op);
+106 -108
View File
@@ -64,15 +64,13 @@ static CPUArchState *next_cpu;
static bool cpu_thread_is_idle(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
if (cpu->stop || cpu->queued_work_first) {
if (env->stop || env->queued_work_first) {
return false;
}
if (cpu->stopped || !runstate_is_running()) {
if (env->stopped || !runstate_is_running()) {
return true;
}
if (!env->halted || qemu_cpu_has_work(cpu) ||
if (!env->halted || qemu_cpu_has_work(env) ||
kvm_async_interrupts_enabled()) {
return false;
}
@@ -397,7 +395,11 @@ void hw_error(const char *fmt, ...)
fprintf(stderr, "\n");
for(env = first_cpu; env != NULL; env = env->next_cpu) {
fprintf(stderr, "CPU #%d:\n", env->cpu_index);
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU);
#ifdef TARGET_I386
cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
#else
cpu_dump_state(env, stderr, fprintf, 0);
#endif
}
va_end(ap);
abort();
@@ -430,9 +432,9 @@ void cpu_synchronize_all_post_init(void)
}
}
bool cpu_is_stopped(CPUState *cpu)
int cpu_is_stopped(CPUArchState *env)
{
return !runstate_is_running() || cpu->stopped;
return !runstate_is_running() || env->stopped;
}
static void do_vm_stop(RunState state)
@@ -448,24 +450,22 @@ static void do_vm_stop(RunState state)
}
}
static bool cpu_can_run(CPUState *cpu)
static int cpu_can_run(CPUArchState *env)
{
if (cpu->stop) {
return false;
if (env->stop) {
return 0;
}
if (cpu->stopped || !runstate_is_running()) {
return false;
if (env->stopped || !runstate_is_running()) {
return 0;
}
return true;
return 1;
}
static void cpu_handle_guest_debug(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
gdb_set_stop_cpu(env);
qemu_system_debug_request();
cpu->stopped = true;
env->stopped = 1;
}
static void cpu_signal(int sig)
@@ -613,7 +613,7 @@ static void qemu_tcg_init_cpu_signals(void)
}
#endif /* _WIN32 */
static QemuMutex qemu_global_mutex;
QemuMutex qemu_global_mutex;
static QemuCond qemu_io_proceeded_cond;
static bool iothread_requesting_mutex;
@@ -640,27 +640,27 @@ void qemu_init_cpu_loop(void)
qemu_thread_get_self(&io_thread);
}
void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data)
{
struct qemu_work_item wi;
if (qemu_cpu_is_self(cpu)) {
if (qemu_cpu_is_self(env)) {
func(data);
return;
}
wi.func = func;
wi.data = data;
if (cpu->queued_work_first == NULL) {
cpu->queued_work_first = &wi;
if (!env->queued_work_first) {
env->queued_work_first = &wi;
} else {
cpu->queued_work_last->next = &wi;
env->queued_work_last->next = &wi;
}
cpu->queued_work_last = &wi;
env->queued_work_last = &wi;
wi.next = NULL;
wi.done = false;
qemu_cpu_kick(cpu);
qemu_cpu_kick(env);
while (!wi.done) {
CPUArchState *self_env = cpu_single_env;
@@ -669,31 +669,33 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
}
}
static void flush_queued_work(CPUState *cpu)
static void flush_queued_work(CPUArchState *env)
{
struct qemu_work_item *wi;
if (cpu->queued_work_first == NULL) {
if (!env->queued_work_first) {
return;
}
while ((wi = cpu->queued_work_first)) {
cpu->queued_work_first = wi->next;
while ((wi = env->queued_work_first)) {
env->queued_work_first = wi->next;
wi->func(wi->data);
wi->done = true;
}
cpu->queued_work_last = NULL;
env->queued_work_last = NULL;
qemu_cond_broadcast(&qemu_work_cond);
}
static void qemu_wait_io_event_common(CPUState *cpu)
static void qemu_wait_io_event_common(CPUArchState *env)
{
if (cpu->stop) {
cpu->stop = false;
cpu->stopped = true;
CPUState *cpu = ENV_GET_CPU(env);
if (env->stop) {
env->stop = 0;
env->stopped = 1;
qemu_cond_signal(&qemu_pause_cond);
}
flush_queued_work(cpu);
flush_queued_work(env);
cpu->thread_kicked = false;
}
@@ -713,20 +715,18 @@ static void qemu_tcg_wait_io_event(void)
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
qemu_wait_io_event_common(ENV_GET_CPU(env));
qemu_wait_io_event_common(env);
}
}
static void qemu_kvm_wait_io_event(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
while (cpu_thread_is_idle(env)) {
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
qemu_cond_wait(env->halt_cond, &qemu_global_mutex);
}
qemu_kvm_eat_signals(env);
qemu_wait_io_event_common(cpu);
qemu_wait_io_event_common(env);
}
static void *qemu_kvm_cpu_thread_fn(void *arg)
@@ -737,7 +737,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
qemu_mutex_lock(&qemu_global_mutex);
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
env->thread_id = qemu_get_thread_id();
cpu_single_env = env;
r = kvm_init_vcpu(env);
@@ -749,11 +749,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
qemu_kvm_init_cpu_signals(env);
/* signal CPU creation */
cpu->created = true;
env->created = 1;
qemu_cond_signal(&qemu_cpu_cond);
while (1) {
if (cpu_can_run(cpu)) {
if (cpu_can_run(env)) {
r = kvm_cpu_exec(env);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(env);
@@ -778,13 +778,13 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
env->thread_id = qemu_get_thread_id();
sigemptyset(&waitset);
sigaddset(&waitset, SIG_IPI);
/* signal CPU creation */
cpu->created = true;
env->created = 1;
qemu_cond_signal(&qemu_cpu_cond);
cpu_single_env = env;
@@ -801,7 +801,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
}
qemu_mutex_lock_iothread();
cpu_single_env = env;
qemu_wait_io_event_common(cpu);
qemu_wait_io_event_common(env);
}
return NULL;
@@ -812,8 +812,8 @@ static void tcg_exec_all(void);
static void *qemu_tcg_cpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
CPUArchState *env;
CPUArchState *env = arg;
CPUState *cpu = ENV_GET_CPU(env);
qemu_tcg_init_cpu_signals();
qemu_thread_get_self(cpu->thread);
@@ -821,19 +821,18 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
/* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu = ENV_GET_CPU(env);
cpu->thread_id = qemu_get_thread_id();
cpu->created = true;
env->thread_id = qemu_get_thread_id();
env->created = 1;
}
qemu_cond_signal(&qemu_cpu_cond);
/* wait for initial kick-off after machine start */
while (ENV_GET_CPU(first_cpu)->stopped) {
while (first_cpu->stopped) {
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
/* process any pending work */
for (env = first_cpu; env != NULL; env = env->next_cpu) {
qemu_wait_io_event_common(ENV_GET_CPU(env));
qemu_wait_io_event_common(env);
}
}
@@ -848,8 +847,9 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
return NULL;
}
static void qemu_cpu_kick_thread(CPUState *cpu)
static void qemu_cpu_kick_thread(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
#ifndef _WIN32
int err;
@@ -859,7 +859,7 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
exit(1);
}
#else /* _WIN32 */
if (!qemu_cpu_is_self(cpu)) {
if (!qemu_cpu_is_self(env)) {
SuspendThread(cpu->hThread);
cpu_signal(0);
ResumeThread(cpu->hThread);
@@ -867,11 +867,14 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
#endif
}
void qemu_cpu_kick(CPUState *cpu)
void qemu_cpu_kick(void *_env)
{
qemu_cond_broadcast(cpu->halt_cond);
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
qemu_cond_broadcast(env->halt_cond);
if (!tcg_enabled() && !cpu->thread_kicked) {
qemu_cpu_kick_thread(cpu);
qemu_cpu_kick_thread(env);
cpu->thread_kicked = true;
}
}
@@ -883,7 +886,7 @@ void qemu_cpu_kick_self(void)
CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
if (!cpu_single_cpu->thread_kicked) {
qemu_cpu_kick_thread(cpu_single_cpu);
qemu_cpu_kick_thread(cpu_single_env);
cpu_single_cpu->thread_kicked = true;
}
#else
@@ -891,14 +894,12 @@ void qemu_cpu_kick_self(void)
#endif
}
bool qemu_cpu_is_self(CPUState *cpu)
int qemu_cpu_is_self(void *_env)
{
return qemu_thread_is_self(cpu->thread);
}
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
static bool qemu_in_vcpu_thread(void)
{
return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env));
return qemu_thread_is_self(cpu->thread);
}
void qemu_mutex_lock_iothread(void)
@@ -908,7 +909,7 @@ void qemu_mutex_lock_iothread(void)
} else {
iothread_requesting_mutex = true;
if (qemu_mutex_trylock(&qemu_global_mutex)) {
qemu_cpu_kick_thread(ENV_GET_CPU(first_cpu));
qemu_cpu_kick_thread(first_cpu);
qemu_mutex_lock(&qemu_global_mutex);
}
iothread_requesting_mutex = false;
@@ -926,8 +927,7 @@ static int all_vcpus_paused(void)
CPUArchState *penv = first_cpu;
while (penv) {
CPUState *pcpu = ENV_GET_CPU(penv);
if (!pcpu->stopped) {
if (!penv->stopped) {
return 0;
}
penv = penv->next_cpu;
@@ -942,19 +942,17 @@ void pause_all_vcpus(void)
qemu_clock_enable(vm_clock, false);
while (penv) {
CPUState *pcpu = ENV_GET_CPU(penv);
pcpu->stop = true;
qemu_cpu_kick(pcpu);
penv->stop = 1;
qemu_cpu_kick(penv);
penv = penv->next_cpu;
}
if (qemu_in_vcpu_thread()) {
if (!qemu_thread_is_self(&io_thread)) {
cpu_stop_current();
if (!kvm_enabled()) {
while (penv) {
CPUState *pcpu = ENV_GET_CPU(penv);
pcpu->stop = 0;
pcpu->stopped = true;
penv->stop = 0;
penv->stopped = 1;
penv = penv->next_cpu;
}
return;
@@ -965,7 +963,7 @@ void pause_all_vcpus(void)
qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
penv = first_cpu;
while (penv) {
qemu_cpu_kick(ENV_GET_CPU(penv));
qemu_cpu_kick(penv);
penv = penv->next_cpu;
}
}
@@ -977,34 +975,36 @@ void resume_all_vcpus(void)
qemu_clock_enable(vm_clock, true);
while (penv) {
CPUState *pcpu = ENV_GET_CPU(penv);
pcpu->stop = false;
pcpu->stopped = false;
qemu_cpu_kick(pcpu);
penv->stop = 0;
penv->stopped = 0;
qemu_cpu_kick(penv);
penv = penv->next_cpu;
}
}
static void qemu_tcg_init_vcpu(CPUState *cpu)
static void qemu_tcg_init_vcpu(void *_env)
{
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
/* share a single thread for all cpus with TCG */
if (!tcg_cpu_thread) {
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
tcg_halt_cond = cpu->halt_cond;
qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, cpu,
env->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
tcg_halt_cond = env->halt_cond;
qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, env,
QEMU_THREAD_JOINABLE);
#ifdef _WIN32
cpu->hThread = qemu_thread_get_handle(cpu->thread);
#endif
while (!cpu->created) {
while (env->created == 0) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
tcg_cpu_thread = cpu->thread;
} else {
cpu->thread = tcg_cpu_thread;
cpu->halt_cond = tcg_halt_cond;
env->halt_cond = tcg_halt_cond;
}
}
@@ -1013,11 +1013,11 @@ static void qemu_kvm_start_vcpu(CPUArchState *env)
CPUState *cpu = ENV_GET_CPU(env);
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
env->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
qemu_thread_create(cpu->thread, qemu_kvm_cpu_thread_fn, env,
QEMU_THREAD_JOINABLE);
while (!cpu->created) {
while (env->created == 0) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
@@ -1027,11 +1027,11 @@ static void qemu_dummy_start_vcpu(CPUArchState *env)
CPUState *cpu = ENV_GET_CPU(env);
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
env->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
qemu_thread_create(cpu->thread, qemu_dummy_cpu_thread_fn, env,
QEMU_THREAD_JOINABLE);
while (!cpu->created) {
while (env->created == 0) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
@@ -1039,15 +1039,14 @@ static void qemu_dummy_start_vcpu(CPUArchState *env)
void qemu_init_vcpu(void *_env)
{
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
cpu->stopped = true;
env->stopped = 1;
if (kvm_enabled()) {
qemu_kvm_start_vcpu(env);
} else if (tcg_enabled()) {
qemu_tcg_init_vcpu(cpu);
qemu_tcg_init_vcpu(env);
} else {
qemu_dummy_start_vcpu(env);
}
@@ -1056,9 +1055,8 @@ void qemu_init_vcpu(void *_env)
void cpu_stop_current(void)
{
if (cpu_single_env) {
CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
cpu_single_cpu->stop = false;
cpu_single_cpu->stopped = true;
cpu_single_env->stop = 0;
cpu_single_env->stopped = 1;
cpu_exit(cpu_single_env);
qemu_cond_signal(&qemu_pause_cond);
}
@@ -1066,7 +1064,7 @@ void cpu_stop_current(void)
void vm_stop(RunState state)
{
if (qemu_in_vcpu_thread()) {
if (!qemu_thread_is_self(&io_thread)) {
qemu_system_vmstop_request(state);
/*
* FIXME: should not return to device code in case
@@ -1139,18 +1137,17 @@ static void tcg_exec_all(void)
}
for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
CPUArchState *env = next_cpu;
CPUState *cpu = ENV_GET_CPU(env);
qemu_clock_enable(vm_clock,
(env->singlestep_enabled & SSTEP_NOTIMER) == 0);
if (cpu_can_run(cpu)) {
if (cpu_can_run(env)) {
r = tcg_cpu_exec(env);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(env);
break;
}
} else if (cpu->stop || cpu->stopped) {
} else if (env->stop || env->stopped) {
break;
}
}
@@ -1195,8 +1192,10 @@ void set_cpu_log_filename(const char *optarg)
void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
{
/* XXX: implement xxx_cpu_list for targets that still miss it */
#if defined(cpu_list)
cpu_list(f, cpu_fprintf);
#if defined(cpu_list_id)
cpu_list_id(f, cpu_fprintf, optarg);
#elif defined(cpu_list)
cpu_list(f, cpu_fprintf); /* deprecated */
#endif
}
@@ -1205,8 +1204,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
CpuInfoList *head = NULL, *cur_item = NULL;
CPUArchState *env;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
CPUState *cpu = ENV_GET_CPU(env);
for(env = first_cpu; env != NULL; env = env->next_cpu) {
CpuInfoList *info;
cpu_synchronize_state(env);
@@ -1216,7 +1214,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
info->value->CPU = env->cpu_index;
info->value->current = (env == first_cpu);
info->value->halted = env->halted;
info->value->thread_id = cpu->thread_id;
info->value->thread_id = env->thread_id;
#if defined(TARGET_I386)
info->value->has_pc = true;
info->value->pc = env->eip + env->segs[R_CS].base;
+5 -5
View File
@@ -21,11 +21,11 @@
#include "cpu.h"
#include "exec-all.h"
#include "memory.h"
#include "exec-memory.h"
#include "cputlb.h"
#include "memory-internal.h"
#define WANT_EXEC_OBSOLETE
#include "exec-obsolete.h"
//#define DEBUG_TLB
//#define DEBUG_TLB_CHECK
@@ -237,7 +237,7 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
supplied size is only used by tlb_flush_page. */
void tlb_set_page(CPUArchState *env, target_ulong vaddr,
hwaddr paddr, int prot,
target_phys_addr_t paddr, int prot,
int mmu_idx, target_ulong size)
{
MemoryRegionSection *section;
@@ -246,13 +246,13 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
target_ulong code_address;
uintptr_t addend;
CPUTLBEntry *te;
hwaddr iotlb;
target_phys_addr_t iotlb;
assert(size >= TARGET_PAGE_SIZE);
if (size != TARGET_PAGE_SIZE) {
tlb_add_large_page(env, vaddr, size);
}
section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS);
section = phys_page_find(paddr >> TARGET_PAGE_BITS);
#if defined(DEBUG_TLB)
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
" prot=%x idx=%d pd=0x%08lx\n",
+3 -4
View File
@@ -26,18 +26,17 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
target_ulong vaddr);
void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
uintptr_t length);
MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d,
hwaddr index);
MemoryRegionSection *phys_page_find(target_phys_addr_t index);
void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length);
void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
extern int tlb_flush_count;
/* exec.c */
void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr);
hwaddr memory_region_section_get_iotlb(CPUArchState *env,
target_phys_addr_t memory_region_section_get_iotlb(CPUArchState *env,
MemoryRegionSection *section,
target_ulong vaddr,
hwaddr paddr,
target_phys_addr_t paddr,
int prot,
target_ulong *address);
bool memory_region_is_unassigned(MemoryRegion *mr);
+109 -1
View File
@@ -115,7 +115,7 @@ time_t mktimegm(struct tm *tm)
m += 12;
y--;
}
t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
t = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
y / 400 - 719469);
t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
return t;
@@ -142,6 +142,109 @@ int qemu_fdatasync(int fd)
#endif
}
/* io vectors */
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
{
qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec));
qiov->niov = 0;
qiov->nalloc = alloc_hint;
qiov->size = 0;
}
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
{
int i;
qiov->iov = iov;
qiov->niov = niov;
qiov->nalloc = -1;
qiov->size = 0;
for (i = 0; i < niov; i++)
qiov->size += iov[i].iov_len;
}
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
{
assert(qiov->nalloc != -1);
if (qiov->niov == qiov->nalloc) {
qiov->nalloc = 2 * qiov->nalloc + 1;
qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
}
qiov->iov[qiov->niov].iov_base = base;
qiov->iov[qiov->niov].iov_len = len;
qiov->size += len;
++qiov->niov;
}
/*
* Concatenates (partial) iovecs from src to the end of dst.
* It starts copying after skipping `soffset' bytes at the
* beginning of src and adds individual vectors from src to
* dst copies up to `sbytes' bytes total, or up to the end
* of src if it comes first. This way, it is okay to specify
* very large value for `sbytes' to indicate "up to the end
* of src".
* Only vector pointers are processed, not the actual data buffers.
*/
void qemu_iovec_concat(QEMUIOVector *dst,
QEMUIOVector *src, size_t soffset, size_t sbytes)
{
int i;
size_t done;
struct iovec *siov = src->iov;
assert(dst->nalloc != -1);
assert(src->size >= soffset);
for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
if (soffset < siov[i].iov_len) {
size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
done += len;
soffset = 0;
} else {
soffset -= siov[i].iov_len;
}
}
/* return done; */
}
void qemu_iovec_destroy(QEMUIOVector *qiov)
{
assert(qiov->nalloc != -1);
qemu_iovec_reset(qiov);
g_free(qiov->iov);
qiov->nalloc = 0;
qiov->iov = NULL;
}
void qemu_iovec_reset(QEMUIOVector *qiov)
{
assert(qiov->nalloc != -1);
qiov->niov = 0;
qiov->size = 0;
}
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
void *buf, size_t bytes)
{
return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
}
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
const void *buf, size_t bytes)
{
return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
}
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
int fillc, size_t bytes)
{
return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
}
/*
* Checks if a buffer is all zeroes
*
@@ -280,6 +383,11 @@ int qemu_parse_fd(const char *param)
return fd;
}
int qemu_parse_fdset(const char *param)
{
return qemu_parse_fd(param);
}
/* round down to the nearest power of 2*/
int64_t pow2floor(int64_t value)
{
-1
View File
@@ -22,7 +22,6 @@ CONFIG_ADS7846=y
CONFIG_MAX111X=y
CONFIG_SSI=y
CONFIG_SSI_SD=y
CONFIG_SSI_M25P80=y
CONFIG_LAN9118=y
CONFIG_SMC91C111=y
CONFIG_DS1338=y
-2
View File
@@ -5,5 +5,3 @@ CONFIG_PFLASH_CFI01=y
CONFIG_SERIAL=y
CONFIG_XILINX=y
CONFIG_XILINX_AXI=y
CONFIG_SSI=y
CONFIG_SSI_M25P80=y
-2
View File
@@ -5,5 +5,3 @@ CONFIG_PFLASH_CFI01=y
CONFIG_SERIAL=y
CONFIG_XILINX=y
CONFIG_XILINX_AXI=y
CONFIG_SSI=y
CONFIG_SSI_M25P80=y
-2
View File
@@ -19,5 +19,3 @@ CONFIG_IDE_PCI=y
CONFIG_AHCI=y
CONFIG_ESP=y
CONFIG_ESP_PCI=y
CONFIG_SERIAL=y
CONFIG_SERIAL_PCI=y
+1
View File
@@ -6,6 +6,7 @@ CONFIG_M48T59=y
CONFIG_PTIMER=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
CONFIG_VGA_CIRRUS=y
CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_PCKBD=y
-15
View File
@@ -304,18 +304,3 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
g_free(dupname);
return retval;
}
void qemu_devtree_dumpdtb(void *fdt, int size)
{
QemuOpts *machine_opts;
machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
if (machine_opts) {
const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb");
if (dumpdtb) {
/* Dump the dtb to a file and quit */
exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
}
}
}
-2
View File
@@ -49,6 +49,4 @@ int qemu_devtree_add_subnode(void *fdt, const char *name);
sizeof(qdt_tmp)); \
} while (0)
void qemu_devtree_dumpdtb(void *fdt, int size);
#endif /* __DEVICE_TREE_H__ */
+68 -81
View File
@@ -7,11 +7,6 @@
#include "cpu.h"
#include "disas.h"
typedef struct CPUDebug {
struct disassemble_info info;
CPUArchState *env;
} CPUDebug;
/* Filled in by elfload.c. Simplistic, but will do for now. */
struct syminfo *syminfos = NULL;
@@ -37,9 +32,7 @@ target_read_memory (bfd_vma memaddr,
int length,
struct disassemble_info *info)
{
CPUDebug *s = container_of(info, CPUDebug, info);
cpu_memory_rw_debug(s->env, memaddr, myaddr, length, 0);
cpu_memory_rw_debug(cpu_single_env, memaddr, myaddr, length, 0);
return 0;
}
@@ -165,35 +158,32 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
ppc - nonzero means little endian
other targets - unused
*/
void target_disas(FILE *out, CPUArchState *env, target_ulong code,
target_ulong size, int flags)
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
{
target_ulong pc;
int count;
CPUDebug s;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
s.env = env;
s.info.read_memory_func = target_read_memory;
s.info.buffer_vma = code;
s.info.buffer_length = size;
s.info.print_address_func = generic_print_target_address;
disasm_info.read_memory_func = target_read_memory;
disasm_info.buffer_vma = code;
disasm_info.buffer_length = size;
disasm_info.print_address_func = generic_print_target_address;
#ifdef TARGET_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_BIG;
disasm_info.endian = BFD_ENDIAN_BIG;
#else
s.info.endian = BFD_ENDIAN_LITTLE;
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (flags == 2) {
s.info.mach = bfd_mach_x86_64;
} else if (flags == 1) {
s.info.mach = bfd_mach_i386_i8086;
} else {
s.info.mach = bfd_mach_i386_i386;
}
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
if (flags & 1) {
@@ -203,28 +193,27 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
}
if (flags & 2) {
#ifdef TARGET_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_LITTLE;
disasm_info.endian = BFD_ENDIAN_LITTLE;
#else
s.info.endian = BFD_ENDIAN_BIG;
disasm_info.endian = BFD_ENDIAN_BIG;
#endif
}
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
s.info.mach = bfd_mach_sparc_v9b;
disasm_info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(TARGET_PPC)
if (flags >> 16) {
s.info.endian = BFD_ENDIAN_LITTLE;
}
if (flags >> 16)
disasm_info.endian = BFD_ENDIAN_LITTLE;
if (flags & 0xFFFF) {
/* If we have a precise definitions of the instructions set, use it */
s.info.mach = flags & 0xFFFF;
disasm_info.mach = flags & 0xFFFF;
} else {
#ifdef TARGET_PPC64
s.info.mach = bfd_mach_ppc64;
disasm_info.mach = bfd_mach_ppc64;
#else
s.info.mach = bfd_mach_ppc;
disasm_info.mach = bfd_mach_ppc;
#endif
}
print_insn = print_insn_ppc;
@@ -237,27 +226,27 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_SH4)
s.info.mach = bfd_mach_sh4;
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#elif defined(TARGET_ALPHA)
s.info.mach = bfd_mach_alpha_ev6;
disasm_info.mach = bfd_mach_alpha_ev6;
print_insn = print_insn_alpha;
#elif defined(TARGET_CRIS)
if (flags != 32) {
s.info.mach = bfd_mach_cris_v0_v10;
disasm_info.mach = bfd_mach_cris_v0_v10;
print_insn = print_insn_crisv10;
} else {
s.info.mach = bfd_mach_cris_v32;
disasm_info.mach = bfd_mach_cris_v32;
print_insn = print_insn_crisv32;
}
#elif defined(TARGET_S390X)
s.info.mach = bfd_mach_s390_64;
disasm_info.mach = bfd_mach_s390_64;
print_insn = print_insn_s390;
#elif defined(TARGET_MICROBLAZE)
s.info.mach = bfd_arch_microblaze;
disasm_info.mach = bfd_arch_microblaze;
print_insn = print_insn_microblaze;
#elif defined(TARGET_LM32)
s.info.mach = bfd_mach_lm32;
disasm_info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
#else
fprintf(out, "0x" TARGET_FMT_lx
@@ -267,14 +256,14 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
for (pc = code; size > 0; pc += count, size -= count) {
fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &s.info);
count = print_insn(pc, &disasm_info);
#if 0
{
int i;
uint8_t b;
fprintf(out, " {");
for(i = 0; i < count; i++) {
target_read_memory(pc + i, &b, 1, &s.info);
target_read_memory(pc + i, &b, 1, &disasm_info);
fprintf(out, " %02x", b);
}
fprintf(out, " }");
@@ -298,28 +287,28 @@ void disas(FILE *out, void *code, unsigned long size)
{
uintptr_t pc;
int count;
CPUDebug s;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
s.info.print_address_func = generic_print_host_address;
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
disasm_info.print_address_func = generic_print_host_address;
s.info.buffer = code;
s.info.buffer_vma = (uintptr_t)code;
s.info.buffer_length = size;
disasm_info.buffer = code;
disasm_info.buffer_vma = (uintptr_t)code;
disasm_info.buffer_length = size;
#ifdef HOST_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_BIG;
disasm_info.endian = BFD_ENDIAN_BIG;
#else
s.info.endian = BFD_ENDIAN_LITTLE;
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(CONFIG_TCG_INTERPRETER)
print_insn = print_insn_tci;
#elif defined(__i386__)
s.info.mach = bfd_mach_i386_i386;
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(__x86_64__)
s.info.mach = bfd_mach_x86_64;
disasm_info.mach = bfd_mach_x86_64;
print_insn = print_insn_i386;
#elif defined(_ARCH_PPC)
print_insn = print_insn_ppc;
@@ -327,7 +316,7 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_alpha;
#elif defined(__sparc__)
print_insn = print_insn_sparc;
s.info.mach = bfd_mach_sparc_v9b;
disasm_info.mach = bfd_mach_sparc_v9b;
#elif defined(__arm__)
print_insn = print_insn_arm;
#elif defined(__MIPSEB__)
@@ -349,7 +338,7 @@ void disas(FILE *out, void *code, unsigned long size)
#endif
for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
fprintf(out, "0x%08" PRIxPTR ": ", pc);
count = print_insn(pc, &s.info);
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
break;
@@ -377,17 +366,16 @@ const char *lookup_symbol(target_ulong orig_addr)
#include "monitor.h"
static int monitor_disas_is_physical;
static CPUArchState *monitor_disas_env;
static int
monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
struct disassemble_info *info)
{
CPUDebug *s = container_of(info, CPUDebug, info);
if (monitor_disas_is_physical) {
cpu_physical_memory_read(memaddr, myaddr, length);
} else {
cpu_memory_rw_debug(s->env, memaddr,myaddr, length, 0);
cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
}
return 0;
}
@@ -406,31 +394,30 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
target_ulong pc, int nb_insn, int is_physical, int flags)
{
int count, i;
CPUDebug s;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);
INIT_DISASSEMBLE_INFO(disasm_info, (FILE *)mon, monitor_fprintf);
s.env = env;
monitor_disas_env = env;
monitor_disas_is_physical = is_physical;
s.info.read_memory_func = monitor_read_memory;
s.info.print_address_func = generic_print_target_address;
disasm_info.read_memory_func = monitor_read_memory;
disasm_info.print_address_func = generic_print_target_address;
s.info.buffer_vma = pc;
disasm_info.buffer_vma = pc;
#ifdef TARGET_WORDS_BIGENDIAN
s.info.endian = BFD_ENDIAN_BIG;
disasm_info.endian = BFD_ENDIAN_BIG;
#else
s.info.endian = BFD_ENDIAN_LITTLE;
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (flags == 2) {
s.info.mach = bfd_mach_x86_64;
} else if (flags == 1) {
s.info.mach = bfd_mach_i386_i8086;
} else {
s.info.mach = bfd_mach_i386_i386;
}
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
@@ -439,13 +426,13 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
s.info.mach = bfd_mach_sparc_v9b;
disasm_info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(TARGET_PPC)
#ifdef TARGET_PPC64
s.info.mach = bfd_mach_ppc64;
disasm_info.mach = bfd_mach_ppc64;
#else
s.info.mach = bfd_mach_ppc;
disasm_info.mach = bfd_mach_ppc;
#endif
print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
@@ -457,13 +444,13 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_SH4)
s.info.mach = bfd_mach_sh4;
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#elif defined(TARGET_S390X)
s.info.mach = bfd_mach_s390_64;
disasm_info.mach = bfd_mach_s390_64;
print_insn = print_insn_s390;
#elif defined(TARGET_LM32)
s.info.mach = bfd_mach_lm32;
disasm_info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
#else
monitor_printf(mon, "0x" TARGET_FMT_lx
@@ -473,7 +460,7 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
for(i = 0; i < nb_insn; i++) {
monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &s.info);
count = print_insn(pc, &disasm_info);
monitor_printf(mon, "\n");
if (count < 0)
break;
+2 -3
View File
@@ -6,8 +6,7 @@
#ifdef NEED_CPU_H
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size);
void target_disas(FILE *out, CPUArchState *env, target_ulong code,
target_ulong size, int flags);
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
void monitor_disas(Monitor *mon, CPUArchState *env,
target_ulong pc, int nb_insn, int is_physical, int flags);
@@ -23,7 +22,7 @@ struct elf64_sym;
#if defined(CONFIG_USER_ONLY)
typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_ulong orig_addr);
#else
typedef const char *(*lookup_symbol_t)(struct syminfo *s, hwaddr orig_addr);
typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_phys_addr_t orig_addr);
#endif
struct syminfo {
+19 -18
View File
@@ -14,8 +14,7 @@
/* #define DEBUG_IOMMU */
static void do_dma_memory_set(AddressSpace *as,
dma_addr_t addr, uint8_t c, dma_addr_t len)
static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len)
{
#define FILLBUF_SIZE 512
uint8_t fillbuf[FILLBUF_SIZE];
@@ -24,7 +23,7 @@ static void do_dma_memory_set(AddressSpace *as,
memset(fillbuf, c, FILLBUF_SIZE);
while (len > 0) {
l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
address_space_rw(as, addr, fillbuf, l, true);
cpu_physical_memory_rw(addr, fillbuf, l, true);
len -= l;
addr += l;
}
@@ -37,7 +36,7 @@ int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
if (dma_has_iommu(dma)) {
return iommu_dma_memory_set(dma, addr, c, len);
}
do_dma_memory_set(dma->as, addr, c, len);
do_dma_memory_set(addr, c, len);
return 0;
}
@@ -195,7 +194,7 @@ static void dma_aio_cancel(BlockDriverAIOCB *acb)
dma_complete(dbs, 0);
}
static const AIOCBInfo dma_aiocb_info = {
static AIOPool dma_aio_pool = {
.aiocb_size = sizeof(DMAAIOCB),
.cancel = dma_aio_cancel,
};
@@ -205,7 +204,7 @@ BlockDriverAIOCB *dma_bdrv_io(
DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
void *opaque, DMADirection dir)
{
DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
@@ -281,7 +280,7 @@ void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
DMADirection dir)
{
hwaddr paddr, plen;
target_phys_addr_t paddr, plen;
#ifdef DEBUG_IOMMU
fprintf(stderr, "dma_memory_check context=%p addr=0x" DMA_ADDR_FMT
@@ -308,7 +307,7 @@ bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
void *buf, dma_addr_t len, DMADirection dir)
{
hwaddr paddr, plen;
target_phys_addr_t paddr, plen;
int err;
#ifdef DEBUG_IOMMU
@@ -333,7 +332,8 @@ int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
plen = len;
}
address_space_rw(dma->as, paddr, buf, plen, dir == DMA_DIRECTION_FROM_DEVICE);
cpu_physical_memory_rw(paddr, buf, plen,
dir == DMA_DIRECTION_FROM_DEVICE);
len -= plen;
addr += plen;
@@ -346,7 +346,7 @@ int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
dma_addr_t len)
{
hwaddr paddr, plen;
target_phys_addr_t paddr, plen;
int err;
#ifdef DEBUG_IOMMU
@@ -366,7 +366,7 @@ int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
plen = len;
}
do_dma_memory_set(dma->as, paddr, c, plen);
do_dma_memory_set(paddr, c, plen);
len -= plen;
addr += plen;
@@ -375,14 +375,13 @@ int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
return 0;
}
void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
void dma_context_init(DMAContext *dma, DMATranslateFunc translate,
DMAMapFunc map, DMAUnmapFunc unmap)
{
#ifdef DEBUG_IOMMU
fprintf(stderr, "dma_context_init(%p, %p, %p, %p)\n",
dma, translate, map, unmap);
#endif
dma->as = as;
dma->translate = translate;
dma->map = map;
dma->unmap = unmap;
@@ -392,7 +391,7 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
DMADirection dir)
{
int err;
hwaddr paddr, plen;
target_phys_addr_t paddr, plen;
void *buf;
if (dma->map) {
@@ -408,13 +407,14 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
/*
* If this is true, the virtual region is contiguous,
* but the translated physical region isn't. We just
* clamp *len, much like address_space_map() does.
* clamp *len, much like cpu_physical_memory_map() does.
*/
if (plen < *len) {
*len = plen;
}
buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE);
buf = cpu_physical_memory_map(paddr, &plen,
dir == DMA_DIRECTION_FROM_DEVICE);
*len = plen;
return buf;
@@ -428,7 +428,8 @@ void iommu_dma_memory_unmap(DMAContext *dma, void *buffer, dma_addr_t len,
return;
}
address_space_unmap(dma->as, buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
access_len);
cpu_physical_memory_unmap(buffer, len,
dir == DMA_DIRECTION_FROM_DEVICE,
access_len);
}
+13 -17
View File
@@ -11,7 +11,6 @@
#define DMA_H
#include <stdio.h>
#include "memory.h"
#include "hw/hw.h"
#include "block.h"
#include "kvm.h"
@@ -32,7 +31,7 @@ struct QEMUSGList {
DMAContext *dma;
};
#ifndef CONFIG_USER_ONLY
#if defined(TARGET_PHYS_ADDR_BITS)
/*
* When an IOMMU is present, bus addresses become distinct from
@@ -48,8 +47,8 @@ typedef uint64_t dma_addr_t;
typedef int DMATranslateFunc(DMAContext *dma,
dma_addr_t addr,
hwaddr *paddr,
hwaddr *len,
target_phys_addr_t *paddr,
target_phys_addr_t *len,
DMADirection dir);
typedef void* DMAMapFunc(DMAContext *dma,
dma_addr_t addr,
@@ -62,17 +61,11 @@ typedef void DMAUnmapFunc(DMAContext *dma,
dma_addr_t access_len);
struct DMAContext {
AddressSpace *as;
DMATranslateFunc *translate;
DMAMapFunc *map;
DMAUnmapFunc *unmap;
};
/* A global DMA context corresponding to the address_space_memory
* AddressSpace, for sysbus devices which do DMA.
*/
extern DMAContext dma_context_memory;
static inline void dma_barrier(DMAContext *dma, DMADirection dir)
{
/*
@@ -100,7 +93,7 @@ static inline void dma_barrier(DMAContext *dma, DMADirection dir)
static inline bool dma_has_iommu(DMAContext *dma)
{
return dma && dma->translate;
return !!dma;
}
/* Checks that the given range of addresses is valid for DMA. This is
@@ -127,7 +120,8 @@ static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr,
{
if (!dma_has_iommu(dma)) {
/* Fast-path for no IOMMU */
address_space_rw(dma->as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
cpu_physical_memory_rw(addr, buf, len,
dir == DMA_DIRECTION_FROM_DEVICE);
return 0;
} else {
return iommu_dma_memory_rw(dma, addr, buf, len, dir);
@@ -182,10 +176,11 @@ static inline void *dma_memory_map(DMAContext *dma,
DMADirection dir)
{
if (!dma_has_iommu(dma)) {
hwaddr xlen = *len;
target_phys_addr_t xlen = *len;
void *p;
p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
p = cpu_physical_memory_map(addr, &xlen,
dir == DMA_DIRECTION_FROM_DEVICE);
*len = xlen;
return p;
} else {
@@ -201,8 +196,9 @@ static inline void dma_memory_unmap(DMAContext *dma,
DMADirection dir, dma_addr_t access_len)
{
if (!dma_has_iommu(dma)) {
address_space_unmap(dma->as, buffer, (hwaddr)len,
dir == DMA_DIRECTION_FROM_DEVICE, access_len);
cpu_physical_memory_unmap(buffer, (target_phys_addr_t)len,
dir == DMA_DIRECTION_FROM_DEVICE,
access_len);
} else {
iommu_dma_memory_unmap(dma, buffer, len, dir, access_len);
}
@@ -246,7 +242,7 @@ DEFINE_LDST_DMA(q, q, 64, be);
#undef DEFINE_LDST_DMA
void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
void dma_context_init(DMAContext *dma, DMATranslateFunc translate,
DMAMapFunc map, DMAUnmapFunc unmap);
struct ScatterGatherEntry {
-109
View File
@@ -1,109 +0,0 @@
; qemupciserial.inf for QEMU, based on MSPORTS.INF
; The driver itself is shipped with Windows (serial.sys). This is
; just a inf file to tell windows which pci id the serial pci card
; emulated by qemu has, and to apply a name tag to it which windows
; will show in the device manager.
; Installing the driver: Go to device manager. You should find a "pci
; serial card" tagged with a yellow question mark. Open properties.
; Pick "update driver". Then "select driver manually". Pick "Ports
; (Com+Lpt)" from the list. Click "Have a disk". Select this file.
; Procedure may vary a bit depending on the windows version.
; FIXME: This file covers the single port version only.
[Version]
Signature="$CHICAGO$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%QEMU%
DriverVer=09/24/2012,1.3.0
[SourceDisksNames]
3426=windows cd
[SourceDisksFiles]
serial.sys = 3426
serenum.sys = 3426
[DestinationDirs]
DefaultDestDir = 11 ;LDID_SYS
ComPort.NT.Copy = 12 ;DIRID_DRIVERS
SerialEnumerator.NT.Copy=12 ;DIRID_DRIVERS
; Drivers
;----------------------------------------------------------
[Manufacturer]
%QEMU%=QEMU,NTx86
[QEMU.NTx86]
%QEMU-PCI_SERIAL.DeviceDesc% = ComPort, "PCI\VEN_1b36&DEV_0002&CC_0700"
; COM sections
;----------------------------------------------------------
[ComPort.AddReg]
HKR,,PortSubClass,1,01
[ComPort.NT]
AddReg=ComPort.AddReg, ComPort.NT.AddReg
LogConfig=caa
SyssetupPnPFlags = 1
[ComPort.NT.HW]
AddReg=ComPort.NT.HW.AddReg
[ComPort.NT.AddReg]
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[ComPort.NT.HW.AddReg]
HKR,,"UpperFilters",0x00010000,"serenum"
;-------------- Service installation
; Port Driver (function driver for this device)
[ComPort.NT.Services]
AddService = Serial, 0x00000002, Serial_Service_Inst, Serial_EventLog_Inst
AddService = Serenum,,Serenum_Service_Inst
; -------------- Serial Port Driver install sections
[Serial_Service_Inst]
DisplayName = %Serial.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 1 ; SERVICE_SYSTEM_START (this driver may do detection)
ErrorControl = 0 ; SERVICE_ERROR_IGNORE
ServiceBinary = %12%\serial.sys
LoadOrderGroup = Extended base
; -------------- Serenum Driver install section
[Serenum_Service_Inst]
DisplayName = %Serenum.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\serenum.sys
LoadOrderGroup = PNP Filter
[Serial_EventLog_Inst]
AddReg = Serial_EventLog_AddReg
[Serial_EventLog_AddReg]
HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\serial.sys"
HKR,,TypesSupported,0x00010001,7
; The following sections are COM port resource configs.
; Section name format means:
; Char 1 = c (COM port)
; Char 2 = I/O config: 1 (3f8), 2 (2f8), 3 (3e8), 4 (2e8), a (any)
; Char 3 = IRQ config: #, a (any)
[caa] ; Any base, any IRQ
ConfigPriority=HARDRECONFIG
IOConfig=8@100-ffff%fff8(3ff::)
IRQConfig=S:3,4,5,7,9,10,11,12,14,15
[Strings]
QEMU="QEMU"
QEMU-PCI_SERIAL.DeviceDesc="QEMU Serial PCI Card"
Serial.SVCDESC = "Serial port driver"
Serenum.SVCDESC = "Serenum Filter Driver"
-34
View File
@@ -1,34 +0,0 @@
QEMU pci serial devices
=======================
There is one single-port variant and two muliport-variants. Linux
guests out-of-the box with all cards. There is a Windows inf file
(docs/qemupciserial.inf) to setup the single-port card in Windows
guests.
single-port card
----------------
Name: pci-serial
PCI ID: 1b36:0002
PCI Region 0:
IO bar, 8 bytes long, with the 16550 uart mapped to it.
Interrupt is wired to pin A.
multiport cards
---------------
Name: pci-serial-2x
PCI ID: 1b36:0003
Name: pci-serial-4x
PCI ID: 1b36:0004
PCI Region 0:
IO bar, with two/four 16550 uart mapped after each other.
The first is at offset 0, second at offset 8, ...
Interrupt is wired to pin A.
-65
View File
@@ -1,65 +0,0 @@
QEMU Standard VGA
=================
Exists in two variants, for isa and pci.
command line switches:
-vga std [ picks isa for -M isapc, otherwise pci ]
-device VGA [ pci variant ]
-device isa-vga [ isa variant ]
PCI spec
--------
Applies to the pci variant only for obvious reasons.
PCI ID: 1234:1111
PCI Region 0:
Framebuffer memory, 16 MB in size (by default).
Size is tunable via vga_mem_mb property.
PCI Region 1:
Reserved (so we have the option to make the framebuffer bar 64bit).
PCI Region 2:
MMIO bar, 4096 bytes in size (qemu 1.3+)
PCI ROM Region:
Holds the vgabios (qemu 0.14+).
IO ports used
-------------
03c0 - 03df : standard vga ports
01ce : bochs vbe interface index port
01cf : bochs vbe interface data port (x86 only)
01d0 : bochs vbe interface data port
Memory regions used
-------------------
0xe0000000 : Framebuffer memory, isa variant only.
The pci variant used to mirror the framebuffer bar here, qemu 0.14+
stops doing that (except when in -M pc-$old compat mode).
MMIO area spec
--------------
Likewise applies to the pci variant only for obvious reasons.
0000 - 03ff : reserved, for possible virtio extension.
0400 - 041f : vga ioports (0x3c0 -> 0x3df), remapped 1:1.
word access is supported, bytes are written
in little endia order (aka index port first),
so indexed registers can be updated with a
single mmio write (and thus only one vmexit).
0500 - 0515 : bochs dispi interface registers, mapped flat
without index/data ports. Use (index << 1)
as offset for (16bit) register access.
+9 -4
View File
@@ -139,10 +139,6 @@ having a common prefix in a batch. For example, virtio-blk trace events could
be enabled using:
trace-event virtio_blk_* on
If a line in the "-trace events=<file>" file begins with a '-', the trace event
will be disabled instead of enabled. This is useful when a wildcard was used
to enable an entire family of events but one noisy event needs to be disabled.
== Trace backends ==
The "tracetool" script automates tedious trace event code generation and also
@@ -189,6 +185,15 @@ records the char* pointer value instead of the string that is pointed to.
==== Monitor commands ====
* info trace
Display the contents of trace buffer. This command dumps the trace buffer
with simple formatting. For full pretty-printing, use the simpletrace.py
script on a binary trace file.
The trace buffer is written into until full. The full trace buffer is
flushed and emptied. This means the 'info trace' will display few or no
entries if the buffer has just been flushed.
* trace-file on|off|flush|set <path>
Enable/disable/flush the trace file or set the trace file name.
+22 -14
View File
@@ -15,7 +15,7 @@
#include "elf.h"
#include "cpu.h"
#include "cpu-all.h"
#include "hwaddr.h"
#include "targphys.h"
#include "monitor.h"
#include "kvm.h"
#include "dump.h"
@@ -66,7 +66,7 @@ typedef struct DumpState {
bool have_section;
bool resume;
size_t note_size;
hwaddr memory_offset;
target_phys_addr_t memory_offset;
int fd;
RAMBlock *block;
@@ -100,11 +100,18 @@ static void dump_error(DumpState *s, const char *reason)
static int fd_write_vmcore(void *buf, size_t size, void *opaque)
{
DumpState *s = opaque;
size_t written_size;
int fd = s->fd;
size_t writen_size;
written_size = qemu_write_full(s->fd, buf, size);
if (written_size != size) {
return -1;
/* The fd may be passed from user, and it can be non-blocked */
while (size) {
writen_size = qemu_write_full(fd, buf, size);
if (writen_size != size && errno != EAGAIN) {
return -1;
}
buf += writen_size;
size -= writen_size;
}
return 0;
@@ -187,7 +194,7 @@ static int write_elf32_header(DumpState *s)
}
static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
int phdr_index, hwaddr offset)
int phdr_index, target_phys_addr_t offset)
{
Elf64_Phdr phdr;
int ret;
@@ -216,7 +223,7 @@ static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
}
static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
int phdr_index, hwaddr offset)
int phdr_index, target_phys_addr_t offset)
{
Elf32_Phdr phdr;
int ret;
@@ -248,7 +255,7 @@ static int write_elf64_note(DumpState *s)
{
Elf64_Phdr phdr;
int endian = s->dump_info.d_endian;
hwaddr begin = s->memory_offset - s->note_size;
target_phys_addr_t begin = s->memory_offset - s->note_size;
int ret;
memset(&phdr, 0, sizeof(Elf64_Phdr));
@@ -296,7 +303,7 @@ static int write_elf64_notes(DumpState *s)
static int write_elf32_note(DumpState *s)
{
hwaddr begin = s->memory_offset - s->note_size;
target_phys_addr_t begin = s->memory_offset - s->note_size;
Elf32_Phdr phdr;
int endian = s->dump_info.d_endian;
int ret;
@@ -414,11 +421,11 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
}
/* get the memory's offset in the vmcore */
static hwaddr get_offset(hwaddr phys_addr,
static target_phys_addr_t get_offset(target_phys_addr_t phys_addr,
DumpState *s)
{
RAMBlock *block;
hwaddr offset = s->memory_offset;
target_phys_addr_t offset = s->memory_offset;
int64_t size_in_block, start;
if (s->has_filter) {
@@ -463,7 +470,7 @@ static hwaddr get_offset(hwaddr phys_addr,
static int write_elf_loads(DumpState *s)
{
hwaddr offset;
target_phys_addr_t offset;
MemoryMapping *memory_mapping;
uint32_t phdr_index = 1;
int ret;
@@ -829,8 +836,9 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
#if !defined(WIN32)
if (strstart(file, "fd:", &p)) {
fd = monitor_get_fd(cur_mon, p, errp);
fd = monitor_get_fd(cur_mon, p);
if (fd == -1) {
error_set(errp, QERR_FD_NOT_FOUND, p);
return;
}
}
-28
View File
@@ -43,34 +43,6 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
*errp = err;
}
void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
const char *fmt, ...)
{
Error *err;
char *msg1;
va_list ap;
if (errp == NULL) {
return;
}
assert(*errp == NULL);
err = g_malloc0(sizeof(*err));
va_start(ap, fmt);
msg1 = g_strdup_vprintf(fmt, ap);
if (os_errno != 0) {
err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno));
g_free(msg1);
} else {
err->msg = msg1;
}
va_end(ap);
err->err_class = err_class;
*errp = err;
}
Error *error_copy(const Error *err)
{
Error *err_new;
-15
View File
@@ -29,21 +29,6 @@ typedef struct Error Error;
*/
void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4);
/**
* Set an indirect pointer to an error given a ErrorClass value and a
* printf-style human message, followed by a strerror() string if
* @os_error is not zero.
*/
void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
/**
* Same as error_set(), but sets a generic error
*/
#define error_setg(err, fmt, ...) \
error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
#define error_setg_errno(err, os_error, fmt, ...) \
error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
/**
* Returns true if an indirect pointer to an error is pointing to a valid
* error object.
-120
View File
@@ -1,120 +0,0 @@
/*
* event notifier support
*
* Copyright Red Hat, Inc. 2010
*
* Authors:
* Michael S. Tsirkin <mst@redhat.com>
*
* 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 "qemu-common.h"
#include "event_notifier.h"
#include "qemu-char.h"
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif
void event_notifier_init_fd(EventNotifier *e, int fd)
{
e->rfd = fd;
e->wfd = fd;
}
int event_notifier_init(EventNotifier *e, int active)
{
int fds[2];
int ret;
#ifdef CONFIG_EVENTFD
ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
#else
ret = -1;
errno = ENOSYS;
#endif
if (ret >= 0) {
e->rfd = e->wfd = ret;
} else {
if (errno != ENOSYS) {
return -errno;
}
if (qemu_pipe(fds) < 0) {
return -errno;
}
ret = fcntl_setfl(fds[0], O_NONBLOCK);
if (ret < 0) {
ret = -errno;
goto fail;
}
ret = fcntl_setfl(fds[1], O_NONBLOCK);
if (ret < 0) {
ret = -errno;
goto fail;
}
e->rfd = fds[0];
e->wfd = fds[1];
}
if (active) {
event_notifier_set(e);
}
return 0;
fail:
close(fds[0]);
close(fds[1]);
return ret;
}
void event_notifier_cleanup(EventNotifier *e)
{
if (e->rfd != e->wfd) {
close(e->rfd);
}
close(e->wfd);
}
int event_notifier_get_fd(EventNotifier *e)
{
return e->rfd;
}
int event_notifier_set_handler(EventNotifier *e,
EventNotifierHandler *handler)
{
return qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e);
}
int event_notifier_set(EventNotifier *e)
{
static const uint64_t value = 1;
ssize_t ret;
do {
ret = write(e->wfd, &value, sizeof(value));
} while (ret < 0 && errno == EINTR);
/* EAGAIN is fine, a read must be pending. */
if (ret < 0 && errno != EAGAIN) {
return -errno;
}
return 0;
}
int event_notifier_test_and_clear(EventNotifier *e)
{
int value;
ssize_t len;
char buffer[512];
/* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
value = 0;
do {
len = read(e->rfd, buffer, sizeof(buffer));
value |= (len > 0);
} while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
return value;
}
-59
View File
@@ -1,59 +0,0 @@
/*
* event notifier support
*
* Copyright Red Hat, Inc. 2010
*
* Authors:
* Michael S. Tsirkin <mst@redhat.com>
*
* 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 "qemu-common.h"
#include "event_notifier.h"
#include "main-loop.h"
int event_notifier_init(EventNotifier *e, int active)
{
e->event = CreateEvent(NULL, TRUE, FALSE, NULL);
assert(e->event);
return 0;
}
void event_notifier_cleanup(EventNotifier *e)
{
CloseHandle(e->event);
}
HANDLE event_notifier_get_handle(EventNotifier *e)
{
return e->event;
}
int event_notifier_set_handler(EventNotifier *e,
EventNotifierHandler *handler)
{
if (handler) {
return qemu_add_wait_object(e->event, (IOHandler *)handler, e);
} else {
qemu_del_wait_object(e->event, (IOHandler *)handler, e);
return 0;
}
}
int event_notifier_set(EventNotifier *e)
{
SetEvent(e->event);
return 0;
}
int event_notifier_test_and_clear(EventNotifier *e)
{
int ret = WaitForSingleObject(e->event, 0);
if (ret == WAIT_OBJECT_0) {
ResetEvent(e->event);
return true;
}
return false;
}
+67
View File
@@ -0,0 +1,67 @@
/*
* event notifier support
*
* Copyright Red Hat, Inc. 2010
*
* Authors:
* Michael S. Tsirkin <mst@redhat.com>
*
* 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 "qemu-common.h"
#include "event_notifier.h"
#include "qemu-char.h"
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif
void event_notifier_init_fd(EventNotifier *e, int fd)
{
e->fd = fd;
}
int event_notifier_init(EventNotifier *e, int active)
{
#ifdef CONFIG_EVENTFD
int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
if (fd < 0)
return -errno;
e->fd = fd;
return 0;
#else
return -ENOSYS;
#endif
}
void event_notifier_cleanup(EventNotifier *e)
{
close(e->fd);
}
int event_notifier_get_fd(EventNotifier *e)
{
return e->fd;
}
int event_notifier_set_handler(EventNotifier *e,
EventNotifierHandler *handler)
{
return qemu_set_fd_handler(e->fd, (IOHandler *)handler, NULL, e);
}
int event_notifier_set(EventNotifier *e)
{
uint64_t value = 1;
int r = write(e->fd, &value, sizeof(value));
return r == sizeof(value);
}
int event_notifier_test_and_clear(EventNotifier *e)
{
uint64_t value;
int r = read(e->fd, &value, sizeof(value));
return r == sizeof(value);
}
+3 -17
View File
@@ -15,32 +15,18 @@
#include "qemu-common.h"
#ifdef _WIN32
#include <windows.h>
#endif
struct EventNotifier {
#ifdef _WIN32
HANDLE event;
#else
int rfd;
int wfd;
#endif
int fd;
};
typedef void EventNotifierHandler(EventNotifier *);
void event_notifier_init_fd(EventNotifier *, int fd);
int event_notifier_init(EventNotifier *, int active);
void event_notifier_cleanup(EventNotifier *);
int event_notifier_get_fd(EventNotifier *);
int event_notifier_set(EventNotifier *);
int event_notifier_test_and_clear(EventNotifier *);
int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *);
#ifdef CONFIG_POSIX
void event_notifier_init_fd(EventNotifier *, int fd);
int event_notifier_get_fd(EventNotifier *);
#else
HANDLE event_notifier_get_handle(EventNotifier *);
#endif
#endif
+11 -48
View File
@@ -103,9 +103,9 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
void tlb_flush_page(CPUArchState *env, target_ulong addr);
void tlb_flush(CPUArchState *env, int flush_global);
void tlb_set_page(CPUArchState *env, target_ulong vaddr,
hwaddr paddr, int prot,
target_phys_addr_t paddr, int prot,
int mmu_idx, target_ulong size);
void tb_invalidate_phys_addr(hwaddr addr);
void tb_invalidate_phys_addr(target_phys_addr_t addr);
#else
static inline void tlb_flush_page(CPUArchState *env, target_ulong addr)
{
@@ -121,6 +121,8 @@ static inline void tlb_flush(CPUArchState *env, int flush_global)
#define CODE_GEN_PHYS_HASH_BITS 15
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
#define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024)
/* estimated block size for TB allocation */
/* XXX: use a per code average code fragment size and modulate it
according to the host CPU */
@@ -194,6 +196,8 @@ static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
void tb_free(TranslationBlock *tb);
void tb_flush(CPUArchState *env);
void tb_link_page(TranslationBlock *tb,
tb_page_addr_t phys_pc, tb_page_addr_t phys_page2);
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
@@ -290,11 +294,9 @@ extern int tb_invalidated_flag;
/* The return address may point to the start of the next instruction.
Subtracting one gets us the call instruction itself. */
#if defined(CONFIG_TCG_INTERPRETER)
/* Softmmu, Alpha, MIPS, SH4 and SPARC user mode emulations call GETPC().
/* Alpha and SH4 user mode emulations and Softmmu call GETPC().
For all others, GETPC remains undefined (which makes TCI a little faster. */
# if defined(CONFIG_SOFTMMU) || \
defined(TARGET_ALPHA) || defined(TARGET_MIPS) || \
defined(TARGET_SH4) || defined(TARGET_SPARC)
# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4)
extern uintptr_t tci_tb_ptr;
# define GETPC() tci_tb_ptr
# endif
@@ -309,51 +311,12 @@ extern uintptr_t tci_tb_ptr;
# define GETPC() ((uintptr_t)__builtin_return_address(0) - 1)
#endif
#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
/* qemu_ld/st optimization split code generation to fast and slow path, thus,
it needs special handling for an MMU helper which is called from the slow
path, to get the fast path's pc without any additional argument.
It uses a tricky solution which embeds the fast path pc into the slow path.
Code flow in slow path:
(1) pre-process
(2) call MMU helper
(3) jump to (5)
(4) fast path information (implementation specific)
(5) post-process (e.g. stack adjust)
(6) jump to corresponding code of the next of fast path
*/
# if defined(__i386__) || defined(__x86_64__)
/* To avoid broken disassembling, long jmp is used for embedding fast path pc,
so that the destination is the next code of fast path, though this jmp is
never executed.
call MMU helper
jmp POST_PROC (2byte) <- GETRA()
jmp NEXT_CODE (5byte)
POST_PROCESS ... <- GETRA() + 7
*/
# define GETRA() ((uintptr_t)__builtin_return_address(0))
# define GETPC_LDST() ((uintptr_t)(GETRA() + 7 + \
*(int32_t *)((void *)GETRA() + 3) - 1))
# elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64)
# define GETRA() ((uintptr_t)__builtin_return_address(0))
# define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1))
# else
# error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!"
# endif
bool is_tcg_gen_code(uintptr_t pc_ptr);
# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC())
#else
# define GETPC_EXT() GETPC()
#endif
#if !defined(CONFIG_USER_ONLY)
struct MemoryRegion *iotlb_to_region(hwaddr index);
uint64_t io_mem_read(struct MemoryRegion *mr, hwaddr addr,
struct MemoryRegion *iotlb_to_region(target_phys_addr_t index);
uint64_t io_mem_read(struct MemoryRegion *mr, target_phys_addr_t addr,
unsigned size);
void io_mem_write(struct MemoryRegion *mr, hwaddr addr,
void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr,
uint64_t value, unsigned size);
void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
+5 -2
View File
@@ -33,8 +33,11 @@ MemoryRegion *get_system_memory(void);
*/
MemoryRegion *get_system_io(void);
extern AddressSpace address_space_memory;
extern AddressSpace address_space_io;
/* Set the root memory region. This region is the system memory map. */
void set_system_memory_map(MemoryRegion *mr);
/* Set the I/O memory region. This region is the I/O memory map. */
void set_system_io_map(MemoryRegion *mr);
#endif
+22 -27
View File
@@ -16,32 +16,14 @@
* The functions declared here will be removed soon.
*/
#ifndef MEMORY_INTERNAL_H
#define MEMORY_INTERNAL_H
#ifndef EXEC_OBSOLETE_H
#define EXEC_OBSOLETE_H
#ifndef WANT_EXEC_OBSOLETE
#error Do not include exec-obsolete.h
#endif
#ifndef CONFIG_USER_ONLY
#include "hw/xen.h"
typedef struct PhysPageEntry PhysPageEntry;
struct PhysPageEntry {
uint16_t is_leaf : 1;
/* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */
uint16_t ptr : 15;
};
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
struct AddressSpaceDispatch {
/* This is a multi-level map on the physical address space.
* The bottom level has pointers to MemoryRegionSections.
*/
PhysPageEntry phys_map;
MemoryListener listener;
};
void address_space_init_dispatch(AddressSpace *as);
void address_space_destroy_dispatch(AddressSpace *as);
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr);
@@ -51,9 +33,13 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
struct MemoryRegion;
struct MemoryRegionSection;
void cpu_register_physical_memory_log(struct MemoryRegionSection *section,
bool readonly);
void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size);
void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size);
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
int cpu_physical_memory_set_dirty_tracking(int enable);
#define VGA_DIRTY_FLAG 0x01
#define CODE_DIRTY_FLAG 0x02
@@ -88,6 +74,11 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
int dirty_flags)
{
if ((dirty_flags & MIGRATION_DIRTY_FLAG) &&
!cpu_physical_memory_get_dirty(addr, TARGET_PAGE_SIZE,
MIGRATION_DIRTY_FLAG)) {
ram_list.dirty_pages++;
}
return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
}
@@ -101,6 +92,11 @@ static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr,
{
int mask = ~dirty_flags;
if ((dirty_flags & MIGRATION_DIRTY_FLAG) &&
cpu_physical_memory_get_dirty(addr, TARGET_PAGE_SIZE,
MIGRATION_DIRTY_FLAG)) {
ram_list.dirty_pages--;
}
return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
}
@@ -115,7 +111,6 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
cpu_physical_memory_set_dirty_flags(addr, dirty_flags);
}
xen_modified_memory(addr, length);
}
static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
+423 -400
View File
File diff suppressed because it is too large. Load diff
+2 -97
View File
@@ -41,13 +41,6 @@ these four paragraphs for those parts of this code that are retained.
#define SNAN_BIT_IS_ONE 0
#endif
#if defined(TARGET_XTENSA)
/* Define for architectures which deviate from IEEE in not supporting
* signaling NaNs (so all NaNs are treated as quiet).
*/
#define NO_SIGNALING_NANS 1
#endif
/*----------------------------------------------------------------------------
| The pattern for a default generated half-precision NaN.
*----------------------------------------------------------------------------*/
@@ -64,8 +57,7 @@ const float16 float16_default_nan = const_float16(0xFE00);
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
const float32 float32_default_nan = const_float32(0x7FFFFFFF);
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
defined(TARGET_XTENSA)
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
const float32 float32_default_nan = const_float32(0x7FC00000);
#elif SNAN_BIT_IS_ONE
const float32 float32_default_nan = const_float32(0x7FBFFFFF);
@@ -135,17 +127,6 @@ typedef struct {
uint64_t high, low;
} commonNaNT;
#ifdef NO_SIGNALING_NANS
int float16_is_quiet_nan(float16 a_)
{
return float16_is_any_nan(a_);
}
int float16_is_signaling_nan(float16 a_)
{
return 0;
}
#else
/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
@@ -175,7 +156,6 @@ int float16_is_signaling_nan(float16 a_)
return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
#endif
}
#endif
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the half-precision floating point value `a' is a
@@ -237,17 +217,6 @@ static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM)
}
}
#ifdef NO_SIGNALING_NANS
int float32_is_quiet_nan(float32 a_)
{
return float32_is_any_nan(a_);
}
int float32_is_signaling_nan(float32 a_)
{
return 0;
}
#else
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
@@ -277,7 +246,6 @@ int float32_is_signaling_nan( float32 a_ )
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
#endif
}
#endif
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the single-precision floating point value `a' is a
@@ -404,7 +372,7 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
return 1;
}
}
#elif defined(TARGET_PPC) || defined(TARGET_XTENSA)
#elif defined(TARGET_PPC)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag aIsLargerSignificand)
{
@@ -486,33 +454,6 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
return 1;
}
}
#elif defined(TARGET_MIPS)
static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag cIsQNaN, flag cIsSNaN, flag infzero STATUS_PARAM)
{
/* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns
* the default NaN
*/
if (infzero) {
float_raise(float_flag_invalid STATUS_VAR);
return 3;
}
/* Prefer sNaN over qNaN, in the a, b, c order. */
if (aIsSNaN) {
return 0;
} else if (bIsSNaN) {
return 1;
} else if (cIsSNaN) {
return 2;
} else if (aIsQNaN) {
return 0;
} else if (bIsQNaN) {
return 1;
} else {
return 2;
}
}
#elif defined(TARGET_PPC)
static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag cIsQNaN, flag cIsSNaN, flag infzero STATUS_PARAM)
@@ -645,17 +586,6 @@ static float32 propagateFloat32MulAddNaN(float32 a, float32 b,
}
}
#ifdef NO_SIGNALING_NANS
int float64_is_quiet_nan(float64 a_)
{
return float64_is_any_nan(a_);
}
int float64_is_signaling_nan(float64 a_)
{
return 0;
}
#else
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
@@ -689,7 +619,6 @@ int float64_is_signaling_nan( float64 a_ )
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
#endif
}
#endif
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the double-precision floating point value `a' is a
@@ -844,17 +773,6 @@ static float64 propagateFloat64MulAddNaN(float64 a, float64 b,
}
}
#ifdef NO_SIGNALING_NANS
int floatx80_is_quiet_nan(floatx80 a_)
{
return floatx80_is_any_nan(a_);
}
int floatx80_is_signaling_nan(floatx80 a_)
{
return 0;
}
#else
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
| quiet NaN; otherwise returns 0. This slightly differs from the same
@@ -898,7 +816,6 @@ int floatx80_is_signaling_nan( floatx80 a )
&& ( a.low == aLow );
#endif
}
#endif
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the extended double-precision floating point value
@@ -1012,17 +929,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
}
}
#ifdef NO_SIGNALING_NANS
int float128_is_quiet_nan(float128 a_)
{
return float128_is_any_nan(a_);
}
int float128_is_signaling_nan(float128 a_)
{
return 0;
}
#else
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
@@ -1058,7 +964,6 @@ int float128_is_signaling_nan( float128 a )
&& ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
#endif
}
#endif
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the quadruple-precision floating point value `a' is
+1 -1
View File
@@ -3007,7 +3007,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
if (aSig) {
return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
}
return packFloat32(aSign, 0xff, 0);
return packFloat32(aSign, 0xff, aSig << 13);
}
if (aExp == 0) {
int8 shiftCount;
Loaded 100 of 1436 files, more files were not shown because too many files have changed in this diff. Show more